Use string literal directly when available in format
Previous implementation used the `Parser::parse_expr` function in order to extract the format expression. If the first comma following the format expression was mistakenly replaced with a dot, then the next format expression was eaten by the function, because it looked as a syntactically valid expression, which resulted in incorrectly spanned error messages. The way the format expression is exctracted is changed: we first look at the first available token in the first argument supplied to the `format!` macro call. If it is a string literal, then it is promoted as a format expression immediatly, otherwise we fall back to the original `parse_expr`-related method. This allows us to ensure that the parser won't consume too much tokens when a typo is made. A test has been created so that it is ensured that the issue is properly fixed.
This commit is contained in:
parent
85fbf49ce0
commit
f6d18db402
4 changed files with 75 additions and 2 deletions
|
@ -135,7 +135,26 @@ fn parse_args<'a>(
|
|||
return Err(ecx.struct_span_err(sp, "requires at least a format string argument"));
|
||||
}
|
||||
|
||||
let fmtstr = p.parse_expr()?;
|
||||
let first_token = &p.token;
|
||||
let fmtstr = match first_token.kind {
|
||||
token::TokenKind::Literal(token::Lit {
|
||||
kind: token::LitKind::Str | token::LitKind::StrRaw(_),
|
||||
..
|
||||
}) => {
|
||||
// If the first token is a string literal, then a format expression
|
||||
// is constructed from it.
|
||||
//
|
||||
// This allows us to properly handle cases when the first comma
|
||||
// after the format string is mistakenly replaced with any operator,
|
||||
// which cause the expression parser to eat too much tokens.
|
||||
p.parse_literal_maybe_minus()?
|
||||
}
|
||||
_ => {
|
||||
// Otherwise, we fall back to the expression parser.
|
||||
p.parse_expr()?
|
||||
}
|
||||
};
|
||||
|
||||
let mut first = true;
|
||||
let mut named = false;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue