Skip to content

Commit 15d183b

Browse files
committed
Initial Attempt limiting number of token tree in macro expansion.
1 parent 83f9cc6 commit 15d183b

File tree

5 files changed

+119
-45
lines changed

5 files changed

+119
-45
lines changed

crates/hir-def/src/nameres/attr_resolution.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ pub(super) fn derive_macro_as_call_id(
136136
call_site: SyntaxContextId,
137137
krate: CrateId,
138138
resolver: impl Fn(path::ModPath) -> Option<(MacroId, MacroDefId)>,
139+
derive_macro_id: MacroCallId,
139140
) -> Result<(MacroId, MacroDefId, MacroCallId), UnresolvedMacro> {
140141
let (macro_id, def_id) = resolver(item_attr.path.clone())
141142
.filter(|(_, def_id)| def_id.is_derive())
@@ -147,6 +148,7 @@ pub(super) fn derive_macro_as_call_id(
147148
ast_id: item_attr.ast_id,
148149
derive_index: derive_pos,
149150
derive_attr_index,
151+
derive_macro_id,
150152
},
151153
call_site,
152154
);

crates/hir-def/src/nameres/collector.rs

Lines changed: 84 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,58 +3,86 @@
33
//! `DefCollector::collect` contains the fixed-point iteration loop which
44
//! resolves imports and expands macros.
55
6-
use std::{cmp::Ordering, iter, mem, ops::Not};
6+
use std::{iter, mem};
77

8+
use crate::attr::Attrs;
9+
use crate::item_tree::Fields;
10+
use crate::item_tree::FileItemTreeId;
11+
use crate::item_tree::MacroCall;
12+
use crate::item_tree::MacroRules;
13+
use crate::item_tree::Mod;
14+
use crate::item_tree::ModKind;
15+
use crate::macro_call_as_call_id_with_eager;
16+
17+
use crate::nameres::mod_resolution::ModDir;
18+
19+
use crate::item_tree::ItemTree;
820
use base_db::{CrateId, Dependency, FileId};
921
use cfg::{CfgExpr, CfgOptions};
22+
23+
use crate::item_tree::TreeId;
24+
25+
use crate::LocalModuleId;
26+
use crate::{
27+
item_tree::{ExternCrate, ItemTreeId, Macro2, ModItem},
28+
nameres::{
29+
diagnostics::DefDiagnostic, proc_macro::parse_macro_name_and_helper_attrs,
30+
sub_namespace_match, BuiltinShadowMode, DefMap, MacroSubNs, ModuleData, ModuleOrigin,
31+
ResolveMode,
32+
},
33+
path::ModPath,
34+
per_ns::PerNs,
35+
tt,
36+
visibility::Visibility,
37+
AstId, AstIdWithPath, ConstLoc, EnumLoc, EnumVariantLoc, ExternBlockLoc, ExternCrateId,
38+
ExternCrateLoc, FunctionLoc, ImplLoc, Intern, ItemContainerId, Macro2Loc, MacroExpander,
39+
MacroRulesLoc, MacroRulesLocFlags, ModuleDefId, ModuleId, StaticLoc, StructLoc, TraitAliasLoc,
40+
TraitLoc, TypeAliasLoc, UnionLoc, UseLoc,
41+
};
42+
43+
use std::{cmp::Ordering, ops::Not};
44+
1045
use either::Either;
1146
use hir_expand::{
12-
attrs::{Attr, AttrId},
13-
builtin_attr_macro::{find_builtin_attr, BuiltinAttrExpander},
47+
builtin_attr_macro::find_builtin_attr,
1448
builtin_derive_macro::find_builtin_derive,
1549
builtin_fn_macro::find_builtin_macro,
16-
name::{name, AsName, Name},
50+
name::{AsName, Name},
51+
HirFileId, InFile,
52+
};
53+
54+
use itertools::Itertools;
55+
use span::{ErasedFileAstId, FileAstId, Span, SyntaxContextId};
56+
57+
use hir_expand::{
58+
attrs::{Attr, AttrId},
59+
builtin_attr_macro::BuiltinAttrExpander,
60+
name::name,
1761
proc_macro::CustomProcMacroExpander,
18-
ExpandResult, ExpandTo, HirFileId, InFile, MacroCallId, MacroCallKind, MacroCallLoc,
19-
MacroDefId, MacroDefKind,
62+
ExpandResult, ExpandTo, MacroCallId, MacroCallKind, MacroCallLoc, MacroDefId, MacroDefKind,
2063
};
21-
use itertools::{izip, Itertools};
64+
use itertools::izip;
2265
use la_arena::Idx;
2366
use limit::Limit;
2467
use rustc_hash::{FxHashMap, FxHashSet};
25-
use span::{Edition, ErasedFileAstId, FileAstId, Span, SyntaxContextId};
2668
use stdx::always;
2769
use syntax::{ast, SmolStr};
2870
use triomphe::Arc;
2971

3072
use crate::{
31-
attr::Attrs,
3273
db::DefDatabase,
3374
item_scope::{ImportId, ImportOrExternCrate, ImportType, PerNsGlobImports},
34-
item_tree::{
35-
self, ExternCrate, Fields, FileItemTreeId, ImportKind, ItemTree, ItemTreeId, ItemTreeNode,
36-
Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId,
37-
},
38-
macro_call_as_call_id, macro_call_as_call_id_with_eager,
75+
item_tree::{self, ImportKind, ItemTreeNode},
76+
macro_call_as_call_id,
3977
nameres::{
4078
attr_resolution::{attr_macro_as_call_id, derive_macro_as_call_id},
41-
diagnostics::DefDiagnostic,
42-
mod_resolution::ModDir,
4379
path_resolution::ReachedFixedPoint,
44-
proc_macro::{parse_macro_name_and_helper_attrs, ProcMacroDef, ProcMacroKind},
45-
sub_namespace_match, BuiltinShadowMode, DefMap, MacroSubNs, ModuleData, ModuleOrigin,
46-
ResolveMode,
80+
proc_macro::{ProcMacroDef, ProcMacroKind},
4781
},
48-
path::{ImportAlias, ModPath, PathKind},
49-
per_ns::PerNs,
50-
tt,
51-
visibility::{RawVisibility, Visibility},
52-
AdtId, AstId, AstIdWithPath, ConstLoc, CrateRootModuleId, EnumLoc, EnumVariantLoc,
53-
ExternBlockLoc, ExternCrateId, ExternCrateLoc, FunctionId, FunctionLoc, ImplLoc, Intern,
54-
ItemContainerId, LocalModuleId, Lookup, Macro2Id, Macro2Loc, MacroExpander, MacroId,
55-
MacroRulesId, MacroRulesLoc, MacroRulesLocFlags, ModuleDefId, ModuleId, ProcMacroId,
56-
ProcMacroLoc, StaticLoc, StructLoc, TraitAliasLoc, TraitLoc, TypeAliasLoc, UnionLoc,
57-
UnresolvedMacro, UseId, UseLoc,
82+
path::{ImportAlias, PathKind},
83+
visibility::RawVisibility,
84+
AdtId, CrateRootModuleId, FunctionId, Lookup, Macro2Id, MacroId, MacroRulesId, ProcMacroId,
85+
ProcMacroLoc, UnresolvedMacro, UseId,
5886
};
5987

6088
static GLOB_RECURSION_LIMIT: Limit = Limit::new(100);
@@ -237,6 +265,8 @@ enum MacroDirectiveKind {
237265
derive_attr: AttrId,
238266
derive_pos: usize,
239267
ctxt: SyntaxContextId,
268+
/// The "parent" macro it is resolved to.
269+
derive_macro_id: MacroCallId,
240270
},
241271
Attr {
242272
ast_id: AstIdWithPath<ast::Item>,
@@ -1146,7 +1176,13 @@ impl DefCollector<'_> {
11461176
return Resolved::Yes;
11471177
}
11481178
}
1149-
MacroDirectiveKind::Derive { ast_id, derive_attr, derive_pos, ctxt: call_site } => {
1179+
MacroDirectiveKind::Derive {
1180+
ast_id,
1181+
derive_attr,
1182+
derive_pos,
1183+
ctxt: call_site,
1184+
derive_macro_id,
1185+
} => {
11501186
let id = derive_macro_as_call_id(
11511187
self.db,
11521188
ast_id,
@@ -1155,6 +1191,7 @@ impl DefCollector<'_> {
11551191
*call_site,
11561192
self.def_map.krate,
11571193
resolver,
1194+
*derive_macro_id,
11581195
);
11591196

11601197
if let Ok((macro_id, def_id, call_id)) = id {
@@ -1223,7 +1260,9 @@ impl DefCollector<'_> {
12231260
Some(def) if def.is_attribute() => def,
12241261
_ => return Resolved::No,
12251262
};
1226-
1263+
// We will treat derive macros as an attribute as a reference for the input to derives
1264+
let call_id =
1265+
attr_macro_as_call_id(self.db, file_ast_id, attr, self.def_map.krate, def);
12271266
if let MacroDefId {
12281267
kind:
12291268
MacroDefKind::BuiltInAttr(
@@ -1267,6 +1306,7 @@ impl DefCollector<'_> {
12671306
derive_attr: attr.id,
12681307
derive_pos: idx,
12691308
ctxt: call_site.ctx,
1309+
derive_macro_id: call_id,
12701310
},
12711311
container: directive.container,
12721312
});
@@ -1301,10 +1341,6 @@ impl DefCollector<'_> {
13011341
return recollect_without(self);
13021342
}
13031343

