Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-def/src/nameres/collector.rs')
-rw-r--r--crates/hir-def/src/nameres/collector.rs100
1 files changed, 66 insertions, 34 deletions
diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs
index a18ac4b28c..fc15a77e8c 100644
--- a/crates/hir-def/src/nameres/collector.rs
+++ b/crates/hir-def/src/nameres/collector.rs
@@ -23,7 +23,7 @@ use itertools::{izip, Itertools};
use la_arena::Idx;
use limit::Limit;
use rustc_hash::{FxHashMap, FxHashSet};
-use span::{Span, SyntaxContextId};
+use span::{ErasedFileAstId, Span, SyntaxContextId};
use stdx::always;
use syntax::{ast, SmolStr};
use triomphe::Arc;
@@ -51,7 +51,7 @@ use crate::{
per_ns::PerNs,
tt,
visibility::{RawVisibility, Visibility},
- AdtId, AstId, AstIdWithPath, ConstLoc, CrateRootModuleId, EnumLoc, EnumVariantId,
+ AdtId, AstId, AstIdWithPath, ConstLoc, CrateRootModuleId, EnumLoc, EnumVariantLoc,
ExternBlockLoc, ExternCrateId, ExternCrateLoc, FunctionId, FunctionLoc, ImplLoc, Intern,
ItemContainerId, LocalModuleId, Lookup, Macro2Id, Macro2Loc, MacroExpander, MacroId,
MacroRulesId, MacroRulesLoc, MacroRulesLocFlags, ModuleDefId, ModuleId, ProcMacroId,
@@ -980,24 +980,35 @@ impl DefCollector<'_> {
cov_mark::hit!(glob_enum);
// glob import from enum => just import all the variants
- // XXX: urgh, so this works by accident! Here, we look at
- // the enum data, and, in theory, this might require us to
- // look back at the crate_def_map, creating a cycle. For
- // example, `enum E { crate::some_macro!(); }`. Luckily, the
- // only kind of macro that is allowed inside enum is a
- // `cfg_macro`, and we don't need to run name resolution for
- // it, but this is sheer luck!
- let enum_data = self.db.enum_data(e);
- let resolutions = enum_data
- .variants
- .iter()
- .map(|(local_id, variant_data)| {
- let name = variant_data.name.clone();
- let variant = EnumVariantId { parent: e, local_id };
- let res = PerNs::both(variant.into(), variant.into(), vis, None);
- (Some(name), res)
- })
- .collect::<Vec<_>>();
+ // We need to check if the def map the enum is from is us, then we can't
+ // call the def-map query since we are currently constructing it!
+ let loc = e.lookup(self.db);
+ let tree = loc.id.item_tree(self.db);
+ let current_def_map = self.def_map.krate == loc.container.krate
+ && self.def_map.block_id() == loc.container.block;
+ let resolutions = if current_def_map {
+ self.def_map.modules[loc.container.local_id].scope.enums[&e]
+ .iter()
+ .map(|&variant| {
+ let name = tree[variant.lookup(self.db).id.value].name.clone();
+ let res =
+ PerNs::both(variant.into(), variant.into(), vis, None);
+ (Some(name), res)
+ })
+ .collect::<Vec<_>>()
+ } else {
+ loc.container.def_map(self.db).modules[loc.container.local_id]
+ .scope
+ .enums[&e]
+ .iter()
+ .map(|&variant| {
+ let name = tree[variant.lookup(self.db).id.value].name.clone();
+ let res =
+ PerNs::both(variant.into(), variant.into(), vis, None);
+ (Some(name), res)
+ })
+ .collect::<Vec<_>>()
+ };
self.update(module_id, &resolutions, vis, Some(ImportType::Glob(id)));
}
Some(d) => {
@@ -1577,7 +1588,7 @@ impl ModCollector<'_, '_> {
let attrs = self.item_tree.attrs(db, krate, item.into());
if let Some(cfg) = attrs.cfg() {
if !self.is_cfg_enabled(&cfg) {
- self.emit_unconfigured_diagnostic(item, &cfg);
+ self.emit_unconfigured_diagnostic(item.ast_id(self.item_tree).erase(), &cfg);
return;
}
}
@@ -1708,17 +1719,40 @@ impl ModCollector<'_, '_> {
}
ModItem::Enum(id) => {
let it = &self.item_tree[id];
+ let enum_ =
+ EnumLoc { container: module, id: ItemTreeId::new(self.tree_id, id) }
+ .intern(db);
let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
- update_def(
- self.def_collector,
- EnumLoc { container: module, id: ItemTreeId::new(self.tree_id, id) }
- .intern(db)
- .into(),
- &it.name,
- vis,
- false,
- );
+ update_def(self.def_collector, enum_.into(), &it.name, vis, false);
+
+ let variants = FileItemTreeId::range_iter(it.variants.clone())
+ .filter_map(|variant| {
+ let attrs = self.item_tree.attrs(db, krate, variant.into());
+ if let Some(cfg) = attrs.cfg() {
+ if !self.is_cfg_enabled(&cfg) {
+ self.emit_unconfigured_diagnostic(
+ self.item_tree[variant.index()].ast_id.erase(),
+ &cfg,
+ );
+ return None;
+ }
+ }
+
+ Some(
+ EnumVariantLoc {
+ container: module,
+ id: ItemTreeId::new(self.tree_id, variant),
+ parent: enum_,
+ }
+ .intern(db),
+ )
+ })
+ .collect();
+ self.def_collector.def_map.modules[module_id]
+ .scope
+ .enums
+ .insert(enum_, variants);
}
ModItem::Const(id) => {
let it = &self.item_tree[id];
@@ -2360,10 +2394,8 @@ impl ModCollector<'_, '_> {
self.def_collector.cfg_options.check(cfg) != Some(false)
}
- fn emit_unconfigured_diagnostic(&mut self, item: ModItem, cfg: &CfgExpr) {
- let ast_id = item.ast_id(self.item_tree);
-
- let ast_id = InFile::new(self.file_id(), ast_id.erase());
+ fn emit_unconfigured_diagnostic(&mut self, ast_id: ErasedFileAstId, cfg: &CfgExpr) {
+ let ast_id = InFile::new(self.file_id(), ast_id);
self.def_collector.def_map.diagnostics.push(DefDiagnostic::unconfigured_code(
self.module_id,
ast_id,