Skip to content

Commit e09d309

Browse files
committed
Move enum variant collection from defmap to separate query
1 parent 6ff5188 commit e09d309

File tree

8 files changed

+113
-112
lines changed

8 files changed

+113
-112
lines changed

crates/hir-def/src/db.rs

+12-3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use intern::sym;
66
use la_arena::ArenaMap;
77
use span::{EditionedFileId, MacroCallId};
88
use syntax::{AstPtr, ast};
9+
use thin_vec::ThinVec;
910
use triomphe::Arc;
1011

1112
use crate::{
@@ -30,8 +31,8 @@ use crate::{
3031
},
3132
signatures::{
3233
ConstSignature, EnumSignature, EnumVariants, FunctionSignature, ImplSignature,
33-
StaticSignature, StructSignature, TraitAliasSignature, TraitSignature, TypeAliasSignature,
34-
UnionSignature, VariantFields,
34+
InactiveEnumVariantCode, StaticSignature, StructSignature, TraitAliasSignature,
35+
TraitSignature, TypeAliasSignature, UnionSignature, VariantFields,
3536
},
3637
tt,
3738
visibility::{self, Visibility},
@@ -141,8 +142,16 @@ pub trait DefDatabase:
141142
id: VariantId,
142143
) -> (Arc<VariantFields>, Arc<ExpressionStoreSourceMap>);
143144

145+
#[salsa::tracked]
146+
fn enum_variants(&self, id: EnumId) -> Arc<EnumVariants> {
147+
self.enum_variants_with_diagnostics(id).0
148+
}
149+
144150
#[salsa::invoke_actual(EnumVariants::enum_variants_query)]
145-
fn enum_variants(&self, id: EnumId) -> Arc<EnumVariants>;
151+
fn enum_variants_with_diagnostics(
152+
&self,
153+
id: EnumId,
154+
) -> (Arc<EnumVariants>, Arc<ThinVec<InactiveEnumVariantCode>>);
146155

147156
#[salsa::transparent]
148157
#[salsa::invoke_actual(ImplItems::impl_items_query)]

