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:
commit
a6596f2a4d
5 changed files with 38 additions and 8 deletions
|
@ -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(),
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue