From 4547b622d8d29df964fa2914213088b148c498fc Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:18:32 +0200 Subject: Merging upstream version 1.67.1+dfsg1. Signed-off-by: Daniel Baumann --- compiler/rustc_parse/src/parser/diagnostics.rs | 85 +++++++++++++++++--------- 1 file changed, 57 insertions(+), 28 deletions(-) (limited to 'compiler/rustc_parse/src/parser/diagnostics.rs') diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 309717350..c316a4dd6 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -18,6 +18,7 @@ use crate::errors::{ }; use crate::lexer::UnmatchedBrace; +use crate::parser; use rustc_ast as ast; use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter, Lit, LitKind, TokenKind}; @@ -37,11 +38,10 @@ use rustc_session::errors::ExprParenthesesNeeded; use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::{Span, SpanSnippetError, DUMMY_SP}; -use std::ops::{Deref, DerefMut}; - use std::mem::take; - -use crate::parser; +use std::ops::{Deref, DerefMut}; +use thin_vec::{thin_vec, ThinVec}; +use tracing::{debug, trace}; /// Creates a placeholder argument. pub(super) fn dummy_arg(ident: Ident) -> Param { @@ -65,7 +65,7 @@ pub(super) fn dummy_arg(ident: Ident) -> Param { pub(super) trait RecoverQPath: Sized + 'static { const PATH_STYLE: PathStyle = PathStyle::Expr; fn to_ty(&self) -> Option>; - fn recovered(qself: Option, path: ast::Path) -> Self; + fn recovered(qself: Option>, path: ast::Path) -> Self; } impl RecoverQPath for Ty { @@ -73,7 +73,7 @@ impl RecoverQPath for Ty { fn to_ty(&self) -> Option> { Some(P(self.clone())) } - fn recovered(qself: Option, path: ast::Path) -> Self { + fn recovered(qself: Option>, path: ast::Path) -> Self { Self { span: path.span, kind: TyKind::Path(qself, path), @@ -87,7 +87,7 @@ impl RecoverQPath for Pat { fn to_ty(&self) -> Option> { self.to_ty() } - fn recovered(qself: Option, path: ast::Path) -> Self { + fn recovered(qself: Option>, path: ast::Path) -> Self { Self { span: path.span, kind: PatKind::Path(qself, path), @@ -101,7 +101,7 @@ impl RecoverQPath for Expr { fn to_ty(&self) -> Option> { self.to_ty() } - fn recovered(qself: Option, path: ast::Path) -> Self { + fn recovered(qself: Option>, path: ast::Path) -> Self { Self { span: path.span, kind: ExprKind::Path(qself, path), @@ -224,9 +224,9 @@ impl MultiSugg { } } -// SnapshotParser is used to create a snapshot of the parser -// without causing duplicate errors being emitted when the `Parser` -// is dropped. +/// SnapshotParser is used to create a snapshot of the parser +/// without causing duplicate errors being emitted when the `Parser` +/// is dropped. pub struct SnapshotParser<'a> { parser: Parser<'a>, unclosed_delims: Vec, @@ -638,8 +638,11 @@ impl<'a> Parser<'a> { // field: value, // } let mut snapshot = self.create_snapshot_for_diagnostic(); - let path = - Path { segments: vec![], span: self.prev_token.span.shrink_to_lo(), tokens: None }; + let path = Path { + segments: ThinVec::new(), + span: self.prev_token.span.shrink_to_lo(), + tokens: None, + }; let struct_expr = snapshot.parse_struct_expr(None, path, false); let block_tail = self.parse_block_tail(lo, s, AttemptLocalParseRecovery::No); return Some(match (struct_expr, block_tail) { @@ -769,6 +772,10 @@ impl<'a> Parser<'a> { segment: &PathSegment, end: &[&TokenKind], ) -> bool { + if !self.may_recover() { + return false; + } + // This function is intended to be invoked after parsing a path segment where there are two // cases: // @@ -863,6 +870,10 @@ impl<'a> Parser<'a> { /// Check if a method call with an intended turbofish has been written without surrounding /// angle brackets. pub(super) fn check_turbofish_missing_angle_brackets(&mut self, segment: &mut PathSegment) { + if !self.may_recover() { + return; + } + if token::ModSep == self.token.kind && segment.args.is_none() { let snapshot = self.create_snapshot_for_diagnostic(); self.bump(); @@ -926,7 +937,7 @@ impl<'a> Parser<'a> { if self.eat(&token::Gt) { e.span_suggestion_verbose( binop.span.shrink_to_lo(), - fluent::parser_sugg_turbofish_syntax, + fluent::parse_sugg_turbofish_syntax, "::", Applicability::MaybeIncorrect, ) @@ -962,7 +973,7 @@ impl<'a> Parser<'a> { inner_op: &Expr, outer_op: &Spanned, ) -> bool /* advanced the cursor */ { - if let ExprKind::Binary(op, ref l1, ref r1) = inner_op.kind { + if let ExprKind::Binary(op, l1, r1) = &inner_op.kind { if let ExprKind::Field(_, ident) = l1.kind && ident.as_str().parse::().is_err() && !matches!(r1.kind, ExprKind::Lit(_)) @@ -1068,8 +1079,8 @@ impl<'a> Parser<'a> { let mk_err_expr = |this: &Self, span| Ok(Some(this.mk_expr(span, ExprKind::Err))); - match inner_op.kind { - ExprKind::Binary(op, ref l1, ref r1) if op.node.is_comparison() => { + match &inner_op.kind { + ExprKind::Binary(op, l1, r1) if op.node.is_comparison() => { let mut err = ComparisonOperatorsCannotBeChained { span: vec![op.span, self.prev_token.span], suggest_turbofish: None, @@ -1226,8 +1237,8 @@ impl<'a> Parser<'a> { let bounds = self.parse_generic_bounds(None)?; let sum_span = ty.span.to(self.prev_token.span); - let sub = match ty.kind { - TyKind::Rptr(ref lifetime, ref mut_ty) => { + let sub = match &ty.kind { + TyKind::Rptr(lifetime, mut_ty) => { let sum_with_parens = pprust::to_string(|s| { s.s.word("&"); s.print_opt_lifetime(lifetime); @@ -1396,6 +1407,10 @@ impl<'a> Parser<'a> { &mut self, base: P, ) -> PResult<'a, P> { + if !self.may_recover() { + return Ok(base); + } + // Do not add `::` to expected tokens. if self.token == token::ModSep { if let Some(ty) = base.to_ty() { @@ -1414,7 +1429,7 @@ impl<'a> Parser<'a> { ) -> PResult<'a, P> { self.expect(&token::ModSep)?; - let mut path = ast::Path { segments: Vec::new(), span: DUMMY_SP, tokens: None }; + let mut path = ast::Path { segments: ThinVec::new(), span: DUMMY_SP, tokens: None }; self.parse_path_segments(&mut path.segments, T::PATH_STYLE, None)?; path.span = ty_span.to(self.prev_token.span); @@ -1425,7 +1440,7 @@ impl<'a> Parser<'a> { }); let path_span = ty_span.shrink_to_hi(); // Use an empty path since `position == 0`. - Ok(P(T::recovered(Some(QSelf { ty, path_span, position: 0 }), path))) + Ok(P(T::recovered(Some(P(QSelf { ty, path_span, position: 0 })), path))) } pub fn maybe_consume_incorrect_semicolon(&mut self, items: &[P]) -> bool { @@ -1641,15 +1656,29 @@ impl<'a> Parser<'a> { (token::CloseDelim(Delimiter::Parenthesis), Some(begin_par_sp)) => { self.bump(); + let sm = self.sess.source_map(); + let left = begin_par_sp; + let right = self.prev_token.span; + let left_snippet = if let Ok(snip) = sm.span_to_prev_source(left) && + !snip.ends_with(' ') { + " ".to_string() + } else { + "".to_string() + }; + + let right_snippet = if let Ok(snip) = sm.span_to_next_source(right) && + !snip.starts_with(' ') { + " ".to_string() + } else { + "".to_string() + }; + self.sess.emit_err(ParenthesesInForHead { - span: vec![begin_par_sp, self.prev_token.span], + span: vec![left, right], // With e.g. `for (x) in y)` this would replace `(x) in y)` // with `x) in y)` which is syntactically invalid. // However, this is prevented before we get here. - sugg: ParenthesesInForHeadSugg { - left: begin_par_sp, - right: self.prev_token.span, - }, + sugg: ParenthesesInForHeadSugg { left, right, left_snippet, right_snippet }, }); // Unwrap `(pat)` into `pat` to avoid the `unused_parens` lint. @@ -2408,7 +2437,7 @@ impl<'a> Parser<'a> { None, Path { span: new_span, - segments: vec![ + segments: thin_vec![ PathSegment::from_ident(*old_ident), PathSegment::from_ident(*ident), ], @@ -2536,7 +2565,7 @@ impl<'a> Parser<'a> { if let [a, b] = segments { let (a_span, b_span) = (a.span(), b.span()); let between_span = a_span.shrink_to_hi().to(b_span.shrink_to_lo()); - if self.span_to_snippet(between_span).as_ref().map(|a| &a[..]) == Ok(":: ") { + if self.span_to_snippet(between_span).as_deref() == Ok(":: ") { return Err(DoubleColonInBound { span: path.span.shrink_to_hi(), between: between_span, -- cgit v1.2.3