Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion compiler/rustc_parse/src/parser/generics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
45 changes: 45 additions & 0 deletions tests/ui/const-generics/incorrect-const-param.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// #84327
Copy link
Member

@fmease fmease Jan 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get that it's nice to group all 3 cases from the issue but is it really necessary? We already have tests in separate files for the other 2 cases we've already addressed (in your PR: #151077, and in mine: #120570).

This doesn't increase test coverage unless I've missed sth. and the added test cases exercise things the preexisting tests don't.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It exercises that the parser recovers correctly besides just providing the suggestion. I tend to group related checks either in the same file when possible, or with files with similar naming. I considered only having this case in the test and then a type error, but felt that having all of them (even if redundant because individual cases are already tested) would help in the future if someone makes changes that incidentally touches these to notice that there are similarly handled cases.


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() {}
70 changes: 70 additions & 0 deletions tests/ui/const-generics/incorrect-const-param.stderr
Original file line number Diff line number Diff line change
@@ -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`.
Loading