about summary refs log tree commit diff
path: root/compiler/rustc_parse
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-10-26 17:35:23 +0000
committerbors <bors@rust-lang.org>2023-10-26 17:35:23 +0000
commit8396efecf7d30ca9f7edcf76aba2ea388300f6ab (patch)
treeed8e51672d07e7f546ea7dce8fac167872cd77e7 /compiler/rustc_parse
parent698db856de0b67313ddcb96b6599598058489ea9 (diff)
parenta461de73099102ab1b50e6d66390c55b288aede0 (diff)
downloadrust-8396efecf7d30ca9f7edcf76aba2ea388300f6ab.tar.gz
rust-8396efecf7d30ca9f7edcf76aba2ea388300f6ab.zip
Auto merge of #117228 - matthiaskrgr:rollup-23zzepv, r=matthiaskrgr
Rollup of 8 pull requests

Successful merges:

 - #116905 (refactor(compiler/resolve): simplify some code)
 - #117095 (Add way to differentiate argument locals from other locals in Stable MIR)
 - #117143 (Avoid unbounded O(n^2) when parsing nested type args)
 - #117194 (Minor improvements to `rustc_incremental`)
 - #117202 (Revert "Remove TaKO8Ki from reviewers")
 - #117207 (The value of `-Cinstrument-coverage=` doesn't need to be `Option`)
 - #117214 (Quietly fail if an error has already occurred)
 - #117221 (Rename type flag `HAS_TY_GENERATOR` to `HAS_TY_COROUTINE`)

r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'compiler/rustc_parse')
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs6
-rw-r--r--compiler/rustc_parse/src/parser/path.rs25
2 files changed, 25 insertions, 6 deletions
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)
+            }
         }
     }