]> git.proxmox.com Git - rustc.git/blobdiff - compiler/rustc_passes/src/stability.rs
New upstream version 1.63.0+dfsg1
[rustc.git] / compiler / rustc_passes / src / stability.rs
index e1bc248971ae25ff1b7245553a77341315607dcb..9eaefc8b8aa8fa9eeb90024ba54cc3622868f200 100644 (file)
@@ -9,10 +9,10 @@ use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
 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};
+use rustc_hir::{FieldDef, Generics, HirId, Item, ItemKind, TraitRef, Ty, TyKind, Variant};
 use rustc_middle::hir::nested_filter;
 use rustc_middle::middle::privacy::AccessLevels;
-use rustc_middle::middle::stability::{DeprecationEntry, Index};
+use rustc_middle::middle::stability::{AllowUnstable, DeprecationEntry, Index};
 use rustc_middle::ty::{self, query::Providers, TyCtxt};
 use rustc_session::lint;
 use rustc_session::lint::builtin::{INEFFECTIVE_UNSTABLE_TRAIT_IMPL, USELESS_DEPRECATED};
@@ -125,7 +125,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
                         .span_suggestion_short(
                             *span,
                             "remove the unnecessary deprecation attribute",
-                            String::new(),
+                            "",
                             rustc_errors::Applicability::MachineApplicable,
                         )
                         .emit();
@@ -147,7 +147,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
             // 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() {
+                if inherit_deprecation.yes() && stab.is_unstable() {
                     self.index.stab_map.insert(def_id, stab);
                 }
             }
@@ -190,7 +190,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
         if const_stab.is_none() {
             debug!("annotate: const_stab not found, parent = {:?}", self.parent_const_stab);
             if let Some(parent) = self.parent_const_stab {
-                if parent.level.is_unstable() {
+                if parent.is_const_unstable() {
                     self.index.const_stab_map.insert(def_id, parent);
                 }
             }
@@ -272,9 +272,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
         if stab.is_none() {
             debug!("annotate: stab not found, parent = {:?}", self.parent_stab);
             if let Some(stab) = self.parent_stab {
-                if inherit_deprecation.yes() && stab.level.is_unstable()
-                    || inherit_from_parent.yes()
-                {
+                if inherit_deprecation.yes() && stab.is_unstable() || inherit_from_parent.yes() {
                     self.index.stab_map.insert(def_id, stab);
                 }
             }
@@ -532,7 +530,8 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> {
             return;
         }
 
-        let is_const = self.tcx.is_const_fn(def_id.to_def_id());
+        let is_const = self.tcx.is_const_fn(def_id.to_def_id())
+            || self.tcx.is_const_trait_impl_raw(def_id.to_def_id());
         let is_stable = self
             .tcx
             .lookup_stability(def_id)
@@ -661,7 +660,7 @@ fn stability_index(tcx: TyCtxt<'_>, (): ()) -> Index {
 /// Cross-references the feature names of unstable APIs with enabled
 /// features and possibly prints errors.
 fn check_mod_unstable_api_usage(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
-    tcx.hir().visit_item_likes_in_module(module_def_id, &mut Checker { tcx }.as_deep_visitor());
+    tcx.hir().deep_visit_item_likes_in_module(module_def_id, &mut Checker { tcx });
 }
 
 pub(crate) fn provide(providers: &mut Providers) {
@@ -710,16 +709,23 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
             // For implementations of traits, check the stability of each item
             // individually as it's possible to have a stable trait with unstable
             // items.
-            hir::ItemKind::Impl(hir::Impl { of_trait: Some(ref t), self_ty, items, .. }) => {
-                if self.tcx.features().staged_api {
+            hir::ItemKind::Impl(hir::Impl {
+                of_trait: Some(ref t),
+                self_ty,
+                items,
+                constness,
+                ..
+            }) => {
+                let features = self.tcx.features();
+                if features.staged_api {
+                    let attrs = self.tcx.hir().attrs(item.hir_id());
+                    let (stab, const_stab) = attr::find_stability(&self.tcx.sess, attrs, item.span);
+
                     // If this impl block has an #[unstable] attribute, give an
                     // error if all involved types and traits are stable, because
                     // it will have no effect.
                     // See: https://github.com/rust-lang/rust/issues/55436
-                    let attrs = self.tcx.hir().attrs(item.hir_id());
-                    if let (Some((Stability { level: attr::Unstable { .. }, .. }, span)), _) =
-                        attr::find_stability(&self.tcx.sess, attrs, item.span)
-                    {
+                    if let Some((Stability { level: attr::Unstable { .. }, .. }, span)) = stab {
                         let mut c = CheckTraitImplStable { tcx: self.tcx, fully_stable: true };
                         c.visit_ty(self_ty);
                         c.visit_trait_ref(t);
@@ -735,6 +741,19 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
                             );
                         }
                     }
+
+                    // `#![feature(const_trait_impl)]` is unstable, so any impl declared stable
+                    // needs to have an error emitted.
+                    if features.const_trait_impl
+                        && *constness == hir::Constness::Const
+                        && const_stab.map_or(false, |(stab, _)| stab.is_const_stable())
+                    {
+                        self.tcx
+                            .sess
+                            .struct_span_err(item.span, "trait implementations cannot be const stable yet")
+                            .note("see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information")
+                            .emit();
+                    }
                 }
 
                 for impl_item_ref in *items {
@@ -788,12 +807,46 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
     fn visit_path(&mut self, path: &'tcx hir::Path<'tcx>, id: hir::HirId) {
         if let Some(def_id) = path.res.opt_def_id() {
             let method_span = path.segments.last().map(|s| s.ident.span);
-            self.tcx.check_stability(def_id, Some(id), path.span, method_span)
+            self.tcx.check_stability_allow_unstable(
+                def_id,
+                Some(id),
+                path.span,
+                method_span,
+                if is_unstable_reexport(self.tcx, id) {
+                    AllowUnstable::Yes
+                } else {
+                    AllowUnstable::No
+                },
+            )
         }
         intravisit::walk_path(self, path)
     }
 }
 
+/// Check whether a path is a `use` item that has been marked as unstable.
+///
+/// See issue #94972 for details on why this is a special case
+fn is_unstable_reexport<'tcx>(tcx: TyCtxt<'tcx>, id: hir::HirId) -> bool {
+    // Get the LocalDefId so we can lookup the item to check the kind.
+    let Some(def_id) = tcx.hir().opt_local_def_id(id) else { return false; };
+
+    let Some(stab) = tcx.stability().local_stability(def_id) else {
+        return false;
+    };
+
+    if stab.level.is_stable() {
+        // The re-export is not marked as unstable, don't override
+        return false;
+    }
+
+    // If this is a path that isn't a use, we don't need to do anything special
+    if !matches!(tcx.hir().item(hir::ItemId { def_id }).kind, ItemKind::Use(..)) {
+        return false;
+    }
+
+    true
+}
+
 struct CheckTraitImplStable<'tcx> {
     tcx: TyCtxt<'tcx>,
     fully_stable: bool,
@@ -837,7 +890,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
         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);
-        tcx.hir().visit_all_item_likes(&mut missing.as_deep_visitor());
+        tcx.hir().deep_visit_all_item_likes(&mut missing);
     }
 
     let declared_lang_features = &tcx.features().declared_lang_features;