Merge the ~const
and impl const
checks and add some explanatory notes
This commit is contained in:
parent
33bcea8f61
commit
c72c6e01c8
4 changed files with 34 additions and 45 deletions
|
@ -191,32 +191,6 @@ impl<'tcx> Visitor<'tcx> for CheckConstVisitor<'tcx> {
|
||||||
self.tcx.hir()
|
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) {
|
fn visit_anon_const(&mut self, anon: &'tcx hir::AnonConst) {
|
||||||
let kind = Some(hir::ConstContext::Const);
|
let kind = Some(hir::ConstContext::Const);
|
||||||
self.recurse_into(kind, None, |this| intravisit::walk_anon_const(this, anon));
|
self.recurse_into(kind, None, |this| intravisit::walk_anon_const(this, anon));
|
||||||
|
|
|
@ -309,8 +309,30 @@ impl<'tcx> WfPredicates<'tcx> {
|
||||||
self.nominal_obligations_without_const(trait_ref.def_id, trait_ref.substs)
|
self.nominal_obligations_without_const(trait_ref.def_id, trait_ref.substs)
|
||||||
} else {
|
} else {
|
||||||
if !tcx.has_attr(trait_ref.def_id, rustc_span::sym::const_trait) {
|
if !tcx.has_attr(trait_ref.def_id, rustc_span::sym::const_trait) {
|
||||||
tcx.sess
|
if let Some(item) = self.item &&
|
||||||
.span_err(self.span, "~const can only be applied to `#[const_trait]` traits");
|
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)
|
self.nominal_obligations(trait_ref.def_id, trait_ref.substs)
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
#![feature(const_trait_impl)]
|
#![feature(const_trait_impl)]
|
||||||
|
|
||||||
pub trait A {}
|
pub trait A {}
|
||||||
//~^ NOTE: this trait must be annotated with `#[const_trait]`
|
//~^ HELP: mark `A` as const
|
||||||
|
|
||||||
impl const A for () {}
|
impl const A for () {}
|
||||||
//~^ ERROR: const `impl`s must be for traits marked with `#[const_trait]`
|
//~^ ERROR: const `impl` for trait `A` which is not marked with `#[const_trait]`
|
||||||
//~| ERROR: ~const can only be applied to `#[const_trait]` traits
|
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -1,20 +1,14 @@
|
||||||
error: const `impl`s must be for traits marked with `#[const_trait]`
|
error: const `impl` for trait `A` which is not 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
|
|
||||||
--> $DIR/const-impl-requires-const-trait.rs:6:12
|
--> $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 () {}
|
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
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue