From 894aa0ed0d181668ca33e4c5d2e08b4a49ae20d7 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 2 Sep 2022 17:43:20 +0200 Subject: [PATCH] Clarify the state of (extern) preludes for block def maps --- crates/hir-def/src/nameres.rs | 4 + crates/hir-def/src/nameres/collector.rs | 13 +-- crates/hir-def/src/resolver.rs | 103 +++++++++++------------- 3 files changed, 60 insertions(+), 60 deletions(-) diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs index fc8444394cf..2e392f741bf 100644 --- a/crates/hir-def/src/nameres.rs +++ b/crates/hir-def/src/nameres.rs @@ -98,7 +98,11 @@ pub struct DefMap { /// The prelude module for this crate. This either comes from an import /// marked with the `prelude_import` attribute, or (in the normal case) from /// a dependency (`std` or `core`). + /// The prelude is empty for non-block DefMaps (unless `#[prelude_import]` was used, + /// but that attribute is nightly and when used in a block, it affects resolution globally + /// so we aren't handling this correctly anyways). prelude: Option, + /// The extern prelude is only populated for non-block DefMaps extern_prelude: FxHashMap, /// Side table for resolving derive helpers. diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index ee27aa2554a..495bbe4579f 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -512,10 +512,9 @@ impl DefCollector<'_> { Edition::Edition2021 => name![rust_2021], }; - let path_kind = if self.def_map.edition == Edition::Edition2015 { - PathKind::Plain - } else { - PathKind::Abs + let path_kind = match self.def_map.edition { + Edition::Edition2015 => PathKind::Plain, + _ => PathKind::Abs, }; let path = ModPath::from_segments(path_kind, [krate.clone(), name![prelude], edition].into_iter()); @@ -535,7 +534,6 @@ impl DefCollector<'_> { match per_ns.types { Some((ModuleDefId::ModuleId(m), _)) => { self.def_map.prelude = Some(m); - return; } types => { tracing::debug!( @@ -850,7 +848,10 @@ impl DefCollector<'_> { tracing::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def); // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658 - if import.is_extern_crate && module_id == self.def_map.root { + if import.is_extern_crate + && self.def_map.block.is_none() + && module_id == self.def_map.root + { if let (Some(ModuleDefId::ModuleId(def)), Some(name)) = (def.take_types(), name) { self.def_map.extern_prelude.insert(name.clone(), def); diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs index 769aa9dcb0c..8aa5973cac5 100644 --- a/crates/hir-def/src/resolver.rs +++ b/crates/hir-def/src/resolver.rs @@ -368,34 +368,43 @@ impl Resolver { for scope in self.scopes() { scope.process_names(&mut res, db); } - process_module_scope_names(&mut res, db, &self.module_scope); + let ModuleItemMap { ref def_map, module_id } = self.module_scope; + // FIXME: should we provide `self` here? + // f( + // Name::self_param(), + // PerNs::types(Resolution::Def { + // def: m.module.into(), + // }), + // ); + def_map[module_id].scope.entries().for_each(|(name, def)| { + res.add_per_ns(name, def); + }); + def_map[module_id].scope.legacy_macros().for_each(|(name, macs)| { + macs.iter().for_each(|&mac| { + res.add(name, ScopeDef::ModuleDef(ModuleDefId::MacroId(MacroId::from(mac)))); + }) + }); + def_map.extern_prelude().for_each(|(name, &def)| { + res.add(name, ScopeDef::ModuleDef(ModuleDefId::ModuleId(def))); + }); + BUILTIN_SCOPE.iter().for_each(|(name, &def)| { + res.add_per_ns(name, def); + }); + if let Some(prelude) = def_map.prelude() { + let prelude_def_map = prelude.def_map(db); + for (name, def) in prelude_def_map[prelude.local_id].scope.entries() { + res.add_per_ns(name, def) + } + } res.map } pub fn traits_in_scope(&self, db: &dyn DefDatabase) -> FxHashSet { let mut traits = FxHashSet::default(); - let collect_module_traits = |traits: &mut FxHashSet<_>, m: &ModuleItemMap| { - if let Some(prelude) = m.def_map.prelude() { - let prelude_def_map = prelude.def_map(db); - traits.extend(prelude_def_map[prelude.local_id].scope.traits()); - } - traits.extend(m.def_map[m.module_id].scope.traits()); - - // Add all traits that are in scope because of the containing DefMaps - m.def_map.with_ancestor_maps(db, m.module_id, &mut |def_map, module| { - if let Some(prelude) = def_map.prelude() { - let prelude_def_map = prelude.def_map(db); - traits.extend(prelude_def_map[prelude.local_id].scope.traits()); - } - traits.extend(def_map[module].scope.traits()); - None::<()> - }); - }; - for scope in self.scopes() { match scope { - Scope::BlockScope(m) => collect_module_traits(&mut traits, m), + Scope::BlockScope(m) => traits.extend(m.def_map[m.module_id].scope.traits()), &Scope::ImplDefScope(impl_) => { if let Some(target_trait) = &db.impl_data(impl_).target_trait { if let Some(TypeNs::TraitId(trait_)) = @@ -409,7 +418,13 @@ impl Resolver { } } - collect_module_traits(&mut traits, &self.module_scope); + // Fill in the prelude traits + if let Some(prelude) = self.module_scope.def_map.prelude() { + let prelude_def_map = prelude.def_map(db); + traits.extend(prelude_def_map[prelude.local_id].scope.traits()); + } + // Fill in module visible traits + traits.extend(self.module_scope.def_map[self.module_scope.module_id].scope.traits()); traits } @@ -493,42 +508,22 @@ pub enum ScopeDef { Label(LabelId), } -fn process_module_scope_names(acc: &mut ScopeNames, db: &dyn DefDatabase, m: &ModuleItemMap) { - // FIXME: should we provide `self` here? - // f( - // Name::self_param(), - // PerNs::types(Resolution::Def { - // def: m.module.into(), - // }), - // ); - m.def_map[m.module_id].scope.entries().for_each(|(name, def)| { - acc.add_per_ns(name, def); - }); - m.def_map[m.module_id].scope.legacy_macros().for_each(|(name, macs)| { - macs.iter().for_each(|&mac| { - acc.add(name, ScopeDef::ModuleDef(ModuleDefId::MacroId(MacroId::from(mac)))); - }) - }); - m.def_map.extern_prelude().for_each(|(name, &def)| { - acc.add(name, ScopeDef::ModuleDef(ModuleDefId::ModuleId(def))); - }); - if m.def_map.block_id().is_none() { - BUILTIN_SCOPE.iter().for_each(|(name, &def)| { - acc.add_per_ns(name, def); - }); - } - if let Some(prelude) = m.def_map.prelude() { - let prelude_def_map = prelude.def_map(db); - for (name, def) in prelude_def_map[prelude.local_id].scope.entries() { - acc.add_per_ns(name, def) - } - } -} - impl Scope { fn process_names(&self, acc: &mut ScopeNames, db: &dyn DefDatabase) { match self { - Scope::BlockScope(m) => process_module_scope_names(acc, db, m), + Scope::BlockScope(m) => { + m.def_map[m.module_id].scope.entries().for_each(|(name, def)| { + acc.add_per_ns(name, def); + }); + m.def_map[m.module_id].scope.legacy_macros().for_each(|(name, macs)| { + macs.iter().for_each(|&mac| { + acc.add( + name, + ScopeDef::ModuleDef(ModuleDefId::MacroId(MacroId::from(mac))), + ); + }) + }); + } Scope::GenericParams { params, def: parent } => { let parent = *parent; for (local_id, param) in params.type_or_consts.iter() {