about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2023-08-17 10:52:13 +0200
committerLukas Wirth <lukastw97@gmail.com>2023-08-17 10:52:13 +0200
commita17d73ad36baaec68078fe8b44c0b43e94a8e46a (patch)
tree5a673adfa89f06cc72ec1e0cdc1bc31f8963f754
parentc4e9b5ac649c62a46110660b612776468ba0d07f (diff)
downloadrust-a17d73ad36baaec68078fe8b44c0b43e94a8e46a.tar.gz
rust-a17d73ad36baaec68078fe8b44c0b43e94a8e46a.zip
Thread imports through the resolver
-rw-r--r--crates/hir-def/src/item_scope.rs60
-rw-r--r--crates/hir-def/src/macro_expansion_tests/mod.rs2
-rw-r--r--crates/hir-def/src/nameres/collector.rs13
-rw-r--r--crates/hir-def/src/nameres/path_resolution.rs76
-rw-r--r--crates/hir-def/src/per_ns.rs37
-rw-r--r--crates/hir-def/src/resolver.rs116
-rw-r--r--crates/hir-ty/src/diagnostics/unsafe_check.rs2
-rw-r--r--crates/hir-ty/src/infer.rs8
-rw-r--r--crates/hir-ty/src/infer/closure.rs2
-rw-r--r--crates/hir-ty/src/infer/path.rs4
-rw-r--r--crates/hir-ty/src/lower.rs12
-rw-r--r--crates/hir-ty/src/mir/lower.rs4
-rw-r--r--crates/hir-ty/src/mir/lower/pattern_matching.rs2
-rw-r--r--crates/hir/src/semantics.rs2
-rw-r--r--crates/hir/src/source_analyzer.rs9
15 files changed, 218 insertions, 131 deletions
diff --git a/crates/hir-def/src/item_scope.rs b/crates/hir-def/src/item_scope.rs
index 59a1c5f49e2..0baf3fa7f44 100644
--- a/crates/hir-def/src/item_scope.rs
+++ b/crates/hir-def/src/item_scope.rs
@@ -34,7 +34,7 @@ pub enum ImportOrExternCrate {
 }
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
-pub enum ImportType {
+pub(crate) enum ImportType {
     Import(ImportId),
     Glob(UseId),
     ExternCrate(ExternCrateId),
@@ -118,7 +118,7 @@ struct DeriveMacroInvocation {
 pub(crate) static BUILTIN_SCOPE: Lazy<FxHashMap<Name, PerNs>> = Lazy::new(|| {
     BuiltinType::ALL
         .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()
 });
 
@@ -234,9 +234,16 @@ impl ItemScope {
 
     pub(crate) fn resolutions(&self) -> impl Iterator<Item = (Option<Name>, PerNs)> + '_ {
         self.entries().map(|(name, res)| (Some(name.clone()), res)).chain(
-            self.unnamed_trait_imports
-                .iter()
-                .map(|(tr, (vis, _))| (None, PerNs::types(ModuleDefId::TraitId(*tr), *vis))),
+            self.unnamed_trait_imports.iter().map(|(tr, (vis, i))| {
+                (
+                    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> {
         self.unnamed_trait_imports.get(&tr).copied().map(|(a, _)| a)
     }
 
     pub(crate) fn push_unnamed_trait(&mut self, tr: TraitId, vis: Visibility) {
+        // FIXME: import
         self.unnamed_trait_imports.insert(tr, (vis, None));
     }
 
@@ -344,6 +353,8 @@ impl ItemScope {
     ) -> bool {
         let mut changed = false;
 
+        // FIXME: Document and simplify this
+
         if let Some(mut fld) = def.types {
             let existing = self.types.entry(lookup.1.clone());
             match existing {
@@ -626,28 +637,39 @@ impl ItemScope {
 }
 
 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 {
-            ModuleDefId::ModuleId(_) => PerNs::types(def, v),
-            ModuleDefId::FunctionId(_) => PerNs::values(def, v),
+            ModuleDefId::ModuleId(_) => PerNs::types(def, v, import),
+            ModuleDefId::FunctionId(_) => {
+                PerNs::values(def, v, import.and_then(ImportOrExternCrate::into_import))
+            }
             ModuleDefId::AdtId(adt) => match adt {
-                AdtId::UnionId(_) => PerNs::types(def, v),
-                AdtId::EnumId(_) => PerNs::types(def, v),
+                AdtId::UnionId(_) => PerNs::types(def, v, import),
+                AdtId::EnumId(_) => PerNs::types(def, v, import),
                 AdtId::StructId(_) => {
                     if has_constructor {
-                        PerNs::both(def, def, v)
+                        PerNs::both(def, def, v, import)
                     } else {
-                        PerNs::types(def, v)
+                        PerNs::types(def, v, import)
                     }
                 }
             },
-            ModuleDefId::EnumVariantId(_) => PerNs::both(def, def, v),
-            ModuleDefId::ConstId(_) | ModuleDefId::StaticId(_) => PerNs::values(def, v),
-            ModuleDefId::TraitId(_) => PerNs::types(def, v),
-            ModuleDefId::TraitAliasId(_) => PerNs::types(def, v),
-            ModuleDefId::TypeAliasId(_) => PerNs::types(def, v),
-            ModuleDefId::BuiltinType(_) => PerNs::types(def, v),
-            ModuleDefId::MacroId(mac) => PerNs::macros(mac, v),
+            ModuleDefId::EnumVariantId(_) => PerNs::both(def, def, v, import),
+            ModuleDefId::ConstId(_) | ModuleDefId::StaticId(_) => {
+                PerNs::values(def, v, import.and_then(ImportOrExternCrate::into_import))
+            }
+            ModuleDefId::TraitId(_) => PerNs::types(def, v, import),
+            ModuleDefId::TraitAliasId(_) => PerNs::types(def, v, import),
+            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))
+            }
         }
     }
 }
diff --git a/crates/hir-def/src/macro_expansion_tests/mod.rs b/crates/hir-def/src/macro_expansion_tests/mod.rs
index 7a87e61c693..8adced4e082 100644
--- a/crates/hir-def/src/macro_expansion_tests/mod.rs
+++ b/crates/hir-def/src/macro_expansion_tests/mod.rs
@@ -131,7 +131,7 @@ pub fn identity_when_valid(_attr: TokenStream, item: TokenStream) -> TokenStream
             .as_call_id_with_errors(&db, krate, |path| {
                 resolver
                     .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();
         let macro_call_id = res.value.unwrap();
diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs
index 48eaec0f4e5..e9e71a8747f 100644
--- a/crates/hir-def/src/nameres/collector.rs
+++ b/crates/hir-def/src/nameres/collector.rs
@@ -648,7 +648,7 @@ impl DefCollector<'_> {
             self.def_map.modules[module_id].scope.declare(macro_.into());
             self.update(
                 module_id,
-                &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public))],
+                &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public, None))],
                 Visibility::Public,
                 None,
             );
@@ -684,7 +684,7 @@ impl DefCollector<'_> {
         self.def_map.modules[module_id].scope.declare(macro_.into());
         self.update(
             module_id,
-            &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public))],
+            &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public, None))],
             vis,
             None,
         );
