Rust: skip unexpanded stuff in library emission#19585
Conversation
This will skip all unexpanded entities in library extraction, where we only really care about expanded things. This means skipping: * the token tree of macro calls * the unexpanded AST of attribute macros In the latter case, in order to replace the single `Item` with its expansion (which is a `MacroItems` entity), we wrap the `MacroItems` in a dummy `MacroCall` with null path.
|
DCA shows a moderate speedup, and improvement in call graph resolution (with one exception being |
There was a problem hiding this comment.
Pull Request Overview
This PR enhances library-mode emission by skipping unexpanded macro entities and only emitting fully expanded items.
- Updated
pre_emit!to useprepare_item_expansionfor early returns of attribute macro expansions. - Added logic to skip nodes inside unexpanded macro call token trees during library extraction.
- Introduced
prepare_item_expansionandemit_attribute_macro_expansionto wrap attribute macro expansions in a dummyMacroCalland refactoredemit_item_expansion.
Comments suppressed due to low confidence (1)
rust/extractor/src/translate/base.rs:692
- New skip logic for nodes inside unexpanded macro call token trees lacks accompanying tests; consider adding unit tests to verify that these nodes are correctly ignored in library mode.
if syntax
| ) -> Option<Label<generated::Item>> { | ||
| if self.source_kind == SourceKind::Library { | ||
| // if the item expands via an attribute macro, we want to only emit the expansion | ||
| if let Some(expanded) = self.emit_attribute_macro_expansion(node) { |
There was a problem hiding this comment.
emit_attribute_macro_expansion is invoked both in prepare_item_expansion and again in emit_item_expansion, which may lead to duplicate work or inconsistent emission. Consider caching the result or ensuring it's only called once.
| if let Some(expanded) = self.emit_attribute_macro_expansion(node) { | |
| let node_id = node.syntax().text_range().start().into(); // Use a unique identifier for the node | |
| if let Some(expanded) = self.macro_expansion_cache.get(&node_id).cloned() | |
| .or_else(|| { | |
| let result = self.emit_attribute_macro_expansion(node); | |
| if let Some(ref expansion) = result { | |
| self.macro_expansion_cache.insert(node_id, expansion.clone()); | |
| } | |
| result | |
| }) | |
| { |
rust/extractor/src/translate/base.rs
Outdated
| { | ||
| return true; | ||
| } | ||
| if syntax |
There was a problem hiding this comment.
I think we can simply drop any node of type TokenTree. That includes macro call arguments, as well as macro rule/definition bodies. Like done in #19581
This will skip all unexpanded entities in library extraction, where we only really care about expanded things. This means skipping:
In the latter case, in order to replace the single
Itemwith its expansion (which is aMacroItemsentity), we wrap theMacroItemsin a dummyMacroCallwith null path.