Skip to content

Commit 184c5ab

Browse files
committed
Auto merge of #121589 - bvanjoi:fix-98291, r=petrochenkov
delay expand macro bang when there has indeterminate path Related #98291 I will attempt to clarify the root problem through several examples: Firstly, ```rs // rustc code.rs --edition=2018 macro_rules! wrap { () => { macro_rules! _a { () => { "Hello world" }; } }; } wrap!(); use _a as a; fn main() { format_args!(_a!()); } ``` The above case will compile successfully because `_a` is defined after the `wrap` expaned, ensuring `_a` can be resolved without any issues. And, ```rs // rustc code.rs --edition=2018 macro_rules! wrap { () => { macro_rules! _a { () => { "Hello world" }; } }; } wrap!(); use _a as a; fn main() { format_args!("{}", a!()); } ``` The above example will also compile successfully because the `parse_args` in `expand_format_args_impl` will return a value `MacroInput { fmtstr: Expr::Lit::Str, args: [Expr::MacroCall]}`. Since the graph for `args` will be build lately, `a` will eventually be resolved. However, in the case of: ```rs // rustc code.rs --edition=2018 macro_rules! wrap { () => { macro_rules! _a { () => { "Hello world" }; } }; } wrap!(); use _a as a; fn main() { format_args!(a!()); } ``` The result of `parse_args` is `MacroInput {fmtstr: Expr::Lit::Macro, args: [] }`, we attempt to expand `fmtstr` **eagerly** within `expr_to_spanned_string`. Although we have recorded `(root, _a)` into resolutions, `use _a as a` is an indeterminate import, which will not try to resolve under the conditions of `expander.monotonic = false`. Therefore, I've altered the strategy for resolving indeterminate imports, ensuring it will also resolve during eager expansion. This could be a significant change to the resolution infra. However, I think it's acceptable if the goal of avoiding resolution under eager expansion is to save time. r? `@petrochenkov`
2 parents 9ce37dc + 8fcdf54 commit 184c5ab

22 files changed

+509
-263
lines changed

compiler/rustc_builtin_macros/src/asm.rs

+44-32
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use rustc_ast::token::{self, Delimiter};
55
use rustc_ast::tokenstream::TokenStream;
66
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
77
use rustc_errors::PResult;
8-
use rustc_expand::base::{self, *};
8+
use rustc_expand::base::*;
99
use rustc_index::bit_set::GrowableBitSet;
1010
use rustc_parse::parser::Parser;
1111
use rustc_parse_format as parse;
@@ -443,7 +443,7 @@ fn parse_reg<'a>(
443443
fn expand_preparsed_asm(
444444
ecx: &mut ExtCtxt<'_>,
445445
args: AsmArgs,
446-
) -> Result<ast::InlineAsm, ErrorGuaranteed> {
446+
) -> ExpandResult<Result<ast::InlineAsm, ErrorGuaranteed>, ()> {
447447
let mut template = vec![];
448448
// Register operands are implicitly used since they are not allowed to be
449449
// referenced in the template string.
@@ -465,16 +465,20 @@ fn expand_preparsed_asm(
465465

466466
let msg = "asm template must be a string literal";
467467
let template_sp = template_expr.span;
468-
let (template_str, template_style, template_span) =
469-
match expr_to_spanned_string(ecx, template_expr, msg) {
468+
let (template_str, template_style, template_span) = {
469+
let ExpandResult::Ready(mac) = expr_to_spanned_string(ecx, template_expr, msg) else {
470+
return ExpandResult::Retry(());
471+
};
472+
match mac {
470473
Ok(template_part) => template_part,
471474
Err(err) => {
472-
return Err(match err {
475+
return ExpandResult::Ready(Err(match err {
473476
Ok((err, _)) => err.emit(),
474477
Err(guar) => guar,
475-
});
478+
}));
476479
}
477-
};
480+
}
481+
};
478482

479483
let str_style = match template_style {
480484
ast::StrStyle::Cooked => None,
@@ -562,7 +566,7 @@ fn expand_preparsed_asm(
562566
e.span_label(err_sp, label);
563567
}
564568
let guar = e.emit();
565-
return Err(guar);
569+
return ExpandResult::Ready(Err(guar));
566570
}
567571

568572
curarg = parser.curarg;
@@ -729,24 +733,27 @@ fn expand_preparsed_asm(
729733
}
730734
}
731735

732-
Ok(ast::InlineAsm {
736+
ExpandResult::Ready(Ok(ast::InlineAsm {
733737
template,
734738
template_strs: template_strs.into_boxed_slice(),
735739
operands: args.operands,
736740
clobber_abis: args.clobber_abis,
737741
options: args.options,
738742
line_spans,
739-
})
743+
}))
740744
}
741745

742746
pub(super) fn expand_asm<'cx>(
743747
ecx: &'cx mut ExtCtxt<'_>,
744748
sp: Span,
745749
tts: TokenStream,
746-
) -> Box<dyn base::MacResult + 'cx> {
747-
match parse_args(ecx, sp, tts, false) {
750+
) -> MacroExpanderResult<'cx> {
751+
ExpandResult::Ready(match parse_args(ecx, sp, tts, false) {
748752
Ok(args) => {
749-
let expr = match expand_preparsed_asm(ecx, args) {
753+
let ExpandResult::Ready(mac) = expand_preparsed_asm(ecx, args) else {
754+
return ExpandResult::Retry(());
755+
};
756+
let expr = match mac {
750757
Ok(inline_asm) => P(ast::Expr {
751758
id: ast::DUMMY_NODE_ID,
752759
kind: ast::ExprKind::InlineAsm(P(inline_asm)),
@@ -762,34 +769,39 @@ pub(super) fn expand_asm<'cx>(
762769
let guar = err.emit();
763770
DummyResult::any(sp, guar)
764771
}
765-
}
772+
})
766773
}
767774

768775
pub(super) fn expand_global_asm<'cx>(
769776
ecx: &'cx mut ExtCtxt<'_>,
770777
sp: Span,
771778
tts: TokenStream,
772-
) -> Box<dyn base::MacResult + 'cx> {
773-
match parse_args(ecx, sp, tts, true) {
774-
Ok(args) => match expand_preparsed_asm(ecx, args) {
775-
Ok(inline_asm) => MacEager::items(smallvec![P(ast::Item {
776-
ident: Ident::empty(),
777-
attrs: ast::AttrVec::new(),
778-
id: ast::DUMMY_NODE_ID,
779-
kind: ast::ItemKind::GlobalAsm(Box::new(inline_asm)),
780-
vis: ast::Visibility {
781-
span: sp.shrink_to_lo(),
782-
kind: ast::VisibilityKind::Inherited,
779+
) -> MacroExpanderResult<'cx> {
780+
ExpandResult::Ready(match parse_args(ecx, sp, tts, true) {
781+
Ok(args) => {
782+
let ExpandResult::Ready(mac) = expand_preparsed_asm(ecx, args) else {
783+
return ExpandResult::Retry(());
784+
};
785+
match mac {
786+
Ok(inline_asm) => MacEager::items(smallvec![P(ast::Item {
787+
ident: Ident::empty(),
788+
attrs: ast::AttrVec::new(),
789+
id: ast::DUMMY_NODE_ID,
790+
kind: ast::ItemKind::GlobalAsm(Box::new(inline_asm)),
791+
vis: ast::Visibility {
792+
span: sp.shrink_to_lo(),
793+
kind: ast::VisibilityKind::Inherited,
794+
tokens: None,
795+
},
796+
span: sp,
783797
tokens: None,
784-
},
785-
span: sp,
786-
tokens: None,
787-
})]),
788-
Err(guar) => DummyResult::any(sp, guar),
789-
},
798+
})]),
799+
Err(guar) => DummyResult::any(sp, guar),
800+
}
801+
}
790802
Err(err) => {
791803
let guar = err.emit();
792804
DummyResult::any(sp, guar)
793805
}
794-
}
806+
})
795807
}

compiler/rustc_builtin_macros/src/assert.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use rustc_ast::tokenstream::{DelimSpan, TokenStream};
99
use rustc_ast::{DelimArgs, Expr, ExprKind, MacCall, Path, PathSegment, UnOp};
1010
use rustc_ast_pretty::pprust;
1111
use rustc_errors::PResult;
12-
use rustc_expand::base::{DummyResult, ExtCtxt, MacEager, MacResult};
12+
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult};
1313
use rustc_parse::parser::Parser;
1414
use rustc_span::symbol::{sym, Ident, Symbol};
1515
use rustc_span::{Span, DUMMY_SP};
@@ -19,12 +19,12 @@ pub fn expand_assert<'cx>(
1919
cx: &'cx mut ExtCtxt<'_>,
2020
span: Span,
2121
tts: TokenStream,
22-
) -> Box<dyn MacResult + 'cx> {
22+
) -> MacroExpanderResult<'cx> {
2323
let Assert { cond_expr, custom_message } = match parse_assert(cx, span, tts) {
2424
Ok(assert) => assert,
2525
Err(err) => {
2626
let guar = err.emit();
27-
return DummyResult::any(span, guar);
27+
return ExpandResult::Ready(DummyResult::any(span, guar));
2828
}
2929
};
3030

@@ -92,7 +92,7 @@ pub fn expand_assert<'cx>(
9292
expr_if_not(cx, call_site_span, cond_expr, then, None)
9393
};
9494

95-
MacEager::expr(expr)
95+
ExpandResult::Ready(MacEager::expr(expr))
9696
}
9797

9898
struct Assert {

compiler/rustc_builtin_macros/src/cfg.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,17 @@ use rustc_ast::token;
88
use rustc_ast::tokenstream::TokenStream;
99
use rustc_attr as attr;
1010
use rustc_errors::PResult;
11-
use rustc_expand::base::{DummyResult, ExtCtxt, MacEager, MacResult};
11+
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult};
1212
use rustc_span::Span;
1313

1414
pub fn expand_cfg(
1515
cx: &mut ExtCtxt<'_>,
1616
sp: Span,
1717
tts: TokenStream,
18-
) -> Box<dyn MacResult + 'static> {
18+
) -> MacroExpanderResult<'static> {
1919
let sp = cx.with_def_site_ctxt(sp);
2020

21-
match parse_cfg(cx, sp, tts) {
21+
ExpandResult::Ready(match parse_cfg(cx, sp, tts) {
2222
Ok(cfg) => {
2323
let matches_cfg = attr::cfg_matches(
2424
&cfg,
@@ -32,7 +32,7 @@ pub fn expand_cfg(
3232
let guar = err.emit();
3333
DummyResult::any(sp, guar)
3434
}
35-
}
35+
})
3636
}
3737

3838
fn parse_cfg<'a>(cx: &mut ExtCtxt<'a>, span: Span, tts: TokenStream) -> PResult<'a, ast::MetaItem> {
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,26 @@
11
// The compiler code necessary to support the compile_error! extension.
22

33
use rustc_ast::tokenstream::TokenStream;
4-
use rustc_expand::base::{get_single_str_from_tts, DummyResult, ExtCtxt, MacResult};
4+
use rustc_expand::base::get_single_str_from_tts;
5+
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult};
56
use rustc_span::Span;
67

78
pub fn expand_compile_error<'cx>(
89
cx: &'cx mut ExtCtxt<'_>,
910
sp: Span,
1011
tts: TokenStream,
11-
) -> Box<dyn MacResult + 'cx> {
12-
let var = match get_single_str_from_tts(cx, sp, tts, "compile_error!") {
12+
) -> MacroExpanderResult<'cx> {
13+
let ExpandResult::Ready(mac) = get_single_str_from_tts(cx, sp, tts, "compile_error!") else {
14+
return ExpandResult::Retry(());
15+
};
16+
let var = match mac {
1317
Ok(var) => var,
14-
Err(guar) => return DummyResult::any(sp, guar),
18+
Err(guar) => return ExpandResult::Ready(DummyResult::any(sp, guar)),
1519
};
1620

1721
#[expect(rustc::diagnostic_outside_of_impl, reason = "diagnostic message is specified by user")]
1822
#[expect(rustc::untranslatable_diagnostic, reason = "diagnostic message is specified by user")]
1923
let guar = cx.dcx().span_err(sp, var.to_string());
2024

21-
DummyResult::any(sp, guar)
25+
ExpandResult::Ready(DummyResult::any(sp, guar))
2226
}

compiler/rustc_builtin_macros/src/concat.rs

+15-10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use rustc_ast::tokenstream::TokenStream;
22
use rustc_ast::{ExprKind, LitKind, UnOp};
3-
use rustc_expand::base::{get_exprs_from_tts, DummyResult, ExtCtxt, MacEager, MacResult};
3+
use rustc_expand::base::get_exprs_from_tts;
4+
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult};
45
use rustc_session::errors::report_lit_error;
56
use rustc_span::symbol::Symbol;
67

@@ -10,10 +11,13 @@ pub fn expand_concat(
1011
cx: &mut ExtCtxt<'_>,
1112
sp: rustc_span::Span,
1213
tts: TokenStream,
13-
) -> Box<dyn MacResult + 'static> {
14-
let es = match get_exprs_from_tts(cx, tts) {
14+
) -> MacroExpanderResult<'static> {
15+
let ExpandResult::Ready(mac) = get_exprs_from_tts(cx, tts) else {
16+
return ExpandResult::Retry(());
17+
};
18+
let es = match mac {
1519
Ok(es) => es,
16-
Err(guar) => return DummyResult::any(sp, guar),
20+
Err(guar) => return ExpandResult::Ready(DummyResult::any(sp, guar)),
1721
};
1822
let mut accumulator = String::new();
1923
let mut missing_literal = vec![];
@@ -70,12 +74,13 @@ pub fn expand_concat(
7074
}
7175
}
7276

73-
if !missing_literal.is_empty() {
77+
ExpandResult::Ready(if !missing_literal.is_empty() {
7478
let guar = cx.dcx().emit_err(errors::ConcatMissingLiteral { spans: missing_literal });
75-
return DummyResult::any(sp, guar);
79+
DummyResult::any(sp, guar)
7680
} else if let Some(guar) = guar {
77-
return DummyResult::any(sp, guar);
78-
}
79-
let sp = cx.with_def_site_ctxt(sp);
80-
MacEager::expr(cx.expr_str(sp, Symbol::intern(&accumulator)))
81+
DummyResult::any(sp, guar)
82+
} else {
83+
let sp = cx.with_def_site_ctxt(sp);
84+
MacEager::expr(cx.expr_str(sp, Symbol::intern(&accumulator)))
85+
})
8186
}

compiler/rustc_builtin_macros/src/concat_bytes.rs

+15-10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use rustc_ast::{ptr::P, token, tokenstream::TokenStream, ExprKind, LitIntType, LitKind, UintTy};
2-
use rustc_expand::base::{get_exprs_from_tts, DummyResult, ExtCtxt, MacEager, MacResult};
2+
use rustc_expand::base::get_exprs_from_tts;
3+
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult};
34
use rustc_session::errors::report_lit_error;
45
use rustc_span::{ErrorGuaranteed, Span};
56

@@ -111,10 +112,13 @@ pub fn expand_concat_bytes(
111112
cx: &mut ExtCtxt<'_>,
112113
sp: Span,
113114
tts: TokenStream,
114-
) -> Box<dyn MacResult + 'static> {
115-
let es = match get_exprs_from_tts(cx, tts) {
115+
) -> MacroExpanderResult<'static> {
116+
let ExpandResult::Ready(mac) = get_exprs_from_tts(cx, tts) else {
117+
return ExpandResult::Retry(());
118+
};
119+
let es = match mac {
116120
Ok(es) => es,
117-
Err(guar) => return DummyResult::any(sp, guar),
121+
Err(guar) => return ExpandResult::Ready(DummyResult::any(sp, guar)),
118122
};
119123
let mut accumulator = Vec::new();
120124
let mut missing_literals = vec![];
@@ -170,12 +174,13 @@ pub fn expand_concat_bytes(
170174
}
171175
}
172176
}
173-
if !missing_literals.is_empty() {
177+
ExpandResult::Ready(if !missing_literals.is_empty() {
174178
let guar = cx.dcx().emit_err(errors::ConcatBytesMissingLiteral { spans: missing_literals });
175-
return MacEager::expr(DummyResult::raw_expr(sp, Some(guar)));
179+
MacEager::expr(DummyResult::raw_expr(sp, Some(guar)))
176180
} else if let Some(guar) = guar {
177-
return MacEager::expr(DummyResult::raw_expr(sp, Some(guar)));
178-
}
179-
let sp = cx.with_def_site_ctxt(sp);
180-
MacEager::expr(cx.expr_byte_str(sp, accumulator))
181+
MacEager::expr(DummyResult::raw_expr(sp, Some(guar)))
182+
} else {
183+
let sp = cx.with_def_site_ctxt(sp);
184+
MacEager::expr(cx.expr_byte_str(sp, accumulator))
185+
})
181186
}

compiler/rustc_builtin_macros/src/concat_idents.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use rustc_ast::ptr::P;
22
use rustc_ast::token::{self, Token};
33
use rustc_ast::tokenstream::{TokenStream, TokenTree};
44
use rustc_ast::{AttrVec, Expr, ExprKind, Path, Ty, TyKind, DUMMY_NODE_ID};
5-
use rustc_expand::base::{DummyResult, ExtCtxt, MacResult};
5+
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacResult, MacroExpanderResult};
66
use rustc_span::symbol::{Ident, Symbol};
77
use rustc_span::Span;
88

@@ -12,10 +12,10 @@ pub fn expand_concat_idents<'cx>(
1212
cx: &'cx mut ExtCtxt<'_>,
1313
sp: Span,
1414
tts: TokenStream,
15-
) -> Box<dyn MacResult + 'cx> {
15+
) -> MacroExpanderResult<'cx> {
1616
if tts.is_empty() {
1717
let guar = cx.dcx().emit_err(errors::ConcatIdentsMissingArgs { span: sp });
18-
return DummyResult::any(sp, guar);
18+
return ExpandResult::Ready(DummyResult::any(sp, guar));
1919
}
2020

2121
let mut res_str = String::new();
@@ -25,7 +25,7 @@ pub fn expand_concat_idents<'cx>(
2525
TokenTree::Token(Token { kind: token::Comma, .. }, _) => {}
2626
_ => {
2727
let guar = cx.dcx().emit_err(errors::ConcatIdentsMissingComma { span: sp });
28-
return DummyResult::any(sp, guar);
28+
return ExpandResult::Ready(DummyResult::any(sp, guar));
2929
}
3030
}
3131
} else {
@@ -37,7 +37,7 @@ pub fn expand_concat_idents<'cx>(
3737
}
3838

3939
let guar = cx.dcx().emit_err(errors::ConcatIdentsIdentArgs { span: sp });
40-
return DummyResult::any(sp, guar);
40+
return ExpandResult::Ready(DummyResult::any(sp, guar));
4141
}
4242
}
4343

@@ -68,5 +68,5 @@ pub fn expand_concat_idents<'cx>(
6868
}
6969
}
7070

71-
Box::new(ConcatIdentsResult { ident })
71+
ExpandResult::Ready(Box::new(ConcatIdentsResult { ident }))
7272
}

0 commit comments

Comments
 (0)