1
Fork 0

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
This commit is contained in:
Dylan DPC 2020-03-21 13:06:33 +01:00 committed by GitHub
commit a6596f2a4d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 38 additions and 8 deletions

View file

@ -922,6 +922,7 @@ pub struct ExpansionData {
pub struct ExtCtxt<'a> { pub struct ExtCtxt<'a> {
pub parse_sess: &'a ParseSess, pub parse_sess: &'a ParseSess,
pub ecfg: expand::ExpansionConfig<'a>, pub ecfg: expand::ExpansionConfig<'a>,
pub reduced_recursion_limit: Option<usize>,
pub root_path: PathBuf, pub root_path: PathBuf,
pub resolver: &'a mut dyn Resolver, pub resolver: &'a mut dyn Resolver,
pub current_expansion: ExpansionData, pub current_expansion: ExpansionData,
@ -940,6 +941,7 @@ impl<'a> ExtCtxt<'a> {
ExtCtxt { ExtCtxt {
parse_sess, parse_sess,
ecfg, ecfg,
reduced_recursion_limit: None,
resolver, resolver,
extern_mod_loaded, extern_mod_loaded,
root_path: PathBuf::new(), root_path: PathBuf::new(),

View file

@ -17,7 +17,7 @@ use rustc_ast::util::map_in_place::MapInPlace;
use rustc_ast::visit::{self, AssocCtxt, Visitor}; use rustc_ast::visit::{self, AssocCtxt, Visitor};
use rustc_ast_pretty::pprust; use rustc_ast_pretty::pprust;
use rustc_attr::{self as attr, is_builtin_attr, HasAttrs}; 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_feature::Features;
use rustc_parse::parser::Parser; use rustc_parse::parser::Parser;
use rustc_parse::validate_attr; use rustc_parse::validate_attr;
@ -645,7 +645,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
)) ))
.emit(); .emit();
self.cx.trace_macros_diag(); self.cx.trace_macros_diag();
FatalError.raise();
} }
/// A macro's expansion does not fit in this fragment kind. /// A macro's expansion does not fit in this fragment kind.
@ -665,8 +664,17 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
invoc: Invocation, invoc: Invocation,
ext: &SyntaxExtensionKind, ext: &SyntaxExtensionKind,
) -> ExpandResult<AstFragment, Invocation> { ) -> ExpandResult<AstFragment, Invocation> {
if self.cx.current_expansion.depth > self.cx.ecfg.recursion_limit { let recursion_limit =
self.error_recursion_limit_reached(); 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()); let (fragment_kind, span) = (invoc.fragment_kind, invoc.span());

View file

@ -312,6 +312,8 @@ fn configure_and_expand_inner<'a>(
ecx.parse_sess.missing_fragment_specifiers.borrow().iter().cloned().collect(); ecx.parse_sess.missing_fragment_specifiers.borrow().iter().cloned().collect();
missing_fragment_specifiers.sort(); missing_fragment_specifiers.sort();
let recursion_limit_hit = ecx.reduced_recursion_limit.is_some();
for span in missing_fragment_specifiers { for span in missing_fragment_specifiers {
let lint = lint::builtin::MISSING_FRAGMENT_SPECIFIER; let lint = lint::builtin::MISSING_FRAGMENT_SPECIFIER;
let msg = "missing fragment specifier"; let msg = "missing fragment specifier";
@ -320,8 +322,15 @@ fn configure_and_expand_inner<'a>(
if cfg!(windows) { if cfg!(windows) {
env::set_var("PATH", &old_path); 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", || { sess.time("maybe_building_test_harness", || {
rustc_builtin_macros::test_harness::inject( rustc_builtin_macros::test_harness::inject(

View file

@ -13,7 +13,7 @@ macro_rules! pat_macro {
pat_macro!(A{a:a, b:0, c:_, ..}); pat_macro!(A{a:a, b:0, c:_, ..});
}; };
($a:pat) => { ($a:pat) => {
$a $a //~ ERROR expected expression
}; };
} }

View file

@ -49,5 +49,16 @@ LL | my_recursive_macro!();
= note: expanding `my_recursive_macro! { }` = note: expanding `my_recursive_macro! { }`
= note: to `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