Temporarily allow const impl and impl const at the same time to migrate

This commit is contained in:
Oli Scherer 2025-07-22 10:06:49 +00:00 committed by Oli Scherer
parent a16ff533b9
commit 08c391ca09
7 changed files with 42 additions and 91 deletions

View file

@ -562,9 +562,7 @@ impl<'a> Parser<'a> {
attrs: &mut AttrVec,
defaultness: Defaultness,
) -> PResult<'a, ItemKind> {
if self.eat_keyword(exp!(Const)) {
return self.recover_const_impl(self.prev_token.span, attrs, defaultness);
}
let mut constness = self.parse_constness(Case::Sensitive);
let safety = self.parse_safety(Case::Sensitive);
self.expect_keyword(exp!(Impl))?;
@ -579,7 +577,11 @@ impl<'a> Parser<'a> {
generics
};
let constness = self.parse_constness(Case::Sensitive);
if let Const::No = constness {
// FIXME(const_trait_impl): disallow `impl const Trait`
constness = self.parse_constness(Case::Sensitive);
}
if let Const::Yes(span) = constness {
self.psess.gated_spans.gate(sym::const_trait_impl, span);
}
@ -1355,46 +1357,6 @@ impl<'a> Parser<'a> {
}
}
/// Recover on `const impl` with `const` already eaten.
fn recover_const_impl(
&mut self,
const_span: Span,
attrs: &mut AttrVec,
defaultness: Defaultness,
) -> PResult<'a, ItemKind> {
let impl_span = self.token.span;
let err = self.expected_ident_found_err();
// Only try to recover if this is implementing a trait for a type
let mut item_kind = match self.parse_item_impl(attrs, defaultness) {
Ok(item_kind) => item_kind,
Err(recovery_error) => {
// Recovery failed, raise the "expected identifier" error
recovery_error.cancel();
return Err(err);
}
};
match &mut item_kind {
ItemKind::Impl(Impl { of_trait: Some(of_trait), .. }) => {
of_trait.constness = Const::Yes(const_span);
let before_trait = of_trait.trait_ref.path.span.shrink_to_lo();
let const_up_to_impl = const_span.with_hi(impl_span.lo());
err.with_multipart_suggestion(
"you might have meant to write a const trait impl",
vec![(const_up_to_impl, "".to_owned()), (before_trait, "const ".to_owned())],
Applicability::MaybeIncorrect,
)
.emit();
}
ItemKind::Impl { .. } => return Err(err),
_ => unreachable!(),
}
Ok(item_kind)
}
/// Parse a static item with the prefix `"static" "mut"?` already parsed and stored in
/// `mutability`.
///

View file

@ -1,5 +1,6 @@
trait T { const
impl //~ ERROR: expected identifier, found keyword `impl`
}
trait T {
const //~ ERROR: const trait impls are experimental
impl
} //~ ERROR: expected type, found `}`
fn main() {}

View file

@ -1,17 +1,25 @@
error: expected identifier, found keyword `impl`
error: expected type, found `}`
--> $DIR/issue-81806.rs:4:1
|
LL | trait T {
| - while parsing this item list starting here
...
LL | }
| ^
| |
| expected type
| the item list ends here
error[E0658]: const trait impls are experimental
--> $DIR/issue-81806.rs:2:1
|
LL | trait T { const
| - while parsing this item list starting here
LL | impl
| ^^^^ expected identifier, found keyword
LL | }
| - the item list ends here
LL | const
| ^^^^^
|
help: escape `impl` to use it as an identifier
|
LL | r#impl
| ++
= note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error: aborting due to 1 previous error
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0658`.

View file

@ -2,7 +2,7 @@
struct Foo;
const impl Foo { //~ ERROR: expected identifier, found keyword
const impl Foo { //~ ERROR: inherent impls cannot be const
fn bar() {}
}

View file

@ -1,8 +1,12 @@
error: expected identifier, found keyword `impl`
--> $DIR/const-impl-norecover.rs:5:7
error: inherent impls cannot be const
--> $DIR/const-impl-norecover.rs:5:12
|
LL | const impl Foo {
| ^^^^ expected identifier, found keyword
| ----- ^^^ inherent impl for this type
| |
| const because of this
|
= note: only trait implementations may be annotated with `const`
error: aborting due to 1 previous error

View file

@ -1,12 +1,14 @@
#![feature(const_trait_impl)]
//@ check-pass
const trait Foo {}
const impl Foo for i32 {} //~ ERROR: expected identifier, found keyword
const impl Foo for i32 {}
const trait Bar {}
const impl<T: Foo> Bar for T {} //~ ERROR: expected identifier, found keyword
const impl<T: Foo> Bar for T {}
const fn still_implements<T: Bar>() {}

View file

@ -1,26 +0,0 @@
error: expected identifier, found keyword `impl`
--> $DIR/const-impl-recovery.rs:5:7
|
LL | const impl Foo for i32 {}
| ^^^^ expected identifier, found keyword
|
help: you might have meant to write a const trait impl
|
LL - const impl Foo for i32 {}
LL + impl const Foo for i32 {}
|
error: expected identifier, found keyword `impl`
--> $DIR/const-impl-recovery.rs:9:7
|
LL | const impl<T: Foo> Bar for T {}
| ^^^^ expected identifier, found keyword
|
help: you might have meant to write a const trait impl
|
LL - const impl<T: Foo> Bar for T {}
LL + impl<T: Foo> const Bar for T {}
|
error: aborting due to 2 previous errors