Thread imports through the resolver

This commit is contained in:
Lukas Wirth 2023-08-17 10:52:13 +02:00
parent c4e9b5ac64
commit a17d73ad36
15 changed files with 218 additions and 131 deletions

View File

@ -34,7 +34,7 @@ pub enum ImportOrExternCrate {
} }
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum ImportType { pub(crate) enum ImportType {
Import(ImportId), Import(ImportId),
Glob(UseId), Glob(UseId),
ExternCrate(ExternCrateId), ExternCrate(ExternCrateId),
@ -118,7 +118,7 @@ struct DeriveMacroInvocation {
pub(crate) static BUILTIN_SCOPE: Lazy<FxHashMap<Name, PerNs>> = Lazy::new(|| { pub(crate) static BUILTIN_SCOPE: Lazy<FxHashMap<Name, PerNs>> = Lazy::new(|| {
BuiltinType::ALL BuiltinType::ALL
.iter() .iter()
.map(|(name, ty)| (name.clone(), PerNs::types((*ty).into(), Visibility::Public))) .map(|(name, ty)| (name.clone(), PerNs::types((*ty).into(), Visibility::Public, None)))
.collect() .collect()
}); });
@ -234,9 +234,16 @@ impl ItemScope {
pub(crate) fn resolutions(&self) -> impl Iterator<Item = (Option<Name>, PerNs)> + '_ { pub(crate) fn resolutions(&self) -> impl Iterator<Item = (Option<Name>, PerNs)> + '_ {
self.entries().map(|(name, res)| (Some(name.clone()), res)).chain( self.entries().map(|(name, res)| (Some(name.clone()), res)).chain(
self.unnamed_trait_imports self.unnamed_trait_imports.iter().map(|(tr, (vis, i))| {
.iter() (
.map(|(tr, (vis, _))| (None, PerNs::types(ModuleDefId::TraitId(*tr), *vis))), None,
PerNs::types(
ModuleDefId::TraitId(*tr),
*vis,
i.map(ImportOrExternCrate::Import),
),
)
}),
) )
} }
} }
@ -327,11 +334,13 @@ impl ItemScope {
}) })
} }
// FIXME: This is only used in collection, we should move the relevant parts of it out of ItemScope
pub(crate) fn unnamed_trait_vis(&self, tr: TraitId) -> Option<Visibility> { pub(crate) fn unnamed_trait_vis(&self, tr: TraitId) -> Option<Visibility> {
self.unnamed_trait_imports.get(&tr).copied().map(|(a, _)| a) self.unnamed_trait_imports.get(&tr).copied().map(|(a, _)| a)
} }
pub(crate) fn push_unnamed_trait(&mut self, tr: TraitId, vis: Visibility) { pub(crate) fn push_unnamed_trait(&mut self, tr: TraitId, vis: Visibility) {
// FIXME: import
self.unnamed_trait_imports.insert(tr, (vis, None)); self.unnamed_trait_imports.insert(tr, (vis, None));
} }
@ -344,6 +353,8 @@ impl ItemScope {
) -> bool { ) -> bool {
let mut changed = false; let mut changed = false;
// FIXME: Document and simplify this
if let Some(mut fld) = def.types { if let Some(mut fld) = def.types {
let existing = self.types.entry(lookup.1.clone()); let existing = self.types.entry(lookup.1.clone());
match existing { match existing {
@ -626,28 +637,39 @@ impl ItemScope {
} }
impl PerNs { impl PerNs {
pub(crate) fn from_def(def: ModuleDefId, v: Visibility, has_constructor: bool) -> PerNs { pub(crate) fn from_def(
def: ModuleDefId,
v: Visibility,
has_constructor: bool,
import: Option<ImportOrExternCrate>,
) -> PerNs {
match def { match def {
ModuleDefId::ModuleId(_) => PerNs::types(def, v), ModuleDefId::ModuleId(_) => PerNs::types(def, v, import),
ModuleDefId::FunctionId(_) => PerNs::values(def, v), ModuleDefId::FunctionId(_) => {
PerNs::values(def, v, import.and_then(ImportOrExternCrate::into_import))
}
ModuleDefId::AdtId(adt) => match adt { ModuleDefId::AdtId(adt) => match adt {
AdtId::UnionId(_) => PerNs::types(def, v), AdtId::UnionId(_) => PerNs::types(def, v, import),
AdtId::EnumId(_) => PerNs::types(def, v), AdtId::EnumId(_) => PerNs::types(def, v, import),
AdtId::StructId(_) => { AdtId::StructId(_) => {
if has_constructor { if has_constructor {
PerNs::both(def, def, v) PerNs::both(def, def, v, import)
} else { } else {
PerNs::types(def, v) PerNs::types(def, v, import)
} }
} }
}, },
ModuleDefId::EnumVariantId(_) => PerNs::both(def, def, v), ModuleDefId::EnumVariantId(_) => PerNs::both(def, def, v, import),
ModuleDefId::ConstId(_) | ModuleDefId::StaticId(_) => PerNs::values(def, v), ModuleDefId::ConstId(_) | ModuleDefId::StaticId(_) => {
ModuleDefId::TraitId(_) => PerNs::types(def, v), PerNs::values(def, v, import.and_then(ImportOrExternCrate::into_import))
ModuleDefId::TraitAliasId(_) => PerNs::types(def, v), }
ModuleDefId::TypeAliasId(_) => PerNs::types(def, v), ModuleDefId::TraitId(_) => PerNs::types(def, v, import),
ModuleDefId::BuiltinType(_) => PerNs::types(def, v), ModuleDefId::TraitAliasId(_) => PerNs::types(def, v, import),
ModuleDefId::MacroId(mac) => PerNs::macros(mac, v), ModuleDefId::TypeAliasId(_) => PerNs::types(def, v, import),
ModuleDefId::BuiltinType(_) => PerNs::types(def, v, import),
ModuleDefId::MacroId(mac) => {
PerNs::macros(mac, v, import.and_then(ImportOrExternCrate::into_import))
}
} }
} }
} }

View File

@ -131,7 +131,7 @@ pub fn identity_when_valid(_attr: TokenStream, item: TokenStream) -> TokenStream
.as_call_id_with_errors(&db, krate, |path| { .as_call_id_with_errors(&db, krate, |path| {
resolver resolver
.resolve_path_as_macro(&db, &path, Some(MacroSubNs::Bang)) .resolve_path_as_macro(&db, &path, Some(MacroSubNs::Bang))
.map(|it| macro_id_to_def_id(&db, it)) .map(|(it, _)| macro_id_to_def_id(&db, it))
}) })
.unwrap(); .unwrap();
let macro_call_id = res.value.unwrap(); let macro_call_id = res.value.unwrap();

View File

@ -648,7 +648,7 @@ impl DefCollector<'_> {
self.def_map.modules[module_id].scope.declare(macro_.into()); self.def_map.modules[module_id].scope.declare(macro_.into());
self.update( self.update(
module_id, module_id,
&[(Some(name), PerNs::macros(macro_.into(), Visibility::Public))], &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public, None))],
Visibility::Public, Visibility::Public,
None, None,
); );
@ -684,7 +684,7 @@ impl DefCollector<'_> {
self.def_map.modules[module_id].scope.declare(macro_.into()); self.def_map.modules[module_id].scope.declare(macro_.into());
self.update( self.update(
module_id, module_id,
&[(Some(name), PerNs::macros(macro_.into(), Visibility::Public))], &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public, None))],
vis, vis,
None, None,
); );
@ -699,7 +699,7 @@ impl DefCollector<'_> {
self.def_map.modules[module_id].scope.declare(macro_.into()); self.def_map.modules[module_id].scope.declare(macro_.into());
self.update( self.update(
module_id, module_id,
&[(Some(name), PerNs::macros(macro_.into(), Visibility::Public))], &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public, None))],
Visibility::Public, Visibility::Public,
None, None,
); );
@ -783,6 +783,7 @@ impl DefCollector<'_> {
Some(res) => PartialResolvedImport::Resolved(PerNs::types( Some(res) => PartialResolvedImport::Resolved(PerNs::types(
res.into(), res.into(),
Visibility::Public, Visibility::Public,
None,
)), )),
None => PartialResolvedImport::Unresolved, None => PartialResolvedImport::Unresolved,
} }
@ -967,7 +968,7 @@ impl DefCollector<'_> {
.map(|(local_id, variant_data)| { .map(|(local_id, variant_data)| {
let name = variant_data.name.clone(); let name = variant_data.name.clone();
let variant = EnumVariantId { parent: e, local_id }; let variant = EnumVariantId { parent: e, local_id };
let res = PerNs::both(variant.into(), variant.into(), vis); let res = PerNs::both(variant.into(), variant.into(), vis, None);
(Some(name), res) (Some(name), res)
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
@ -1547,7 +1548,7 @@ impl ModCollector<'_, '_> {
def_collector.def_map.modules[module_id].scope.declare(id); def_collector.def_map.modules[module_id].scope.declare(id);
def_collector.update( def_collector.update(
module_id, module_id,
&[(Some(name.clone()), PerNs::from_def(id, vis, has_constructor))], &[(Some(name.clone()), PerNs::from_def(id, vis, has_constructor, None))],
vis, vis,
None, None,
) )
@ -1977,7 +1978,7 @@ impl ModCollector<'_, '_> {
def_map.modules[self.module_id].scope.declare(def); def_map.modules[self.module_id].scope.declare(def);
self.def_collector.update( self.def_collector.update(
self.module_id, self.module_id,
&[(Some(name), PerNs::from_def(def, vis, false))], &[(Some(name), PerNs::from_def(def, vis, false, None))],
vis, vis,
None, None,
); );

View File

@ -15,8 +15,9 @@ use hir_expand::name::Name;
use triomphe::Arc; use triomphe::Arc;
use crate::{ use crate::{
data::adt::VariantData,
db::DefDatabase, db::DefDatabase,
item_scope::BUILTIN_SCOPE, item_scope::{ImportOrExternCrate, BUILTIN_SCOPE},
nameres::{sub_namespace_match, BlockInfo, BuiltinShadowMode, DefMap, MacroSubNs}, nameres::{sub_namespace_match, BlockInfo, BuiltinShadowMode, DefMap, MacroSubNs},
path::{ModPath, PathKind}, path::{ModPath, PathKind},
per_ns::PerNs, per_ns::PerNs,
@ -196,15 +197,15 @@ impl DefMap {
PathKind::DollarCrate(krate) => { PathKind::DollarCrate(krate) => {
if krate == self.krate { if krate == self.krate {
cov_mark::hit!(macro_dollar_crate_self); cov_mark::hit!(macro_dollar_crate_self);
PerNs::types(self.crate_root().into(), Visibility::Public) PerNs::types(self.crate_root().into(), Visibility::Public, None)
} else { } else {
let def_map = db.crate_def_map(krate); let def_map = db.crate_def_map(krate);
let module = def_map.module_id(Self::ROOT); let module = def_map.module_id(Self::ROOT);
cov_mark::hit!(macro_dollar_crate_other); cov_mark::hit!(macro_dollar_crate_other);
PerNs::types(module.into(), Visibility::Public) PerNs::types(module.into(), Visibility::Public, None)
} }
} }
PathKind::Crate => PerNs::types(self.crate_root().into(), Visibility::Public), PathKind::Crate => PerNs::types(self.crate_root().into(), Visibility::Public, None),
// plain import or absolute path in 2015: crate-relative with // plain import or absolute path in 2015: crate-relative with
// fallback to extern prelude (with the simplification in // fallback to extern prelude (with the simplification in
// rust-lang/rust#57745) // rust-lang/rust#57745)
@ -291,7 +292,7 @@ impl DefMap {
); );
} }
PerNs::types(module.into(), Visibility::Public) PerNs::types(module.into(), Visibility::Public, None)
} }
PathKind::Abs => { PathKind::Abs => {
// 2018-style absolute path -- only extern prelude // 2018-style absolute path -- only extern prelude
@ -299,9 +300,13 @@ impl DefMap {
Some((_, segment)) => segment, Some((_, segment)) => segment,
None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
}; };
if let Some(&(def, _extern_crate)) = self.data.extern_prelude.get(segment) { if let Some(&(def, extern_crate)) = self.data.extern_prelude.get(segment) {
tracing::debug!("absolute path {:?} resolved to crate {:?}", path, def); tracing::debug!("absolute path {:?} resolved to crate {:?}", path, def);
PerNs::types(def.into(), Visibility::Public) PerNs::types(
def.into(),
Visibility::Public,
extern_crate.map(ImportOrExternCrate::ExternCrate),
)
} else { } else {
return ResolvePathResult::empty(ReachedFixedPoint::No); // extern crate declarations can add to the extern prelude return ResolvePathResult::empty(ReachedFixedPoint::No); // extern crate declarations can add to the extern prelude
} }
@ -309,7 +314,7 @@ impl DefMap {
}; };
for (i, segment) in segments { for (i, segment) in segments {
let (curr, vis) = match curr_per_ns.take_types_vis() { let (curr, vis, imp) = match curr_per_ns.take_types_full() {
Some(r) => r, Some(r) => r,
None => { None => {
// we still have path segments left, but the path so far // we still have path segments left, but the path so far
@ -364,18 +369,20 @@ impl DefMap {
Some(local_id) => { Some(local_id) => {
let variant = EnumVariantId { parent: e, local_id }; let variant = EnumVariantId { parent: e, local_id };
match &*enum_data.variants[local_id].variant_data { match &*enum_data.variants[local_id].variant_data {
crate::data::adt::VariantData::Record(_) => { VariantData::Record(_) => {
PerNs::types(variant.into(), Visibility::Public) PerNs::types(variant.into(), Visibility::Public, None)
}
crate::data::adt::VariantData::Tuple(_)
| crate::data::adt::VariantData::Unit => {
PerNs::both(variant.into(), variant.into(), Visibility::Public)
} }
VariantData::Tuple(_) | VariantData::Unit => PerNs::both(
variant.into(),
variant.into(),
Visibility::Public,
None,
),
} }
} }
None => { None => {
return ResolvePathResult::with( return ResolvePathResult::with(
PerNs::types(e.into(), vis), PerNs::types(e.into(), vis, imp),
ReachedFixedPoint::Yes, ReachedFixedPoint::Yes,
Some(i), Some(i),
Some(self.krate), Some(self.krate),
@ -393,7 +400,7 @@ impl DefMap {
); );
return ResolvePathResult::with( return ResolvePathResult::with(
PerNs::types(s, vis), PerNs::types(s, vis, imp),
ReachedFixedPoint::Yes, ReachedFixedPoint::Yes,
Some(i), Some(i),
Some(self.krate), Some(self.krate),
@ -430,7 +437,7 @@ impl DefMap {
.filter(|&id| { .filter(|&id| {
sub_namespace_match(Some(MacroSubNs::from_id(db, id)), expected_macro_subns) sub_namespace_match(Some(MacroSubNs::from_id(db, id)), expected_macro_subns)
}) })
.map_or_else(PerNs::none, |m| PerNs::macros(m, Visibility::Public)); .map_or_else(PerNs::none, |m| PerNs::macros(m, Visibility::Public, None));
let from_scope = self[module].scope.get(name).filter_macro(db, expected_macro_subns); let from_scope = self[module].scope.get(name).filter_macro(db, expected_macro_subns);
let from_builtin = match self.block { let from_builtin = match self.block {
Some(_) => { Some(_) => {
@ -449,16 +456,26 @@ impl DefMap {
let extern_prelude = || { let extern_prelude = || {
if self.block.is_some() { if self.block.is_some() {
// Don't resolve extern prelude in block `DefMap`s. // Don't resolve extern prelude in block `DefMap`s, defer it to the crate def map so
// that blocks can properly shadow them
return PerNs::none(); return PerNs::none();
} }
self.data.extern_prelude.get(name).map_or(PerNs::none(), |&(it, _extern_crate)| { self.data.extern_prelude.get(name).map_or(PerNs::none(), |&(it, extern_crate)| {
PerNs::types(it.into(), Visibility::Public) PerNs::types(
it.into(),
Visibility::Public,
extern_crate.map(ImportOrExternCrate::ExternCrate),
)
}) })
}; };
let macro_use_prelude = || { let macro_use_prelude = || {
self.macro_use_prelude.get(name).map_or(PerNs::none(), |&(it, _extern_crate)| { self.macro_use_prelude.get(name).map_or(PerNs::none(), |&(it, _extern_crate)| {
PerNs::macros(it.into(), Visibility::Public) PerNs::macros(
it.into(),
Visibility::Public,
// FIXME?
None, // extern_crate.map(ImportOrExternCrate::ExternCrate),
)
}) })
}; };
let prelude = || self.resolve_in_prelude(db, name); let prelude = || self.resolve_in_prelude(db, name);
@ -487,13 +504,16 @@ impl DefMap {
// Don't resolve extern prelude in block `DefMap`s. // Don't resolve extern prelude in block `DefMap`s.
return PerNs::none(); return PerNs::none();
} }
self.data self.data.extern_prelude.get(name).copied().map_or(
.extern_prelude PerNs::none(),
.get(name) |(it, extern_crate)| {
.copied() PerNs::types(
.map_or(PerNs::none(), |(it, _extern_crate)| { it.into(),
PerNs::types(it.into(), Visibility::Public) Visibility::Public,
}) extern_crate.map(ImportOrExternCrate::ExternCrate),
)
},
)
}; };
from_crate_root.or_else(from_extern_prelude) from_crate_root.or_else(from_extern_prelude)

View File

@ -27,20 +27,29 @@ impl PerNs {
PerNs { types: None, values: None, macros: None } PerNs { types: None, values: None, macros: None }
} }
pub fn values(t: ModuleDefId, v: Visibility) -> PerNs { pub fn values(t: ModuleDefId, v: Visibility, i: Option<ImportId>) -> PerNs {
PerNs { types: None, values: Some((t, v, None)), macros: None } PerNs { types: None, values: Some((t, v, i)), macros: None }
} }
pub fn types(t: ModuleDefId, v: Visibility) -> PerNs { pub fn types(t: ModuleDefId, v: Visibility, i: Option<ImportOrExternCrate>) -> PerNs {
PerNs { types: Some((t, v, None)), values: None, macros: None } PerNs { types: Some((t, v, i)), values: None, macros: None }
} }
pub fn both(types: ModuleDefId, values: ModuleDefId, v: Visibility) -> PerNs { pub fn both(
PerNs { types: Some((types, v, None)), values: Some((values, v, None)), macros: None } types: ModuleDefId,
values: ModuleDefId,
v: Visibility,
i: Option<ImportOrExternCrate>,
) -> PerNs {
PerNs {
types: Some((types, v, i)),
values: Some((values, v, i.and_then(ImportOrExternCrate::into_import))),
macros: None,
}
} }
pub fn macros(macro_: MacroId, v: Visibility) -> PerNs { pub fn macros(macro_: MacroId, v: Visibility, i: Option<ImportId>) -> PerNs {
PerNs { types: None, values: None, macros: Some((macro_, v, None)) } PerNs { types: None, values: None, macros: Some((macro_, v, i)) }
} }
pub fn is_none(&self) -> bool { pub fn is_none(&self) -> bool {
@ -55,18 +64,26 @@ impl PerNs {
self.types.map(|it| it.0) self.types.map(|it| it.0)
} }
pub fn take_types_vis(self) -> Option<(ModuleDefId, Visibility)> { pub fn take_types_full(self) -> Option<(ModuleDefId, Visibility, Option<ImportOrExternCrate>)> {
self.types.map(|(a, b, _)| (a, b)) self.types
} }
pub fn take_values(self) -> Option<ModuleDefId> { pub fn take_values(self) -> Option<ModuleDefId> {
self.values.map(|it| it.0) self.values.map(|it| it.0)
} }
pub fn take_values_import(self) -> Option<(ModuleDefId, Option<ImportId>)> {
self.values.map(|it| (it.0, it.2))
}
pub fn take_macros(self) -> Option<MacroId> { pub fn take_macros(self) -> Option<MacroId> {
self.macros.map(|it| it.0) self.macros.map(|it| it.0)
} }
pub fn take_macros_import(self) -> Option<(MacroId, Option<ImportId>)> {
self.macros.map(|it| (it.0, it.2))
}
pub fn filter_visibility(self, mut f: impl FnMut(Visibility) -> bool) -> PerNs { pub fn filter_visibility(self, mut f: impl FnMut(Visibility) -> bool) -> PerNs {
let _p = profile::span("PerNs::filter_visibility"); let _p = profile::span("PerNs::filter_visibility");
PerNs { PerNs {

View File

@ -15,7 +15,7 @@ use crate::{
db::DefDatabase, db::DefDatabase,
generics::{GenericParams, TypeOrConstParamData}, generics::{GenericParams, TypeOrConstParamData},
hir::{BindingId, ExprId, LabelId}, hir::{BindingId, ExprId, LabelId},
item_scope::{BuiltinShadowMode, BUILTIN_SCOPE}, item_scope::{BuiltinShadowMode, ImportId, ImportOrExternCrate, BUILTIN_SCOPE},
lang_item::LangItemTarget, lang_item::LangItemTarget,
nameres::{DefMap, MacroSubNs}, nameres::{DefMap, MacroSubNs},
path::{ModPath, Path, PathKind}, path::{ModPath, Path, PathKind},
@ -100,8 +100,8 @@ pub enum TypeNs {
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum ResolveValueResult { pub enum ResolveValueResult {
ValueNs(ValueNs), ValueNs(ValueNs, Option<ImportId>),
Partial(TypeNs, usize), Partial(TypeNs, usize, Option<ImportOrExternCrate>),
} }
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
@ -152,7 +152,7 @@ impl Resolver {
&self, &self,
db: &dyn DefDatabase, db: &dyn DefDatabase,
path: &Path, path: &Path,
) -> Option<(TypeNs, Option<usize>)> { ) -> Option<(TypeNs, Option<usize>, Option<ImportOrExternCrate>)> {
let path = match path { let path = match path {
Path::Normal { mod_path, .. } => mod_path, Path::Normal { mod_path, .. } => mod_path,
Path::LangItem(l) => { Path::LangItem(l) => {
@ -169,6 +169,7 @@ impl Resolver {
| LangItemTarget::Static(_) => return None, | LangItemTarget::Static(_) => return None,
}, },
None, None,
None,
)) ))
} }
}; };
@ -185,17 +186,17 @@ impl Resolver {
Scope::ExprScope(_) => continue, Scope::ExprScope(_) => continue,
Scope::GenericParams { params, def } => { Scope::GenericParams { params, def } => {
if let Some(id) = params.find_type_by_name(first_name, *def) { if let Some(id) = params.find_type_by_name(first_name, *def) {
return Some((TypeNs::GenericParam(id), remaining_idx())); return Some((TypeNs::GenericParam(id), remaining_idx(), None));
} }
} }
&Scope::ImplDefScope(impl_) => { &Scope::ImplDefScope(impl_) => {
if first_name == &name![Self] { if first_name == &name![Self] {
return Some((TypeNs::SelfType(impl_), remaining_idx())); return Some((TypeNs::SelfType(impl_), remaining_idx(), None));
} }
} }
&Scope::AdtScope(adt) => { &Scope::AdtScope(adt) => {
if first_name == &name![Self] { if first_name == &name![Self] {
return Some((TypeNs::AdtSelfType(adt), remaining_idx())); return Some((TypeNs::AdtSelfType(adt), remaining_idx(), None));
} }
} }
Scope::BlockScope(m) => { Scope::BlockScope(m) => {
@ -208,12 +209,24 @@ impl Resolver {
self.module_scope.resolve_path_in_type_ns(db, path) self.module_scope.resolve_path_in_type_ns(db, path)
} }
pub fn resolve_path_in_type_ns_fully_with_imports(
&self,
db: &dyn DefDatabase,
path: &Path,
) -> Option<(TypeNs, Option<ImportOrExternCrate>)> {
let (res, unresolved, imp) = self.resolve_path_in_type_ns(db, path)?;
if unresolved.is_some() {
return None;
}
Some((res, imp))
}
pub fn resolve_path_in_type_ns_fully( pub fn resolve_path_in_type_ns_fully(
&self, &self,
db: &dyn DefDatabase, db: &dyn DefDatabase,
path: &Path, path: &Path,
) -> Option<TypeNs> { ) -> Option<TypeNs> {
let (res, unresolved) = self.resolve_path_in_type_ns(db, path)?; let (res, unresolved, _) = self.resolve_path_in_type_ns(db, path)?;
if unresolved.is_some() { if unresolved.is_some() {
return None; return None;
} }
@ -235,7 +248,6 @@ impl Resolver {
RawVisibility::Public => Some(Visibility::Public), RawVisibility::Public => Some(Visibility::Public),
} }
} }
pub fn resolve_path_in_value_ns( pub fn resolve_path_in_value_ns(
&self, &self,
db: &dyn DefDatabase, db: &dyn DefDatabase,
@ -244,7 +256,8 @@ impl Resolver {
let path = match path { let path = match path {
Path::Normal { mod_path, .. } => mod_path, Path::Normal { mod_path, .. } => mod_path,
Path::LangItem(l) => { Path::LangItem(l) => {
return Some(ResolveValueResult::ValueNs(match *l { return Some(ResolveValueResult::ValueNs(
match *l {
LangItemTarget::Function(it) => ValueNs::FunctionId(it), LangItemTarget::Function(it) => ValueNs::FunctionId(it),
LangItemTarget::Static(it) => ValueNs::StaticId(it), LangItemTarget::Static(it) => ValueNs::StaticId(it),
LangItemTarget::Struct(it) => ValueNs::StructId(it), LangItemTarget::Struct(it) => ValueNs::StructId(it),
@ -254,7 +267,9 @@ impl Resolver {
| LangItemTarget::TypeAlias(_) | LangItemTarget::TypeAlias(_)
| LangItemTarget::Trait(_) | LangItemTarget::Trait(_)
| LangItemTarget::EnumId(_) => return None, | LangItemTarget::EnumId(_) => return None,
})) },
None,
))
} }
}; };
let n_segments = path.segments().len(); let n_segments = path.segments().len();
@ -276,20 +291,24 @@ impl Resolver {
.find(|entry| entry.name() == first_name); .find(|entry| entry.name() == first_name);
if let Some(e) = entry { if let Some(e) = entry {
return Some(ResolveValueResult::ValueNs(ValueNs::LocalBinding( return Some(ResolveValueResult::ValueNs(
e.binding(), ValueNs::LocalBinding(e.binding()),
))); None,
));
} }
} }
Scope::GenericParams { params, def } => { Scope::GenericParams { params, def } => {
if let Some(id) = params.find_const_by_name(first_name, *def) { if let Some(id) = params.find_const_by_name(first_name, *def) {
let val = ValueNs::GenericParam(id); let val = ValueNs::GenericParam(id);
return Some(ResolveValueResult::ValueNs(val)); return Some(ResolveValueResult::ValueNs(val, None));
} }
} }
&Scope::ImplDefScope(impl_) => { &Scope::ImplDefScope(impl_) => {
if first_name == &name![Self] { if first_name == &name![Self] {
return Some(ResolveValueResult::ValueNs(ValueNs::ImplSelf(impl_))); return Some(ResolveValueResult::ValueNs(
ValueNs::ImplSelf(impl_),
None,
));
} }
} }
// bare `Self` doesn't work in the value namespace in a struct/enum definition // bare `Self` doesn't work in the value namespace in a struct/enum definition
@ -308,18 +327,22 @@ impl Resolver {
Scope::GenericParams { params, def } => { Scope::GenericParams { params, def } => {
if let Some(id) = params.find_type_by_name(first_name, *def) { if let Some(id) = params.find_type_by_name(first_name, *def) {
let ty = TypeNs::GenericParam(id); let ty = TypeNs::GenericParam(id);
return Some(ResolveValueResult::Partial(ty, 1)); return Some(ResolveValueResult::Partial(ty, 1, None));
} }
} }
&Scope::ImplDefScope(impl_) => { &Scope::ImplDefScope(impl_) => {
if first_name == &name![Self] { if first_name == &name![Self] {
return Some(ResolveValueResult::Partial(TypeNs::SelfType(impl_), 1)); return Some(ResolveValueResult::Partial(
TypeNs::SelfType(impl_),
1,
None,
));
} }
} }
Scope::AdtScope(adt) => { Scope::AdtScope(adt) => {
if first_name == &name![Self] { if first_name == &name![Self] {
let ty = TypeNs::AdtSelfType(*adt); let ty = TypeNs::AdtSelfType(*adt);
return Some(ResolveValueResult::Partial(ty, 1)); return Some(ResolveValueResult::Partial(ty, 1, None));
} }
} }
Scope::BlockScope(m) => { Scope::BlockScope(m) => {
@ -340,7 +363,7 @@ impl Resolver {
// `use core::u16;`. // `use core::u16;`.
if path.kind == PathKind::Plain && n_segments > 1 { if path.kind == PathKind::Plain && n_segments > 1 {
if let Some(builtin) = BuiltinType::by_name(first_name) { if let Some(builtin) = BuiltinType::by_name(first_name) {
return Some(ResolveValueResult::Partial(TypeNs::BuiltinType(builtin), 1)); return Some(ResolveValueResult::Partial(TypeNs::BuiltinType(builtin), 1, None));
} }
} }
@ -353,7 +376,7 @@ impl Resolver {
path: &Path, path: &Path,
) -> Option<ValueNs> { ) -> Option<ValueNs> {
match self.resolve_path_in_value_ns(db, path)? { match self.resolve_path_in_value_ns(db, path)? {
ResolveValueResult::ValueNs(it) => Some(it), ResolveValueResult::ValueNs(it, _) => Some(it),
ResolveValueResult::Partial(..) => None, ResolveValueResult::Partial(..) => None,
} }
} }
@ -363,12 +386,12 @@ impl Resolver {
db: &dyn DefDatabase, db: &dyn DefDatabase,
path: &ModPath, path: &ModPath,
expected_macro_kind: Option<MacroSubNs>, expected_macro_kind: Option<MacroSubNs>,
) -> Option<MacroId> { ) -> Option<(MacroId, Option<ImportId>)> {
let (item_map, module) = self.item_scope(); let (item_map, module) = self.item_scope();
item_map item_map
.resolve_path(db, module, path, BuiltinShadowMode::Other, expected_macro_kind) .resolve_path(db, module, path, BuiltinShadowMode::Other, expected_macro_kind)
.0 .0
.take_macros() .take_macros_import()
} }
/// Returns a set of names available in the current scope. /// Returns a set of names available in the current scope.
@ -776,11 +799,12 @@ impl ModuleItemMap {
self.def_map.resolve_path_locally(db, self.module_id, path, BuiltinShadowMode::Other); self.def_map.resolve_path_locally(db, self.module_id, path, BuiltinShadowMode::Other);
match idx { match idx {
None => { None => {
let value = to_value_ns(module_def)?; let (value, import) = to_value_ns(module_def)?;
Some(ResolveValueResult::ValueNs(value)) Some(ResolveValueResult::ValueNs(value, import))
} }
Some(idx) => { Some(idx) => {
let ty = match module_def.take_types()? { let (def, _, import) = module_def.take_types_full()?;
let ty = match def {
ModuleDefId::AdtId(it) => TypeNs::AdtId(it), ModuleDefId::AdtId(it) => TypeNs::AdtId(it),
ModuleDefId::TraitId(it) => TypeNs::TraitId(it), ModuleDefId::TraitId(it) => TypeNs::TraitId(it),
ModuleDefId::TraitAliasId(it) => TypeNs::TraitAliasId(it), ModuleDefId::TraitAliasId(it) => TypeNs::TraitAliasId(it),
@ -794,7 +818,7 @@ impl ModuleItemMap {
| ModuleDefId::MacroId(_) | ModuleDefId::MacroId(_)
| ModuleDefId::StaticId(_) => return None, | ModuleDefId::StaticId(_) => return None,
}; };
Some(ResolveValueResult::Partial(ty, idx)) Some(ResolveValueResult::Partial(ty, idx, import))
} }
} }
} }
@ -803,16 +827,17 @@ impl ModuleItemMap {
&self, &self,
db: &dyn DefDatabase, db: &dyn DefDatabase,
path: &ModPath, path: &ModPath,
) -> Option<(TypeNs, Option<usize>)> { ) -> Option<(TypeNs, Option<usize>, Option<ImportOrExternCrate>)> {
let (module_def, idx) = let (module_def, idx) =
self.def_map.resolve_path_locally(db, self.module_id, path, BuiltinShadowMode::Other); self.def_map.resolve_path_locally(db, self.module_id, path, BuiltinShadowMode::Other);
let res = to_type_ns(module_def)?; let (res, import) = to_type_ns(module_def)?;
Some((res, idx)) Some((res, idx, import))
} }
} }
fn to_value_ns(per_ns: PerNs) -> Option<ValueNs> { fn to_value_ns(per_ns: PerNs) -> Option<(ValueNs, Option<ImportId>)> {
let res = match per_ns.take_values()? { let (def, import) = per_ns.take_values_import()?;
let res = match def {
ModuleDefId::FunctionId(it) => ValueNs::FunctionId(it), ModuleDefId::FunctionId(it) => ValueNs::FunctionId(it),
ModuleDefId::AdtId(AdtId::StructId(it)) => ValueNs::StructId(it), ModuleDefId::AdtId(AdtId::StructId(it)) => ValueNs::StructId(it),
ModuleDefId::EnumVariantId(it) => ValueNs::EnumVariantId(it), ModuleDefId::EnumVariantId(it) => ValueNs::EnumVariantId(it),
@ -827,11 +852,12 @@ fn to_value_ns(per_ns: PerNs) -> Option<ValueNs> {
| ModuleDefId::MacroId(_) | ModuleDefId::MacroId(_)
| ModuleDefId::ModuleId(_) => return None, | ModuleDefId::ModuleId(_) => return None,
}; };
Some(res) Some((res, import))
} }
fn to_type_ns(per_ns: PerNs) -> Option<TypeNs> { fn to_type_ns(per_ns: PerNs) -> Option<(TypeNs, Option<ImportOrExternCrate>)> {
let res = match per_ns.take_types()? { let (def, _, import) = per_ns.take_types_full()?;
let res = match def {
ModuleDefId::AdtId(it) => TypeNs::AdtId(it), ModuleDefId::AdtId(it) => TypeNs::AdtId(it),
ModuleDefId::EnumVariantId(it) => TypeNs::EnumVariantId(it), ModuleDefId::EnumVariantId(it) => TypeNs::EnumVariantId(it),
@ -847,7 +873,7 @@ fn to_type_ns(per_ns: PerNs) -> Option<TypeNs> {
| ModuleDefId::StaticId(_) | ModuleDefId::StaticId(_)
| ModuleDefId::ModuleId(_) => return None, | ModuleDefId::ModuleId(_) => return None,
}; };
Some(res) Some((res, import))
} }
type FxIndexMap<K, V> = IndexMap<K, V, BuildHasherDefault<rustc_hash::FxHasher>>; type FxIndexMap<K, V> = IndexMap<K, V, BuildHasherDefault<rustc_hash::FxHasher>>;

View File

@ -75,7 +75,7 @@ fn walk_unsafe(
Expr::Path(path) => { Expr::Path(path) => {
let resolver = resolver_for_expr(db.upcast(), def, current); let resolver = resolver_for_expr(db.upcast(), def, current);
let value_or_partial = resolver.resolve_path_in_value_ns(db.upcast(), path); let value_or_partial = resolver.resolve_path_in_value_ns(db.upcast(), path);
if let Some(ResolveValueResult::ValueNs(ValueNs::StaticId(id))) = value_or_partial { if let Some(ResolveValueResult::ValueNs(ValueNs::StaticId(id), _)) = value_or_partial {
if db.static_data(id).mutable { if db.static_data(id).mutable {
unsafe_expr_cb(UnsafeExpr { expr: current, inside_unsafe_block }); unsafe_expr_cb(UnsafeExpr { expr: current, inside_unsafe_block });
} }

View File

@ -1017,7 +1017,7 @@ impl<'a> InferenceContext<'a> {
let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver, self.owner.into()); let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver, self.owner.into());
let (resolution, unresolved) = if value_ns { let (resolution, unresolved) = if value_ns {
match self.resolver.resolve_path_in_value_ns(self.db.upcast(), path) { match self.resolver.resolve_path_in_value_ns(self.db.upcast(), path) {
Some(ResolveValueResult::ValueNs(value)) => match value { Some(ResolveValueResult::ValueNs(value, _)) => match value {
ValueNs::EnumVariantId(var) => { ValueNs::EnumVariantId(var) => {
let substs = ctx.substs_from_path(path, var.into(), true); let substs = ctx.substs_from_path(path, var.into(), true);
let ty = self.db.ty(var.parent.into()); let ty = self.db.ty(var.parent.into());
@ -1033,12 +1033,14 @@ impl<'a> InferenceContext<'a> {
ValueNs::ImplSelf(impl_id) => (TypeNs::SelfType(impl_id), None), ValueNs::ImplSelf(impl_id) => (TypeNs::SelfType(impl_id), None),
_ => return (self.err_ty(), None), _ => return (self.err_ty(), None),
}, },
Some(ResolveValueResult::Partial(typens, unresolved)) => (typens, Some(unresolved)), Some(ResolveValueResult::Partial(typens, unresolved, _)) => {
(typens, Some(unresolved))
}
None => return (self.err_ty(), None), None => return (self.err_ty(), None),
} }
} else { } else {
match self.resolver.resolve_path_in_type_ns(self.db.upcast(), path) { match self.resolver.resolve_path_in_type_ns(self.db.upcast(), path) {
Some(it) => it, Some((it, idx, _)) => (it, idx),
None => return (self.err_ty(), None), None => return (self.err_ty(), None),
} }
}; };

View File

@ -322,7 +322,7 @@ impl InferenceContext<'_> {
Expr::Path(p) => { Expr::Path(p) => {
let resolver = resolver_for_expr(self.db.upcast(), self.owner, tgt_expr); let resolver = resolver_for_expr(self.db.upcast(), self.owner, tgt_expr);
if let Some(r) = resolver.resolve_path_in_value_ns(self.db.upcast(), p) { if let Some(r) = resolver.resolve_path_in_value_ns(self.db.upcast(), p) {
if let ResolveValueResult::ValueNs(v) = r { if let ResolveValueResult::ValueNs(v, _) = r {
if let ValueNs::LocalBinding(b) = v { if let ValueNs::LocalBinding(b) = v {
return Some(HirPlace { local: b, projections: vec![] }); return Some(HirPlace { local: b, projections: vec![] });
} }

View File

@ -61,8 +61,8 @@ impl InferenceContext<'_> {
self.resolver.resolve_path_in_value_ns(self.db.upcast(), path)?; self.resolver.resolve_path_in_value_ns(self.db.upcast(), path)?;
match value_or_partial { match value_or_partial {
ResolveValueResult::ValueNs(it) => (it, None), ResolveValueResult::ValueNs(it, _) => (it, None),
ResolveValueResult::Partial(def, remaining_index) => self ResolveValueResult::Partial(def, remaining_index, _) => self
.resolve_assoc_item(def, path, remaining_index, id) .resolve_assoc_item(def, path, remaining_index, id)
.map(|(it, substs)| (it, Some(substs)))?, .map(|(it, substs)| (it, Some(substs)))?,
} }

View File

@ -390,11 +390,9 @@ impl<'a> TyLoweringContext<'a> {
let ty = { let ty = {
let macro_call = macro_call.to_node(self.db.upcast()); let macro_call = macro_call.to_node(self.db.upcast());
let resolver = |path| { let resolver = |path| {
self.resolver.resolve_path_as_macro( self.resolver
self.db.upcast(), .resolve_path_as_macro(self.db.upcast(), &path, Some(MacroSubNs::Bang))
&path, .map(|(it, _)| it)
Some(MacroSubNs::Bang),
)
}; };
match expander.enter_expand::<ast::Type>(self.db.upcast(), macro_call, resolver) match expander.enter_expand::<ast::Type>(self.db.upcast(), macro_call, resolver)
{ {
@ -446,7 +444,7 @@ impl<'a> TyLoweringContext<'a> {
return None; return None;
} }
let resolution = match self.resolver.resolve_path_in_type_ns(self.db.upcast(), path) { let resolution = match self.resolver.resolve_path_in_type_ns(self.db.upcast(), path) {
Some((it, None)) => it, Some((it, None, _)) => it,
_ => return None, _ => return None,
}; };
match resolution { match resolution {
@ -626,7 +624,7 @@ impl<'a> TyLoweringContext<'a> {
return self.lower_ty_relative_path(ty, res, path.segments()); return self.lower_ty_relative_path(ty, res, path.segments());
} }
let (resolution, remaining_index) = let (resolution, remaining_index, _) =
match self.resolver.resolve_path_in_type_ns(self.db.upcast(), path) { match self.resolver.resolve_path_in_type_ns(self.db.upcast(), path) {
Some(it) => it, Some(it) => it,
None => return (TyKind::Error.intern(Interner), None), None => return (TyKind::Error.intern(Interner), None),

View File

@ -1352,14 +1352,14 @@ impl<'ctx> MirLowerCtx<'ctx> {
.resolve_path_in_value_ns(self.db.upcast(), c) .resolve_path_in_value_ns(self.db.upcast(), c)
.ok_or_else(unresolved_name)?; .ok_or_else(unresolved_name)?;
match pr { match pr {
ResolveValueResult::ValueNs(v) => { ResolveValueResult::ValueNs(v, _) => {
if let ValueNs::ConstId(c) = v { if let ValueNs::ConstId(c) = v {
self.lower_const_to_operand(Substitution::empty(Interner), c.into(), ty) self.lower_const_to_operand(Substitution::empty(Interner), c.into(), ty)
} else { } else {
not_supported!("bad path in range pattern"); not_supported!("bad path in range pattern");
} }
} }
ResolveValueResult::Partial(_, _) => { ResolveValueResult::Partial(_, _, _) => {
not_supported!("associated constants in range pattern") not_supported!("associated constants in range pattern")
} }
} }

View File

@ -323,7 +323,7 @@ impl MirLowerCtx<'_> {
break 'b (c, x.1); break 'b (c, x.1);
} }
} }
if let ResolveValueResult::ValueNs(v) = pr { if let ResolveValueResult::ValueNs(v, _) = pr {
if let ValueNs::ConstId(c) = v { if let ValueNs::ConstId(c) = v {
break 'b (c, Substitution::empty(Interner)); break 'b (c, Substitution::empty(Interner));
} }

View File

@ -606,7 +606,7 @@ impl<'db> SemanticsImpl<'db> {
let macro_call_id = macro_call.as_call_id(self.db.upcast(), krate, |path| { let macro_call_id = macro_call.as_call_id(self.db.upcast(), krate, |path| {
resolver resolver
.resolve_path_as_macro(self.db.upcast(), &path, Some(MacroSubNs::Bang)) .resolve_path_as_macro(self.db.upcast(), &path, Some(MacroSubNs::Bang))
.map(|it| macro_id_to_def_id(self.db.upcast(), it)) .map(|(it, _)| macro_id_to_def_id(self.db.upcast(), it))
})?; })?;
hir_expand::db::expand_speculative( hir_expand::db::expand_speculative(
self.db.upcast(), self.db.upcast(),

View File

@ -487,7 +487,7 @@ impl SourceAnalyzer {
let path = macro_call.value.path().and_then(|ast| Path::from_src(ast, &ctx))?; let path = macro_call.value.path().and_then(|ast| Path::from_src(ast, &ctx))?;
self.resolver self.resolver
.resolve_path_as_macro(db.upcast(), path.mod_path()?, Some(MacroSubNs::Bang)) .resolve_path_as_macro(db.upcast(), path.mod_path()?, Some(MacroSubNs::Bang))
.map(|it| it.into()) .map(|(it, _)| it.into())
} }
pub(crate) fn resolve_bind_pat_to_const( pub(crate) fn resolve_bind_pat_to_const(
@ -760,7 +760,7 @@ impl SourceAnalyzer {
let macro_call_id = macro_call.as_call_id(db.upcast(), krate, |path| { let macro_call_id = macro_call.as_call_id(db.upcast(), krate, |path| {
self.resolver self.resolver
.resolve_path_as_macro(db.upcast(), &path, Some(MacroSubNs::Bang)) .resolve_path_as_macro(db.upcast(), &path, Some(MacroSubNs::Bang))
.map(|it| macro_id_to_def_id(db.upcast(), it)) .map(|(it, _)| macro_id_to_def_id(db.upcast(), it))
})?; })?;
Some(macro_call_id.as_file()).filter(|it| it.expansion_level(db.upcast()) < 64) Some(macro_call_id.as_file()).filter(|it| it.expansion_level(db.upcast()) < 64)
} }
@ -966,6 +966,7 @@ pub(crate) fn resolve_hir_path_as_attr_macro(
) -> Option<Macro> { ) -> Option<Macro> {
resolver resolver
.resolve_path_as_macro(db.upcast(), path.mod_path()?, Some(MacroSubNs::Attr)) .resolve_path_as_macro(db.upcast(), path.mod_path()?, Some(MacroSubNs::Attr))
.map(|(it, _)| it)
.map(Into::into) .map(Into::into)
} }
@ -983,7 +984,7 @@ fn resolve_hir_path_(
res.map(|ty_ns| (ty_ns, path.segments().first())) res.map(|ty_ns| (ty_ns, path.segments().first()))
} }
None => { None => {
let (ty, remaining_idx) = resolver.resolve_path_in_type_ns(db.upcast(), path)?; let (ty, remaining_idx, _) = resolver.resolve_path_in_type_ns(db.upcast(), path)?;
match remaining_idx { match remaining_idx {
Some(remaining_idx) => { Some(remaining_idx) => {
if remaining_idx + 1 == path.segments().len() { if remaining_idx + 1 == path.segments().len() {
@ -1067,7 +1068,7 @@ fn resolve_hir_path_(
let macros = || { let macros = || {
resolver resolver
.resolve_path_as_macro(db.upcast(), path.mod_path()?, None) .resolve_path_as_macro(db.upcast(), path.mod_path()?, None)
.map(|def| PathResolution::Def(ModuleDef::Macro(def.into()))) .map(|(def, _)| PathResolution::Def(ModuleDef::Macro(def.into())))
}; };
if prefer_value_ns { values().or_else(types) } else { types().or_else(values) } if prefer_value_ns { values().or_else(types) } else { types().or_else(values) }