about summary refs log tree commit diff
path: root/compiler/rustc_passes/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_passes/src')
-rw-r--r--compiler/rustc_passes/src/errors.rs39
-rw-r--r--compiler/rustc_passes/src/stability.rs60
2 files changed, 85 insertions, 14 deletions
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 51b5861ee0a..9bb9b2353dc 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -1553,6 +1553,45 @@ pub(crate) struct TraitImplConstStable {
 }
 
 #[derive(Diagnostic)]
+#[diag(passes_trait_impl_const_stability_mismatch)]
+pub(crate) struct TraitImplConstStabilityMismatch {
+    #[primary_span]
+    pub span: Span,
+    #[subdiagnostic]
+    pub impl_stability: ImplConstStability,
+    #[subdiagnostic]
+    pub trait_stability: TraitConstStability,
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum TraitConstStability {
+    #[note(passes_trait_impl_const_stability_mismatch_trait_stable)]
+    Stable {
+        #[primary_span]
+        span: Span,
+    },
+    #[note(passes_trait_impl_const_stability_mismatch_trait_unstable)]
+    Unstable {
+        #[primary_span]
+        span: Span,
+    },
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum ImplConstStability {
+    #[note(passes_trait_impl_const_stability_mismatch_impl_stable)]
+    Stable {
+        #[primary_span]
+        span: Span,
+    },
+    #[note(passes_trait_impl_const_stability_mismatch_impl_unstable)]
+    Unstable {
+        #[primary_span]
+        span: Span,
+    },
+}
+
+#[derive(Diagnostic)]
 #[diag(passes_unknown_feature, code = E0635)]
 pub(crate) struct UnknownFeature {
     #[primary_span]
diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs
index 8a4bdf3875c..0fcf6a80ec4 100644
--- a/compiler/rustc_passes/src/stability.rs
+++ b/compiler/rustc_passes/src/stability.rs
@@ -313,7 +313,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
             .map(|(stab, _span)| ConstStability::from_partial(stab, const_stability_indirect));
 
         // If this is a const fn but not annotated with stability markers, see if we can inherit regular stability.
-        if fn_sig.is_some_and(|s| s.header.is_const())  && const_stab.is_none() &&
+        if fn_sig.is_some_and(|s| s.header.is_const()) && const_stab.is_none() &&
             // We only ever inherit unstable features.
             let Some(inherit_regular_stab) =
                 final_stab.filter(|s| s.is_unstable())
@@ -826,24 +826,56 @@ 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()
-                        && self.tcx.is_const_trait_impl(item.owner_id.to_def_id())
-                        && const_stab.is_some_and(|stab| stab.is_const_stable())
+                        && let hir::Constness::Const = constness
                     {
-                        self.tcx.dcx().emit_err(errors::TraitImplConstStable { span: item.span });
+                        let stable_or_implied_stable = match const_stab {
+                            None => true,
+                            Some(stab) if stab.is_const_stable() => {
+                                // `#![feature(const_trait_impl)]` is unstable, so any impl declared stable
+                                // needs to have an error emitted.
+                                // Note: Remove this error once `const_trait_impl` is stabilized
+                                self.tcx
+                                    .dcx()
+                                    .emit_err(errors::TraitImplConstStable { span: item.span });
+                                true
+                            }
+                            Some(_) => false,
+                        };
+
+                        if let Some(trait_id) = t.trait_def_id()
+                            && let Some(const_stab) = self.tcx.lookup_const_stability(trait_id)
+                        {
+                            // the const stability of a trait impl must match the const stability on the trait.
+                            if const_stab.is_const_stable() != stable_or_implied_stable {
+                                let trait_span = self.tcx.def_ident_span(trait_id).unwrap();
+
+                                let impl_stability = if stable_or_implied_stable {
+                                    errors::ImplConstStability::Stable { span: item.span }
+                                } else {
+                                    errors::ImplConstStability::Unstable { span: item.span }
+                                };
+                                let trait_stability = if const_stab.is_const_stable() {
+                                    errors::TraitConstStability::Stable { span: trait_span }
+                                } else {
+                                    errors::TraitConstStability::Unstable { span: trait_span }
+                                };
+
+                                self.tcx.dcx().emit_err(errors::TraitImplConstStabilityMismatch {
+                                    span: item.span,
+                                    impl_stability,
+                                    trait_stability,
+                                });
+                            }
+                        }
                     }
                 }
 
-                match constness {
-                    rustc_hir::Constness::Const => {
-                        if let Some(def_id) = t.trait_def_id() {
-                            // FIXME(const_trait_impl): Improve the span here.
-                            self.tcx.check_const_stability(def_id, t.path.span, t.path.span);
-                        }
-                    }
-                    rustc_hir::Constness::NotConst => {}
+                if let hir::Constness::Const = constness
+                    && let Some(def_id) = t.trait_def_id()
+                {
+                    // FIXME(const_trait_impl): Improve the span here.
+                    self.tcx.check_const_stability(def_id, t.path.span, t.path.span);
                 }
 
                 for impl_item_ref in *items {