X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=compiler%2Frustc_middle%2Fsrc%2Fmiddle%2Fstability.rs;h=0fbad3f0f0f06761c56b77ce6740cfdc936eb1ba;hb=6246d66c6da3064f658831c0ed8162df169a001e;hp=802b7852bace1b332b064f6d641b4a6f8f3b4f35;hpb=ff5e5ec71f934f7d8f273151b3843167e14549bc;p=rust.git diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index 802b7852bac..0fbad3f0f0f 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -62,6 +62,19 @@ pub struct Index { pub stab_map: FxHashMap, pub const_stab_map: FxHashMap, pub depr_map: FxHashMap, + /// Mapping from feature name to feature name based on the `implied_by` field of `#[unstable]` + /// attributes. If a `#[unstable(feature = "implier", implied_by = "impliee")]` attribute + /// exists, then this map will have a `impliee -> implier` entry. + /// + /// This mapping is necessary unless both the `#[stable]` and `#[unstable]` attributes should + /// specify their implications (both `implies` and `implied_by`). If only one of the two + /// attributes do (as in the current implementation, `implied_by` in `#[unstable]`), then this + /// mapping is necessary for diagnostics. When a "unnecessary feature attribute" error is + /// reported, only the `#[stable]` attribute information is available, so the map is necessary + /// to know that the feature implies another feature. If it were reversed, and the `#[stable]` + /// attribute had an `implies` meta item, then a map would be necessary when avoiding a "use of + /// unstable feature" error for a feature that was implied. + pub implications: FxHashMap, } impl Index { @@ -423,7 +436,9 @@ pub fn eval_stability_allow_unstable( match stability { Some(Stability { - level: attr::Unstable { reason, issue, is_soft }, feature, .. + level: attr::Unstable { reason, issue, is_soft, implied_by }, + feature, + .. }) => { if span.allows_unstable(feature) { debug!("stability: skipping span={:?} since it is internal", span); @@ -433,6 +448,13 @@ pub fn eval_stability_allow_unstable( return EvalResult::Allow; } + // If this item was previously part of a now-stabilized feature which is still + // active (i.e. the user hasn't removed the attribute for the stabilized feature + // yet) then allow use of this item. + if let Some(implied_by) = implied_by && self.features().active(implied_by) { + return EvalResult::Allow; + } + // When we're compiling the compiler itself we may pull in // crates from crates.io, but those crates may depend on other // crates also pulled in from crates.io. We want to ideally be @@ -443,7 +465,7 @@ pub fn eval_stability_allow_unstable( // compiling a compiler crate), then let this missing feature // annotation slide. if feature == sym::rustc_private && issue == NonZeroU32::new(27812) { - if self.sess.opts.debugging_opts.force_unstable_if_unmarked { + if self.sess.opts.unstable_opts.force_unstable_if_unmarked { return EvalResult::Allow; } } @@ -471,13 +493,15 @@ pub fn eval_stability_allow_unstable( /// /// This function will also check if the item is deprecated. /// If so, and `id` is not `None`, a deprecated lint attached to `id` will be emitted. + /// + /// Returns `true` if item is allowed aka, stable or unstable under an enabled feature. pub fn check_stability( self, def_id: DefId, id: Option, span: Span, method_span: Option, - ) { + ) -> bool { self.check_stability_allow_unstable(def_id, id, span, method_span, AllowUnstable::No) } @@ -490,6 +514,8 @@ pub fn check_stability( /// If so, and `id` is not `None`, a deprecated lint attached to `id` will be emitted. /// /// Pass `AllowUnstable::Yes` to `allow_unstable` to force an unstable item to be allowed. Deprecation warnings will be emitted normally. + /// + /// Returns `true` if item is allowed aka, stable or unstable under an enabled feature. pub fn check_stability_allow_unstable( self, def_id: DefId, @@ -497,7 +523,7 @@ pub fn check_stability_allow_unstable( span: Span, method_span: Option, allow_unstable: AllowUnstable, - ) { + ) -> bool { self.check_optional_stability( def_id, id, @@ -516,6 +542,8 @@ pub fn check_stability_allow_unstable( /// missing stability attributes (not necessarily just emit a `bug!`). This is necessary /// for default generic parameters, which only have stability attributes if they were /// added after the type on which they're defined. + /// + /// Returns `true` if item is allowed aka, stable or unstable under an enabled feature. pub fn check_optional_stability( self, def_id: DefId, @@ -524,13 +552,16 @@ pub fn check_optional_stability( method_span: Option, allow_unstable: AllowUnstable, unmarked: impl FnOnce(Span, DefId), - ) { + ) -> bool { let soft_handler = |lint, span, msg: &_| { self.struct_span_lint_hir(lint, id.unwrap_or(hir::CRATE_HIR_ID), span, |lint| { lint.build(msg).emit(); }) }; - match self.eval_stability_allow_unstable(def_id, id, span, method_span, allow_unstable) { + let eval_result = + self.eval_stability_allow_unstable(def_id, id, span, method_span, allow_unstable); + let is_allowed = matches!(eval_result, EvalResult::Allow); + match eval_result { EvalResult::Allow => {} EvalResult::Deny { feature, reason, issue, suggestion, is_soft } => report_unstable( self.sess, @@ -544,6 +575,8 @@ pub fn check_optional_stability( ), EvalResult::Unmarked => unmarked(span, def_id), } + + is_allowed } pub fn lookup_deprecation(self, id: DefId) -> Option {