|
1 |
| -use super::{Parser, PResult, TokenType}; |
| 1 | +use super::{Parser, PResult, Restrictions, TokenType}; |
2 | 2 |
|
3 | 3 | use crate::{maybe_whole, ThinVec};
|
4 | 4 | use crate::ast::{self, QSelf, Path, PathSegment, Ident, ParenthesizedArgs, AngleBracketedArgs};
|
@@ -414,10 +414,52 @@ impl<'a> Parser<'a> {
|
414 | 414 | assoc_ty_constraints.push(span);
|
415 | 415 | } else if self.check_const_arg() {
|
416 | 416 | // Parse const argument.
|
| 417 | + let invalid = self.look_ahead(1, |t| t != &token::Lt && t != &token::Comma); |
417 | 418 | let expr = if let token::OpenDelim(token::Brace) = self.token.kind {
|
418 | 419 | self.parse_block_expr(
|
419 | 420 | None, self.token.span, BlockCheckMode::Default, ThinVec::new()
|
420 | 421 | )?
|
| 422 | + } else if invalid { |
| 423 | + // This can't possibly be a valid const arg, it is likely missing braces. |
| 424 | + let snapshot = self.clone(); |
| 425 | + match self.parse_expr_res(Restrictions::CONST_EXPR_RECOVERY, None) { |
| 426 | + Ok(expr) => { |
| 427 | + if self.token == token::Comma || self.token == token::Gt { |
| 428 | + // We parsed the whole const argument successfully without braces. |
| 429 | + if !expr.node.is_valid_const_on_its_own() { |
| 430 | + // But it wasn't a literal, so we emit a custom error and |
| 431 | + // suggest the appropriate code. |
| 432 | + let msg = |
| 433 | + "complex const arguments must be surrounded by braces"; |
| 434 | + let appl = Applicability::MachineApplicable; |
| 435 | + self.span_fatal(expr.span, msg) |
| 436 | + .multipart_suggestion( |
| 437 | + "surround this const argument in braces", |
| 438 | + vec![ |
| 439 | + (expr.span.shrink_to_lo(), "{ ".to_string()), |
| 440 | + (expr.span.shrink_to_hi(), " }".to_string()), |
| 441 | + ], |
| 442 | + appl, |
| 443 | + ) |
| 444 | + .emit(); |
| 445 | + } |
| 446 | + expr |
| 447 | + } else { |
| 448 | + // We parsed *some* expression, but it isn't the whole argument |
| 449 | + // so we can't ensure it was a const argument with missing braces. |
| 450 | + // Roll-back and emit a regular parser error. |
| 451 | + mem::replace(self, snapshot); |
| 452 | + self.parse_literal_maybe_minus()? |
| 453 | + } |
| 454 | + } |
| 455 | + Err(mut err) => { |
| 456 | + // We couldn't parse an expression successfully. |
| 457 | + // Roll-back, hide the error and emit a regular parser error. |
| 458 | + err.cancel(); |
| 459 | + mem::replace(self, snapshot); |
| 460 | + self.parse_literal_maybe_minus()? |
| 461 | + } |
| 462 | + } |
421 | 463 | } else if self.token.is_ident() {
|
422 | 464 | // FIXME(const_generics): to distinguish between idents for types and consts,
|
423 | 465 | // we should introduce a GenericArg::Ident in the AST and distinguish when
|
|
0 commit comments