Skip to content

Commit e80c8ad

Browse files
authored
Rollup merge of rust-lang#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
2 parents f4090a6 + bdaf9e4 commit e80c8ad

File tree

5 files changed

+38
-8
lines changed

5 files changed

+38
-8
lines changed

Diff for: src/librustc_expand/base.rs

+2
Original file line numberDiff line numberDiff line change
@@ -921,6 +921,7 @@ pub struct ExpansionData {
921921
pub struct ExtCtxt<'a> {
922922
pub parse_sess: &'a ParseSess,
923923
pub ecfg: expand::ExpansionConfig<'a>,
924+
pub reduced_recursion_limit: Option<usize>,
924925
pub root_path: PathBuf,
925926
pub resolver: &'a mut dyn Resolver,
926927
pub current_expansion: ExpansionData,
@@ -936,6 +937,7 @@ impl<'a> ExtCtxt<'a> {
936937
ExtCtxt {
937938
parse_sess,
938939
ecfg,
940+
reduced_recursion_limit: None,
939941
root_path: PathBuf::new(),
940942
resolver,
941943
current_expansion: ExpansionData {

Diff for: src/librustc_expand/expand.rs

+12-4
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use rustc_ast::util::map_in_place::MapInPlace;
1515
use rustc_ast::visit::{self, AssocCtxt, Visitor};
1616
use rustc_ast_pretty::pprust;
1717
use rustc_attr::{self as attr, is_builtin_attr, HasAttrs};
18-
use rustc_errors::{Applicability, FatalError, PResult};
18+
use rustc_errors::{Applicability, PResult};
1919
use rustc_feature::Features;
2020
use rustc_parse::configure;
2121
use rustc_parse::parser::Parser;
@@ -645,7 +645,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
645645
))
646646
.emit();
647647
self.cx.trace_macros_diag();
648-
FatalError.raise();
649648
}
650649

651650
/// A macro's expansion does not fit in this fragment kind.
@@ -665,8 +664,17 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
665664
invoc: Invocation,
666665
ext: &SyntaxExtensionKind,
667666
) -> ExpandResult<AstFragment, Invocation> {
668-
if self.cx.current_expansion.depth > self.cx.ecfg.recursion_limit {
669-
self.error_recursion_limit_reached();
667+
let recursion_limit =
668+
self.cx.reduced_recursion_limit.unwrap_or(self.cx.ecfg.recursion_limit);
669+
if self.cx.current_expansion.depth > recursion_limit {
670+
if self.cx.reduced_recursion_limit.is_none() {
671+
self.error_recursion_limit_reached();
672+
}
673+
674+
// Reduce the recursion limit by half each time it triggers.
675+
self.cx.reduced_recursion_limit = Some(recursion_limit / 2);
676+
677+
return ExpandResult::Ready(invoc.fragment_kind.dummy(invoc.span()));
670678
}
671679

672680
let (fragment_kind, span) = (invoc.fragment_kind, invoc.span());

Diff for: src/librustc_interface/passes.rs

+11-2
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,8 @@ fn configure_and_expand_inner<'a>(
306306
ecx.parse_sess.missing_fragment_specifiers.borrow().iter().cloned().collect();
307307
missing_fragment_specifiers.sort();
308308

309+
let recursion_limit_hit = ecx.reduced_recursion_limit.is_some();
310+
309311
for span in missing_fragment_specifiers {
310312
let lint = lint::builtin::MISSING_FRAGMENT_SPECIFIER;
311313
let msg = "missing fragment specifier";
@@ -314,8 +316,15 @@ fn configure_and_expand_inner<'a>(
314316
if cfg!(windows) {
315317
env::set_var("PATH", &old_path);
316318
}
317-
krate
318-
});
319+
320+
if recursion_limit_hit {
321+
// If we hit a recursion limit, exit early to avoid later passes getting overwhelmed
322+
// with a large AST
323+
Err(ErrorReported)
324+
} else {
325+
Ok(krate)
326+
}
327+
})?;
319328

320329
sess.time("maybe_building_test_harness", || {
321330
rustc_builtin_macros::test_harness::inject(

Diff for: src/test/ui/macros/trace_faulty_macros.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ macro_rules! pat_macro {
1313
pat_macro!(A{a:a, b:0, c:_, ..});
1414
};
1515
($a:pat) => {
16-
$a
16+
$a //~ ERROR expected expression
1717
};
1818
}
1919

Diff for: src/test/ui/macros/trace_faulty_macros.stderr

+12-1
Original file line numberDiff line numberDiff line change
@@ -49,5 +49,16 @@ LL | my_recursive_macro!();
4949
= note: expanding `my_recursive_macro! { }`
5050
= note: to `my_recursive_macro ! () ;`
5151

52-
error: aborting due to 2 previous errors
52+
error: expected expression, found `A { a: a, b: 0, c: _, .. }`
53+
--> $DIR/trace_faulty_macros.rs:16:9
54+
|
55+
LL | $a
56+
| ^^ expected expression
57+
...
58+
LL | let a = pat_macro!();
59+
| ------------ in this macro invocation
60+
|
61+
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
62+
63+
error: aborting due to 3 previous errors
5364

0 commit comments

Comments
 (0)