Skip to content

Commit 3250b8e

Browse files
authored
Rollup merge of rust-lang#62042 - petrochenkov:macstab, r=matthewjasper
Support stability and deprecation checking for all macros RELNOTES: Deprecation attributes on macros now have effect. Fixes rust-lang#34079 Fixes rust-lang#49912 Unblocks rust-lang#62086 Unblocks rust-lang#61000
2 parents 9cd75fb + 941653b commit 3250b8e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+517
-431
lines changed

src/librustc/hir/lowering.rs

+5
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ pub struct LoweringContext<'a> {
9090
impl_items: BTreeMap<hir::ImplItemId, hir::ImplItem>,
9191
bodies: BTreeMap<hir::BodyId, hir::Body>,
9292
exported_macros: Vec<hir::MacroDef>,
93+
non_exported_macro_attrs: Vec<ast::Attribute>,
9394

9495
trait_impls: BTreeMap<DefId, Vec<hir::HirId>>,
9596

@@ -252,6 +253,7 @@ pub fn lower_crate(
252253
trait_impls: BTreeMap::new(),
253254
modules: BTreeMap::new(),
254255
exported_macros: Vec::new(),
256+
non_exported_macro_attrs: Vec::new(),
255257
catch_scopes: Vec::new(),
256258
loop_scopes: Vec::new(),
257259
is_in_loop_condition: false,
@@ -662,6 +664,7 @@ impl<'a> LoweringContext<'a> {
662664
attrs,
663665
span: c.span,
664666
exported_macros: hir::HirVec::from(self.exported_macros),
667+
non_exported_macro_attrs: hir::HirVec::from(self.non_exported_macro_attrs),
665668
items: self.items,
666669
trait_items: self.trait_items,
667670
impl_items: self.impl_items,
@@ -4022,6 +4025,8 @@ impl<'a> LoweringContext<'a> {
40224025
body,
40234026
legacy: def.legacy,
40244027
});
4028+
} else {
4029+
self.non_exported_macro_attrs.extend(attrs.into_iter());
40254030
}
40264031
return None;
40274032
}

src/librustc/hir/map/collector.rs

+1
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
119119
span,
120120
// These fields are handled separately:
121121
exported_macros: _,
122+
non_exported_macro_attrs: _,
122123
items: _,
123124
trait_items: _,
124125
impl_items: _,

src/librustc/hir/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -727,6 +727,8 @@ pub struct Crate {
727727
pub attrs: HirVec<Attribute>,
728728
pub span: Span,
729729
pub exported_macros: HirVec<MacroDef>,
730+
// Attributes from non-exported macros, kept only for collecting the library feature list.
731+
pub non_exported_macro_attrs: HirVec<Attribute>,
730732

731733
// N.B., we use a BTreeMap here so that `visit_all_items` iterates
732734
// over the ids in increasing order. In principle it should not

src/librustc/lint/builtin.rs

+5
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@
55
//! lints are all available in `rustc_lint::builtin`.
66
77
use crate::lint::{LintPass, LateLintPass, LintArray};
8+
use crate::middle::stability;
89
use crate::session::Session;
910
use errors::{Applicability, DiagnosticBuilder};
1011
use syntax::ast;
1112
use syntax::source_map::Span;
13+
use syntax::symbol::Symbol;
1214

1315
declare_lint! {
1416
pub EXCEEDING_BITSHIFTS,
@@ -461,6 +463,7 @@ pub enum BuiltinLintDiagnostics {
461463
UnusedImports(String, Vec<(Span, String)>),
462464
NestedImplTrait { outer_impl_trait_span: Span, inner_impl_trait_span: Span },
463465
RedundantImport(Vec<(Span, bool)>, ast::Ident),
466+
DeprecatedMacro(Option<Symbol>, Span),
464467
}
465468

466469
pub(crate) fn add_elided_lifetime_in_path_suggestion(
@@ -586,6 +589,8 @@ impl BuiltinLintDiagnostics {
586589
);
587590
}
588591
}
592+
BuiltinLintDiagnostics::DeprecatedMacro(suggestion, span) =>
593+
stability::deprecation_suggestion(db, suggestion, span),
589594
}
590595
}
591596
}

