Skip to content

Commit ea02f4c

Browse files
committed
Auto merge of #15251 - Veykril:builtin-expand, r=Veykril
Skip building subtrees for builtin derives This is a waste of resources, we go from node to subtree just to go from subtree to node in the expander impl. We can skip the subtree building and only build the tokenmap instead.
2 parents 785a33d + f6c0909 commit ea02f4c

File tree

12 files changed

+458
-229
lines changed

12 files changed

+458
-229
lines changed

crates/hir-def/src/macro_expansion_tests/mod.rs

+23-26
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ use ::mbe::TokenMap;
2020
use base_db::{fixture::WithFixture, ProcMacro, SourceDatabase};
2121
use expect_test::Expect;
2222
use hir_expand::{
23-
db::{ExpandDatabase, TokenExpander},
24-
AstId, InFile, MacroDefId, MacroDefKind, MacroFile,
23+
db::{DeclarativeMacroExpander, ExpandDatabase},
24+
AstId, InFile, MacroFile,
2525
};
2626
use stdx::format_to;
2727
use syntax::{
@@ -100,32 +100,29 @@ pub fn identity_when_valid(_attr: TokenStream, item: TokenStream) -> TokenStream
100100
let call_offset = macro_.syntax().text_range().start().into();
101101
let file_ast_id = db.ast_id_map(source.file_id).ast_id(&macro_);
102102
let ast_id = AstId::new(source.file_id, file_ast_id.upcast());
103-
let kind = MacroDefKind::Declarative(ast_id);
104103

105-
let macro_def = db
106-
.macro_def(MacroDefId { krate, kind, local_inner: false, allow_internal_unsafe: false })
107-
.unwrap();
108-
if let TokenExpander::DeclarativeMacro { mac, def_site_token_map } = &*macro_def {
109-
let tt = match &macro_ {
110-
ast::Macro::MacroRules(mac) => mac.token_tree().unwrap(),
111-
ast::Macro::MacroDef(_) => unimplemented!(""),
112-
};
104+
let DeclarativeMacroExpander { mac, def_site_token_map } =
105+
&*db.decl_macro_expander(krate, ast_id);
106+
assert_eq!(mac.err(), None);
107+
let tt = match &macro_ {
108+
ast::Macro::MacroRules(mac) => mac.token_tree().unwrap(),
109+
ast::Macro::MacroDef(_) => unimplemented!(""),
110+
};
113111

114-
let tt_start = tt.syntax().text_range().start();
115-
tt.syntax().descendants_with_tokens().filter_map(SyntaxElement::into_token).for_each(
116-
|token| {
117-
let range = token.text_range().checked_sub(tt_start).unwrap();
118-
if let Some(id) = def_site_token_map.token_by_range(range) {
119-
let offset = (range.end() + tt_start).into();
120-
text_edits.push((offset..offset, format!("#{}", id.0)));
121-
}
122-
},
123-
);
124-
text_edits.push((
125-
call_offset..call_offset,
126-
format!("// call ids will be shifted by {:?}\n", mac.shift()),
127-
));
128-
}
112+
let tt_start = tt.syntax().text_range().start();
113+
tt.syntax().descendants_with_tokens().filter_map(SyntaxElement::into_token).for_each(
114+
|token| {
115+
let range = token.text_range().checked_sub(tt_start).unwrap();
116+
if let Some(id) = def_site_token_map.token_by_range(range) {
117+
let offset = (range.end() + tt_start).into();
118+
text_edits.push((offset..offset, format!("#{}", id.0)));
119+
}
120+
},
121+
);
122+
text_edits.push((
123+
call_offset..call_offset,
124+
format!("// call ids will be shifted by {:?}\n", mac.shift()),
125+
));
129126
}
130127

