diff options
| author | Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de> | 2022-10-04 08:59:20 +0000 |
|---|---|---|
| committer | Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de> | 2022-10-04 08:59:20 +0000 |
| commit | c72c6e01c8020c7a285b76a9b61934e3501b80f3 (patch) | |
| tree | 01541dd2c18f1f923a430c9511de92da304c5abd | |
| parent | 33bcea8f614f5019012f16b49dc3cd934326ca87 (diff) | |
| download | rust-c72c6e01c8020c7a285b76a9b61934e3501b80f3.tar.gz rust-c72c6e01c8020c7a285b76a9b61934e3501b80f3.zip | |
Merge the `~const` and `impl const` checks and add some explanatory notes
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 |