src/librustc/middle/lib_features.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,10 @@ impl Visitor<'tcx> for LibFeatureCollector<'tcx> {
144144

145145
pub fn collect(tcx: TyCtxt<'_>) -> LibFeatures {
146146
let mut collector = LibFeatureCollector::new(tcx);
147-
intravisit::walk_crate(&mut collector, tcx.hir().krate());
147+
let krate = tcx.hir().krate();
148+
for attr in &krate.non_exported_macro_attrs {
149+
collector.visit_attribute(attr);
150+
}
151+
intravisit::walk_crate(&mut collector, krate);
148152
collector.lib_features
149153
}

src/librustc/middle/stability.rs

+117-91
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,21 @@
44
pub use self::StabilityLevel::*;
55

66
use crate::lint::{self, Lint, in_derive_expansion};
7+
use crate::lint::builtin::BuiltinLintDiagnostics;
78
use crate::hir::{self, Item, Generics, StructField, Variant, HirId};
89
use crate::hir::def::{Res, DefKind};
910
use crate::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE};
1011
use crate::hir::intravisit::{self, Visitor, NestedVisitorMap};
1112
use crate::ty::query::Providers;
1213
use crate::middle::privacy::AccessLevels;
1314
use crate::session::{DiagnosticMessageId, Session};
15+
use errors::DiagnosticBuilder;
1416
use syntax::symbol::{Symbol, sym};
1517
use syntax_pos::{Span, MultiSpan};
16-
use syntax::ast::Attribute;
18+
use syntax::ast::{Attribute, CRATE_NODE_ID};
1719
use syntax::errors::Applicability;
1820
use syntax::feature_gate::{GateIssue, emit_feature_err};
19-
use syntax::attr::{self, Stability, Deprecation};
21+
use syntax::attr::{self, Stability, Deprecation, RustcDeprecation};
2022
use crate::ty::{self, TyCtxt};
2123
use crate::util::nodemap::{FxHashSet, FxHashMap};
2224

@@ -477,6 +479,36 @@ pub fn provide(providers: &mut Providers<'_>) {
477479
};
478480
}
479481

482+
pub fn report_unstable(
483+
sess: &Session, feature: Symbol, reason: Option<Symbol>, issue: u32, span: Span
484+
) {
485+
let msg = match reason {
486+
Some(r) => format!("use of unstable library feature '{}': {}", feature, r),
487+
None => format!("use of unstable library feature '{}'", &feature)
488+
};
489+
490+
let msp: MultiSpan = span.into();
491+
let cm = &sess.parse_sess.source_map();
492+
let span_key = msp.primary_span().and_then(|sp: Span|
493+
if !sp.is_dummy() {
494+
let file = cm.lookup_char_pos(sp.lo()).file;
495+
if file.name.is_macros() {
496+
None
497+
} else {
498+
Some(span)
499+
}
500+
} else {
501+
None
502+
}
503+
);
504+
505+
let error_id = (DiagnosticMessageId::StabilityId(issue), span_key, msg.clone());
506+
let fresh = sess.one_time_diagnostics.borrow_mut().insert(error_id);
507+
if fresh {
508+
emit_feature_err(&sess.parse_sess, feature, span, GateIssue::Library(Some(issue)), &msg);
509+
}
510+
}
511+
480512
/// Checks whether an item marked with `deprecated(since="X")` is currently
481513
/// deprecated (i.e., whether X is not greater than the current rustc version).
482514
pub fn deprecation_in_effect(since: &str) -> bool {
@@ -501,6 +533,79 @@ pub fn deprecation_in_effect(since: &str) -> bool {
501533
}
502534
}
503535

