Skip to content

Commit 55f3297

Browse files
bors[bot]Veykril
andauthored
Merge #11156
11156: internal: Record unresolved derive invocations in hir r=Veykril a=Veykril Co-authored-by: Lukas Wirth <[email protected]>
2 parents 0e5d888 + 44d6176 commit 55f3297

File tree

7 files changed

+55
-28
lines changed

7 files changed

+55
-28
lines changed

crates/hir/src/semantics.rs

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use hir_def::{
1010
resolver::{self, HasResolver, Resolver, TypeNs},
1111
AsMacroCall, FunctionId, TraitId, VariantId,
1212
};
13-
use hir_expand::{name::AsName, ExpansionInfo, MacroCallId, MacroCallLoc};
13+
use hir_expand::{name::AsName, ExpansionInfo, MacroCallId};
1414
use hir_ty::{associated_type_shorthand_candidates, Interner};
1515
use itertools::Itertools;
1616
use rustc_hash::{FxHashMap, FxHashSet};
@@ -160,7 +160,7 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
160160
self.imp.expand_attr_macro(item)
161161
}
162162

163-
pub fn resolve_derive_macro(&self, derive: &ast::Attr) -> Option<Vec<MacroDef>> {
163+
pub fn resolve_derive_macro(&self, derive: &ast::Attr) -> Option<Vec<Option<MacroDef>>> {
164164
self.imp.resolve_derive_macro(derive)
165165
}
166166

@@ -447,24 +447,21 @@ impl<'db> SemanticsImpl<'db> {
447447
Some(node)
448448
}
449449

450-
fn resolve_derive_macro(&self, attr: &ast::Attr) -> Option<Vec<MacroDef>> {
450+
fn resolve_derive_macro(&self, attr: &ast::Attr) -> Option<Vec<Option<MacroDef>>> {
451451
let res = self
452452
.derive_macro_calls(attr)?
453-
.iter()
454-
.map(|&call| {
455-
let loc: MacroCallLoc = self.db.lookup_intern_macro_call(call);
456-
MacroDef { id: loc.def }
457-
})
453+
.into_iter()
454+
.map(|call| Some(MacroDef { id: self.db.lookup_intern_macro_call(call?).def }))
458455
.collect();
459456
Some(res)
460457
}
461458

462459
fn expand_derive_macro(&self, attr: &ast::Attr) -> Option<Vec<SyntaxNode>> {
463460
let res: Vec<_> = self
464461
.derive_macro_calls(attr)?
465-
.iter()
466-
.map(|call| call.as_file())
467-
.flat_map(|file_id| {
462+
.into_iter()
463+
.flat_map(|call| {
464+
let file_id = call?.as_file();
468465
let node = self.db.parse_or_expand(file_id)?;
469466
self.cache(node.clone(), file_id);
470467
Some(node)
@@ -473,7 +470,7 @@ impl<'db> SemanticsImpl<'db> {
473470
Some(res)
474471
}
475472

476-
fn derive_macro_calls(&self, attr: &ast::Attr) -> Option<Vec<MacroCallId>> {
473+
fn derive_macro_calls(&self, attr: &ast::Attr) -> Option<Vec<Option<MacroCallId>>> {
477474
let item = attr.syntax().parent().and_then(ast::Item::cast)?;
478475
let file_id = self.find_file(item.syntax()).file_id;
479476
let item = InFile::new(file_id, &item);

crates/hir/src/semantics/source_to_def.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ impl SourceToDefCtx<'_, '_> {
248248
&mut self,
249249
item: InFile<&ast::Item>,
250250
src: InFile<ast::Attr>,
251-
) -> Option<&[MacroCallId]> {
251+
) -> Option<&[Option<MacroCallId>]> {
252252
let map = self.dyn_map(item)?;
253253
map[keys::DERIVE_MACRO].get(&src).map(AsRef::as_ref)
254254
}

crates/hir_def/src/child_by_source.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
77
use either::Either;
88
use hir_expand::HirFileId;
9-
use itertools::Itertools;
109
use syntax::ast::HasAttrs;
1110

1211
use crate::{
@@ -123,8 +122,7 @@ impl ChildBySource for ItemScope {
123122
});
124123
self.derive_macro_invocs().for_each(|(ast_id, calls)| {
125124
let item = ast_id.to_node(db.upcast());
126-
let grouped = calls.iter().copied().into_group_map();
127-
for (attr_id, calls) in grouped {
125+
for (attr_id, calls) in calls {
128126
if let Some(attr) = item.attrs().nth(attr_id.ast_index as usize) {
129127
res[keys::DERIVE_MACRO].insert(ast_id.with_value(attr), calls.into());
130128
}

crates/hir_def/src/item_scope.rs

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use hir_expand::{name::Name, AstId, MacroCallId, MacroDefKind};
88
use once_cell::sync::Lazy;
99
use profile::Count;
1010
use rustc_hash::{FxHashMap, FxHashSet};
11-
use smallvec::SmallVec;
11+
use smallvec::{smallvec, SmallVec};
1212
use stdx::format_to;
1313
use syntax::ast;
1414

@@ -64,7 +64,10 @@ pub struct ItemScope {
6464
// be all resolved to the last one defined if shadowing happens.
6565
legacy_macros: FxHashMap<Name, MacroDefId>,
6666
attr_macros: FxHashMap<AstId<ast::Item>, MacroCallId>,
67-
derive_macros: FxHashMap<AstId<ast::Item>, SmallVec<[(AttrId, MacroCallId); 1]>>,
67+
/// The derive macro invocations in this scope, keyed by the owner item over the actual derive attributes
68+
/// paired with the derive macro invocations for the specific attribute.
69+
derive_macros:
70+
FxHashMap<AstId<ast::Item>, SmallVec<[(AttrId, SmallVec<[Option<MacroCallId>; 1]>); 1]>>,
6871
}
6972

7073
pub(crate) static BUILTIN_SCOPE: Lazy<FxHashMap<Name, PerNs>> = Lazy::new(|| {
@@ -199,19 +202,40 @@ impl ItemScope {
199202
self.attr_macros.iter().map(|(k, v)| (*k, *v))
200203
}
201204

202-
pub(crate) fn add_derive_macro_invoc(
205+
pub(crate) fn set_derive_macro_invoc(
203206
&mut self,
204207
item: AstId<ast::Item>,
205208
call: MacroCallId,
206209
attr_id: AttrId,
210+
idx: usize,
207211
) {
208-
self.derive_macros.entry(item).or_default().push((attr_id, call));
212+
if let Some(derives) = self.derive_macros.get_mut(&item) {
213+
if let Some((_, invocs)) = derives.iter_mut().find(|&&mut (id, _)| id == attr_id) {
214+
invocs[idx] = Some(call);
215+
}
216+
}
217+
}
218+
219+
/// We are required to set this up front as derive invocation recording happens out of order
220+
/// due to the fixed pointer iteration loop being able to record some derives later than others
221+
/// independent of their indices.
222+
pub(crate) fn init_derive_attribute(
223+
&mut self,
224+
item: AstId<ast::Item>,
225+
attr_id: AttrId,
226+
len: usize,
227+
) {
228+
self.derive_macros.entry(item).or_default().push((attr_id, smallvec![None; len]));
209229
}
210230

211231
pub(crate) fn derive_macro_invocs(
212232
&self,
213-
) -> impl Iterator<Item = (AstId<ast::Item>, &[(AttrId, MacroCallId)])> + '_ {
214-
self.derive_macros.iter().map(|(k, v)| (*k, v.as_ref()))
233+
) -> impl Iterator<
234+
Item = (AstId<ast::Item>, impl Iterator<Item = (AttrId, &[Option<MacroCallId>])>),
235+
> + '_ {
236+
self.derive_macros
237+
.iter()
238+
.map(|(k, v)| (*k, v.iter().map(|(attr_id, invocs)| (*attr_id, &**invocs))))
215239
}
216240

217241
pub(crate) fn unnamed_trait_vis(&self, tr: TraitId) -> Option<Visibility> {

crates/hir_def/src/keys.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ pub const CONST_PARAM: Key<ast::ConstParam, ConstParamId> = Key::new();
3333

3434
pub const MACRO: Key<ast::Macro, MacroDefId> = Key::new();
3535
pub const ATTR_MACRO: Key<ast::Item, MacroCallId> = Key::new();
36-
pub const DERIVE_MACRO: Key<ast::Attr, Box<[MacroCallId]>> = Key::new();
36+
pub const DERIVE_MACRO: Key<ast::Attr, Box<[Option<MacroCallId>]>> = Key::new();
3737

3838
/// XXX: AST Nodes and SyntaxNodes have identity equality semantics: nodes are
3939
/// equal if they point to exactly the same object.

crates/hir_def/src/nameres/collector.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ struct MacroDirective {
219219
#[derive(Clone, Debug, Eq, PartialEq)]
220220
enum MacroDirectiveKind {
221221
FnLike { ast_id: AstIdWithPath<ast::MacroCall>, expand_to: ExpandTo },
222-
Derive { ast_id: AstIdWithPath<ast::Item>, derive_attr: AttrId },
222+
Derive { ast_id: AstIdWithPath<ast::Item>, derive_attr: AttrId, derive_pos: usize },
223223
Attr { ast_id: AstIdWithPath<ast::Item>, attr: Attr, mod_item: ModItem, tree: TreeId },
224224
}
225225

@@ -1064,7 +1064,7 @@ impl DefCollector<'_> {
10641064
return false;
10651065
}
10661066
}
1067-
MacroDirectiveKind::Derive { ast_id, derive_attr } => {
1067+
MacroDirectiveKind::Derive { ast_id, derive_attr, derive_pos } => {
10681068
let call_id = derive_macro_as_call_id(
10691069
ast_id,
10701070
*derive_attr,
@@ -1073,10 +1073,11 @@ impl DefCollector<'_> {
10731073
&resolver,
10741074
);
10751075
if let Ok(call_id) = call_id {
1076-
self.def_map.modules[directive.module_id].scope.add_derive_macro_invoc(
1076+
self.def_map.modules[directive.module_id].scope.set_derive_macro_invoc(
10771077
ast_id.ast_id,
10781078
call_id,
10791079
*derive_attr,
1080+
*derive_pos,
10801081
);
10811082

10821083
resolved.push((
@@ -1146,18 +1147,25 @@ impl DefCollector<'_> {
11461147

11471148
match attr.parse_derive() {
11481149
Some(derive_macros) => {
1149-
for path in derive_macros {
1150+
let mut len = 0;
1151+
for (idx, path) in derive_macros.enumerate() {
11501152
let ast_id = AstIdWithPath::new(file_id, ast_id.value, path);
11511153
self.unresolved_macros.push(MacroDirective {
11521154
module_id: directive.module_id,
11531155
depth: directive.depth + 1,
11541156
kind: MacroDirectiveKind::Derive {
11551157
ast_id,
11561158
derive_attr: attr.id,
1159+
derive_pos: idx,
11571160
},
11581161
container: directive.container,
11591162
});
1163+
len = idx;
11601164
}
1165+
1166+
self.def_map.modules[directive.module_id]
1167+
.scope
1168+
.init_derive_attribute(ast_id, attr.id, len + 1);
11611169
}
11621170
None => {
11631171
let diag = DefDiagnostic::malformed_derive(

crates/ide_completion/src/completions/attribute/derive.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use crate::{
1616
pub(super) fn complete_derive(acc: &mut Completions, ctx: &CompletionContext, attr: &ast::Attr) {
1717
let core = ctx.famous_defs().core();
1818
let existing_derives: FxHashSet<_> =
19-
ctx.sema.resolve_derive_macro(attr).into_iter().flatten().collect();
19+
ctx.sema.resolve_derive_macro(attr).into_iter().flatten().flatten().collect();
2020

2121
for (name, mac) in get_derives_in_scope(ctx) {
2222
if existing_derives.contains(&mac) {

0 commit comments

Comments
 (0)