diff options
| author | Mazdak Farrokhzad <twingoow@gmail.com> | 2019-07-07 17:00:17 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-07-07 17:00:17 +0200 |
| commit | 3250b8ee596afc9881aee092279efaa57486d2ea (patch) | |
| tree | c445db0b21aa62544140ff60894f770dc8fade07 /src/librustc | |
| parent | 9cd75fb35f1d24f805c6759fd6236cd708b81ee1 (diff) | |
| parent | 941653b528deb96d5ed13935143db14c45d99d6e (diff) | |
| download | rust-3250b8ee596afc9881aee092279efaa57486d2ea.tar.gz rust-3250b8ee596afc9881aee092279efaa57486d2ea.zip | |
Rollup merge of #62042 - petrochenkov:macstab, r=matthewjasper
Support stability and deprecation checking for all macros RELNOTES: Deprecation attributes on macros now have effect. Fixes https://github.com/rust-lang/rust/issues/34079 Fixes https://github.com/rust-lang/rust/issues/49912 Unblocks https://github.com/rust-lang/rust/pull/62086 Unblocks https://github.com/rust-lang/rust/pull/61000
Diffstat (limited to 'src/librustc')
| -rw-r--r-- | src/librustc/hir/lowering.rs | 5 | ||||
| -rw-r--r-- | src/librustc/hir/map/collector.rs | 1 | ||||
| -rw-r--r-- | src/librustc/hir/mod.rs | 2 | ||||
| -rw-r--r-- | src/librustc/lint/builtin.rs | 5 | ||||
| -rw-r--r-- | src/librustc/middle/lib_features.rs | 6 | ||||
| -rw-r--r-- | src/librustc/middle/stability.rs | 208 |
6 files changed, 135 insertions, 92 deletions
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 271fac544a4..2a9fd58f84b 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -90,6 +90,7 @@ pub struct LoweringContext<'a> { impl_items: BTreeMap<hir::ImplItemId, hir::ImplItem>, bodies: BTreeMap<hir::BodyId, hir::Body>, exported_macros: Vec<hir::MacroDef>, + non_exported_macro_attrs: Vec<ast::Attribute>, trait_impls: BTreeMap<DefId, Vec<hir::HirId>>, @@ -252,6 +253,7 @@ pub fn lower_crate( trait_impls: BTreeMap::new(), modules: BTreeMap::new(), exported_macros: Vec::new(), + non_exported_macro_attrs: Vec::new(), catch_scopes: Vec::new(), loop_scopes: Vec::new(), is_in_loop_condition: false, @@ -662,6 +664,7 @@ impl<'a> LoweringContext<'a> { attrs, span: c.span, exported_macros: hir::HirVec::from(self.exported_macros), + non_exported_macro_attrs: hir::HirVec::from(self.non_exported_macro_attrs), items: self.items, trait_items: self.trait_items, impl_items: self.impl_items, @@ -4022,6 +4025,8 @@ impl<'a> LoweringContext<'a> { body, legacy: def.legacy, }); + } else { + self.non_exported_macro_attrs.extend(attrs.into_iter()); } return None; } diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index 8a59f6b69bc..12ea772c1fb 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -119,6 +119,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { span, // These fields are handled separately: exported_macros: _, + non_exported_macro_attrs: _, items: _, trait_items: _, impl_items: _, diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 7b760a87238..e7b37d40b4b 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -727,6 +727,8 @@ pub struct Crate { pub attrs: HirVec<Attribute>, pub span: Span, pub exported_macros: HirVec<MacroDef>, + // Attributes from non-exported macros, kept only for collecting the library feature list. + pub non_exported_macro_attrs: HirVec<Attribute>, // N.B., we use a BTreeMap here so that `visit_all_items` iterates // over the ids in increasing order. In principle it should not diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 45e598531b9..dd879ec6aff 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -5,10 +5,12 @@ //! lints are all available in `rustc_lint::builtin`. use crate::lint::{LintPass, LateLintPass, LintArray}; +use crate::middle::stability; use crate::session::Session; use errors::{Applicability, DiagnosticBuilder}; use syntax::ast; use syntax::source_map::Span; +use syntax::symbol::Symbol; declare_lint! { pub EXCEEDING_BITSHIFTS, @@ -461,6 +463,7 @@ pub enum BuiltinLintDiagnostics { UnusedImports(String, Vec<(Span, String)>), NestedImplTrait { outer_impl_trait_span: Span, inner_impl_trait_span: Span }, RedundantImport(Vec<(Span, bool)>, ast::Ident), + DeprecatedMacro(Option<Symbol>, Span), } pub(crate) fn add_elided_lifetime_in_path_suggestion( @@ -586,6 +589,8 @@ impl BuiltinLintDiagnostics { ); } } + BuiltinLintDiagnostics::DeprecatedMacro(suggestion, span) => + stability::deprecation_suggestion(db, suggestion, span), } } } diff --git a/src/librustc/middle/lib_features.rs b/src/librustc/middle/lib_features.rs index 694b0a98629..0d6d016e507 100644 --- a/src/librustc/middle/lib_features.rs +++ b/src/librustc/middle/lib_features.rs @@ -144,6 +144,10 @@ impl Visitor<'tcx> for LibFeatureCollector<'tcx> { pub fn collect(tcx: TyCtxt<'_>) -> LibFeatures { let mut collector = LibFeatureCollector::new(tcx); - intravisit::walk_crate(&mut collector, tcx.hir().krate()); + let krate = tcx.hir().krate(); + for attr in &krate.non_exported_macro_attrs { + collector.visit_attribute(attr); + } + intravisit::walk_crate(&mut collector, krate); collector.lib_features } diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 7757336cf9c..5ab762ab225 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -4,6 +4,7 @@ pub use self::StabilityLevel::*; use crate::lint::{self, Lint, in_derive_expansion}; +use crate::lint::builtin::BuiltinLintDiagnostics; use crate::hir::{self, Item, Generics, StructField, Variant, HirId}; use crate::hir::def::{Res, DefKind}; use crate::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE}; @@ -11,12 +12,13 @@ use crate::hir::intravisit::{self, Visitor, NestedVisitorMap}; use crate::ty::query::Providers; use crate::middle::privacy::AccessLevels; use crate::session::{DiagnosticMessageId, Session}; +use errors::DiagnosticBuilder; use syntax::symbol::{Symbol, sym}; use syntax_pos::{Span, MultiSpan}; -use syntax::ast::Attribute; +use syntax::ast::{Attribute, CRATE_NODE_ID}; use syntax::errors::Applicability; use syntax::feature_gate::{GateIssue, emit_feature_err}; -use syntax::attr::{self, Stability, Deprecation}; +use syntax::attr::{self, Stability, Deprecation, RustcDeprecation}; use crate::ty::{self, TyCtxt}; use crate::util::nodemap::{FxHashSet, FxHashMap}; @@ -477,6 +479,36 @@ pub fn provide(providers: &mut Providers<'_>) { }; } +pub fn report_unstable( + sess: &Session, feature: Symbol, reason: Option<Symbol>, issue: u32, span: Span +) { + let msg = match reason { + Some(r) => format!("use of unstable library feature '{}': {}", feature, r), + None => format!("use of unstable library feature '{}'", &feature) + }; + + let msp: MultiSpan = span.into(); + let cm = &sess.parse_sess.source_map(); + let span_key = msp.primary_span().and_then(|sp: Span| + if !sp.is_dummy() { + let file = cm.lookup_char_pos(sp.lo()).file; + if file.name.is_macros() { + None + } else { + Some(span) + } + } else { + None + } + ); + + let error_id = (DiagnosticMessageId::StabilityId(issue), span_key, msg.clone()); + let fresh = sess.one_time_diagnostics.borrow_mut().insert(error_id); + if fresh { + emit_feature_err(&sess.parse_sess, feature, span, GateIssue::Library(Some(issue)), &msg); + } +} + /// Checks whether an item marked with `deprecated(since="X")` is currently /// deprecated (i.e., whether X is not greater than the current rustc version). pub fn deprecation_in_effect(since: &str) -> bool { @@ -501,6 +533,79 @@ pub fn deprecation_in_effect(since: &str) -> bool { } } +pub fn deprecation_suggestion( + diag: &mut DiagnosticBuilder<'_>, suggestion: Option<Symbol>, span: Span +) { + if let Some(suggestion) = suggestion { + diag.span_suggestion( + span, + "replace the use of the deprecated item", + suggestion.to_string(), + Applicability::MachineApplicable, + ); + } +} + +fn deprecation_message_common(message: String, reason: Option<Symbol>) -> String { + match reason { + Some(reason) => format!("{}: {}", message, reason), + None => message, + } +} + +pub fn deprecation_message(depr: &Deprecation, path: &str) -> (String, &'static Lint) { + let message = format!("use of deprecated item '{}'", path); + (deprecation_message_common(message, depr.note), lint::builtin::DEPRECATED) +} + +pub fn rustc_deprecation_message(depr: &RustcDeprecation, path: &str) -> (String, &'static Lint) { + let (message, lint) = if deprecation_in_effect(&depr.since.as_str()) { + (format!("use of deprecated item '{}'", path), lint::builtin::DEPRECATED) + } else { + (format!("use of item '{}' that will be deprecated in future version {}", path, depr.since), + lint::builtin::DEPRECATED_IN_FUTURE) + }; + (deprecation_message_common(message, Some(depr.reason)), lint) +} + +pub fn early_report_deprecation( + sess: &Session, + message: &str, + suggestion: Option<Symbol>, + lint: &'static Lint, + span: Span, +) { + if in_derive_expansion(span) { + return; + } + + let diag = BuiltinLintDiagnostics::DeprecatedMacro(suggestion, span); + sess.buffer_lint_with_diagnostic(lint, CRATE_NODE_ID, span, message, diag); +} + +fn late_report_deprecation( + tcx: TyCtxt<'_>, + message: &str, + suggestion: Option<Symbol>, + lint: &'static Lint, + span: Span, + def_id: DefId, + hir_id: HirId, +) { + if in_derive_expansion(span) { + return; + } + + let mut diag = tcx.struct_span_lint_hir(lint, hir_id, span, message); + if let hir::Node::Expr(_) = tcx.hir().get(hir_id) { + deprecation_suggestion(&mut diag, suggestion, span); + } + diag.emit(); + if hir_id == hir::DUMMY_HIR_ID { + span_bug!(span, "emitted a {} lint with dummy HIR id: {:?}", lint.name, def_id); + } +} + struct Checker<'tcx> { tcx: TyCtxt<'tcx>, } @@ -563,38 +668,6 @@ impl<'tcx> TyCtxt<'tcx> { /// deprecated. If the item is indeed deprecated, we will emit a deprecation lint attached to /// `id`. pub fn eval_stability(self, def_id: DefId, id: Option<HirId>, span: Span) -> EvalResult { - let lint_deprecated = |def_id: DefId, - id: HirId, - note: Option<Symbol>, - suggestion: Option<Symbol>, - message: &str, - lint: &'static Lint| { - if in_derive_expansion(span) { - return; - } - let msg = if let Some(note) = note { - format!("{}: {}", message, note) - } else { - format!("{}", message) - }; - - let mut diag = self.struct_span_lint_hir(lint, id, span, &msg); - if let Some(suggestion) = suggestion { - if let hir::Node::Expr(_) = self.hir().get(id) { - diag.span_suggestion( - span, - "replace the use of the deprecated item", - suggestion.to_string(), - Applicability::MachineApplicable, - ); - } - } - diag.emit(); - if id == hir::DUMMY_HIR_ID { - span_bug!(span, "emitted a {} lint with dummy HIR id: {:?}", lint.name, def_id); - } - }; - // Deprecated attributes apply in-crate and cross-crate. if let Some(id) = id { if let Some(depr_entry) = self.lookup_deprecation_entry(def_id) { @@ -604,14 +677,9 @@ impl<'tcx> TyCtxt<'tcx> { .map_or(false, |parent_depr| parent_depr.same_origin(&depr_entry)); if !skip { - let path = self.def_path_str(def_id); - let message = format!("use of deprecated item '{}'", path); - lint_deprecated(def_id, - id, - depr_entry.attr.note, - None, - &message, - lint::builtin::DEPRECATED); + let (message, lint) = + deprecation_message(&depr_entry.attr, &self.def_path_str(def_id)); + late_report_deprecation(self, &message, None, lint, span, def_id, id); } }; } @@ -631,27 +699,11 @@ impl<'tcx> TyCtxt<'tcx> { if let Some(id) = id { if let Some(stability) = stability { if let Some(depr) = &stability.rustc_depr { - let path = self.def_path_str(def_id); - if deprecation_in_effect(&depr.since.as_str()) { - let message = format!("use of deprecated item '{}'", path); - lint_deprecated(def_id, - id, - Some(depr.reason), - depr.suggestion, - &message, - lint::builtin::DEPRECATED); - } else { - let message = format!("use of item '{}' \ - that will be deprecated in future version {}", - path, - depr.since); - lint_deprecated(def_id, - id, - Some(depr.reason), - depr.suggestion, - &message, - lint::builtin::DEPRECATED_IN_FUTURE); - } + let (message, lint) = + rustc_deprecation_message(depr, &self.def_path_str(def_id)); + late_report_deprecation( + self, &message, depr.suggestion, lint, span, def_id, id + ); } } } @@ -715,34 +767,8 @@ impl<'tcx> TyCtxt<'tcx> { pub fn check_stability(self, def_id: DefId, id: Option<HirId>, span: Span) { match self.eval_stability(def_id, id, span) { EvalResult::Allow => {} - EvalResult::Deny { feature, reason, issue } => { - let msg = match reason { - Some(r) => format!("use of unstable library feature '{}': {}", feature, r), - None => format!("use of unstable library feature '{}'", &feature) - }; - - let msp: MultiSpan = span.into(); - let cm = &self.sess.parse_sess.source_map(); - let span_key = msp.primary_span().and_then(|sp: Span| - if !sp.is_dummy() { - let file = cm.lookup_char_pos(sp.lo()).file; - if file.name.is_macros() { - None - } else { - Some(span) - } - } else { - None - } - ); - - let error_id = (DiagnosticMessageId::StabilityId(issue), span_key, msg.clone()); - let fresh = self.sess.one_time_diagnostics.borrow_mut().insert(error_id); - if fresh { - emit_feature_err(&self.sess.parse_sess, feature, span, - GateIssue::Library(Some(issue)), &msg); - } - } + EvalResult::Deny { feature, reason, issue } => + report_unstable(self.sess, feature, reason, issue, span), EvalResult::Unmarked => { // The API could be uncallable for other reasons, for example when a private module // was referenced. |