1304-
// Not resolved to a derive helper or the derive attribute, so try to treat as a normal attribute.
1305-
let call_id =
1306-
attr_macro_as_call_id(self.db, file_ast_id, attr, self.def_map.krate, def);
1307-
13081344
// Skip #[test]/#[bench] expansion, which would merely result in more memory usage
13091345
// due to duplicating functions into macro expansions
13101346
if matches!(
@@ -1460,13 +1496,20 @@ impl DefCollector<'_> {
14601496
));
14611497
}
14621498
}
1463-
MacroDirectiveKind::Derive { ast_id, derive_attr, derive_pos, ctxt: _ } => {
1499+
MacroDirectiveKind::Derive {
1500+
ast_id,
1501+
derive_attr,
1502+
derive_pos,
1503+
derive_macro_id,
1504+
..
1505+
} => {
14641506
self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call(
14651507
directive.module_id,
14661508
MacroCallKind::Derive {
14671509
ast_id: ast_id.ast_id,
14681510
derive_attr_index: *derive_attr,
14691511
derive_index: *derive_pos as u32,
1512+
derive_macro_id: *derive_macro_id,
14701513
},
14711514
ast_id.path.clone(),
14721515
));
@@ -2289,7 +2332,7 @@ impl ModCollector<'_, '_> {
22892332

22902333
fn collect_macro_call(
22912334
&mut self,
2292-
&MacroCall { ref path, ast_id, expand_to, ctxt }: &MacroCall,
2335+
&MacroCall { ref path, ast_id, expand_to, ctxt, .. }: &MacroCall,
22932336
container: ItemContainerId,
22942337
) {
22952338
let ast_id = AstIdWithPath::new(self.file_id(), ast_id, ModPath::clone(path));
@@ -2428,7 +2471,10 @@ mod tests {
24282471
use base_db::SourceDatabase;
24292472
use test_fixture::WithFixture;
24302473

2431-
use crate::{nameres::DefMapCrateData, test_db::TestDB};
2474+
use crate::{
2475+
nameres::{DefMapCrateData, ModuleData, ModuleOrigin},
2476+
test_db::TestDB,
2477+
};
24322478

24332479
use super::*;
24342480

crates/hir-expand/src/db.rs

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -338,13 +338,33 @@ pub(crate) fn parse_with_map(
338338
}
339339
}
340340
}
341+
/// This is just to ensure the types of smart_macro_arg and macro_arg are the same
342+
type MacroArgResult = (Arc<tt::Subtree>, SyntaxFixupUndoInfo, Span) ;
343+
/// Imagine the word smart in quotes.
344+
///
345+
/// This resolves the [MacroCallId] to check if it is a derive macro if so get the [macro_arg] for the derive.
346+
/// Other wise return the [macro_arg] for the macro_call_id.
347+
///
348+
/// This is not connected to the database so it does not cached the result. However, the inner [macro_arg] query is
349+
///
350+
/// FIXME: Pick a better name
351+
fn smart_macro_arg(db: &dyn ExpandDatabase, id: MacroCallId) -> MacroArgResult {
352+
let loc = db.lookup_intern_macro_call(id);
353+
// FIXME: We called lookup_intern_macro_call twice.
354+
match loc.kind {
355+
// Get the macro arg for the derive macro
356+
MacroCallKind::Derive { derive_macro_id, .. } => db.macro_arg(derive_macro_id),
357+
// Normal macro arg
358+
_ => db.macro_arg(id),
359+
}
360+
}
341361

342-
// FIXME: for derive attributes, this will return separate copies of the same structures! Though
343-
// they may differ in spans due to differing call sites...
344362
fn macro_arg(
345363
db: &dyn ExpandDatabase,
346364
id: MacroCallId,
347-
) -> (Arc<tt::Subtree>, SyntaxFixupUndoInfo, Span) {
365+
// FIXME: consider the following by putting fixup info into eager call info args
366+
// ) -> ValueResult<Arc<(tt::Subtree, SyntaxFixupUndoInfo)>, Arc<Box<[SyntaxError]>>> {
367+
) -> MacroArgResult {
348368
let loc = db.lookup_intern_macro_call(id);
349369

350370
if let MacroCallLoc {
@@ -526,7 +546,8 @@ fn macro_expand(
526546
let (ExpandResult { value: tt, err }, span) = match loc.def.kind {
527547
MacroDefKind::ProcMacro(..) => return db.expand_proc_macro(macro_call_id).map(CowArc::Arc),
528548
_ => {
529-
let (macro_arg, undo_info, span) = db.macro_arg(macro_call_id);
549+
let (macro_arg, undo_info, span) =
550+
smart_macro_arg(db, macro_call_id);
530551

531552
let arg = &*macro_arg;
532553
let res =
@@ -603,7 +624,7 @@ fn proc_macro_span(db: &dyn ExpandDatabase, ast: AstId<ast::Fn>) -> Span {
603624

604625
fn expand_proc_macro(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<Arc<tt::Subtree>> {
605626
let loc = db.lookup_intern_macro_call(id);
606-
let (macro_arg, undo_info, span) = db.macro_arg(id);
627+
let (macro_arg, undo_info, span) = smart_macro_arg(db, id);
607628

608629
let (expander, ast) = match loc.def.kind {
609630
MacroDefKind::ProcMacro(expander, _, ast) => (expander, ast),

crates/hir-expand/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,9 @@ pub enum MacroCallKind {
224224
derive_attr_index: AttrId,
225225
/// Index of the derive macro in the derive attribute
226226
derive_index: u32,
227+
/// The "parent" macro call.
228+
/// We will resolve the same token tree for all derive macros in the same derive attribute.
229+
derive_macro_id: MacroCallId,
227230
},
228231
Attr {
229232
ast_id: AstId<ast::Item>,

crates/hir/src/lib.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -972,7 +972,8 @@ fn precise_macro_call_location(
972972
MacroKind::ProcMacro,
973973
)
974974
}
975-
MacroCallKind::Derive { ast_id, derive_attr_index, derive_index } => {
975+
// TODO: derive_macro_id
976+
MacroCallKind::Derive { ast_id, derive_attr_index, derive_index, derive_macro_id } => {
976977
let node = ast_id.to_node(db.upcast());
977978
// Compute the precise location of the macro name's token in the derive
978979
// list.
@@ -3709,7 +3710,8 @@ impl Impl {
37093710
let macro_file = src.file_id.macro_file()?;
37103711
let loc = macro_file.macro_call_id.lookup(db.upcast());
37113712
let (derive_attr, derive_index) = match loc.kind {
3712-
MacroCallKind::Derive { ast_id, derive_attr_index, derive_index } => {
3713+
// TODO: derive_macro_id
3714+
MacroCallKind::Derive { ast_id, derive_attr_index, derive_index, derive_macro_id } => {
37133715
let module_id = self.id.lookup(db.upcast()).container;
37143716
(
37153717
db.crate_def_map(module_id.krate())[module_id.local_id]

0 commit comments

Comments
 (0)