]> git.lizzy.rs Git - rust.git/blobdiff - compiler/rustc_parse/src/parser/expr.rs
Auto merge of #95068 - TaKO8Ki:use-create-snapshot-for-diagnostic, r=davidtwco
[rust.git] / compiler / rustc_parse / src / parser / expr.rs
index df865d77b9bb4cc5d40a66adc61c72a4f305ebfc..a907f50a11bbff139c327e7684fe3ed115a4455a 100644 (file)
@@ -1,9 +1,10 @@
+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;
@@ -20,7 +21,6 @@
 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};
@@ -224,7 +224,7 @@ pub(super) fn parse_assoc_expr_with(
                     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),
@@ -442,10 +442,10 @@ fn check_assoc_op(&self) -> Option<Spanned<AssocOp>> {
 
     /// 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,
             )
@@ -704,7 +704,7 @@ fn parse_assoc_op_cast(
                         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),
@@ -726,7 +726,7 @@ fn parse_assoc_op_cast(
                             }
                             Err(err) => {
                                 err.cancel();
-                                *self = snapshot;
+                                self.restore_snapshot(snapshot);
                             }
                         }
                     }
@@ -767,9 +767,9 @@ fn parse_assoc_op_cast(
                                 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()),
@@ -971,7 +971,7 @@ fn parse_dot_suffix_expr(&mut self, lo: Span, base: P<Expr>) -> PResult<'a, P<Ex
     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.
@@ -1106,7 +1106,7 @@ fn parse_fn_call_expr(&mut self, lo: Span, fun: P<Expr>) -> P<Expr> {
         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
         };
@@ -1131,7 +1131,7 @@ fn maybe_recover_struct_lit_bad_delims(
         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)))) => {
@@ -1141,7 +1141,7 @@ fn maybe_recover_struct_lit_bad_delims(
                     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() {
@@ -1152,7 +1152,7 @@ fn maybe_recover_struct_lit_bad_delims(
                             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()),
@@ -1160,7 +1160,7 @@ fn maybe_recover_struct_lit_bad_delims(
                                 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()))
@@ -1777,9 +1777,9 @@ fn fix_base_capitalisation(s: &str) -> Option<String> {
                         )
                         .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();
                 }
@@ -1792,9 +1792,9 @@ fn fix_base_capitalisation(s: &str) -> Option<String> {
                     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();
                 }
@@ -1806,7 +1806,7 @@ fn fix_base_capitalisation(s: &str) -> Option<String> {
                     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();
             }
@@ -1826,7 +1826,7 @@ pub(super) fn expect_no_suffix(&self, sp: Span, kind: &str, suffix: Option<Symbo
                 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",
@@ -1843,10 +1843,10 @@ pub(super) fn expect_no_suffix(&self, sp: Span, kind: &str, suffix: Option<Symbo
                 );
                 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();
         }
     }
@@ -1886,7 +1886,7 @@ fn maybe_suggest_brackets_instead_of_braces(
         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;
@@ -1902,7 +1902,7 @@ fn maybe_suggest_brackets_instead_of_braces(
                 .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) => {
@@ -2212,7 +2212,7 @@ fn error_on_if_block_attrs(
         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",
@@ -2370,7 +2370,7 @@ fn parse_arm_body_missing_braces(
         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 =
@@ -2392,7 +2392,7 @@ fn parse_arm_body_missing_braces(
             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()),
@@ -2418,15 +2418,15 @@ fn parse_arm_body_missing_braces(
                 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));
                     }
                 }
@@ -2435,21 +2435,21 @@ fn parse_arm_body_missing_braces(
                 }
             }
 
-            *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;
                 }
             }
@@ -2712,8 +2712,7 @@ pub(super) fn parse_struct_fields(
         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) {