@@ -18,7 +18,7 @@ use hir_expand::{
18
18
ExpandTo , HirFileId , InFile , MacroCallId , MacroCallKind , MacroCallLoc , MacroDefId ,
19
19
MacroDefKind ,
20
20
} ;
21
- use itertools:: Itertools ;
21
+ use itertools:: { izip , Itertools } ;
22
22
use la_arena:: Idx ;
23
23
use limit:: Limit ;
24
24
use rustc_hash:: { FxHashMap , FxHashSet } ;
@@ -110,7 +110,6 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: DefMap, tree_id: T
110
110
proc_macros,
111
111
from_glob_import : Default :: default ( ) ,
112
112
skip_attrs : Default :: default ( ) ,
113
- derive_helpers_in_scope : Default :: default ( ) ,
114
113
is_proc_macro,
115
114
} ;
116
115
if tree_id. is_block ( ) {
@@ -258,9 +257,6 @@ struct DefCollector<'a> {
258
257
/// This also stores the attributes to skip when we resolve derive helpers and non-macro
259
258
/// non-builtin attributes in general.
260
259
skip_attrs : FxHashMap < InFile < ModItem > , AttrId > ,
261
- /// Tracks which custom derives are in scope for an item, to allow resolution of derive helper
262
- /// attributes.
263
- derive_helpers_in_scope : FxHashMap < AstId < ast:: Item > , Vec < Name > > ,
264
260
}
265
261
266
262
impl DefCollector < ' _ > {
@@ -1059,16 +1055,20 @@ impl DefCollector<'_> {
1059
1055
} ;
1060
1056
let mut res = ReachedFixedPoint :: Yes ;
1061
1057
macros. retain ( |directive| {
1062
- let resolver = |path| {
1058
+ let resolver2 = |path| {
1063
1059
let resolved_res = self . def_map . resolve_path_fp_with_macro (
1064
1060
self . db ,
1065
1061
ResolveMode :: Other ,
1066
1062
directive. module_id ,
1067
1063
& path,
1068
1064
BuiltinShadowMode :: Module ,
1069
1065
) ;
1070
- resolved_res. resolved_def . take_macros ( ) . map ( |it| macro_id_to_def_id ( self . db , it) )
1066
+ resolved_res
1067
+ . resolved_def
1068
+ . take_macros ( )
1069
+ . map ( |it| ( it, macro_id_to_def_id ( self . db , it) ) )
1071
1070
} ;
1071
+ let resolver = |path| resolver2 ( path) . map ( |( _, it) | it) ;
1072
1072
1073
1073
match & directive. kind {
1074
1074
MacroDirectiveKind :: FnLike { ast_id, expand_to } => {
@@ -1087,21 +1087,37 @@ impl DefCollector<'_> {
1087
1087
}
1088
1088
}
1089
1089
MacroDirectiveKind :: Derive { ast_id, derive_attr, derive_pos } => {
1090
- let call_id = derive_macro_as_call_id (
1090
+ let id = derive_macro_as_call_id (
1091
1091
self . db ,
1092
1092
ast_id,
1093
1093
* derive_attr,
1094
1094
* derive_pos as u32 ,
1095
1095
self . def_map . krate ,
1096
- & resolver ,
1096
+ & resolver2 ,
1097
1097
) ;
1098
- if let Ok ( call_id) = call_id {
1098
+
1099
+ if let Ok ( ( macro_id, def_id, call_id) ) = id {
1099
1100
self . def_map . modules [ directive. module_id ] . scope . set_derive_macro_invoc (
1100
1101
ast_id. ast_id ,
1101
1102
call_id,
1102
1103
* derive_attr,
1103
1104
* derive_pos,
1104
1105
) ;
1106
+ // Record its helper attributes.
1107
+ if def_id. krate != self . def_map . krate {
1108
+ let def_map = self . db . crate_def_map ( def_id. krate ) ;
1109
+ if let Some ( helpers) = def_map. exported_derives . get ( & def_id) {
1110
+ self . def_map
1111
+ . derive_helpers_in_scope
1112
+ . entry ( ast_id. ast_id . map ( |it| it. upcast ( ) ) )
1113
+ . or_default ( )
1114
+ . extend ( izip ! (
1115
+ helpers. iter( ) . cloned( ) ,
1116
+ iter:: repeat( macro_id) ,
1117
+ iter:: repeat( call_id) ,
1118
+ ) ) ;
1119
+ }
1120
+ }
1105
1121
1106
1122
push_resolved ( directive, call_id) ;
1107
1123
res = ReachedFixedPoint :: No ;
@@ -1132,8 +1148,8 @@ impl DefCollector<'_> {
1132
1148
} ;
1133
1149
1134
1150
if let Some ( ident) = path. as_ident ( ) {
1135
- if let Some ( helpers) = self . derive_helpers_in_scope . get ( & ast_id) {
1136
- if helpers. contains ( ident) {
1151
+ if let Some ( helpers) = self . def_map . derive_helpers_in_scope . get ( & ast_id) {
1152
+ if helpers. iter ( ) . any ( | ( it , .. ) | it == ident) {
1137
1153
cov_mark:: hit!( resolved_derive_helper) ;
1138
1154
// Resolved to derive helper. Collect the item's attributes again,
1139
1155
// starting after the derive helper.
@@ -1148,7 +1164,7 @@ impl DefCollector<'_> {
1148
1164
} ;
1149
1165
if matches ! (
1150
1166
def,
1151
- MacroDefId { kind: MacroDefKind :: BuiltInAttr ( expander, _) , .. }
1167
+ MacroDefId { kind: MacroDefKind :: BuiltInAttr ( expander, _) , .. }
1152
1168
if expander. is_derive( )
1153
1169
) {
1154
1170
// Resolved to `#[derive]`
@@ -1317,19 +1333,6 @@ impl DefCollector<'_> {
1317
1333
self . def_map . diagnostics . push ( diag) ;
1318
1334
}
1319
1335
1320
- // If we've just resolved a derive, record its helper attributes.
1321
- if let MacroCallKind :: Derive { ast_id, .. } = & loc. kind {
1322
- if loc. def . krate != self . def_map . krate {
1323
- let def_map = self . db . crate_def_map ( loc. def . krate ) ;
1324
- if let Some ( helpers) = def_map. exported_derives . get ( & loc. def ) {
1325
- self . derive_helpers_in_scope
1326
- . entry ( ast_id. map ( |it| it. upcast ( ) ) )
1327
- . or_default ( )
1328
- . extend ( helpers. iter ( ) . cloned ( ) ) ;
1329
- }
1330
- }
1331
- }
1332
-
1333
1336
// Then, fetch and process the item tree. This will reuse the expansion result from above.
1334
1337
let item_tree = self . db . file_item_tree ( file_id) ;
1335
1338
let mod_dir = self . mod_dirs [ & module_id] . clone ( ) ;
@@ -2140,7 +2143,6 @@ mod tests {
2140
2143
proc_macros : Default :: default ( ) ,
2141
2144
from_glob_import : Default :: default ( ) ,
2142
2145
skip_attrs : Default :: default ( ) ,
2143
- derive_helpers_in_scope : Default :: default ( ) ,
2144
2146
is_proc_macro : false ,
2145
2147
} ;
2146
2148
collector. seed_with_top_level ( ) ;
0 commit comments