diff options
| author | bors <bors@rust-lang.org> | 2022-03-04 05:49:14 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-03-04 05:49:14 +0000 |
| commit | 65f6d33b775eddfc0128c04083bbf3beea360114 (patch) | |
| tree | b1a38a27de70d46108d6679f217dcb45176a7b6e /compiler | |
| parent | 8fa5d74a7cb01ceaf1a07aa6fcaf42137d8bda58 (diff) | |
| parent | c680d39b1ecf16d3ebd3338ea0193002dec611ac (diff) | |
| download | rust-65f6d33b775eddfc0128c04083bbf3beea360114.tar.gz rust-65f6d33b775eddfc0128c04083bbf3beea360114.zip | |
Auto merge of #94096 - cjgillot:ensure-stability, r=lcnr
Ensure stability directives are checked in all cases Split off #93017 Stability and deprecation were not checked in all cases, for instance if a type error happened. This PR moves the check earlier in the pipeline to ensure the errors are emitted in all cases. r? `@lcnr`
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_ast_passes/src/feature_gate.rs | 25 | ||||
| -rw-r--r-- | compiler/rustc_expand/src/config.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_feature/src/active.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_interface/src/passes.rs | 11 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/middle/stability.rs | 12 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/context.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_passes/src/stability.rs | 107 |
7 files changed, 72 insertions, 99 deletions
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 6c44fb0df23..570ec45557d 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -420,6 +420,31 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } } } + + // Emit errors for non-staged-api crates. + if !self.features.staged_api { + if attr.has_name(sym::rustc_deprecated) + || attr.has_name(sym::unstable) + || attr.has_name(sym::stable) + || attr.has_name(sym::rustc_const_unstable) + || attr.has_name(sym::rustc_const_stable) + { + struct_span_err!( + self.sess, + attr.span, + E0734, + "stability attributes may not be used outside of the standard library", + ) + .emit(); + } + } else { + if attr.has_name(sym::deprecated) { + self.sess + .struct_span_err(attr.span, "`#[deprecated]` cannot be used in staged API") + .span_label(attr.span, "use `#[rustc_deprecated]` instead") + .emit(); + } + } } fn visit_item(&mut self, i: &'a ast::Item) { diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index d43c6fec7d5..762198887cf 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -167,6 +167,7 @@ fn get_features( if let Some(Feature { since, .. }) = ACCEPTED_FEATURES.iter().find(|f| name == f.name) { let since = Some(Symbol::intern(since)); features.declared_lang_features.push((name, mi.span(), since)); + features.active_features.insert(name); continue; } @@ -187,10 +188,12 @@ fn get_features( if let Some(f) = ACTIVE_FEATURES.iter().find(|f| name == f.name) { f.set(&mut features, mi.span()); features.declared_lang_features.push((name, mi.span(), None)); + features.active_features.insert(name); continue; } features.declared_lib_features.push((name, mi.span())); + features.active_features.insert(name); } } diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 1d9d16e85cb..1f7dc769512 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -2,6 +2,7 @@ use super::{to_nonzero, Feature, State}; +use rustc_data_structures::fx::FxHashSet; use rustc_span::edition::Edition; use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; @@ -47,6 +48,8 @@ macro_rules! declare_features { pub declared_lang_features: Vec<(Symbol, Span, Option<Symbol>)>, /// `#![feature]` attrs for non-language (library) features. pub declared_lib_features: Vec<(Symbol, Span)>, + /// Features enabled for this crate. + pub active_features: FxHashSet<Symbol>, $( $(#[doc = $doc])* pub $feature: bool @@ -58,6 +61,11 @@ macro_rules! declare_features { $(f(stringify!($feature), self.$feature);)+ } + /// Is the given feature active? + pub fn active(&self, feature: Symbol) -> bool { + self.active_features.contains(&feature) + } + /// Is the given feature enabled? /// /// Panics if the symbol doesn't correspond to a declared feature. diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 35688a65912..1aceb4e95e6 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -922,11 +922,17 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { }); }, { + sess.time("unused_lib_feature_checking", || { + rustc_passes::stability::check_unused_or_stable_features(tcx) + }); + }, + { // We force these querie to run, // since they might not otherwise get called. // This marks the corresponding crate-level attributes // as used, and ensures that their values are valid. tcx.ensure().limits(()); + tcx.ensure().stability_index(()); } ); }); @@ -999,11 +1005,6 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { .par_for_each_module(|module| tcx.ensure().check_mod_deathness(module)); }, { - sess.time("unused_lib_feature_checking", || { - rustc_passes::stability::check_unused_or_stable_features(tcx) - }); - }, - { sess.time("lint_checking", || { rustc_lint::check_crate(tcx, || { rustc_lint::BuiltinCombinedLateLintPass::new() diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index ff19c33d8e8..167a097d9f8 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -6,12 +6,12 @@ pub use self::StabilityLevel::*; use crate::ty::{self, DefIdTree, TyCtxt}; use rustc_ast::NodeId; use rustc_attr::{self as attr, ConstStability, Deprecation, Stability}; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::FxHashMap; use rustc_errors::{Applicability, Diagnostic}; use rustc_feature::GateIssue; use rustc_hir as hir; use rustc_hir::def::DefKind; -use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX}; +use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_INDEX}; use rustc_hir::{self, HirId}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_session::lint::builtin::{DEPRECATED, DEPRECATED_IN_FUTURE, SOFT_UNSTABLE}; @@ -63,12 +63,6 @@ pub struct Index { pub stab_map: FxHashMap<LocalDefId, Stability>, pub const_stab_map: FxHashMap<LocalDefId, ConstStability>, pub depr_map: FxHashMap<LocalDefId, DeprecationEntry>, - - /// Maps for each crate whether it is part of the staged API. - pub staged_api: FxHashMap<CrateNum, bool>, - - /// Features enabled for this crate. - pub active_features: FxHashSet<Symbol>, } impl Index { @@ -423,7 +417,7 @@ impl<'tcx> TyCtxt<'tcx> { debug!("stability: skipping span={:?} since it is internal", span); return EvalResult::Allow; } - if self.stability().active_features.contains(&feature) { + if self.features().active(feature) { return EvalResult::Allow; } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 8ce1b9d4425..36d93de9a33 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2999,11 +2999,6 @@ pub fn provide(providers: &mut ty::query::Providers) { tcx.arena.alloc(tcx.resolutions(()).glob_map.get(&id).cloned().unwrap_or_default()) }; - providers.lookup_stability = |tcx, id| tcx.stability().local_stability(id.expect_local()); - providers.lookup_const_stability = - |tcx, id| tcx.stability().local_const_stability(id.expect_local()); - providers.lookup_deprecation_entry = - |tcx, id| tcx.stability().local_deprecation_entry(id.expect_local()); providers.extern_mod_stmt_cnum = |tcx, id| tcx.resolutions(()).extern_crate_map.get(&id).cloned(); providers.output_filenames = |tcx, ()| &tcx.output_filenames; diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index df3853d8744..37a9f0ecd8c 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -1,13 +1,12 @@ //! A pass that annotates every item and method with its stability level, //! propagating default levels lexically from parent to children ast nodes. -use rustc_ast::Attribute; use rustc_attr::{self as attr, ConstStability, Stability}; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, CRATE_DEF_INDEX, LOCAL_CRATE}; +use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, CRATE_DEF_INDEX}; use rustc_hir::hir_id::CRATE_HIR_ID; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{FieldDef, Generics, HirId, Item, TraitRef, Ty, TyKind, Variant}; @@ -113,12 +112,8 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { { let attrs = self.tcx.get_attrs(def_id.to_def_id()); debug!("annotate(id = {:?}, attrs = {:?})", def_id, attrs); - let mut did_error = false; - if !self.tcx.features().staged_api { - did_error = self.forbid_staged_api_attrs(def_id, attrs, inherit_deprecation.clone()); - } - let depr = if did_error { None } else { attr::find_deprecation(&self.tcx.sess, attrs) }; + let depr = attr::find_deprecation(&self.tcx.sess, attrs); let mut is_deprecated = false; if let Some((depr, span)) = &depr { is_deprecated = true; @@ -148,16 +143,15 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { } } - if self.tcx.features().staged_api { - if let Some(a) = attrs.iter().find(|a| a.has_name(sym::deprecated)) { - self.tcx - .sess - .struct_span_err(a.span, "`#[deprecated]` cannot be used in staged API") - .span_label(a.span, "use `#[rustc_deprecated]` instead") - .span_label(item_sp, "") - .emit(); + if !self.tcx.features().staged_api { + // Propagate unstability. This can happen even for non-staged-api crates in case + // -Zforce-unstable-if-unmarked is set. + if let Some(stab) = self.parent_stab { + if inherit_deprecation.yes() && stab.level.is_unstable() { + self.index.stab_map.insert(def_id, stab); + } } - } else { + self.recurse_with_stability_attrs( depr.map(|(d, _)| DeprecationEntry::local(d, def_id)), None, @@ -329,47 +323,6 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { self.parent_const_stab = orig_parent_const_stab; } } - - // returns true if an error occurred, used to suppress some spurious errors - fn forbid_staged_api_attrs( - &mut self, - def_id: LocalDefId, - attrs: &[Attribute], - inherit_deprecation: InheritDeprecation, - ) -> bool { - // Emit errors for non-staged-api crates. - let unstable_attrs = [ - sym::unstable, - sym::stable, - sym::rustc_deprecated, - sym::rustc_const_unstable, - sym::rustc_const_stable, - ]; - let mut has_error = false; - for attr in attrs { - let name = attr.name_or_empty(); - if unstable_attrs.contains(&name) { - struct_span_err!( - self.tcx.sess, - attr.span, - E0734, - "stability attributes may not be used outside of the standard library", - ) - .emit(); - has_error = true; - } - } - - // Propagate unstability. This can happen even for non-staged-api crates in case - // -Zforce-unstable-if-unmarked is set. - if let Some(stab) = self.parent_stab { - if inherit_deprecation.yes() && stab.level.is_unstable() { - self.index.stab_map.insert(def_id, stab); - } - } - - has_error - } } impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { @@ -654,28 +607,12 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> { } fn stability_index(tcx: TyCtxt<'_>, (): ()) -> Index { - let is_staged_api = - tcx.sess.opts.debugging_opts.force_unstable_if_unmarked || tcx.features().staged_api; - let mut staged_api = FxHashMap::default(); - staged_api.insert(LOCAL_CRATE, is_staged_api); let mut index = Index { - staged_api, stab_map: Default::default(), const_stab_map: Default::default(), depr_map: Default::default(), - active_features: Default::default(), }; - let active_lib_features = &tcx.features().declared_lib_features; - let active_lang_features = &tcx.features().declared_lang_features; - - // Put the active features into a map for quick lookup. - index.active_features = active_lib_features - .iter() - .map(|&(s, ..)| s) - .chain(active_lang_features.iter().map(|&(s, ..)| s)) - .collect(); - { let mut annotator = Annotator { tcx, @@ -728,7 +665,16 @@ fn check_mod_unstable_api_usage(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { } pub(crate) fn provide(providers: &mut Providers) { - *providers = Providers { check_mod_unstable_api_usage, stability_index, ..*providers }; + *providers = Providers { + check_mod_unstable_api_usage, + stability_index, + lookup_stability: |tcx, id| tcx.stability().local_stability(id.expect_local()), + lookup_const_stability: |tcx, id| tcx.stability().local_const_stability(id.expect_local()), + lookup_deprecation_entry: |tcx, id| { + tcx.stability().local_deprecation_entry(id.expect_local()) + }, + ..*providers + }; } struct Checker<'tcx> { @@ -884,9 +830,10 @@ impl<'tcx> Visitor<'tcx> for CheckTraitImplStable<'tcx> { /// were expected to be library features), and the list of features used from /// libraries, identify activated features that don't exist and error about them. pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) { - let access_levels = &tcx.privacy_access_levels(()); - - if tcx.stability().staged_api[&LOCAL_CRATE] { + let is_staged_api = + tcx.sess.opts.debugging_opts.force_unstable_if_unmarked || tcx.features().staged_api; + if is_staged_api { + let access_levels = &tcx.privacy_access_levels(()); let mut missing = MissingStabilityAnnotations { tcx, access_levels }; missing.check_missing_stability(CRATE_DEF_ID, tcx.hir().span(CRATE_HIR_ID)); tcx.hir().walk_toplevel_module(&mut missing); @@ -907,7 +854,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) { } let declared_lib_features = &tcx.features().declared_lib_features; - let mut remaining_lib_features = FxHashMap::default(); + let mut remaining_lib_features = FxIndexMap::default(); for (feature, span) in declared_lib_features { if !tcx.sess.opts.unstable_features.is_nightly_build() { struct_span_err!( @@ -934,7 +881,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) { remaining_lib_features.remove(&sym::libc); remaining_lib_features.remove(&sym::test); - let check_features = |remaining_lib_features: &mut FxHashMap<_, _>, defined_features: &[_]| { + let check_features = |remaining_lib_features: &mut FxIndexMap<_, _>, defined_features: &[_]| { for &(feature, since) in defined_features { if let Some(since) = since { if let Some(span) = remaining_lib_features.get(&feature) { |