@@ -699,7 +699,7 @@ impl DefCollector<'_> {
         self.def_map.modules[module_id].scope.declare(macro_.into());
         self.update(
             module_id,
-            &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public))],
+            &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public, None))],
             Visibility::Public,
             None,
         );
@@ -783,6 +783,7 @@ impl DefCollector<'_> {
                     Some(res) => PartialResolvedImport::Resolved(PerNs::types(
                         res.into(),
                         Visibility::Public,
+                        None,
                     )),
                     None => PartialResolvedImport::Unresolved,
                 }
@@ -967,7 +968,7 @@ impl DefCollector<'_> {
                             .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);
+                                let res = PerNs::both(variant.into(), variant.into(), vis, None);
                                 (Some(name), res)
                             })
                             .collect::<Vec<_>>();
@@ -1547,7 +1548,7 @@ impl ModCollector<'_, '_> {
                 def_collector.def_map.modules[module_id].scope.declare(id);
                 def_collector.update(
                     module_id,
-                    &[(Some(name.clone()), PerNs::from_def(id, vis, has_constructor))],
+                    &[(Some(name.clone()), PerNs::from_def(id, vis, has_constructor, None))],
                     vis,
                     None,
                 )
@@ -1977,7 +1978,7 @@ impl ModCollector<'_, '_> {
         def_map.modules[self.module_id].scope.declare(def);
         self.def_collector.update(
             self.module_id,
-            &[(Some(name), PerNs::from_def(def, vis, false))],
+            &[(Some(name), PerNs::from_def(def, vis, false, None))],
             vis,
             None,
         );
diff --git a/crates/hir-def/src/nameres/path_resolution.rs b/crates/hir-def/src/nameres/path_resolution.rs
index fc296e1e588..460a908b6db 100644
--- a/crates/hir-def/src/nameres/path_resolution.rs
+++ b/crates/hir-def/src/nameres/path_resolution.rs
@@ -15,8 +15,9 @@ use hir_expand::name::Name;
 use triomphe::Arc;
 
 use crate::{
+    data::adt::VariantData,
     db::DefDatabase,
-    item_scope::BUILTIN_SCOPE,
+    item_scope::{ImportOrExternCrate, BUILTIN_SCOPE},
     nameres::{sub_namespace_match, BlockInfo, BuiltinShadowMode, DefMap, MacroSubNs},
     path::{ModPath, PathKind},
     per_ns::PerNs,
@@ -196,15 +197,15 @@ impl DefMap {
             PathKind::DollarCrate(krate) => {
                 if krate == self.krate {
                     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 {
                     let def_map = db.crate_def_map(krate);
                     let module = def_map.module_id(Self::ROOT);
                     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
             // fallback to extern prelude (with the simplification in
             // 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 => {
                 // 2018-style absolute path -- only extern prelude
@@ -299,9 +300,13 @@ impl DefMap {
                     Some((_, segment)) => segment,
                     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);
-                    PerNs::types(def.into(), Visibility::Public)
+                    PerNs::types(
+                        def.into(),
+                        Visibility::Public,
+                        extern_crate.map(ImportOrExternCrate::ExternCrate),
+                    )
                 } else {
                     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 {
-            let (curr, vis) = match curr_per_ns.take_types_vis() {
+            let (curr, vis, imp) = match curr_per_ns.take_types_full() {
                 Some(r) => r,
                 None => {
                     // we still have path segments left, but the path so far
@@ -364,18 +369,20 @@ impl DefMap {
                         Some(local_id) => {
                             let variant = EnumVariantId { parent: e, local_id };
                             match &*enum_data.variants[local_id].variant_data {
-                                crate::data::adt::VariantData::Record(_) => {
-                                    PerNs::types(variant.into(), Visibility::Public)
-                                }
-                                crate::data::adt::VariantData::Tuple(_)
-                                | crate::data::adt::VariantData::Unit => {
-                                    PerNs::both(variant.into(), variant.into(), Visibility::Public)
+                                VariantData::Record(_) => {
+                                    PerNs::types(variant.into(), Visibility::Public, None)
                                 }
+                                VariantData::Tuple(_) | VariantData::Unit => PerNs::both(
+                                    variant.into(),
+                                    variant.into(),
+                                    Visibility::Public,
+                                    None,
+                                ),
                             }
                         }
                         None => {
                             return ResolvePathResult::with(
-                                PerNs::types(e.into(), vis),
+                                PerNs::types(e.into(), vis, imp),
                                 ReachedFixedPoint::Yes,
                                 Some(i),
                                 Some(self.krate),
@@ -393,7 +400,7 @@ impl DefMap {
                     );
 
                     return ResolvePathResult::with(
-                        PerNs::types(s, vis),
+                        PerNs::types(s, vis, imp),
                         ReachedFixedPoint::Yes,
                         Some(i),
                         Some(self.krate),
@@ -430,7 +437,7 @@ impl DefMap {
             .filter(|&id| {
                 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_builtin = match self.block {
             Some(_) => {
@@ -449,16 +456,26 @@ impl DefMap {
 
         let extern_prelude = || {
             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();
             }
-            self.data.extern_prelude.get(name).map_or(PerNs::none(), |&(it, _extern_crate)| {
-                PerNs::types(it.into(), Visibility::Public)
+            self.data.extern_prelude.get(name).map_or(PerNs::none(), |&(it, extern_crate)| {
+                PerNs::types(
+                    it.into(),
+                    Visibility::Public,
+                    extern_crate.map(ImportOrExternCrate::ExternCrate),
+                )
             })
         };
         let macro_use_prelude = || {
             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);
@@ -487,13 +504,16 @@ impl DefMap {
                 // Don't resolve extern prelude in block `DefMap`s.
                 return PerNs::none();
             }
-            self.data
-                .extern_prelude
-                .get(name)
-                .copied()
-                .map_or(PerNs::none(), |(it, _extern_crate)| {
-                    PerNs::types(it.into(), Visibility::Public)
-                })
+            self.data.extern_prelude.get(name).copied().map_or(
+                PerNs::none(),
+                |(it, extern_crate)| {
+                    PerNs::types(
+                        it.into(),
+                        Visibility::Public,
+                        extern_crate.map(ImportOrExternCrate::ExternCrate),
+                    )
+                },
+            )
         };
 
         from_crate_root.or_else(from_extern_prelude)
diff --git a/crates/hir-def/src/per_ns.rs b/crates/hir-def/src/per_ns.rs
index f32a97d1a3a..3f3f9f42491 100644
--- a/crates/hir-def/src/per_ns.rs
+++ b/crates/hir-def/src/per_ns.rs
@@ -27,20 +27,29 @@ impl PerNs {
         PerNs { types: None, values: None, macros: None }
     }
 
-    pub fn values(t: ModuleDefId, v: Visibility) -> PerNs {
-        PerNs { types: None, values: Some((t, v, None)), macros: None }
+    pub fn values(t: ModuleDefId, v: Visibility, i: Option<ImportId>) -> PerNs {
+        PerNs { types: None, values: Some((t, v, i)), macros: None }
     }
 
-    pub fn types(t: ModuleDefId, v: Visibility) -> PerNs {
-        PerNs { types: Some((t, v, None)), values: None, macros: None }
+    pub fn types(t: ModuleDefId, v: Visibility, i: Option<ImportOrExternCrate>) -> PerNs {
+        PerNs { types: Some((t, v, i)), values: None, macros: None }
     }
 
-    pub fn both(types: ModuleDefId, values: ModuleDefId, v: Visibility) -> PerNs {
-        PerNs { types: Some((types, v, None)), values: Some((values, v, None)), macros: None }
+    pub fn both(
+        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 {
-        PerNs { types: None, values: None, macros: Some((macro_, v, None)) }
+    pub fn macros(macro_: MacroId, v: Visibility, i: Option<ImportId>) -> PerNs {
+        PerNs { types: None, values: None, macros: Some((macro_, v, i)) }
     }
 
     pub fn is_none(&self) -> bool {
@@ -55,18 +64,26 @@ impl PerNs {
         self.types.map(|it| it.0)
     }
 
-    pub fn take_types_vis(self) -> Option<(ModuleDefId, Visibility)> {
-        self.types.map(|(a, b, _)| (a, b))
+    pub fn take_types_full(self) -> Option<(ModuleDefId, Visibility, Option<ImportOrExternCrate>)> {
+        self.types
     }
 
     pub fn take_values(self) -> Option<ModuleDefId> {
         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> {
         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 {
         let _p = profile::span("PerNs::filter_visibility");
         PerNs {
diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs
index 28ab0f8f6ee..62576100ea4 100644
--- a/crates/hir-def/src/resolver.rs
+++ b/crates/hir-def/src/resolver.rs
@@ -15,7 +15,7 @@ use crate::{
     db::DefDatabase,
     generics::{GenericParams, TypeOrConstParamData},
     hir::{BindingId, ExprId, LabelId},
-    item_scope::{BuiltinShadowMode, BUILTIN_SCOPE},
+    item_scope::{BuiltinShadowMode, ImportId, ImportOrExternCrate, BUILTIN_SCOPE},
     lang_item::LangItemTarget,
     nameres::{DefMap, MacroSubNs},
     path::{ModPath, Path, PathKind},
@@ -100,8 +100,8 @@ pub enum TypeNs {
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub enum ResolveValueResult {
-    ValueNs(ValueNs),
-    Partial(TypeNs, usize),
+    ValueNs(ValueNs, Option<ImportId>),
+    Partial(TypeNs, usize, Option<ImportOrExternCrate>),
 }
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
@@ -152,7 +152,7 @@ impl Resolver {
         &self,
         db: &dyn DefDatabase,
         path: &Path,
-    ) -> Option<(TypeNs, Option<usize>)> {
+    ) -> Option<(TypeNs, Option<usize>, Option<ImportOrExternCrate>)> {
         let path = match path {
             Path::Normal { mod_path, .. } => mod_path,
             Path::LangItem(l) => {
@@ -169,6 +169,7 @@ impl Resolver {
                         | LangItemTarget::Static(_) => return None,
                     },
                     None,
+                    None,
                 ))
             }
         };
@@ -185,17 +186,17 @@ impl Resolver {
                 Scope::ExprScope(_) => continue,
                 Scope::GenericParams { params, 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_) => {
                     if first_name == &name![Self] {
-                        return Some((TypeNs::SelfType(impl_), remaining_idx()));
+                        return Some((TypeNs::SelfType(impl_), remaining_idx(), None));
                     }
                 }
                 &Scope::AdtScope(adt) => {
                     if first_name == &name![Self] {
-                        return Some((TypeNs::AdtSelfType(adt), remaining_idx()));
+                        return Some((TypeNs::AdtSelfType(adt), remaining_idx(), None));
                     }
                 }
                 Scope::BlockScope(m) => {
@@ -208,12 +209,24 @@ impl Resolver {
         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(
         &self,
         db: &dyn DefDatabase,
         path: &Path,
     ) -> 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() {
             return None;
         }
@@ -235,7 +248,6 @@ impl Resolver {
             RawVisibility::Public => Some(Visibility::Public),
         }
     }
-
     pub fn resolve_path_in_value_ns(
         &self,
         db: &dyn DefDatabase,
@@ -244,17 +256,20 @@ impl Resolver {
         let path = match path {
             Path::Normal { mod_path, .. } => mod_path,
             Path::LangItem(l) => {
-                return Some(ResolveValueResult::ValueNs(match *l {
-                    LangItemTarget::Function(it) => ValueNs::FunctionId(it),
-                    LangItemTarget::Static(it) => ValueNs::StaticId(it),
-                    LangItemTarget::Struct(it) => ValueNs::StructId(it),
-                    LangItemTarget::EnumVariant(it) => ValueNs::EnumVariantId(it),
-                    LangItemTarget::Union(_)
-                    | LangItemTarget::ImplDef(_)
-                    | LangItemTarget::TypeAlias(_)
-                    | LangItemTarget::Trait(_)
-                    | LangItemTarget::EnumId(_) => return None,
-                }))
+                return Some(ResolveValueResult::ValueNs(
+                    match *l {
+                        LangItemTarget::Function(it) => ValueNs::FunctionId(it),
+                        LangItemTarget::Static(it) => ValueNs::StaticId(it),
+                        LangItemTarget::Struct(it) => ValueNs::StructId(it),
+                        LangItemTarget::EnumVariant(it) => ValueNs::EnumVariantId(it),
+                        LangItemTarget::Union(_)
+                        | LangItemTarget::ImplDef(_)
+                        | LangItemTarget::TypeAlias(_)
+                        | LangItemTarget::Trait(_)
+                        | LangItemTarget::EnumId(_) => return None,
+                    },
+                    None,
+                ))
             }
         };
         let n_segments = path.segments().len();
@@ -276,20 +291,24 @@ impl Resolver {
                             .find(|entry| entry.name() == first_name);
 
                         if let Some(e) = entry {
-                            return Some(ResolveValueResult::ValueNs(ValueNs::LocalBinding(
-                                e.binding(),
-                            )));
+                            return Some(ResolveValueResult::ValueNs(
+                                ValueNs::LocalBinding(e.binding()),
+                                None,
+                            ));
                         }
                     }
                     Scope::GenericParams { params, def } => {
                         if let Some(id) = params.find_const_by_name(first_name, *def) {
                             let val = ValueNs::GenericParam(id);
-                            return Some(ResolveValueResult::ValueNs(val));
+                            return Some(ResolveValueResult::ValueNs(val, None));
                         }
                     }
                     &Scope::ImplDefScope(impl_) => {
                         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
@@ -308,18 +327,22 @@ impl Resolver {
                     Scope::GenericParams { params, def } => {
                         if let Some(id) = params.find_type_by_name(first_name, *def) {
                             let ty = TypeNs::GenericParam(id);
-                            return Some(ResolveValueResult::Partial(ty, 1));
+                            return Some(ResolveValueResult::Partial(ty, 1, None));
                         }
                     }
                     &Scope::ImplDefScope(impl_) => {
                         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) => {
                         if first_name == &name![Self] {
                             let ty = TypeNs::AdtSelfType(*adt);
-                            return Some(ResolveValueResult::Partial(ty, 1));
+                            return Some(ResolveValueResult::Partial(ty, 1, None));
                         }
                     }
                     Scope::BlockScope(m) => {
@@ -340,7 +363,7 @@ impl Resolver {
         // `use core::u16;`.
         if path.kind == PathKind::Plain && n_segments > 1 {
             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,
     ) -> Option<ValueNs> {
         match self.resolve_path_in_value_ns(db, path)? {
-            ResolveValueResult::ValueNs(it) => Some(it),
+            ResolveValueResult::ValueNs(it, _) => Some(it),
             ResolveValueResult::Partial(..) => None,
         }
     }
@@ -363,12 +386,12 @@ impl Resolver {
         db: &dyn DefDatabase,
         path: &ModPath,
         expected_macro_kind: Option<MacroSubNs>,
-    ) -> Option<MacroId> {
+    ) -> Option<(MacroId, Option<ImportId>)> {
         let (item_map, module) = self.item_scope();
         item_map
             .resolve_path(db, module, path, BuiltinShadowMode::Other, expected_macro_kind)
             .0
-            .take_macros()
+            .take_macros_import()
     }
 
     /// 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);
         match idx {
             None => {
-                let value = to_value_ns(module_def)?;
-                Some(ResolveValueResult::ValueNs(value))
+                let (value, import) = to_value_ns(module_def)?;
+                Some(ResolveValueResult::ValueNs(value, import))
             }
             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::TraitId(it) => TypeNs::TraitId(it),
                     ModuleDefId::TraitAliasId(it) => TypeNs::TraitAliasId(it),
@@ -794,7 +818,7 @@ impl ModuleItemMap {
                     | ModuleDefId::MacroId(_)
                     | ModuleDefId::StaticId(_) => return None,
                 };
-                Some(ResolveValueResult::Partial(ty, idx))
+                Some(ResolveValueResult::Partial(ty, idx, import))
             }
         }
     }
@@ -803,16 +827,17 @@ impl ModuleItemMap {
         &self,
         db: &dyn DefDatabase,
         path: &ModPath,
-    ) -> Option<(TypeNs, Option<usize>)> {
+    ) -> Option<(TypeNs, Option<usize>, Option<ImportOrExternCrate>)> {
         let (module_def, idx) =
             self.def_map.resolve_path_locally(db, self.module_id, path, BuiltinShadowMode::Other);
-        let res = to_type_ns(module_def)?;
-        Some((res, idx))
+        let (res, import) = to_type_ns(module_def)?;
+        Some((res, idx, import))
     }
 }
 
-fn to_value_ns(per_ns: PerNs) -> Option<ValueNs> {
-    let res = match per_ns.take_values()? {
+fn to_value_ns(per_ns: PerNs) -> Option<(ValueNs, Option<ImportId>)> {
+    let (def, import) = per_ns.take_values_import()?;
+    let res = match def {
         ModuleDefId::FunctionId(it) => ValueNs::FunctionId(it),
         ModuleDefId::AdtId(AdtId::StructId(it)) => ValueNs::StructId(it),
         ModuleDefId::EnumVariantId(it) => ValueNs::EnumVariantId(it),
@@ -827,11 +852,12 @@ fn to_value_ns(per_ns: PerNs) -> Option<ValueNs> {
         | ModuleDefId::MacroId(_)
         | ModuleDefId::ModuleId(_) => return None,
     };
-    Some(res)
+    Some((res, import))
 }
 
-fn to_type_ns(per_ns: PerNs) -> Option<TypeNs> {
-    let res = match per_ns.take_types()? {
+fn to_type_ns(per_ns: PerNs) -> Option<(TypeNs, Option<ImportOrExternCrate>)> {
+    let (def, _, import) = per_ns.take_types_full()?;
+    let res = match def {
         ModuleDefId::AdtId(it) => TypeNs::AdtId(it),
         ModuleDefId::EnumVariantId(it) => TypeNs::EnumVariantId(it),
 
@@ -847,7 +873,7 @@ fn to_type_ns(per_ns: PerNs) -> Option<TypeNs> {
         | ModuleDefId::StaticId(_)
         | ModuleDefId::ModuleId(_) => return None,
     };
-    Some(res)
+    Some((res, import))
 }
 
 type FxIndexMap<K, V> = IndexMap<K, V, BuildHasherDefault<rustc_hash::FxHasher>>;
diff --git a/crates/hir-ty/src/diagnostics/unsafe_check.rs b/crates/hir-ty/src/diagnostics/unsafe_check.rs
index 9f9a56ffab0..cbca0e801d4 100644
--- a/crates/hir-ty/src/diagnostics/unsafe_check.rs
+++ b/crates/hir-ty/src/diagnostics/unsafe_check.rs
@@ -75,7 +75,7 @@ fn walk_unsafe(
         Expr::Path(path) => {
             let resolver = resolver_for_expr(db.upcast(), def, current);
             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 {
                     unsafe_expr_cb(UnsafeExpr { expr: current, inside_unsafe_block });
                 }
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs
index b4915dbf0f9..0fb4934444b 100644
--- a/crates/hir-ty/src/infer.rs
+++ b/crates/hir-ty/src/infer.rs
@@ -1017,7 +1017,7 @@ impl<'a> InferenceContext<'a> {
         let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver, self.owner.into());
         let (resolution, unresolved) = if value_ns {
             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) => {
                         let substs = ctx.substs_from_path(path, var.into(), true);
                         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),
                     _ => 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),
             }
         } else {
             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),
             }
         };
diff --git a/crates/hir-ty/src/infer/closure.rs b/crates/hir-ty/src/infer/closure.rs
index 1781f6c58f1..23efe616f4f 100644
--- a/crates/hir-ty/src/infer/closure.rs
+++ b/crates/hir-ty/src/infer/closure.rs
@@ -322,7 +322,7 @@ impl InferenceContext<'_> {
             Expr::Path(p) => {
                 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 ResolveValueResult::ValueNs(v) = r {
+                    if let ResolveValueResult::ValueNs(v, _) = r {
                         if let ValueNs::LocalBinding(b) = v {
                             return Some(HirPlace { local: b, projections: vec![] });
                         }
diff --git a/crates/hir-ty/src/infer/path.rs b/crates/hir-ty/src/infer/path.rs
index 79d9e21e797..2a51c84db3a 100644
--- a/crates/hir-ty/src/infer/path.rs
+++ b/crates/hir-ty/src/infer/path.rs
@@ -61,8 +61,8 @@ impl InferenceContext<'_> {
                 self.resolver.resolve_path_in_value_ns(self.db.upcast(), path)?;
 
             match value_or_partial {
-                ResolveValueResult::ValueNs(it) => (it, None),
-                ResolveValueResult::Partial(def, remaining_index) => self
+                ResolveValueResult::ValueNs(it, _) => (it, None),
+                ResolveValueResult::Partial(def, remaining_index, _) => self
                     .resolve_assoc_item(def, path, remaining_index, id)
                     .map(|(it, substs)| (it, Some(substs)))?,
             }
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs
index 20dccfafb38..0ab04b83cf8 100644
--- a/crates/hir-ty/src/lower.rs
+++ b/crates/hir-ty/src/lower.rs
@@ -390,11 +390,9 @@ impl<'a> TyLoweringContext<'a> {
                 let ty = {
                     let macro_call = macro_call.to_node(self.db.upcast());
                     let resolver = |path| {
-                        self.resolver.resolve_path_as_macro(
-                            self.db.upcast(),
-                            &path,
-                            Some(MacroSubNs::Bang),
-                        )
+                        self.resolver
+                            .resolve_path_as_macro(self.db.upcast(), &path, Some(MacroSubNs::Bang))
+                            .map(|(it, _)| it)
                     };
                     match expander.enter_expand::<ast::Type>(self.db.upcast(), macro_call, resolver)
                     {
@@ -446,7 +444,7 @@ impl<'a> TyLoweringContext<'a> {
             return None;
         }
         let resolution = match self.resolver.resolve_path_in_type_ns(self.db.upcast(), path) {
-            Some((it, None)) => it,
+            Some((it, None, _)) => it,
             _ => return None,
         };
         match resolution {
@@ -626,7 +624,7 @@ impl<'a> TyLoweringContext<'a> {
             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) {
                 Some(it) => it,
                 None => return (TyKind::Error.intern(Interner), None),
diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs
index 7ab0c1f7f2f..51cf882d053 100644
--- a/crates/hir-ty/src/mir/lower.rs
+++ b/crates/hir-ty/src/mir/lower.rs
@@ -1352,14 +1352,14 @@ impl<'ctx> MirLowerCtx<'ctx> {
                     .resolve_path_in_value_ns(self.db.upcast(), c)
                     .ok_or_else(unresolved_name)?;
                 match pr {
-                    ResolveValueResult::ValueNs(v) => {
+                    ResolveValueResult::ValueNs(v, _) => {
                         if let ValueNs::ConstId(c) = v {
                             self.lower_const_to_operand(Substitution::empty(Interner), c.into(), ty)
                         } else {
                             not_supported!("bad path in range pattern");
                         }
                     }
-                    ResolveValueResult::Partial(_, _) => {
+                    ResolveValueResult::Partial(_, _, _) => {
                         not_supported!("associated constants in range pattern")
                     }
                 }
diff --git a/crates/hir-ty/src/mir/lower/pattern_matching.rs b/crates/hir-ty/src/mir/lower/pattern_matching.rs
index 3354cbd76a0..1cdfd919742 100644
--- a/crates/hir-ty/src/mir/lower/pattern_matching.rs
+++ b/crates/hir-ty/src/mir/lower/pattern_matching.rs
@@ -323,7 +323,7 @@ impl MirLowerCtx<'_> {
                                 break 'b (c, x.1);
                             }
                         }
-                        if let ResolveValueResult::ValueNs(v) = pr {
+                        if let ResolveValueResult::ValueNs(v, _) = pr {
                             if let ValueNs::ConstId(c) = v {
                                 break 'b (c, Substitution::empty(Interner));
                             }
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index e99d2984c36..55760ba75ab 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -606,7 +606,7 @@ impl<'db> SemanticsImpl<'db> {
         let macro_call_id = macro_call.as_call_id(self.db.upcast(), krate, |path| {
             resolver
                 .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(
             self.db.upcast(),
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index 3499daf1140..f29fb1edf00 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -487,7 +487,7 @@ impl SourceAnalyzer {
         let path = macro_call.value.path().and_then(|ast| Path::from_src(ast, &ctx))?;
         self.resolver
             .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(
@@ -760,7 +760,7 @@ impl SourceAnalyzer {
         let macro_call_id = macro_call.as_call_id(db.upcast(), krate, |path| {
             self.resolver
                 .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)
     }
@@ -966,6 +966,7 @@ pub(crate) fn resolve_hir_path_as_attr_macro(
 ) -> Option<Macro> {
     resolver
         .resolve_path_as_macro(db.upcast(), path.mod_path()?, Some(MacroSubNs::Attr))
+        .map(|(it, _)| it)
         .map(Into::into)
 }
 
@@ -983,7 +984,7 @@ fn resolve_hir_path_(
                 res.map(|ty_ns| (ty_ns, path.segments().first()))
             }
             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 {
                     Some(remaining_idx) => {
                         if remaining_idx + 1 == path.segments().len() {
@@ -1067,7 +1068,7 @@ fn resolve_hir_path_(
     let macros = || {
         resolver
             .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) }