Rollup merge of #120460 - nnethercote:fix-120397, r=compiler-errors
Be more careful about interpreting a label/lifetime as a mistyped char literal. Currently the parser interprets any label/lifetime in certain positions as a mistyped char literal, on the assumption that the trailing single quote was accidentally omitted. In such cases it gives an error with a suggestion to add the trailing single quote, and then puts the appropriate char literal into the AST. This behaviour was introduced in #101293. This is reasonable for a case like this: ``` let c = 'a; ``` because `'a'` is a valid char literal. It's less reasonable for a case like this: ``` let c = 'abc; ``` because `'abc'` is not a valid char literal. Prior to #120329 this could result in some sub-optimal suggestions in error messages, but nothing else. But #120329 changed `LitKind::from_token_lit` to assume that the char/byte/string literals it receives are valid, and to assert if not. This is reasonable because the lexer does not produce invalid char/byte/string literals in general. But in this "interpret label/lifetime as unclosed char literal" case the parser can produce an invalid char literal with contents such as `abc`, which triggers an assertion failure. This PR changes the parser so it's more cautious about interpreting labels/lifetimes as unclosed char literals. Fixes #120397. r? `@compiler-errors`
This commit is contained in:
commit
c00192ae2a
4 changed files with 120 additions and 31 deletions
|
@ -10,6 +10,7 @@ use crate::errors::{
|
|||
UnexpectedParenInRangePat, UnexpectedParenInRangePatSugg,
|
||||
UnexpectedVertVertBeforeFunctionParam, UnexpectedVertVertInPattern,
|
||||
};
|
||||
use crate::parser::expr::could_be_unclosed_char_literal;
|
||||
use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
|
||||
use rustc_ast::mut_visit::{noop_visit_pat, MutVisitor};
|
||||
use rustc_ast::ptr::P;
|
||||
|
@ -535,11 +536,12 @@ impl<'a> Parser<'a> {
|
|||
None => PatKind::Path(qself, path),
|
||||
}
|
||||
}
|
||||
} else if matches!(self.token.kind, token::Lifetime(_))
|
||||
} else if let token::Lifetime(lt) = self.token.kind
|
||||
// In pattern position, we're totally fine with using "next token isn't colon"
|
||||
// as a heuristic. We could probably just always try to recover if it's a lifetime,
|
||||
// because we never have `'a: label {}` in a pattern position anyways, but it does
|
||||
// keep us from suggesting something like `let 'a: Ty = ..` => `let 'a': Ty = ..`
|
||||
&& could_be_unclosed_char_literal(Ident::with_dummy_span(lt))
|
||||
&& !self.look_ahead(1, |token| matches!(token.kind, token::Colon))
|
||||
{
|
||||
// Recover a `'a` as a `'a'` literal
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue