Skip to content

Commit 82ef699

Browse files
committed
Auto merge of rust-lang#15203 - Veykril:proc-macro-expand, r=Veykril
Shuffle some proc_macro_expand query things around Removes some unnecessary extra work we are doing in proc-macro expansion, and more importantly `Arc` the result of the proc_macro_expand query, that way we can reuse the instance for the `macro_expand` query's result
2 parents 8094e05 + bdc3d0f commit 82ef699

File tree

1 file changed

+54
-33
lines changed
  • crates/hir-expand/src

1 file changed

+54
-33
lines changed

crates/hir-expand/src/db.rs

+54-33
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,7 @@ impl TokenExpander {
5757
TokenExpander::BuiltinAttr(it) => it.expand(db, id, tt),
5858
TokenExpander::BuiltinDerive(it) => it.expand(db, id, tt),
5959
TokenExpander::ProcMacro(_) => {
60-
// We store the result in salsa db to prevent non-deterministic behavior in
61-
// some proc-macro implementation
62-
// See #4315 for details
63-
db.expand_proc_macro(id)
60+
unreachable!("ExpandDatabase::expand_proc_macro should be used for proc macros")
6461
}
6562
}
6663
}
@@ -141,8 +138,8 @@ pub trait ExpandDatabase: SourceDatabase {
141138
/// Special case of the previous query for procedural macros. We can't LRU
142139
/// proc macros, since they are not deterministic in general, and
143140
/// non-determinism breaks salsa in a very, very, very bad way.
144-
/// @edwin0cheng heroically debugged this once!
145-
fn expand_proc_macro(&self, call: MacroCallId) -> ExpandResult<tt::Subtree>;
141+
/// @edwin0cheng heroically debugged this once! See #4315 for details
142+
fn expand_proc_macro(&self, call: MacroCallId) -> ExpandResult<Arc<tt::Subtree>>;
146143
/// Firewall query that returns the errors from the `parse_macro_expansion` query.
147144
fn parse_macro_expansion_error(
148145
&self,
@@ -297,6 +294,14 @@ fn parse_macro_expansion(
297294
ExpandResult { value: (parse, Arc::new(rev_token_map)), err }
298295
}
299296

297+
fn parse_macro_expansion_error(
298+
db: &dyn ExpandDatabase,
299+
macro_call_id: MacroCallId,
300+
) -> ExpandResult<Box<[SyntaxError]>> {
301+
db.parse_macro_expansion(MacroFile { macro_call_id })
302+
.map(|it| it.0.errors().to_vec().into_boxed_slice())
303+
}
304+
300305
fn macro_arg(
301306
db: &dyn ExpandDatabase,
302307
id: MacroCallId,
@@ -445,6 +450,11 @@ fn macro_expand(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<Arc<tt
445450
// This is an input expansion for an eager macro. These are already pre-expanded
446451
return ExpandResult { value: Arc::new(arg.0.clone()), err: error.clone() };
447452
}
453+
454+
if let MacroDefKind::ProcMacro(..) = loc.def.kind {
455+
return db.expand_proc_macro(id);
456+
}
457+
448458
let expander = match db.macro_def(loc.def) {
449459
Ok(it) => it,
450460
// FIXME: We should make sure to enforce a variant that invalid macro
@@ -467,7 +477,7 @@ fn macro_expand(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<Arc<tt
467477
token_trees: Vec::new(),
468478
},
469479
),
470-
// FIXME: We should make sure to enforce a variant that invalid macro
480+
// FIXME: We should make sure to enforce an invariant that invalid macro
471481
// calls do not reach this call path!
472482
err: Some(ExpandError::other(
473483
"invalid token tree"
@@ -483,47 +493,29 @@ fn macro_expand(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<Arc<tt
483493
}
484494

485495
// Set a hard limit for the expanded tt
486-
let count = tt.count();
487-
if TOKEN_LIMIT.check(count).is_err() {
488-
return ExpandResult {
489-
value: Arc::new(tt::Subtree {
490-
delimiter: tt::Delimiter::UNSPECIFIED,
491-
token_trees: vec![],
492-
}),
493-
err: Some(ExpandError::other(format!(
494-
"macro invocation exceeds token limit: produced {} tokens, limit is {}",
495-
count,
496-
TOKEN_LIMIT.inner(),
497-
))),
498-
};
496+
if let Err(value) = check_tt_count(&tt) {
497+
return value;
499498
}
500499

501500
fixup::reverse_fixups(&mut tt, arg_tm, undo_info);
502501

503502
ExpandResult { value: Arc::new(tt), err }
504503
}
505504

506-
fn parse_macro_expansion_error(
507-
db: &dyn ExpandDatabase,
508-
macro_call_id: MacroCallId,
509-
) -> ExpandResult<Box<[SyntaxError]>> {
510-
db.parse_macro_expansion(MacroFile { macro_call_id })
511-
.map(|it| it.0.errors().to_vec().into_boxed_slice())
512-
}
513-
514-
fn expand_proc_macro(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<tt::Subtree> {
505+
fn expand_proc_macro(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<Arc<tt::Subtree>> {
515506
let loc = db.lookup_intern_macro_call(id);
516507
let Some(macro_arg) = db.macro_arg(id) else {
517508
return ExpandResult {
518-
value: tt::Subtree {
509+
value: Arc::new(tt::Subtree {
519510
delimiter: tt::Delimiter::UNSPECIFIED,
520511
token_trees: Vec::new(),
521-
},
512+
}),
522513
err: Some(ExpandError::other(
523514
"invalid token tree"
524515
)),
525516
};
526517
};
518+
let (arg_tt, arg_tm, undo_info) = &*macro_arg;
527519

528520
let expander = match loc.def.kind {
529521
MacroDefKind::ProcMacro(expander, ..) => expander,
@@ -533,13 +525,23 @@ fn expand_proc_macro(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<t
533525
let attr_arg = match &loc.kind {
534526
MacroCallKind::Attr { attr_args, .. } => {
535527
let mut attr_args = attr_args.0.clone();
536-
mbe::Shift::new(&macro_arg.0).shift_all(&mut attr_args);
528+
mbe::Shift::new(arg_tt).shift_all(&mut attr_args);
537529
Some(attr_args)
538530
}
539531
_ => None,
540532
};
541533

542-
expander.expand(db, loc.def.krate, loc.krate, &macro_arg.0, attr_arg.as_ref())
534+
let ExpandResult { value: mut tt, err } =
535+
expander.expand(db, loc.def.krate, loc.krate, arg_tt, attr_arg.as_ref());
536+
537+
// Set a hard limit for the expanded tt
538+
if let Err(value) = check_tt_count(&tt) {
539+
return value;
540+
}
541+
542+
fixup::reverse_fixups(&mut tt, arg_tm, undo_info);
543+
544+
ExpandResult { value: Arc::new(tt), err }
543545
}
544546

545547
fn hygiene_frame(db: &dyn ExpandDatabase, file_id: HirFileId) -> Arc<HygieneFrame> {
@@ -563,3 +565,22 @@ fn token_tree_to_syntax_node(
563565
};
564566
mbe::token_tree_to_syntax_node(tt, entry_point)
565567
}
568+
569+
fn check_tt_count(tt: &tt::Subtree) -> Result<(), ExpandResult<Arc<tt::Subtree>>> {
570+
let count = tt.count();
571+
if TOKEN_LIMIT.check(count).is_err() {
572+
Err(ExpandResult {
573+
value: Arc::new(tt::Subtree {
574+
delimiter: tt::Delimiter::UNSPECIFIED,
575+
token_trees: vec![],
576+
}),
577+
err: Some(ExpandError::other(format!(
578+
"macro invocation exceeds token limit: produced {} tokens, limit is {}",
579+
count,
580+
TOKEN_LIMIT.inner(),
581+
))),
582+
})
583+
} else {
584+
Ok(())
585+
}
586+
}

0 commit comments

Comments
 (0)