+use super::diagnostics::SnapshotParser;
use super::pat::{CommaRecoveryMode, RecoverColon, RecoverComma, PARAM_EXPECTED};
use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
use super::{
- AttrWrapper, BlockMode, ClosureSpans, ForceCollect, Parser, PathStyle, Restrictions, TokenType,
+ AttrWrapper, BlockMode, ClosureSpans, ForceCollect, Parser, PathStyle, Restrictions,
+ SemiColonMode, SeqSep, TokenExpectType, TokenType, TrailingToken,
};
-use super::{SemiColonMode, SeqSep, TokenExpectType, TrailingToken};
use crate::maybe_recover_from_interpolated_ty_qpath;
use ast::token::DelimToken;
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, PResult};
use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP;
use rustc_session::lint::BuiltinLintDiagnostics;
-use rustc_span::edition::LATEST_STABLE_EDITION;
use rustc_span::source_map::{self, Span, Spanned};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{BytePos, Pos};
AssocOp::NotEqual => "!=",
_ => unreachable!(),
};
- self.struct_span_err(sp, &format!("invalid comparison operator `{}=`", sugg))
+ self.struct_span_err(sp, &format!("invalid comparison operator `{sugg}=`"))
.span_suggestion_short(
sp,
&format!("`{s}=` is not a valid comparison operator, use `{s}`", s = sugg),
/// Error on `and` and `or` suggesting `&&` and `||` respectively.
fn error_bad_logical_op(&self, bad: &str, good: &str, english: &str) {
- self.struct_span_err(self.token.span, &format!("`{}` is not a logical operator", bad))
+ self.struct_span_err(self.token.span, &format!("`{bad}` is not a logical operator"))
.span_suggestion_short(
self.token.span,
- &format!("use `{}` to perform logical {}", good, english),
+ &format!("use `{good}` to perform logical {english}"),
good.to_string(),
Applicability::MachineApplicable,
)
ExprKind::Path(None, ast::Path { segments, .. }),
TokenKind::Ident(kw::For | kw::Loop | kw::While, false),
) if segments.len() == 1 => {
- let snapshot = self.clone();
+ let snapshot = self.create_snapshot_for_diagnostic();
let label = Label {
ident: Ident::from_str_and_span(
&format!("'{}", segments[0].ident),
}
Err(err) => {
err.cancel();
- *self = snapshot;
+ self.restore_snapshot(snapshot);
}
}
}
self.look_ahead(1, |t| t.span).to(span_after_type),
"interpreted as generic arguments",
)
- .span_label(self.token.span, format!("not interpreted as {}", op_noun))
+ .span_label(self.token.span, format!("not interpreted as {op_noun}"))
.multipart_suggestion(
- &format!("try {} the cast value", op_verb),
+ &format!("try {op_verb} the cast value"),
vec![
(expr.span.shrink_to_lo(), "(".to_string()),
(expr.span.shrink_to_hi(), ")".to_string()),
fn error_unexpected_after_dot(&self) {
// FIXME Could factor this out into non_fatal_unexpected or something.
let actual = pprust::token_to_string(&self.token);
- self.struct_span_err(self.token.span, &format!("unexpected token: `{}`", actual)).emit();
+ self.struct_span_err(self.token.span, &format!("unexpected token: `{actual}`")).emit();
}
// We need an identifier or integer, but the next token is a float.
let snapshot = if self.token.kind == token::OpenDelim(token::Paren)
&& self.look_ahead_type_ascription_as_field()
{
- Some((self.clone(), fun.kind.clone()))
+ Some((self.create_snapshot_for_diagnostic(), fun.kind.clone()))
} else {
None
};
lo: Span,
open_paren: Span,
seq: &mut PResult<'a, P<Expr>>,
- snapshot: Option<(Self, ExprKind)>,
+ snapshot: Option<(SnapshotParser<'a>, ExprKind)>,
) -> Option<P<Expr>> {
match (seq.as_mut(), snapshot) {
(Err(err), Some((mut snapshot, ExprKind::Path(None, path)))) => {
Ok((fields, ..)) if snapshot.eat(&token::CloseDelim(token::Paren)) => {
// We are certain we have `Enum::Foo(a: 3, b: 4)`, suggest
// `Enum::Foo { a: 3, b: 4 }` or `Enum::Foo(3, 4)`.
- *self = snapshot;
+ self.restore_snapshot(snapshot);
let close_paren = self.prev_token.span;
let span = lo.to(self.prev_token.span);
if !fields.is_empty() {
mem::replace(err, replacement_err).cancel();
err.multipart_suggestion(
- &format!("if `{}` is a struct, use braces as delimiters", name),
+ &format!("if `{name}` is a struct, use braces as delimiters"),
vec![
(open_paren, " { ".to_string()),
(close_paren, " }".to_string()),
Applicability::MaybeIncorrect,
);
err.multipart_suggestion(
- &format!("if `{}` is a function, use the arguments directly", name),
+ &format!("if `{name}` is a function, use the arguments directly"),
fields
.into_iter()
.map(|field| (field.span.until(field.expr.span), String::new()))
)
.emit();
} else {
- let msg = format!("invalid suffix `{}` for number literal", suf);
+ let msg = format!("invalid suffix `{suf}` for number literal");
self.struct_span_err(span, &msg)
- .span_label(span, format!("invalid suffix `{}`", suf))
+ .span_label(span, format!("invalid suffix `{suf}`"))
.help("the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)")
.emit();
}
let msg = format!("invalid width `{}` for float literal", &suf[1..]);
self.struct_span_err(span, &msg).help("valid widths are 32 and 64").emit();
} else {
- let msg = format!("invalid suffix `{}` for float literal", suf);
+ let msg = format!("invalid suffix `{suf}` for float literal");
self.struct_span_err(span, &msg)
- .span_label(span, format!("invalid suffix `{}`", suf))
+ .span_label(span, format!("invalid suffix `{suf}`"))
.help("valid suffixes are `f32` and `f64`")
.emit();
}
2 => "binary",
_ => unreachable!(),
};
- self.struct_span_err(span, &format!("{} float literal is not supported", descr))
+ self.struct_span_err(span, &format!("{descr} float literal is not supported"))
.span_label(span, "not supported")
.emit();
}
let mut err = self
.sess
.span_diagnostic
- .struct_span_warn(sp, &format!("suffixes on {} are invalid", kind));
+ .struct_span_warn(sp, &format!("suffixes on {kind} are invalid"));
err.note(&format!(
"`{}` is *temporarily* accepted on tuple index fields as it was \
incorrectly accepted on stable for a few releases",
);
err
} else {
- self.struct_span_err(sp, &format!("suffixes on {} are invalid", kind))
+ self.struct_span_err(sp, &format!("suffixes on {kind} are invalid"))
.forget_guarantee()
};
- err.span_label(sp, format!("invalid suffix `{}`", suf));
+ err.span_label(sp, format!("invalid suffix `{suf}`"));
err.emit();
}
}
lo: Span,
attrs: AttrVec,
) -> Option<P<Expr>> {
- let mut snapshot = self.clone();
+ let mut snapshot = self.create_snapshot_for_diagnostic();
match snapshot.parse_array_or_repeat_expr(attrs, token::Brace) {
Ok(arr) => {
let hi = snapshot.prev_token.span;
.note("to define an array, one would use square brackets instead of curly braces")
.emit();
- *self = snapshot;
+ self.restore_snapshot(snapshot);
Some(self.mk_expr_err(arr.span))
}
Err(e) => {
let ctx = if is_ctx_else { "else" } else { "if" };
self.struct_span_err(last, "outer attributes are not allowed on `if` and `else` branches")
.span_label(branch_span, "the attributes are attached to this branch")
- .span_label(ctx_span, format!("the branch belongs to this `{}`", ctx))
+ .span_label(ctx_span, format!("the branch belongs to this `{ctx}`"))
.span_suggestion(
span,
"remove the attributes",
if self.token.kind != token::Semi {
return None;
}
- let start_snapshot = self.clone();
+ let start_snapshot = self.create_snapshot_for_diagnostic();
let semi_sp = self.token.span;
self.bump(); // `;`
let mut stmts =
err.span_label(arrow_span, "while parsing the `match` arm starting here");
if stmts.len() > 1 {
err.multipart_suggestion(
- &format!("surround the statement{} with a body", s),
+ &format!("surround the statement{s} with a body"),
vec![
(span.shrink_to_lo(), "{ ".to_string()),
(span.shrink_to_hi(), " }".to_string()),
return Some(err(self, stmts));
}
if self.token.kind == token::Comma {
- *self = start_snapshot;
+ self.restore_snapshot(start_snapshot);
return None;
}
- let pre_pat_snapshot = self.clone();
+ let pre_pat_snapshot = self.create_snapshot_for_diagnostic();
match self.parse_pat_no_top_alt(None) {
Ok(_pat) => {
if self.token.kind == token::FatArrow {
// Reached arm end.
- *self = pre_pat_snapshot;
+ self.restore_snapshot(pre_pat_snapshot);
return Some(err(self, stmts));
}
}
}
}
- *self = pre_pat_snapshot;
+ self.restore_snapshot(pre_pat_snapshot);
match self.parse_stmt_without_recovery(true, ForceCollect::No) {
// Consume statements for as long as possible.
Ok(Some(stmt)) => {
stmts.push(stmt);
}
Ok(None) => {
- *self = start_snapshot;
+ self.restore_snapshot(start_snapshot);
break;
}
// We couldn't parse either yet another statement missing it's
// enclosing block nor the next arm's pattern or closing brace.
Err(stmt_err) => {
stmt_err.cancel();
- *self = start_snapshot;
+ self.restore_snapshot(start_snapshot);
break;
}
}
let mut async_block_err = |e: &mut Diagnostic, span: Span| {
recover_async = true;
e.span_label(span, "`async` blocks are only allowed in Rust 2018 or later");
- e.help(&format!("set `edition = \"{}\"` in `Cargo.toml`", LATEST_STABLE_EDITION));
- e.note("for more on editions, read https://doc.rust-lang.org/edition-guide");
+ e.help_use_latest_edition();
};
while self.token != token::CloseDelim(close_delim) {