about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDylan DPC <dylan.dpc@gmail.com>2020-03-21 13:06:33 +0100
committerGitHub <noreply@github.com>2020-03-21 13:06:33 +0100
commita6596f2a4de1ea77a2a023510499de11adb53dc6 (patch)
treea858295f3f7d064dadabc15a388f1ee7fb07dda3
parent98803c182b2ba6ef5dccb6bf501958249295eac0 (diff)
parentd641ad044eb535741cd2160e7cbf96d91c2c54c1 (diff)
downloadrust-a6596f2a4de1ea77a2a023510499de11adb53dc6.tar.gz
rust-a6596f2a4de1ea77a2a023510499de11adb53dc6.zip
Rollup merge of #69497 - Zoxc:ast-fragment-error, r=petrochenkov
Don't unwind when hitting the macro expansion recursion limit

This removes one use of `FatalError.raise()`.

r? @petrochenkov
-rw-r--r--src/librustc_expand/base.rs2
-rw-r--r--src/librustc_expand/expand.rs16
-rw-r--r--src/librustc_interface/passes.rs13
-rw-r--r--src/test/ui/macros/trace_faulty_macros.rs2
-rw-r--r--src/test/ui/macros/trace_faulty_macros.stderr13
5 files changed, 38 insertions, 8 deletions
diff --git a/src/librustc_expand/base.rs b/src/librustc_expand/base.rs
index 74c304c96b9..0fc477bbd0b 100644
--- a/src/librustc_expand/base.rs
+++ b/src/librustc_expand/base.rs
@@ -922,6 +922,7 @@ pub struct ExpansionData {
 pub struct ExtCtxt<'a> {
     pub parse_sess: &'a ParseSess,
     pub ecfg: expand::ExpansionConfig<'a>,
+    pub reduced_recursion_limit: Option<usize>,
     pub root_path: PathBuf,
     pub resolver: &'a mut dyn Resolver,
     pub current_expansion: ExpansionData,
@@ -940,6 +941,7 @@ impl<'a> ExtCtxt<'a> {
         ExtCtxt {
             parse_sess,
             ecfg,
+            reduced_recursion_limit: None,
             resolver,
             extern_mod_loaded,
             root_path: PathBuf::new(),
diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs
index b6cc192cc33..4f568e5456c 100644
--- a/src/librustc_expand/expand.rs
+++ b/src/librustc_expand/expand.rs
@@ -17,7 +17,7 @@ use rustc_ast::util::map_in_place::MapInPlace;
 use rustc_ast::visit::{self, AssocCtxt, Visitor};
 use rustc_ast_pretty::pprust;
 use rustc_attr::{self as attr, is_builtin_attr, HasAttrs};
-use rustc_errors::{Applicability, FatalError, PResult};
+use rustc_errors::{Applicability, PResult};
 use rustc_feature::Features;
 use rustc_parse::parser::Parser;
 use rustc_parse::validate_attr;
@@ -645,7 +645,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
             ))
             .emit();
         self.cx.trace_macros_diag();
-        FatalError.raise();
     }
 
     /// A macro's expansion does not fit in this fragment kind.
@@ -665,8 +664,17 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
         invoc: Invocation,
         ext: &SyntaxExtensionKind,
     ) -> ExpandResult<AstFragment, Invocation> {
-        if self.cx.current_expansion.depth > self.cx.ecfg.recursion_limit {
-            self.error_recursion_limit_reached();
+        let recursion_limit =
+            self.cx.reduced_recursion_limit.unwrap_or(self.cx.ecfg.recursion_limit);
+        if self.cx.current_expansion.depth > recursion_limit {
+            if self.cx.reduced_recursion_limit.is_none() {
+                self.error_recursion_limit_reached();
+            }
+
+            // Reduce the recursion limit by half each time it triggers.
+            self.cx.reduced_recursion_limit = Some(recursion_limit / 2);
+
+            return ExpandResult::Ready(invoc.fragment_kind.dummy(invoc.span()));
         }
 
         let (fragment_kind, span) = (invoc.fragment_kind, invoc.span());
diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs
index b7a5f2f4531..8d9e287cdc9 100644
--- a/src/librustc_interface/passes.rs
+++ b/src/librustc_interface/passes.rs
@@ -312,6 +312,8 @@ fn configure_and_expand_inner<'a>(
             ecx.parse_sess.missing_fragment_specifiers.borrow().iter().cloned().collect();
         missing_fragment_specifiers.sort();
 
+        let recursion_limit_hit = ecx.reduced_recursion_limit.is_some();
+
         for span in missing_fragment_specifiers {
             let lint = lint::builtin::MISSING_FRAGMENT_SPECIFIER;
             let msg = "missing fragment specifier";
@@ -320,8 +322,15 @@ fn configure_and_expand_inner<'a>(
         if cfg!(windows) {
             env::set_var("PATH", &old_path);
         }
-        krate
-    });
+
+        if recursion_limit_hit {
+            // If we hit a recursion limit, exit early to avoid later passes getting overwhelmed
+            // with a large AST
+            Err(ErrorReported)
+        } else {
+            Ok(krate)
+        }
+    })?;
 
     sess.time("maybe_building_test_harness", || {
         rustc_builtin_macros::test_harness::inject(
diff --git a/src/test/ui/macros/trace_faulty_macros.rs b/src/test/ui/macros/trace_faulty_macros.rs
index 627d58abf4c..a55f05414b2 100644
--- a/src/test/ui/macros/trace_faulty_macros.rs
+++ b/src/test/ui/macros/trace_faulty_macros.rs
@@ -13,7 +13,7 @@ macro_rules! pat_macro {
         pat_macro!(A{a:a, b:0, c:_, ..});
     };
     ($a:pat) => {
-        $a
+        $a //~ ERROR expected expression
     };
 }
 
diff --git a/src/test/ui/macros/trace_faulty_macros.stderr b/src/test/ui/macros/trace_faulty_macros.stderr
index a18e22e07f8..109b493b437 100644
--- a/src/test/ui/macros/trace_faulty_macros.stderr
+++ b/src/test/ui/macros/trace_faulty_macros.stderr
@@ -49,5 +49,16 @@ LL |     my_recursive_macro!();
    = note: expanding `my_recursive_macro! {  }`
    = note: to `my_recursive_macro ! () ;`
 
-error: aborting due to 2 previous errors
+error: expected expression, found `A { a: a, b: 0, c: _, .. }`
+  --> $DIR/trace_faulty_macros.rs:16:9
+   |
+LL |         $a
+   |         ^^ expected expression
+...
+LL |     let a = pat_macro!();
+   |             ------------ in this macro invocation
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 3 previous errors