Add lint for items deprecated in future

This commit is contained in:
aheart 2018-12-09 18:17:50 +02:00
parent ea007c6b10
commit aa0428570e
4 changed files with 80 additions and 15 deletions

View File

@ -365,6 +365,13 @@ pub mod parser {
} }
} }
declare_lint! {
pub DEPRECATED_IN_FUTURE,
Allow,
"detects use of items that will be deprecated in a future version",
report_in_external_macro: true
}
/// Does nothing as a lint pass, but registers some `Lint`s /// Does nothing as a lint pass, but registers some `Lint`s
/// that are used by other parts of the compiler. /// that are used by other parts of the compiler.
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
@ -427,6 +434,7 @@ impl LintPass for HardwiredLints {
MACRO_USE_EXTERN_CRATE, MACRO_USE_EXTERN_CRATE,
MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS, MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
parser::QUESTION_MARK_MACRO_SEP, parser::QUESTION_MARK_MACRO_SEP,
DEPRECATED_IN_FUTURE,
) )
} }
} }

View File

@ -13,7 +13,7 @@
pub use self::StabilityLevel::*; pub use self::StabilityLevel::*;
use lint; use lint::{self, Lint};
use hir::{self, Item, Generics, StructField, Variant, HirId}; use hir::{self, Item, Generics, StructField, Variant, HirId};
use hir::def::Def; use hir::def::Def;
use hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE}; use hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE};
@ -562,18 +562,20 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
return EvalResult::Allow; return EvalResult::Allow;
} }
let lint_deprecated = |def_id: DefId, id: NodeId, note: Option<Symbol>| { let lint_deprecated = |def_id: DefId,
let path = self.item_path_str(def_id); id: NodeId,
note: Option<Symbol>,
message: &str,
lint: &'static Lint| {
let msg = if let Some(note) = note { let msg = if let Some(note) = note {
format!("use of deprecated item '{}': {}", path, note) format!("{}: {}", message, note)
} else { } else {
format!("use of deprecated item '{}'", path) format!("{}", message)
}; };
self.lint_node(lint::builtin::DEPRECATED, id, span, &msg); self.lint_node(lint, id, span, &msg);
if id == ast::DUMMY_NODE_ID { if id == ast::DUMMY_NODE_ID {
span_bug!(span, "emitted a deprecated lint with dummy node id: {:?}", def_id); span_bug!(span, "emitted a {} lint with dummy node id: {:?}", lint.name, def_id);
} }
}; };
@ -584,17 +586,40 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
// version, then we should display no warning message. // version, then we should display no warning message.
let deprecated_in_future_version = if let Some(sym) = depr_entry.attr.since { let deprecated_in_future_version = if let Some(sym) = depr_entry.attr.since {
let since = sym.as_str(); let since = sym.as_str();
!deprecation_in_effect(&since) if !deprecation_in_effect(&since) {
Some(since)
} else {
None
}
} else { } else {
false None
}; };
let parent_def_id = self.hir().local_def_id(self.hir().get_parent(id)); let parent_def_id = self.hir().local_def_id(self.hir().get_parent(id));
let skip = deprecated_in_future_version || let skip = self.lookup_deprecation_entry(parent_def_id)
self.lookup_deprecation_entry(parent_def_id)
.map_or(false, |parent_depr| parent_depr.same_origin(&depr_entry)); .map_or(false, |parent_depr| parent_depr.same_origin(&depr_entry));
if !skip {
lint_deprecated(def_id, id, depr_entry.attr.note);
if let Some(since) = deprecated_in_future_version {
let path = self.item_path_str(def_id);
let message = format!("use of item '{}' \
that will be deprecated in future version {}",
path,
since);
lint_deprecated(def_id,
id,
depr_entry.attr.note,
&message,
lint::builtin::DEPRECATED_IN_FUTURE);
} else if !skip {
let path = self.item_path_str(def_id);
let message = format!("use of deprecated item '{}'", path);
lint_deprecated(def_id,
id,
depr_entry.attr.note,
&message,
lint::builtin::DEPRECATED);
} }
}; };
} }
@ -614,8 +639,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
if let Some(&Stability{rustc_depr: Some(attr::RustcDeprecation { reason, since }), ..}) if let Some(&Stability{rustc_depr: Some(attr::RustcDeprecation { reason, since }), ..})
= stability { = stability {
if let Some(id) = id { if let Some(id) = id {
let path = self.item_path_str(def_id);
let message = format!("use of deprecated item '{}'", path);
if deprecation_in_effect(&since.as_str()) { if deprecation_in_effect(&since.as_str()) {
lint_deprecated(def_id, id, Some(reason)); lint_deprecated(def_id,
id,
Some(reason),
&message,
lint::builtin::DEPRECATED);
} }
} }
} }

View File

@ -0,0 +1,12 @@
// ignore-tidy-linelength
#![deny(deprecated_in_future)]
#[deprecated(since = "99.99.99", note = "text")]
pub fn deprecated_future() {}
fn test() {
deprecated_future(); //~ ERROR use of item 'deprecated_future' that will be deprecated in future version 99.99.99: text
}
fn main() {}

View File

@ -0,0 +1,14 @@
error: use of item 'deprecated_future' that will be deprecated in future version 99.99.99: text
--> $DIR/deprecation-in-future.rs:9:5
|
LL | deprecated_future(); //~ ERROR use of item 'deprecated_future' that will be deprecated in future version 99.99.99: text
| ^^^^^^^^^^^^^^^^^
|
note: lint level defined here
--> $DIR/deprecation-in-future.rs:3:9
|
LL | #![deny(deprecated_in_future)]
| ^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error