536+
pub fn deprecation_suggestion(
537+
diag: &mut DiagnosticBuilder<'_>, suggestion: Option<Symbol>, span: Span
538+
) {
539+
if let Some(suggestion) = suggestion {
540+
diag.span_suggestion(
541+
span,
542+
"replace the use of the deprecated item",
543+
suggestion.to_string(),
544+
Applicability::MachineApplicable,
545+
);
546+
}
547+
}
548+
549+
fn deprecation_message_common(message: String, reason: Option<Symbol>) -> String {
550+
match reason {
551+
Some(reason) => format!("{}: {}", message, reason),
552+
None => message,
553+
}
554+
}
555+
556+
pub fn deprecation_message(depr: &Deprecation, path: &str) -> (String, &'static Lint) {
557+
let message = format!("use of deprecated item '{}'", path);
558+
(deprecation_message_common(message, depr.note), lint::builtin::DEPRECATED)
559+
}
560+
561+
pub fn rustc_deprecation_message(depr: &RustcDeprecation, path: &str) -> (String, &'static Lint) {
562+
let (message, lint) = if deprecation_in_effect(&depr.since.as_str()) {
563+
(format!("use of deprecated item '{}'", path), lint::builtin::DEPRECATED)
564+
} else {
565+
(format!("use of item '{}' that will be deprecated in future version {}", path, depr.since),
566+
lint::builtin::DEPRECATED_IN_FUTURE)
567+
};
568+
(deprecation_message_common(message, Some(depr.reason)), lint)
569+
}
570+
571+
pub fn early_report_deprecation(
572+
sess: &Session,
573+
message: &str,
574+
suggestion: Option<Symbol>,
575+
lint: &'static Lint,
576+
span: Span,
577+
) {
578+
if in_derive_expansion(span) {
579+
return;
580+
}
581+
582+
let diag = BuiltinLintDiagnostics::DeprecatedMacro(suggestion, span);
583+
sess.buffer_lint_with_diagnostic(lint, CRATE_NODE_ID, span, message, diag);
584+
}
585+
586+
fn late_report_deprecation(
587+
tcx: TyCtxt<'_>,
588+
message: &str,
589+
suggestion: Option<Symbol>,
590+
lint: &'static Lint,
591+
span: Span,
592+
def_id: DefId,
593+
hir_id: HirId,
594+
) {
595+
if in_derive_expansion(span) {
596+
return;
597+
}
598+
599+
let mut diag = tcx.struct_span_lint_hir(lint, hir_id, span, message);
600+
if let hir::Node::Expr(_) = tcx.hir().get(hir_id) {
601+
deprecation_suggestion(&mut diag, suggestion, span);
602+
}
603+
diag.emit();
604+
if hir_id == hir::DUMMY_HIR_ID {
605+
span_bug!(span, "emitted a {} lint with dummy HIR id: {:?}", lint.name, def_id);
606+
}
607+
}
608+
504609
struct Checker<'tcx> {
505610
tcx: TyCtxt<'tcx>,
506611
}
@@ -563,38 +668,6 @@ impl<'tcx> TyCtxt<'tcx> {
563668
/// deprecated. If the item is indeed deprecated, we will emit a deprecation lint attached to
564669
/// `id`.
565670
pub fn eval_stability(self, def_id: DefId, id: Option<HirId>, span: Span) -> EvalResult {
566-
let lint_deprecated = |def_id: DefId,
567-
id: HirId,
568-
note: Option<Symbol>,
569-
suggestion: Option<Symbol>,
570-
message: &str,
571-
lint: &'static Lint| {
572-
if in_derive_expansion(span) {
573-
return;
574-
}
575-
let msg = if let Some(note) = note {
576-
format!("{}: {}", message, note)
577-
} else {
578-
format!("{}", message)
579-
};
580-
581-
let mut diag = self.struct_span_lint_hir(lint, id, span, &msg);
582-
if let Some(suggestion) = suggestion {
583-
if let hir::Node::Expr(_) = self.hir().get(id) {
584-
diag.span_suggestion(
585-
span,
586-
"replace the use of the deprecated item",
587-
suggestion.to_string(),
588-
Applicability::MachineApplicable,
589-
);
590-
}
591-
}
592-
diag.emit();
593-
if id == hir::DUMMY_HIR_ID {
594-
span_bug!(span, "emitted a {} lint with dummy HIR id: {:?}", lint.name, def_id);
595-
}
596-
};
597-
598671
// Deprecated attributes apply in-crate and cross-crate.
599672
if let Some(id) = id {
600673
if let Some(depr_entry) = self.lookup_deprecation_entry(def_id) {
@@ -604,14 +677,9 @@ impl<'tcx> TyCtxt<'tcx> {
604677
.map_or(false, |parent_depr| parent_depr.same_origin(&depr_entry));
605678

606679
if !skip {
607-
let path = self.def_path_str(def_id);
608-
let message = format!("use of deprecated item '{}'", path);
609-
lint_deprecated(def_id,
610-
id,
611-
depr_entry.attr.note,
612-
None,
613-
&message,
614-
lint::builtin::DEPRECATED);
680+
let (message, lint) =
681+
deprecation_message(&depr_entry.attr, &self.def_path_str(def_id));
682+
late_report_deprecation(self, &message, None, lint, span, def_id, id);
615683
}
616684
};
617685
}
@@ -631,27 +699,11 @@ impl<'tcx> TyCtxt<'tcx> {
631699
if let Some(id) = id {
632700
if let Some(stability) = stability {
633701
if let Some(depr) = &stability.rustc_depr {
634-
let path = self.def_path_str(def_id);
635-
if deprecation_in_effect(&depr.since.as_str()) {
636-
let message = format!("use of deprecated item '{}'", path);
637-
lint_deprecated(def_id,
638-
id,
639-
Some(depr.reason),
640-
depr.suggestion,
641-
&message,
642-
lint::builtin::DEPRECATED);
643-
} else {
644-
let message = format!("use of item '{}' \
645-
that will be deprecated in future version {}",
646-
path,
647-
depr.since);
648-
lint_deprecated(def_id,
649-
id,
650-
Some(depr.reason),
651-
depr.suggestion,
652-
&message,
653-
lint::builtin::DEPRECATED_IN_FUTURE);
654-
}
702+
let (message, lint) =
703+
rustc_deprecation_message(depr, &self.def_path_str(def_id));
704+
late_report_deprecation(
705+
self, &message, depr.suggestion, lint, span, def_id, id
706+
);
655707
}
656708
}
657709
}
@@ -715,34 +767,8 @@ impl<'tcx> TyCtxt<'tcx> {
715767
pub fn check_stability(self, def_id: DefId, id: Option<HirId>, span: Span) {
716768
match self.eval_stability(def_id, id, span) {
717769
EvalResult::Allow => {}
718-
EvalResult::Deny { feature, reason, issue } => {
719-
let msg = match reason {
720-
Some(r) => format!("use of unstable library feature '{}': {}", feature, r),
721-
None => format!("use of unstable library feature '{}'", &feature)
722-
};
723-
724-
let msp: MultiSpan = span.into();
725-
let cm = &self.sess.parse_sess.source_map();
726-
let span_key = msp.primary_span().and_then(|sp: Span|
727-
if !sp.is_dummy() {
728-
let file = cm.lookup_char_pos(sp.lo()).file;
729-
if file.name.is_macros() {
730-
None
731-
} else {
732-
Some(span)
733-
}
734-
} else {
735-
None
736-
}
737-
);
738-
739-
let error_id = (DiagnosticMessageId::StabilityId(issue), span_key, msg.clone());
740-
let fresh = self.sess.one_time_diagnostics.borrow_mut().insert(error_id);
741-
if fresh {
742-
emit_feature_err(&self.sess.parse_sess, feature, span,
743-
GateIssue::Library(Some(issue)), &msg);
744-
}
745-
}
770+
EvalResult::Deny { feature, reason, issue } =>
771+
report_unstable(self.sess, feature, reason, issue, span),
746772
EvalResult::Unmarked => {
747773
// The API could be uncallable for other reasons, for example when a private module
748774
// was referenced.

src/librustc_plugin/registry.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -84,10 +84,7 @@ impl<'a> Registry<'a> {
8484
/// Register a syntax extension of any kind.
8585
///
8686
/// This is the most general hook into `libsyntax`'s expansion behavior.
87-
pub fn register_syntax_extension(&mut self, name: ast::Name, mut extension: SyntaxExtension) {
88-
if extension.def_info.is_none() {
89-
extension.def_info = Some((ast::CRATE_NODE_ID, self.krate_span));
90-
}
87+
pub fn register_syntax_extension(&mut self, name: ast::Name, extension: SyntaxExtension) {
9188
self.syntax_exts.push((name, extension));
9289
}
9390

0 commit comments

Comments
 (0)