about summary refs log tree commit diff
diff options
context:
space:
mode:
authorOli Scherer <git-spam-no-reply9815368754983@oli-obk.de>2022-10-04 08:59:20 +0000
committerOli Scherer <git-spam-no-reply9815368754983@oli-obk.de>2022-10-04 08:59:20 +0000
commitc72c6e01c8020c7a285b76a9b61934e3501b80f3 (patch)
tree01541dd2c18f1f923a430c9511de92da304c5abd
parent33bcea8f614f5019012f16b49dc3cd934326ca87 (diff)
downloadrust-c72c6e01c8020c7a285b76a9b61934e3501b80f3.tar.gz
rust-c72c6e01c8020c7a285b76a9b61934e3501b80f3.zip
Merge the `~const` and `impl const` checks and add some explanatory notes
-rw-r--r--compiler/rustc_passes/src/check_const.rs26
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs26
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.rs5
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.stderr22
4 files changed, 34 insertions, 45 deletions
diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs
index 116aaf48349..e502b9b54e3 100644
--- a/compiler/rustc_passes/src/check_const.rs
+++ b/compiler/rustc_passes/src/check_const.rs
@@ -191,32 +191,6 @@ impl<'tcx> Visitor<'tcx> for CheckConstVisitor<'tcx> {
         self.tcx.hir()
     }
 
-    fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
-        let tcx = self.tcx;
-        if let hir::ItemKind::Impl(hir::Impl {
-            constness: hir::Constness::Const,
-            of_trait: Some(trait_ref),
-            ..
-        }) = item.kind
-            && let Some(def_id) = trait_ref.trait_def_id()
-        {
-            let source_map = tcx.sess.source_map();
-            if !tcx.has_attr(def_id, sym::const_trait) {
-                tcx.sess
-                    .struct_span_err(
-                        source_map.guess_head_span(item.span),
-                        "const `impl`s must be for traits marked with `#[const_trait]`",
-                    )
-                    .span_note(
-                        source_map.guess_head_span(tcx.def_span(def_id)),
-                        "this trait must be annotated with `#[const_trait]`",
-                    )
-                    .emit();
-            }
-        }
-        intravisit::walk_item(self, item);
-    }
-
     fn visit_anon_const(&mut self, anon: &'tcx hir::AnonConst) {
         let kind = Some(hir::ConstContext::Const);
         self.recurse_into(kind, None, |this| intravisit::walk_anon_const(this, anon));
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index ef7b27e408c..5f901d6995e 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -309,8 +309,30 @@ impl<'tcx> WfPredicates<'tcx> {
             self.nominal_obligations_without_const(trait_ref.def_id, trait_ref.substs)
         } else {
             if !tcx.has_attr(trait_ref.def_id, rustc_span::sym::const_trait) {
-                tcx.sess
-                    .span_err(self.span, "~const can only be applied to `#[const_trait]` traits");
+                if let Some(item) = self.item &&
+                   let hir::ItemKind::Impl(impl_) = item.kind &&
+                   let Some(trait_) = &impl_.of_trait &&
+                   let Some(def_id) = trait_.trait_def_id() &&
+                   def_id == trait_ref.def_id
+                {
+                    let trait_name = tcx.item_name(def_id);
+                    let mut err = tcx.sess.struct_span_err(
+                        self.span,
+                        &format!("const `impl` for trait `{trait_name}` which is not marked with `#[const_trait]`"),
+                    );
+                    if def_id.is_local() {
+                        let sp = tcx.def_span(def_id).shrink_to_lo();
+                        err.span_suggestion(sp, &format!("mark `{trait_name}` as const"), "#[const_trait]", rustc_errors::Applicability::MachineApplicable);
+                    }
+                    err.note("marking a trait with `#[const_trait]` ensures all default method bodies are `const`");
+                    err.note("adding a non-const method body in the future would be a breaking change");
+                    err.emit();
+                } else {
+                    tcx.sess.span_err(
+                        self.span,
+                        "~const can only be applied to `#[const_trait]` traits",
+                    );
+                }
             }
             self.nominal_obligations(trait_ref.def_id, trait_ref.substs)
         };
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.rs b/src/test/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.rs
index 8757d74082e..2b4963991db 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.rs
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.rs
@@ -1,10 +1,9 @@
 #![feature(const_trait_impl)]
 
 pub trait A {}
-//~^ NOTE: this trait must be annotated with `#[const_trait]`
+//~^ HELP: mark `A` as const
 
 impl const A for () {}
-//~^ ERROR: const `impl`s must be for traits marked with `#[const_trait]`
-//~| ERROR: ~const can only be applied to `#[const_trait]` traits
+//~^ ERROR: const `impl` for trait `A` which is not marked with `#[const_trait]`
 
 fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.stderr
index f9c69d6c6bf..478adcf3e9e 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.stderr
@@ -1,20 +1,14 @@
-error: const `impl`s must be for traits marked with `#[const_trait]`
-  --> $DIR/const-impl-requires-const-trait.rs:6:1
-   |
-LL | impl const A for () {}
-   | ^^^^^^^^^^^^^^^^^^^
-   |
-note: this trait must be annotated with `#[const_trait]`
-  --> $DIR/const-impl-requires-const-trait.rs:3:1
-   |
-LL | pub trait A {}
-   | ^^^^^^^^^^^
-
-error: ~const can only be applied to `#[const_trait]` traits
+error: const `impl` for trait `A` which is not marked with `#[const_trait]`
   --> $DIR/const-impl-requires-const-trait.rs:6:12
    |
+LL | pub trait A {}
+   | - help: mark `A` as const: `#[const_trait]`
+...
 LL | impl const A for () {}
    |            ^
+   |
+   = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
+   = note: adding a non-const method body in the future would be a breaking change
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error