diff options
Diffstat (limited to 'compiler/rustc_parse/src')
| -rw-r--r-- | compiler/rustc_parse/src/parser/diagnostics.rs | 22 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/expr.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/mod.rs | 6 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/path.rs | 25 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/stmt.rs | 17 |
5 files changed, 47 insertions, 25 deletions
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 75e3393aa96..9f8361a4b1e 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -39,7 +39,7 @@ use rustc_errors::{ use rustc_session::errors::ExprParenthesesNeeded; use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Ident}; -use rustc_span::{Span, SpanSnippetError, Symbol, DUMMY_SP}; +use rustc_span::{BytePos, Span, SpanSnippetError, Symbol, DUMMY_SP}; use std::mem::take; use std::ops::{Deref, DerefMut}; use thin_vec::{thin_vec, ThinVec}; @@ -648,6 +648,26 @@ impl<'a> Parser<'a> { ); } + if let token::DocComment(kind, style, _) = self.token.kind { + // We have something like `expr //!val` where the user likely meant `expr // !val` + let pos = self.token.span.lo() + BytePos(2); + let span = self.token.span.with_lo(pos).with_hi(pos); + err.span_suggestion_verbose( + span, + format!( + "add a space before {} to write a regular comment", + match (kind, style) { + (token::CommentKind::Line, ast::AttrStyle::Inner) => "`!`", + (token::CommentKind::Block, ast::AttrStyle::Inner) => "`!`", + (token::CommentKind::Line, ast::AttrStyle::Outer) => "the last `/`", + (token::CommentKind::Block, ast::AttrStyle::Outer) => "the last `*`", + }, + ), + " ".to_string(), + Applicability::MachineApplicable, + ); + } + // Add suggestion for a missing closing angle bracket if '>' is included in expected_tokens // there are unclosed angle brackets if self.unmatched_angle_bracket_count > 0 diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 44cb90227e7..5157106f4e2 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1848,7 +1848,7 @@ impl<'a> Parser<'a> { let lo = self.prev_token.span; let kind = ExprKind::Yield(self.parse_expr_opt()?); let span = lo.to(self.prev_token.span); - self.sess.gated_spans.gate(sym::generators, span); + self.sess.gated_spans.gate(sym::coroutines, span); let expr = self.mk_expr(span, kind); self.maybe_recover_from_bad_qpath(expr) } diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 597303cae73..41b19ecb63a 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -159,8 +159,9 @@ pub struct Parser<'a> { /// appropriately. /// /// See the comments in the `parse_path_segment` function for more details. - unmatched_angle_bracket_count: u32, - max_angle_bracket_count: u32, + unmatched_angle_bracket_count: u16, + max_angle_bracket_count: u16, + angle_bracket_nesting: u16, last_unexpected_token_span: Option<Span>, /// If present, this `Parser` is not parsing Rust code but rather a macro call. @@ -394,6 +395,7 @@ impl<'a> Parser<'a> { break_last_token: false, unmatched_angle_bracket_count: 0, max_angle_bracket_count: 0, + angle_bracket_nesting: 0, last_unexpected_token_span: None, subparser_name, capture_state: CaptureState { diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 2fcb9a78cfd..4969e672a72 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -487,10 +487,24 @@ impl<'a> Parser<'a> { // Take a snapshot before attempting to parse - we can restore this later. let snapshot = is_first_invocation.then(|| self.clone()); + self.angle_bracket_nesting += 1; debug!("parse_generic_args_with_leading_angle_bracket_recovery: (snapshotting)"); match self.parse_angle_args(ty_generics) { - Ok(args) => Ok(args), + Ok(args) => { + self.angle_bracket_nesting -= 1; + Ok(args) + } + Err(mut e) if self.angle_bracket_nesting > 10 => { + self.angle_bracket_nesting -= 1; + // When encountering severely malformed code where there are several levels of + // nested unclosed angle args (`f::<f::<f::<f::<...`), we avoid severe O(n^2) + // behavior by bailing out earlier (#117080). + e.emit(); + rustc_errors::FatalError.raise(); + } Err(e) if is_first_invocation && self.unmatched_angle_bracket_count > 0 => { + self.angle_bracket_nesting -= 1; + // Swap `self` with our backup of the parser state before attempting to parse // generic arguments. let snapshot = mem::replace(self, snapshot.unwrap()); @@ -520,8 +534,8 @@ impl<'a> Parser<'a> { // Make a span over ${unmatched angle bracket count} characters. // This is safe because `all_angle_brackets` ensures that there are only `<`s, // i.e. no multibyte characters, in this range. - let span = - lo.with_hi(lo.lo() + BytePos(snapshot.unmatched_angle_bracket_count)); + let span = lo + .with_hi(lo.lo() + BytePos(snapshot.unmatched_angle_bracket_count.into())); self.sess.emit_err(errors::UnmatchedAngle { span, plural: snapshot.unmatched_angle_bracket_count > 1, @@ -531,7 +545,10 @@ impl<'a> Parser<'a> { self.parse_angle_args(ty_generics) } } - Err(e) => Err(e), + Err(e) => { + self.angle_bracket_nesting -= 1; + Err(e) + } } } diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index e2f59cb2071..8e3c4568694 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -632,23 +632,6 @@ impl<'a> Parser<'a> { // Recover from parser, skip type error to avoid extra errors. Ok(true) => true, Err(mut e) => { - if let TokenKind::DocComment(..) = self.token.kind - && let Ok(snippet) = self.span_to_snippet(self.token.span) - { - let sp = self.token.span; - let marker = &snippet[..3]; - let (comment_marker, doc_comment_marker) = marker.split_at(2); - - e.span_suggestion( - sp.with_hi(sp.lo() + BytePos(marker.len() as u32)), - format!( - "add a space before `{doc_comment_marker}` to use a regular comment", - ), - format!("{comment_marker} {doc_comment_marker}"), - Applicability::MaybeIncorrect, - ); - } - if self.recover_colon_as_semi() { // recover_colon_as_semi has already emitted a nicer error. e.delay_as_bug(); |
