mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-01 07:48:45 +00:00
Auto merge of #13175 - Veykril:resolver, r=Veykril
Clarify the state of (extern) preludes for block def maps
This commit is contained in:
commit
afa374e58e
3 changed files with 60 additions and 60 deletions
|
@ -98,7 +98,11 @@ pub struct DefMap {
|
||||||
/// The prelude module for this crate. This either comes from an import
|
/// The prelude module for this crate. This either comes from an import
|
||||||
/// marked with the `prelude_import` attribute, or (in the normal case) from
|
/// marked with the `prelude_import` attribute, or (in the normal case) from
|
||||||
/// a dependency (`std` or `core`).
|
/// 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<ModuleId>,
|
prelude: Option<ModuleId>,
|
||||||
|
/// The extern prelude is only populated for non-block DefMaps
|
||||||
extern_prelude: FxHashMap<Name, ModuleId>,
|
extern_prelude: FxHashMap<Name, ModuleId>,
|
||||||
|
|
||||||
/// Side table for resolving derive helpers.
|
/// Side table for resolving derive helpers.
|
||||||
|
|
|
@ -512,10 +512,9 @@ impl DefCollector<'_> {
|
||||||
Edition::Edition2021 => name![rust_2021],
|
Edition::Edition2021 => name![rust_2021],
|
||||||
};
|
};
|
||||||
|
|
||||||
let path_kind = if self.def_map.edition == Edition::Edition2015 {
|
let path_kind = match self.def_map.edition {
|
||||||
PathKind::Plain
|
Edition::Edition2015 => PathKind::Plain,
|
||||||
} else {
|
_ => PathKind::Abs,
|
||||||
PathKind::Abs
|
|
||||||
};
|
};
|
||||||
let path =
|
let path =
|
||||||
ModPath::from_segments(path_kind, [krate.clone(), name![prelude], edition].into_iter());
|
ModPath::from_segments(path_kind, [krate.clone(), name![prelude], edition].into_iter());
|
||||||
|
@ -535,7 +534,6 @@ impl DefCollector<'_> {
|
||||||
match per_ns.types {
|
match per_ns.types {
|
||||||
Some((ModuleDefId::ModuleId(m), _)) => {
|
Some((ModuleDefId::ModuleId(m), _)) => {
|
||||||
self.def_map.prelude = Some(m);
|
self.def_map.prelude = Some(m);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
types => {
|
types => {
|
||||||
tracing::debug!(
|
tracing::debug!(
|
||||||
|
@ -850,7 +848,10 @@ impl DefCollector<'_> {
|
||||||
tracing::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def);
|
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
|
// 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)
|
if let (Some(ModuleDefId::ModuleId(def)), Some(name)) = (def.take_types(), name)
|
||||||
{
|
{
|
||||||
self.def_map.extern_prelude.insert(name.clone(), def);
|
self.def_map.extern_prelude.insert(name.clone(), def);
|
||||||
|
|
|
@ -368,34 +368,43 @@ impl Resolver {
|
||||||
for scope in self.scopes() {
|
for scope in self.scopes() {
|
||||||
scope.process_names(&mut res, db);
|
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
|
res.map
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn traits_in_scope(&self, db: &dyn DefDatabase) -> FxHashSet<TraitId> {
|
pub fn traits_in_scope(&self, db: &dyn DefDatabase) -> FxHashSet<TraitId> {
|
||||||
let mut traits = FxHashSet::default();
|
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() {
|
for scope in self.scopes() {
|
||||||
match scope {
|
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_) => {
|
&Scope::ImplDefScope(impl_) => {
|
||||||
if let Some(target_trait) = &db.impl_data(impl_).target_trait {
|
if let Some(target_trait) = &db.impl_data(impl_).target_trait {
|
||||||
if let Some(TypeNs::TraitId(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
|
traits
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -493,42 +508,22 @@ pub enum ScopeDef {
|
||||||
Label(LabelId),
|
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 {
|
impl Scope {
|
||||||
fn process_names(&self, acc: &mut ScopeNames, db: &dyn DefDatabase) {
|
fn process_names(&self, acc: &mut ScopeNames, db: &dyn DefDatabase) {
|
||||||
match self {
|
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 } => {
|
Scope::GenericParams { params, def: parent } => {
|
||||||
let parent = *parent;
|
let parent = *parent;
|
||||||
for (local_id, param) in params.type_or_consts.iter() {
|
for (local_id, param) in params.type_or_consts.iter() {
|
||||||
|
|
Loading…
Reference in a new issue