Rollup merge of #151099 - issue-84327-2, r=fmease

Recover parse gracefully from `<const N>`

When a const param doesn't have a `: Type`, recover the parser state and provide a structured suggestion. This not only provides guidance on what was missing, but it also makes subsuequent errors to be emitted that would otherwise be silenced.

```
error: expected `:`, found `>`
  --> $DIR/incorrect-const-param.rs:26:16
   |
LL | impl<T, const N> From<[T; N]> for VecWrapper<T>
   |                ^ expected `:`
   |
help: you might have meant to write the type of the const parameter here
   |
LL | impl<T, const N: /* Type */> From<[T; N]> for VecWrapper<T>
   |                ++++++++++++
```

r? @fmease

Follow up to rust-lang/rust#151077. Fix rust-lang/rust#84327.
This commit is contained in:
Jonathan Brouwer 2026-01-14 22:30:00 +01:00 committed by GitHub
commit 00501de1c8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 140 additions and 1 deletions

View file

@ -109,7 +109,31 @@ impl<'a> Parser<'a> {
self.expect_keyword(exp!(Const))?;
let ident = self.parse_ident()?;
self.expect(exp!(Colon))?;
if let Err(mut err) = self.expect(exp!(Colon)) {
return if self.token.kind == token::Comma || self.token.kind == token::Gt {
// Recover parse from `<const N>` where the type is missing.
let span = const_span.to(ident.span);
err.span_suggestion_verbose(
ident.span.shrink_to_hi(),
"you likely meant to write the type of the const parameter here",
": /* Type */".to_string(),
Applicability::HasPlaceholders,
);
let kind = TyKind::Err(err.emit());
let ty = self.mk_ty(span, kind);
Ok(GenericParam {
ident,
id: ast::DUMMY_NODE_ID,
attrs: preceding_attrs,
bounds: Vec::new(),
kind: GenericParamKind::Const { ty, span, default: None },
is_placeholder: false,
colon_span: None,
})
} else {
Err(err)
};
}
let ty = self.parse_ty()?;
// Parse optional const generics default value.

View file

@ -0,0 +1,45 @@
// #84327
struct VecWrapper<T>(Vec<T>);
// Correct
impl<T, const N: usize> From<[T; N]> for VecWrapper<T>
where
T: Clone,
{
fn from(slice: [T; N]) -> Self {
VecWrapper(slice.to_vec())
}
}
// Forgot const
impl<T, N: usize> From<[T; N]> for VecWrapper<T> //~ ERROR expected value, found type parameter `N`
where //~^ ERROR expected trait, found builtin type `usize`
T: Clone,
{
fn from(slice: [T; N]) -> Self { //~ ERROR expected value, found type parameter `N`
VecWrapper(slice.to_vec())
}
}
// Forgot type
impl<T, const N> From<[T; N]> for VecWrapper<T> //~ ERROR expected `:`, found `>`
where
T: Clone,
{
fn from(slice: [T; N]) -> Self {
VecWrapper(slice.to_vec())
}
}
// Forgot const and type
impl<T, N> From<[T; N]> for VecWrapper<T> //~ ERROR expected value, found type parameter `N`
where
T: Clone,
{
fn from(slice: [T; N]) -> Self { //~ ERROR expected value, found type parameter `N`
VecWrapper(slice.to_vec())
}
}
fn main() {}

View file

@ -0,0 +1,70 @@
error: expected `:`, found `>`
--> $DIR/incorrect-const-param.rs:26:16
|
LL | impl<T, const N> From<[T; N]> for VecWrapper<T>
| ^ expected `:`
|
help: you likely meant to write the type of the const parameter here
|
LL | impl<T, const N: /* Type */> From<[T; N]> for VecWrapper<T>
| ++++++++++++
error[E0423]: expected value, found type parameter `N`
--> $DIR/incorrect-const-param.rs:16:28
|
LL | impl<T, N: usize> From<[T; N]> for VecWrapper<T>
| - ^ not a value
| |
| found this type parameter
error[E0404]: expected trait, found builtin type `usize`
--> $DIR/incorrect-const-param.rs:16:12
|
LL | impl<T, N: usize> From<[T; N]> for VecWrapper<T>
| ^^^^^ not a trait
|
help: you might have meant to write a const parameter here
|
LL | impl<T, const N: usize> From<[T; N]> for VecWrapper<T>
| +++++
error[E0423]: expected value, found type parameter `N`
--> $DIR/incorrect-const-param.rs:20:24
|
LL | impl<T, N: usize> From<[T; N]> for VecWrapper<T>
| - found this type parameter
...
LL | fn from(slice: [T; N]) -> Self {
| ^ not a value
error[E0423]: expected value, found type parameter `N`
--> $DIR/incorrect-const-param.rs:36:21
|
LL | impl<T, N> From<[T; N]> for VecWrapper<T>
| - ^ not a value
| |
| found this type parameter
|
help: you might have meant to write a const parameter here
|
LL | impl<T, const N: /* Type */> From<[T; N]> for VecWrapper<T>
| +++++ ++++++++++++
error[E0423]: expected value, found type parameter `N`
--> $DIR/incorrect-const-param.rs:40:24
|
LL | impl<T, N> From<[T; N]> for VecWrapper<T>
| - found this type parameter
...
LL | fn from(slice: [T; N]) -> Self {
| ^ not a value
|
help: you might have meant to write a const parameter here
|
LL | impl<T, const N: /* Type */> From<[T; N]> for VecWrapper<T>
| +++++ ++++++++++++
error: aborting due to 6 previous errors
Some errors have detailed explanations: E0404, E0423.
For more information about an error, try `rustc --explain E0404`.