Skip to content

Commit

Permalink
Don't unwind when hitting the macro expansion recursion limit
Browse files Browse the repository at this point in the history
  • Loading branch information
Zoxc committed Mar 19, 2020
1 parent 3c6f982 commit 82920f3
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 6 deletions.
2 changes: 2 additions & 0 deletions src/librustc_expand/base.rs
Expand Up @@ -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,
Expand All @@ -940,6 +941,7 @@ impl<'a> ExtCtxt<'a> {
ExtCtxt {
parse_sess,
ecfg,
reduced_recursion_limit: None,
resolver,
extern_mod_loaded,
root_path: PathBuf::new(),
Expand Down
16 changes: 12 additions & 4 deletions src/librustc_expand/expand.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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.
Expand All @@ -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());
Expand Down
13 changes: 11 additions & 2 deletions src/librustc_interface/passes.rs
Expand Up @@ -311,6 +311,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";
Expand All @@ -319,8 +321,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(
Expand Down

0 comments on commit 82920f3

Please sign in to comment.