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));
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)
};
#![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() {}
-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