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:
commit
00501de1c8
3 changed files with 140 additions and 1 deletions
|
|
@ -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.
|
||||
|
|
|
|||
45
tests/ui/const-generics/incorrect-const-param.rs
Normal file
45
tests/ui/const-generics/incorrect-const-param.rs
Normal 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() {}
|
||||
70
tests/ui/const-generics/incorrect-const-param.stderr
Normal file
70
tests/ui/const-generics/incorrect-const-param.stderr
Normal 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`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue