Skip to content

Commit c3af98b

Browse files
author
Paolo Tranquilli
committed
Rust: skip unexpanded stuff in library emission
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.
1 parent b99b25c commit c3af98b

File tree

1 file changed

+75
-42
lines changed
  • rust/extractor/src/translate

1 file changed

+75
-42
lines changed

rust/extractor/src/translate/base.rs

Lines changed: 75 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ use ra_ap_syntax::{
2525
#[macro_export]
2626
macro_rules! pre_emit {
2727
(Item, $self:ident, $node:ident) => {
28-
$self.setup_item_expansion($node);
28+
if let Some(label) = $self.prepare_item_expansion($node) {
29+
return Some(label);
30+
}
2931
};
3032
($($_:tt)*) => {};
3133
}
@@ -687,6 +689,14 @@ impl<'a> Translator<'a> {
687689
{
688690
return true;
689691
}
692+
if syntax
693+
.parent()
694+
.and_then(ast::MacroCall::cast)
695+
.and_then(|x| x.token_tree())
696+
.is_some_and(|tt| tt.syntax() == syntax)
697+
{
698+
return true;
699+
}
690700
}
691701
false
692702
}
@@ -723,52 +733,75 @@ impl<'a> Translator<'a> {
723733
}
724734
}
725735

726-
pub(crate) fn setup_item_expansion(&mut self, node: &ast::Item) {
727-
if self.semantics.is_some_and(|s| {
728-
let file = s.hir_file_for(node.syntax());
729-
let node = InFile::new(file, node);
730-
s.is_attr_macro_call(node)
731-
}) {
736+
pub(crate) fn prepare_item_expansion(
737+
&mut self,
738+
node: &ast::Item,
739+
) -> Option<Label<generated::Item>> {
740+
if self.source_kind == SourceKind::Library {
741+
// if the item expands via an attribute macro, we want to only emit the expansion
742+
if let Some(expanded) = self.emit_attribute_macro_expansion(node) {
743+
// we wrap it in a dummy MacroCall to get a single Item label that can replace
744+
// the original Item
745+
let label = self.trap.emit(generated::MacroCall {
746+
id: TrapId::Star,
747+
attrs: vec![],
748+
path: None,
749+
token_tree: None,
750+
});
751+
generated::MacroCall::emit_macro_call_expansion(
752+
label,
753+
expanded.into(),
754+
&mut self.trap.writer,
755+
);
756+
return Some(label.into());
757+
}
758+
}
759+
let semantics = self.semantics.as_ref()?;
760+
let file = semantics.hir_file_for(node.syntax());
761+
let node = InFile::new(file, node);
762+
if semantics.is_attr_macro_call(node) {
732763
self.macro_context_depth += 1;
733764
}
765+
None
734766
}
735767

736-
pub(crate) fn emit_item_expansion(&mut self, node: &ast::Item, label: Label<generated::Item>) {
737-
// TODO: remove this after fixing exponential expansion on libraries like funty-2.0.0
738-
if self.source_kind == SourceKind::Library {
739-
return;
768+
fn emit_attribute_macro_expansion(
769+
&mut self,
770+
node: &ast::Item,
771+
) -> Option<Label<generated::MacroItems>> {
772+
let semantics = self.semantics?;
773+
let file = semantics.hir_file_for(node.syntax());
774+
let infile_node = InFile::new(file, node);
775+
if !semantics.is_attr_macro_call(infile_node) {
776+
return None;
740777
}
741-
(|| {
742-
let semantics = self.semantics?;
743-
let file = semantics.hir_file_for(node.syntax());
744-
let infile_node = InFile::new(file, node);
745-
if !semantics.is_attr_macro_call(infile_node) {
746-
return None;
747-
}
748-
self.macro_context_depth -= 1;
749-
if self.macro_context_depth > 0 {
750-
// only expand the outermost attribute macro
751-
return None;
752-
}
753-
let ExpandResult {
754-
value: expanded, ..
755-
} = semantics.expand_attr_macro(node)?;
756-
self.emit_macro_expansion_parse_errors(node, &expanded);
757-
let macro_items = ast::MacroItems::cast(expanded).or_else(|| {
758-
let message = "attribute macro expansion cannot be cast to MacroItems".to_owned();
759-
let location = self.location_for_node(node);
760-
self.emit_diagnostic(
761-
DiagnosticSeverity::Warning,
762-
"item_expansion".to_owned(),
763-
message.clone(),
764-
message,
765-
location.unwrap_or(UNKNOWN_LOCATION),
766-
);
767-
None
768-
})?;
769-
let expanded = self.emit_macro_items(&macro_items)?;
778+
self.macro_context_depth -= 1;
779+
if self.macro_context_depth > 0 {
780+
// only expand the outermost attribute macro
781+
return None;
782+
}
783+
let ExpandResult {
784+
value: expanded, ..
785+
} = semantics.expand_attr_macro(node)?;
786+
self.emit_macro_expansion_parse_errors(node, &expanded);
787+
let macro_items = ast::MacroItems::cast(expanded).or_else(|| {
788+
let message = "attribute macro expansion cannot be cast to MacroItems".to_owned();
789+
let location = self.location_for_node(node);
790+
self.emit_diagnostic(
791+
DiagnosticSeverity::Warning,
792+
"item_expansion".to_owned(),
793+
message.clone(),
794+
message,
795+
location.unwrap_or(UNKNOWN_LOCATION),
796+
);
797+
None
798+
})?;
799+
self.emit_macro_items(&macro_items)
800+
}
801+
802+
pub(crate) fn emit_item_expansion(&mut self, node: &ast::Item, label: Label<generated::Item>) {
803+
if let Some(expanded) = self.emit_attribute_macro_expansion(node) {
770804
generated::Item::emit_attribute_macro_expansion(label, expanded, &mut self.trap.writer);
771-
Some(())
772-
})();
805+
}
773806
}
774807
}

0 commit comments

Comments
 (0)