Skip to content

Commit 7043696

Browse files
authored
Rollup merge of rust-lang#63717 - petrochenkov:eager, r=matthewjasper
Fix nested eager expansions in arguments of `format_args` Fixes rust-lang#63460 Fixes rust-lang#63685 (regression from making `format_args` opaque - rust-lang#63114) r? @matthewjasper
2 parents d034cca + fe2dc91 commit 7043696

File tree

6 files changed

+75
-21
lines changed

6 files changed

+75
-21
lines changed

src/librustc_resolve/macros.rs

+22-12
Original file line numberDiff line numberDiff line change
@@ -140,9 +140,23 @@ impl<'a> base::Resolver for Resolver<'a> {
140140
ImportResolver { r: self }.resolve_imports()
141141
}
142142

143-
fn resolve_macro_invocation(&mut self, invoc: &Invocation, invoc_id: ExpnId, force: bool)
144-
-> Result<Option<Lrc<SyntaxExtension>>, Indeterminate> {
145-
let parent_scope = self.invocation_parent_scopes[&invoc_id];
143+
fn resolve_macro_invocation(
144+
&mut self, invoc: &Invocation, eager_expansion_root: ExpnId, force: bool
145+
) -> Result<Option<Lrc<SyntaxExtension>>, Indeterminate> {
146+
let invoc_id = invoc.expansion_data.id;
147+
let parent_scope = match self.invocation_parent_scopes.get(&invoc_id) {
148+
Some(parent_scope) => *parent_scope,
149+
None => {
150+
// If there's no entry in the table, then we are resolving an eagerly expanded
151+
// macro, which should inherit its parent scope from its eager expansion root -
152+
// the macro that requested this eager expansion.
153+
let parent_scope = *self.invocation_parent_scopes.get(&eager_expansion_root)
154+
.expect("non-eager expansion without a parent scope");
155+
self.invocation_parent_scopes.insert(invoc_id, parent_scope);
156+
parent_scope
157+
}
158+
};
159+
146160
let (path, kind, derives, after_derive) = match invoc.kind {
147161
InvocationKind::Attr { ref attr, ref derives, after_derive, .. } =>
148162
(&attr.path, MacroKind::Attr, self.arenas.alloc_ast_paths(derives), after_derive),
@@ -161,7 +175,7 @@ impl<'a> base::Resolver for Resolver<'a> {
161175
match self.resolve_macro_path(path, Some(MacroKind::Derive),
162176
&parent_scope, true, force) {
163177
Ok((Some(ref ext), _)) if ext.is_derive_copy => {
164-
self.add_derives(invoc.expansion_data.id, SpecialDerives::COPY);
178+
self.add_derives(invoc_id, SpecialDerives::COPY);
165179
return Ok(None);
166180
}
167181
Err(Determinacy::Undetermined) => result = Err(Indeterminate),
@@ -178,19 +192,15 @@ impl<'a> base::Resolver for Resolver<'a> {
178192
let (ext, res) = self.smart_resolve_macro_path(path, kind, parent_scope, force)?;
179193

180194
let span = invoc.span();
181-
invoc.expansion_data.id.set_expn_data(
182-
ext.expn_data(parent_scope.expansion, span, fast_print_path(path))
183-
);
195+
invoc_id.set_expn_data(ext.expn_data(parent_scope.expansion, span, fast_print_path(path)));
184196

185197
if let Res::Def(_, def_id) = res {
186198
if after_derive {
187199
self.session.span_err(span, "macro attributes must be placed before `#[derive]`");
188200
}
189-
self.macro_defs.insert(invoc.expansion_data.id, def_id);
190-
let normal_module_def_id =
191-
self.macro_def_scope(invoc.expansion_data.id).normal_ancestor_id;
192-
self.definitions.add_parent_module_of_macro_def(invoc.expansion_data.id,
193-
normal_module_def_id);
201+
self.macro_defs.insert(invoc_id, def_id);
202+
let normal_module_def_id = self.macro_def_scope(invoc_id).normal_ancestor_id;
203+
self.definitions.add_parent_module_of_macro_def(invoc_id, normal_module_def_id);
194204
}
195205

196206
Ok(Some(ext))

src/libsyntax/ext/base.rs

+4-6
Original file line numberDiff line numberDiff line change
@@ -682,8 +682,9 @@ pub trait Resolver {
682682

683683
fn resolve_imports(&mut self);
684684

685-
fn resolve_macro_invocation(&mut self, invoc: &Invocation, invoc_id: ExpnId, force: bool)
686-
-> Result<Option<Lrc<SyntaxExtension>>, Indeterminate>;
685+
fn resolve_macro_invocation(
686+
&mut self, invoc: &Invocation, eager_expansion_root: ExpnId, force: bool
687+
) -> Result<Option<Lrc<SyntaxExtension>>, Indeterminate>;
687688

688689
fn check_unused_macros(&self);
689690

@@ -908,12 +909,9 @@ impl<'a> ExtCtxt<'a> {
908909
/// compilation on error, merely emits a non-fatal error and returns `None`.
909910
pub fn expr_to_spanned_string<'a>(
910911
cx: &'a mut ExtCtxt<'_>,
911-
mut expr: P<ast::Expr>,
912+
expr: P<ast::Expr>,
912913
err_msg: &str,
913914
) -> Result<(Symbol, ast::StrStyle, Span), Option<DiagnosticBuilder<'a>>> {
914-
// Update `expr.span`'s ctxt now in case expr is an `include!` macro invocation.
915-
expr.span = expr.span.apply_mark(cx.current_expansion.id);
916-
917915
// Perform eager expansion on the expression.
918916
// We want to be able to handle e.g., `concat!("foo", "bar")`.
919917
let expr = cx.expander().fully_expand_fragment(AstFragment::Expr(expr)).make_expr();

src/libsyntax/ext/expand.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -305,9 +305,11 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
305305
continue
306306
};
307307

308-
let scope =
308+
let eager_expansion_root =
309309
if self.monotonic { invoc.expansion_data.id } else { orig_expansion_data.id };
310-
let ext = match self.cx.resolver.resolve_macro_invocation(&invoc, scope, force) {
310+
let ext = match self.cx.resolver.resolve_macro_invocation(
311+
&invoc, eager_expansion_root, force
312+
) {
311313
Ok(ext) => ext,
312314
Err(Indeterminate) => {
313315
undetermined_invocations.push(invoc);
@@ -318,7 +320,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
318320
progress = true;
319321
let ExpansionData { depth, id: expn_id, .. } = invoc.expansion_data;
320322
self.cx.current_expansion = invoc.expansion_data.clone();
321-
self.cx.current_expansion.id = scope;
322323

323324
// FIXME(jseyfried): Refactor out the following logic
324325
let (expanded_fragment, new_invocations) = if let Some(ext) = ext {
+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Regression test for the issue #63460.
2+
3+
// check-pass
4+
5+
#[macro_export]
6+
macro_rules! separator {
7+
() => { "/" };
8+
}
9+
10+
#[macro_export]
11+
macro_rules! concat_separator {
12+
( $e:literal, $($other:literal),+ ) => {
13+
concat!($e, $crate::separator!(), $crate::concat_separator!($($other),+))
14+
};
15+
( $e:literal ) => {
16+
$e
17+
}
18+
}
19+
20+
fn main() {
21+
println!("{}", concat_separator!(2, 3, 4))
22+
}
+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Opaque macro can eagerly expand its input without breaking its resolution.
2+
// Regression test for issue #63685.
3+
4+
// check-pass
5+
6+
macro_rules! foo {
7+
() => {
8+
"foo"
9+
};
10+
}
11+
12+
macro_rules! bar {
13+
() => {
14+
foo!()
15+
};
16+
}
17+
18+
fn main() {
19+
format_args!(bar!());
20+
}

src/test/ui/macros/derive-in-eager-expansion-hang.stderr

+3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ LL | |
88
LL | | ""
99
LL | | }
1010
| |_____^
11+
...
12+
LL | format_args!(hang!());
13+
| ------- in this macro invocation
1114
help: you might be missing a string literal to format with
1215
|
1316
LL | format_args!("{}", hang!());

0 commit comments

Comments
 (0)