crates/hir-def/src/lang_item.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ impl LangItems {
140140
}
141141
ModuleDefId::AdtId(AdtId::EnumId(e)) => {
142142
lang_items.collect_lang_item(db, e, LangItemTarget::EnumId);
143-
crate_def_map.enum_definitions[&e].iter().for_each(|&id| {
143+
db.enum_variants(e).variants.iter().for_each(|&(id, _)| {
144144
lang_items.collect_lang_item(db, id, LangItemTarget::EnumVariant);
145145
});
146146
}

crates/hir-def/src/nameres.rs

+2-6
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,8 @@ use triomphe::Arc;
7676
use tt::TextRange;
7777

7878
use crate::{
79-
AstId, BlockId, BlockLoc, CrateRootModuleId, EnumId, EnumVariantId, ExternCrateId, FunctionId,
80-
FxIndexMap, LocalModuleId, Lookup, MacroExpander, MacroId, ModuleId, ProcMacroId, UseId,
79+
AstId, BlockId, BlockLoc, CrateRootModuleId, ExternCrateId, FunctionId, FxIndexMap,
80+
LocalModuleId, Lookup, MacroExpander, MacroId, ModuleId, ProcMacroId, UseId,
8181
db::DefDatabase,
8282
item_scope::{BuiltinShadowMode, ItemScope},
8383
item_tree::{ItemTreeId, Mod, TreeId},
@@ -158,7 +158,6 @@ pub struct DefMap {
158158
/// this contains all kinds of macro, not just `macro_rules!` macro.
159159
/// ExternCrateId being None implies it being imported from the general prelude import.
160160
macro_use_prelude: FxHashMap<Name, (MacroId, Option<ExternCrateId>)>,
161-
pub(crate) enum_definitions: FxHashMap<EnumId, Box<[EnumVariantId]>>,
162161

163162
// FIXME: AstId's are fairly unstable
164163
/// Tracks which custom derives are in scope for an item, to allow resolution of derive helper
@@ -458,7 +457,6 @@ impl DefMap {
458457
macro_use_prelude: FxHashMap::default(),
459458
derive_helpers_in_scope: FxHashMap::default(),
460459
diagnostics: Vec::new(),
461-
enum_definitions: FxHashMap::default(),
462460
data: crate_data,
463461
macro_def_to_macro_id: FxHashMap::default(),
464462
}
@@ -474,7 +472,6 @@ impl DefMap {
474472
krate: _,
475473
prelude: _,
476474
data: _,
477-
enum_definitions,
478475
macro_def_to_macro_id,
479476
} = self;
480477

@@ -483,7 +480,6 @@ impl DefMap {
483480
diagnostics.shrink_to_fit();
484481
modules.shrink_to_fit();
485482
derive_helpers_in_scope.shrink_to_fit();
486-
enum_definitions.shrink_to_fit();
487483
for (_, module) in modules.iter_mut() {
488484
module.children.shrink_to_fit();
489485
module.scope.shrink_to_fit();

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

+15-60
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,11 @@ use syntax::ast;
2626
use triomphe::Arc;
2727

2828
use crate::{
29-
AdtId, AstId, AstIdWithPath, ConstLoc, CrateRootModuleId, EnumLoc, EnumVariantLoc,
30-
ExternBlockLoc, ExternCrateId, ExternCrateLoc, FunctionId, FunctionLoc, ImplLoc, Intern,
31-
ItemContainerId, LocalModuleId, Lookup, Macro2Id, Macro2Loc, MacroExpander, MacroId,
32-
MacroRulesId, MacroRulesLoc, MacroRulesLocFlags, ModuleDefId, ModuleId, ProcMacroId,
33-
ProcMacroLoc, StaticLoc, StructLoc, TraitAliasLoc, TraitLoc, TypeAliasLoc, UnionLoc,
34-
UnresolvedMacro, UseId, UseLoc,
29+
AdtId, AstId, AstIdWithPath, ConstLoc, CrateRootModuleId, EnumLoc, ExternBlockLoc,
30+
ExternCrateId, ExternCrateLoc, FunctionId, FunctionLoc, ImplLoc, Intern, ItemContainerId,
31+
LocalModuleId, Lookup, Macro2Id, Macro2Loc, MacroExpander, MacroId, MacroRulesId,
32+
MacroRulesLoc, MacroRulesLocFlags, ModuleDefId, ModuleId, ProcMacroId, ProcMacroLoc, StaticLoc,
33+
StructLoc, TraitAliasLoc, TraitLoc, TypeAliasLoc, UnionLoc, UnresolvedMacro, UseId, UseLoc,
3534
attr::Attrs,
3635
db::DefDatabase,
3736
item_scope::{GlobId, ImportId, ImportOrExternCrate, PerNsGlobImports},
@@ -971,27 +970,16 @@ impl DefCollector<'_> {
971970
Some(ModuleDefId::AdtId(AdtId::EnumId(e))) => {
972971
cov_mark::hit!(glob_enum);
973972
// glob import from enum => just import all the variants
974-
975-
// We need to check if the def map the enum is from is us, if it is we can't
976-
// call the def-map query since we are currently constructing it!
977-
let loc = e.lookup(self.db);
978-
let tree = loc.id.item_tree(self.db);
979-
let current_def_map = self.def_map.krate == loc.container.krate
980-
&& self.def_map.block_id() == loc.container.block;
981-
let def_map;
982-
let resolutions = if current_def_map {
983-
&self.def_map.enum_definitions[&e]
984-
} else {
985-
def_map = loc.container.def_map(self.db);
986-
&def_map.enum_definitions[&e]
987-
}
988-
.iter()
989-
.map(|&variant| {
990-
let name = tree[variant.lookup(self.db).id.value].name.clone();
991-
let res = PerNs::both(variant.into(), variant.into(), vis, None);
992-
(Some(name), res)
993-
})
994-
.collect::<Vec<_>>();
973+
let resolutions = self
974+
.db
975+
.enum_variants(e)
976+
.variants
977+
.iter()
978+
.map(|&(variant, ref name)| {
979+
let res = PerNs::both(variant.into(), variant.into(), vis, None);
980+
(Some(name.clone()), res)
981+
})
982+
.collect::<Vec<_>>();
995983
self.update(
996984
module_id,
997985
&resolutions,
@@ -1894,39 +1882,6 @@ impl ModCollector<'_, '_> {
18941882

18951883
let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]);
18961884
update_def(self.def_collector, enum_.into(), &it.name, vis, false);
1897-
1898-
let mut index = 0;
1899-
let variants = FileItemTreeId::range_iter(it.variants.clone())
1900-
.filter_map(|variant| {
1901-
let is_enabled = self
1902-
.item_tree
1903-
.attrs(db, krate, variant.into())
1904-
.cfg()
1905-
.and_then(|cfg| self.is_cfg_enabled(&cfg).not().then_some(cfg))
1906-
.map_or(Ok(()), Err);
1907-
match is_enabled {
1908-
Err(cfg) => {
1909-
self.emit_unconfigured_diagnostic(
1910-
self.tree_id,
1911-
variant.into(),
1912-
&cfg,
1913-
);
1914-
None
1915-
}
1916-
Ok(()) => Some({
1917-
let loc = EnumVariantLoc {
1918-
id: ItemTreeId::new(self.tree_id, variant),
1919-
parent: enum_,
1920-
index,
1921-
}
1922-
.intern(db);
1923-
index += 1;
1924-
loc
1925-
}),
1926-
}
1927-
})
1928-
.collect();
1929-
self.def_collector.def_map.enum_definitions.insert(enum_, variants);
19301885
}
19311886
ModItem::Const(id) => {
19321887
let it = &self.item_tree[id];

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

+17-26
Original file line numberDiff line numberDiff line change
@@ -509,33 +509,24 @@ impl DefMap {
509509
ModuleDefId::AdtId(AdtId::EnumId(e)) => {
510510
// enum variant
511511
cov_mark::hit!(can_import_enum_variant);
512-
let def_map;
513512

514-
let loc = e.lookup(db);
515-
let tree = loc.id.item_tree(db);
516-
let current_def_map =
517-
self.krate == loc.container.krate && self.block_id() == loc.container.block;
518-
let res = if current_def_map {
519-
&self.enum_definitions[&e]
520-
} else {
521-
def_map = loc.container.def_map(db);
522-
&def_map.enum_definitions[&e]
523-
}
524-
.iter()
525-
.find_map(|&variant| {
526-
let variant_data = &tree[variant.lookup(db).id.value];
527-
(variant_data.name == *segment).then(|| match variant_data.shape {
528-
FieldsShape::Record => {
529-
PerNs::types(variant.into(), Visibility::Public, None)
530-
}
531-
FieldsShape::Tuple | FieldsShape::Unit => PerNs::both(
532-
variant.into(),
533-
variant.into(),
534-
Visibility::Public,
535-
None,
536-
),
537-
})
538-
});
513+
let res =
514+
db.enum_variants(e).variants.iter().find(|(_, name)| name == segment).map(
515+
|&(variant, _)| {
516+
let item_tree_id = variant.lookup(db).id;
517+
match item_tree_id.item_tree(db)[item_tree_id.value].shape {
518+
FieldsShape::Record => {
519+
PerNs::types(variant.into(), Visibility::Public, None)
520+
}
521+
FieldsShape::Tuple | FieldsShape::Unit => PerNs::both(
522+
variant.into(),
523+
variant.into(),
524+
Visibility::Public,
525+
None,
526+
),
527+
}
528+
},
529+
);
539530
// FIXME: Need to filter visibility here and below? Not sure.
540531
return match res {
541532
Some(res) => {

crates/hir-def/src/signatures.rs

+46-12
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,22 @@
11
//! Item signature IR definitions
22
33
use bitflags::bitflags;
4+
use cfg::{CfgExpr, CfgOptions};
45
use either::Either;
5-
use hir_expand::{InFile, Lookup, name::Name};
6+
use hir_expand::{InFile, Intern, Lookup, name::Name};
67
use intern::{Symbol, sym};
78
use la_arena::{Arena, Idx};
89
use rustc_abi::{IntegerType, ReprOptions};
910
use syntax::{
1011
AstNode, SyntaxNodePtr,
1112
ast::{self, HasGenericParams, IsString},
1213
};
14+
use thin_vec::ThinVec;
1315
use triomphe::Arc;
1416

1517
use crate::{
16-
ConstId, EnumId, EnumVariantId, FunctionId, HasModule, ImplId, ItemContainerId, ModuleId,
17-
StaticId, StructId, TraitAliasId, TraitId, TypeAliasId, UnionId, VariantId,
18+
ConstId, EnumId, EnumVariantId, EnumVariantLoc, FunctionId, HasModule, ImplId, ItemContainerId,
19+
ModuleId, StaticId, StructId, TraitAliasId, TraitId, TypeAliasId, UnionId, VariantId,
1820
db::DefDatabase,
1921
expr_store::{
2022
ExpressionStore, ExpressionStoreSourceMap,
@@ -25,8 +27,8 @@ use crate::{
2527
},
2628
hir::{ExprId, PatId, generics::GenericParams},
2729
item_tree::{
28-
AttrOwner, Field, FieldParent, FieldsShape, ItemTree, ModItem, RawVisibility,
29-
RawVisibilityId,
30+
AttrOwner, Field, FieldParent, FieldsShape, FileItemTreeId, ItemTree, ItemTreeId, ModItem,
31+
RawVisibility, RawVisibilityId,
3032
},
3133
lang_item::LangItem,
3234
src::HasSource,
@@ -889,21 +891,53 @@ fn lower_fields<'a>(
889891
(arena, store, col.source_map)
890892
}
891893

894+
#[derive(Debug, PartialEq, Eq)]
895+
pub struct InactiveEnumVariantCode {
896+
pub cfg: CfgExpr,
897+
pub opts: CfgOptions,
898+
pub ast_id: span::FileAstId<ast::Variant>,
899+
}
900+
892901
#[derive(Debug, Clone, PartialEq, Eq)]
893902
pub struct EnumVariants {
894903
pub variants: Box<[(EnumVariantId, Name)]>,
895904
}
905+
896906
impl EnumVariants {
897-
pub(crate) fn enum_variants_query(db: &dyn DefDatabase, e: EnumId) -> Arc<EnumVariants> {
907+
pub(crate) fn enum_variants_query(
908+
db: &dyn DefDatabase,
909+
e: EnumId,
910+
) -> (Arc<EnumVariants>, Arc<ThinVec<InactiveEnumVariantCode>>) {
898911
let loc = e.lookup(db);
899912
let item_tree = loc.id.item_tree(db);
900913

901-
Arc::new(EnumVariants {
902-
variants: loc.container.def_map(db).enum_definitions[&e]
903-
.iter()
904-
.map(|&id| (id, item_tree[id.lookup(db).id.value].name.clone()))
905-
.collect(),
906-
})
914+
let mut diagnostics = ThinVec::new();
915+
let cfg_options = loc.container.krate.cfg_options(db);
916+
let mut index = 0;
917+
let variants = FileItemTreeId::range_iter(item_tree[loc.id.value].variants.clone())
918+
.filter_map(|variant| {
919+
let attrs = item_tree.attrs(db, loc.container.krate, variant.into());
920+
if attrs.is_cfg_enabled(cfg_options) {
921+
let enum_variant = EnumVariantLoc {
922+
id: ItemTreeId::new(loc.id.tree_id(), variant),
923+
parent: e,
924+
index,
925+
}
926+
.intern(db);
927+
index += 1;
928+
Some((enum_variant, item_tree[variant].name.clone()))
929+
} else {
930+
diagnostics.push(InactiveEnumVariantCode {
931+
ast_id: item_tree[variant].ast_id,
932+
cfg: attrs.cfg().unwrap(),
933+
opts: cfg_options.clone(),
934+
});
935+
None
936+
}
937+
})
938+
.collect();
939+
940+
(Arc::new(EnumVariants { variants }), Arc::new(diagnostics))
907941
}
908942

909943
pub fn variant(&self, name: &Name) -> Option<EnumVariantId> {

crates/hir/src/lib.rs

+19-3
Original file line numberDiff line numberDiff line change
@@ -677,12 +677,28 @@ impl Module {
677677
Adt::Enum(e) => {
678678
let source_map = db.enum_signature_with_source_map(e.id).1;
679679
expr_store_diagnostics(db, acc, &source_map);
680-
for v in e.variants(db) {
681-
let source_map = db.variant_fields_with_source_map(v.id.into()).1;
680+
let (variants, diagnostics) = db.enum_variants_with_diagnostics(e.id);
681+
let file = e.id.lookup(db.upcast()).id.file_id();
682+
let ast_id_map = db.ast_id_map(file);
683+
for diag in diagnostics.iter() {
684+
acc.push(
685+
InactiveCode {
686+
node: InFile::new(
687+
file,
688+
ast_id_map.get(diag.ast_id).syntax_node_ptr(),
689+
),
690+
cfg: diag.cfg.clone(),
691+
opts: diag.opts.clone(),
692+
}
693+
.into(),
694+
);
695+
}
696+
for &(v, _) in &variants.variants {
697+
let source_map = db.variant_fields_with_source_map(v.into()).1;
682698
push_ty_diagnostics(
683699
db,
684700
acc,
685-
db.field_types_with_diagnostics(v.id.into()).1,
701+
db.field_types_with_diagnostics(v.into()).1,
686702
&source_map,
687703
);
688704
expr_store_diagnostics(db, acc, &source_map);

crates/ide/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -753,7 +753,7 @@ impl Analysis {
753753
frange: FileRange,
754754
) -> Cancellable<Vec<Assist>> {
755755
let include_fixes = match &assist_config.allowed {
756-
Some(it) => it.iter().any(|&it| it == AssistKind::QuickFix),
756+
Some(it) => it.contains(&AssistKind::QuickFix),
757757
None => true,
758758
};
759759

0 commit comments

Comments
 (0)