Auto merge of #92884 - compiler-errors:const-generic-expr-recovery, r=jackh726
Suggest adding `{ .. }` around more bad const generic exprs Fixes #92776
This commit is contained in:
commit
7c3331ccf9
@ -2030,7 +2030,7 @@ pub fn recover_const_arg(
|
||||
start: Span,
|
||||
mut err: DiagnosticBuilder<'a, ErrorReported>,
|
||||
) -> PResult<'a, GenericArg> {
|
||||
let is_op = AssocOp::from_token(&self.token)
|
||||
let is_op_or_dot = AssocOp::from_token(&self.token)
|
||||
.and_then(|op| {
|
||||
if let AssocOp::Greater
|
||||
| AssocOp::Less
|
||||
@ -2046,17 +2046,18 @@ pub fn recover_const_arg(
|
||||
Some(op)
|
||||
}
|
||||
})
|
||||
.is_some();
|
||||
.is_some()
|
||||
|| self.token.kind == TokenKind::Dot;
|
||||
// This will be true when a trait object type `Foo +` or a path which was a `const fn` with
|
||||
// type params has been parsed.
|
||||
let was_op =
|
||||
matches!(self.prev_token.kind, token::BinOp(token::Plus | token::Shr) | token::Gt);
|
||||
if !is_op && !was_op {
|
||||
if !is_op_or_dot && !was_op {
|
||||
// We perform these checks and early return to avoid taking a snapshot unnecessarily.
|
||||
return Err(err);
|
||||
}
|
||||
let snapshot = self.clone();
|
||||
if is_op {
|
||||
if is_op_or_dot {
|
||||
self.bump();
|
||||
}
|
||||
match self.parse_expr_res(Restrictions::CONST_EXPR, None) {
|
||||
@ -2080,18 +2081,7 @@ pub fn recover_const_arg(
|
||||
// |
|
||||
// LL | let sr: Vec<{ (u32, _, _) = vec![] };
|
||||
// | ^ ^
|
||||
err.multipart_suggestion(
|
||||
"expressions must be enclosed in braces to be used as const generic \
|
||||
arguments",
|
||||
vec![
|
||||
(start.shrink_to_lo(), "{ ".to_string()),
|
||||
(expr.span.shrink_to_hi(), " }".to_string()),
|
||||
],
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
let value = self.mk_expr_err(start.to(expr.span));
|
||||
err.emit();
|
||||
return Ok(GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value }));
|
||||
return Ok(self.dummy_const_arg_needs_braces(err, start.to(expr.span)));
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
@ -2102,6 +2092,23 @@ pub fn recover_const_arg(
|
||||
Err(err)
|
||||
}
|
||||
|
||||
/// Creates a dummy const argument, and reports that the expression must be enclosed in braces
|
||||
pub fn dummy_const_arg_needs_braces(
|
||||
&self,
|
||||
mut err: DiagnosticBuilder<'a, ErrorReported>,
|
||||
span: Span,
|
||||
) -> GenericArg {
|
||||
err.multipart_suggestion(
|
||||
"expressions must be enclosed in braces to be used as const generic \
|
||||
arguments",
|
||||
vec![(span.shrink_to_lo(), "{ ".to_string()), (span.shrink_to_hi(), " }".to_string())],
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
let value = self.mk_expr_err(span);
|
||||
err.emit();
|
||||
GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value })
|
||||
}
|
||||
|
||||
/// Get the diagnostics for the cases where `move async` is found.
|
||||
///
|
||||
/// `move_async_span` starts at the 'm' of the move keyword and ends with the 'c' of the async keyword
|
||||
|
@ -1,5 +1,5 @@
|
||||
use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
|
||||
use super::{Parser, TokenType};
|
||||
use super::{Parser, Restrictions, TokenType};
|
||||
use crate::maybe_whole;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::token::{self, Token};
|
||||
@ -634,7 +634,22 @@ pub(super) fn parse_generic_arg(
|
||||
} else if self.token.is_keyword(kw::Const) {
|
||||
return self.recover_const_param_declaration(ty_generics);
|
||||
} else {
|
||||
return Ok(None);
|
||||
// Fall back by trying to parse a const-expr expression. If we successfully do so,
|
||||
// then we should report an error that it needs to be wrapped in braces.
|
||||
let snapshot = self.clone();
|
||||
match self.parse_expr_res(Restrictions::CONST_EXPR, None) {
|
||||
Ok(expr) => {
|
||||
return Ok(Some(self.dummy_const_arg_needs_braces(
|
||||
self.struct_span_err(expr.span, "invalid const generic expression"),
|
||||
expr.span,
|
||||
)));
|
||||
}
|
||||
Err(err) => {
|
||||
*self = snapshot;
|
||||
err.cancel();
|
||||
return Ok(None);
|
||||
}
|
||||
}
|
||||
};
|
||||
Ok(Some(arg))
|
||||
}
|
||||
|
22
src/test/ui/const-generics/bad-const-generic-exprs.rs
Normal file
22
src/test/ui/const-generics/bad-const-generic-exprs.rs
Normal file
@ -0,0 +1,22 @@
|
||||
struct Wow<const N: usize>;
|
||||
|
||||
fn main() {
|
||||
let _: Wow<if true {}>;
|
||||
//~^ ERROR invalid const generic expression
|
||||
//~| HELP expressions must be enclosed in braces to be used as const generic arguments
|
||||
let _: Wow<|| ()>;
|
||||
//~^ ERROR invalid const generic expression
|
||||
//~| HELP expressions must be enclosed in braces to be used as const generic arguments
|
||||
let _: Wow<A.b>;
|
||||
//~^ ERROR expected one of
|
||||
//~| HELP expressions must be enclosed in braces to be used as const generic arguments
|
||||
let _: Wow<A.0>;
|
||||
//~^ ERROR expected one of
|
||||
//~| HELP expressions must be enclosed in braces to be used as const generic arguments
|
||||
|
||||
// FIXME(compiler-errors): This one is still unsatisfying,
|
||||
// and probably a case I could see someone typing by accident..
|
||||
let _: Wow<[12]>;
|
||||
//~^ ERROR expected type, found
|
||||
//~| ERROR type provided when a constant was expected
|
||||
}
|
59
src/test/ui/const-generics/bad-const-generic-exprs.stderr
Normal file
59
src/test/ui/const-generics/bad-const-generic-exprs.stderr
Normal file
@ -0,0 +1,59 @@
|
||||
error: invalid const generic expression
|
||||
--> $DIR/bad-const-generic-exprs.rs:4:16
|
||||
|
|
||||
LL | let _: Wow<if true {}>;
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
help: expressions must be enclosed in braces to be used as const generic arguments
|
||||
|
|
||||
LL | let _: Wow<{ if true {} }>;
|
||||
| + +
|
||||
|
||||
error: invalid const generic expression
|
||||
--> $DIR/bad-const-generic-exprs.rs:7:16
|
||||
|
|
||||
LL | let _: Wow<|| ()>;
|
||||
| ^^^^^
|
||||
|
|
||||
help: expressions must be enclosed in braces to be used as const generic arguments
|
||||
|
|
||||
LL | let _: Wow<{ || () }>;
|
||||
| + +
|
||||
|
||||
error: expected one of `,` or `>`, found `.`
|
||||
--> $DIR/bad-const-generic-exprs.rs:10:17
|
||||
|
|
||||
LL | let _: Wow<A.b>;
|
||||
| ^ expected one of `,` or `>`
|
||||
|
|
||||
help: expressions must be enclosed in braces to be used as const generic arguments
|
||||
|
|
||||
LL | let _: Wow<{ A.b }>;
|
||||
| + +
|
||||
|
||||
error: expected one of `,` or `>`, found `.`
|
||||
--> $DIR/bad-const-generic-exprs.rs:13:17
|
||||
|
|
||||
LL | let _: Wow<A.0>;
|
||||
| ^ expected one of `,` or `>`
|
||||
|
|
||||
help: expressions must be enclosed in braces to be used as const generic arguments
|
||||
|
|
||||
LL | let _: Wow<{ A.0 }>;
|
||||
| + +
|
||||
|
||||
error: expected type, found `12`
|
||||
--> $DIR/bad-const-generic-exprs.rs:19:17
|
||||
|
|
||||
LL | let _: Wow<[12]>;
|
||||
| ^^ expected type
|
||||
|
||||
error[E0747]: type provided when a constant was expected
|
||||
--> $DIR/bad-const-generic-exprs.rs:19:16
|
||||
|
|
||||
LL | let _: Wow<[12]>;
|
||||
| ^^^^
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0747`.
|
Loading…
Reference in New Issue
Block a user