131128
for macro_call in source_file.syntax().descendants().filter_map(ast::MacroCall::cast) {

crates/hir-expand/src/builtin_derive_macro.rs

+41-45
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,7 @@ use crate::{
1212
name::{AsName, Name},
1313
tt::{self, TokenId},
1414
};
15-
use syntax::ast::{
16-
self, AstNode, FieldList, HasAttrs, HasGenericParams, HasModuleItem, HasName, HasTypeBounds,
17-
};
15+
use syntax::ast::{self, AstNode, FieldList, HasAttrs, HasGenericParams, HasName, HasTypeBounds};
1816

1917
use crate::{db::ExpandDatabase, name, quote, ExpandError, ExpandResult, MacroCallId};
2018

@@ -30,12 +28,13 @@ macro_rules! register_builtin {
3028
&self,
3129
db: &dyn ExpandDatabase,
3230
id: MacroCallId,
33-
tt: &tt::Subtree,
31+
tt: &ast::Adt,
32+
token_map: &TokenMap,
3433
) -> ExpandResult<tt::Subtree> {
3534
let expander = match *self {
3635
$( BuiltinDeriveExpander::$trait => $expand, )*
3736
};
38-
expander(db, id, tt)
37+
expander(db, id, tt, token_map)
3938
}
4039

4140
fn find_by_name(name: &name::Name) -> Option<Self> {
@@ -118,13 +117,13 @@ impl VariantShape {
118117
}
119118
}
120119

121-
fn from(value: Option<FieldList>, token_map: &TokenMap) -> Result<Self, ExpandError> {
120+
fn from(tm: &TokenMap, value: Option<FieldList>) -> Result<Self, ExpandError> {
122121
let r = match value {
123122
None => VariantShape::Unit,
124123
Some(FieldList::RecordFieldList(it)) => VariantShape::Struct(
125124
it.fields()
126125
.map(|it| it.name())
127-
.map(|it| name_to_token(token_map, it))
126+
.map(|it| name_to_token(tm, it))
128127
.collect::<Result<_, _>>()?,
129128
),
130129
Some(FieldList::TupleFieldList(it)) => VariantShape::Tuple(it.fields().count()),
@@ -190,25 +189,12 @@ struct BasicAdtInfo {
190189
associated_types: Vec<tt::Subtree>,
191190
}
192191

193-
fn parse_adt(tt: &tt::Subtree) -> Result<BasicAdtInfo, ExpandError> {
194-
let (parsed, token_map) = mbe::token_tree_to_syntax_node(tt, mbe::TopEntryPoint::MacroItems);
195-
let macro_items = ast::MacroItems::cast(parsed.syntax_node()).ok_or_else(|| {
196-
debug!("derive node didn't parse");
197-
ExpandError::other("invalid item definition")
198-
})?;
199-
let item = macro_items.items().next().ok_or_else(|| {
200-
debug!("no module item parsed");
201-
ExpandError::other("no item found")
202-
})?;
203-
let adt = ast::Adt::cast(item.syntax().clone()).ok_or_else(|| {
204-
debug!("expected adt, found: {:?}", item);
205-
ExpandError::other("expected struct, enum or union")
206-
})?;
192+
fn parse_adt(tm: &TokenMap, adt: &ast::Adt) -> Result<BasicAdtInfo, ExpandError> {
207193
let (name, generic_param_list, shape) = match &adt {
208194
ast::Adt::Struct(it) => (
209195
it.name(),
210196
it.generic_param_list(),
211-
AdtShape::Struct(VariantShape::from(it.field_list(), &token_map)?),
197+
AdtShape::Struct(VariantShape::from(tm, it.field_list())?),
212198
),
213199
ast::Adt::Enum(it) => {
214200
let default_variant = it
@@ -227,8 +213,8 @@ fn parse_adt(tt: &tt::Subtree) -> Result<BasicAdtInfo, ExpandError> {
227213
.flat_map(|it| it.variants())
228214
.map(|it| {
229215
Ok((
230-
name_to_token(&token_map, it.name())?,
231-
VariantShape::from(it.field_list(), &token_map)?,
216+
name_to_token(tm, it.name())?,
217+
VariantShape::from(tm, it.field_list())?,
232218
))
233219
})
234220
.collect::<Result<_, ExpandError>>()?,
@@ -298,7 +284,7 @@ fn parse_adt(tt: &tt::Subtree) -> Result<BasicAdtInfo, ExpandError> {
298284
})
299285
.map(|it| mbe::syntax_node_to_token_tree(it.syntax()).0)
300286
.collect();
301-
let name_token = name_to_token(&token_map, name)?;
287+
let name_token = name_to_token(&tm, name)?;
302288
Ok(BasicAdtInfo { name: name_token, shape, param_types, associated_types })
303289
}
304290

@@ -345,11 +331,12 @@ fn name_to_token(token_map: &TokenMap, name: Option<ast::Name>) -> Result<tt::Id
345331
/// where B1, ..., BN are the bounds given by `bounds_paths`. Z is a phantom type, and
346332
/// therefore does not get bound by the derived trait.
347333
fn expand_simple_derive(
348-
tt: &tt::Subtree,
334+
tt: &ast::Adt,
335+
tm: &TokenMap,
349336
trait_path: tt::Subtree,
350337
make_trait_body: impl FnOnce(&BasicAdtInfo) -> tt::Subtree,
351338
) -> ExpandResult<tt::Subtree> {
352-
let info = match parse_adt(tt) {
339+
let info = match parse_adt(tm, tt) {
353340
Ok(info) => info,
354341
Err(e) => return ExpandResult::new(tt::Subtree::empty(), e),
355342
};
@@ -405,19 +392,21 @@ fn find_builtin_crate(db: &dyn ExpandDatabase, id: MacroCallId) -> tt::TokenTree
405392
fn copy_expand(
406393
db: &dyn ExpandDatabase,
407394
id: MacroCallId,
408-
tt: &tt::Subtree,
395+
tt: &ast::Adt,
396+
tm: &TokenMap,
409397
) -> ExpandResult<tt::Subtree> {
410398
let krate = find_builtin_crate(db, id);
411-
expand_simple_derive(tt, quote! { #krate::marker::Copy }, |_| quote! {})
399+
expand_simple_derive(tt, tm, quote! { #krate::marker::Copy }, |_| quote! {})
412400
}
413401

414402
fn clone_expand(
415403
db: &dyn ExpandDatabase,
416404
id: MacroCallId,
417-
tt: &tt::Subtree,
405+
tt: &ast::Adt,
406+
tm: &TokenMap,
418407
) -> ExpandResult<tt::Subtree> {
419408
let krate = find_builtin_crate(db, id);
420-
expand_simple_derive(tt, quote! { #krate::clone::Clone }, |adt| {
409+
expand_simple_derive(tt, tm, quote! { #krate::clone::Clone }, |adt| {
421410
if matches!(adt.shape, AdtShape::Union) {
422411
let star = tt::Punct {
423412
char: '*',
@@ -479,10 +468,11 @@ fn and_and() -> ::tt::Subtree<TokenId> {
479468
fn default_expand(
480469
db: &dyn ExpandDatabase,
481470
id: MacroCallId,
482-
tt: &tt::Subtree,
471+
tt: &ast::Adt,
472+
tm: &TokenMap,
483473
) -> ExpandResult<tt::Subtree> {
484474
let krate = &find_builtin_crate(db, id);
485-
expand_simple_derive(tt, quote! { #krate::default::Default }, |adt| {
475+
expand_simple_derive(tt, tm, quote! { #krate::default::Default }, |adt| {
486476
let body = match &adt.shape {
487477
AdtShape::Struct(fields) => {
488478
let name = &adt.name;
@@ -518,10 +508,11 @@ fn default_expand(
518508
fn debug_expand(
519509
db: &dyn ExpandDatabase,
520510
id: MacroCallId,
521-
tt: &tt::Subtree,
511+
tt: &ast::Adt,
512+
tm: &TokenMap,
522513
) -> ExpandResult<tt::Subtree> {
523514
let krate = &find_builtin_crate(db, id);
524-
expand_simple_derive(tt, quote! { #krate::fmt::Debug }, |adt| {
515+
expand_simple_derive(tt, tm, quote! { #krate::fmt::Debug }, |adt| {
525516
let for_variant = |name: String, v: &VariantShape| match v {
526517
VariantShape::Struct(fields) => {
527518
let for_fields = fields.iter().map(|it| {
@@ -598,10 +589,11 @@ fn debug_expand(
598589
fn hash_expand(
599590
db: &dyn ExpandDatabase,
600591
id: MacroCallId,
601-
tt: &tt::Subtree,
592+
tt: &ast::Adt,
593+
tm: &TokenMap,
602594
) -> ExpandResult<tt::Subtree> {
603595
let krate = &find_builtin_crate(db, id);
604-
expand_simple_derive(tt, quote! { #krate::hash::Hash }, |adt| {
596+
expand_simple_derive(tt, tm, quote! { #krate::hash::Hash }, |adt| {
605597
if matches!(adt.shape, AdtShape::Union) {
606598
// FIXME: Return expand error here
607599
return quote! {};
@@ -646,19 +638,21 @@ fn hash_expand(
646638
fn eq_expand(
647639
db: &dyn ExpandDatabase,
648640
id: MacroCallId,
649-
tt: &tt::Subtree,
641+
tt: &ast::Adt,
642+
tm: &TokenMap,
650643
) -> ExpandResult<tt::Subtree> {
651644
let krate = find_builtin_crate(db, id);
652-
expand_simple_derive(tt, quote! { #krate::cmp::Eq }, |_| quote! {})
645+
expand_simple_derive(tt, tm, quote! { #krate::cmp::Eq }, |_| quote! {})
653646
}
654647

655648
fn partial_eq_expand(
656649
db: &dyn ExpandDatabase,
657650
id: MacroCallId,
658-
tt: &tt::Subtree,
651+
tt: &ast::Adt,
652+
tm: &TokenMap,
659653
) -> ExpandResult<tt::Subtree> {
660654
let krate = find_builtin_crate(db, id);
661-
expand_simple_derive(tt, quote! { #krate::cmp::PartialEq }, |adt| {
655+
expand_simple_derive(tt, tm, quote! { #krate::cmp::PartialEq }, |adt| {
662656
if matches!(adt.shape, AdtShape::Union) {
663657
// FIXME: Return expand error here
664658
return quote! {};
@@ -722,10 +716,11 @@ fn self_and_other_patterns(
722716
fn ord_expand(
723717
db: &dyn ExpandDatabase,
724718
id: MacroCallId,
725-
tt: &tt::Subtree,
719+
tt: &ast::Adt,
720+
tm: &TokenMap,
726721
) -> ExpandResult<tt::Subtree> {
727722
let krate = &find_builtin_crate(db, id);
728-
expand_simple_derive(tt, quote! { #krate::cmp::Ord }, |adt| {
723+
expand_simple_derive(tt, tm, quote! { #krate::cmp::Ord }, |adt| {
729724
fn compare(
730725
krate: &tt::TokenTree,
731726
left: tt::Subtree,
@@ -786,10 +781,11 @@ fn ord_expand(
786781
fn partial_ord_expand(
787782
db: &dyn ExpandDatabase,
788783
id: MacroCallId,
789-
tt: &tt::Subtree,
784+
tt: &ast::Adt,
785+
tm: &TokenMap,
790786
) -> ExpandResult<tt::Subtree> {
791787
let krate = &find_builtin_crate(db, id);
792-
expand_simple_derive(tt, quote! { #krate::cmp::PartialOrd }, |adt| {
788+
expand_simple_derive(tt, tm, quote! { #krate::cmp::PartialOrd }, |adt| {
793789
fn compare(
794790
krate: &tt::TokenTree,
795791
left: tt::Subtree,

0 commit comments

Comments
 (0)