aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def/src/nameres/path_resolution.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_def/src/nameres/path_resolution.rs')
-rw-r--r--crates/hir_def/src/nameres/path_resolution.rs46
1 files changed, 32 insertions, 14 deletions
diff --git a/crates/hir_def/src/nameres/path_resolution.rs b/crates/hir_def/src/nameres/path_resolution.rs
index fdcdc23ae..db459b1ed 100644
--- a/crates/hir_def/src/nameres/path_resolution.rs
+++ b/crates/hir_def/src/nameres/path_resolution.rs
@@ -13,7 +13,6 @@
13use base_db::Edition; 13use base_db::Edition;
14use hir_expand::name; 14use hir_expand::name;
15use hir_expand::name::Name; 15use hir_expand::name::Name;
16use test_utils::mark;
17 16
18use crate::{ 17use crate::{
19 db::DefDatabase, 18 db::DefDatabase,
@@ -63,7 +62,7 @@ impl ResolvePathResult {
63impl DefMap { 62impl DefMap {
64 pub(super) fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs { 63 pub(super) fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs {
65 if name == &name!(self) { 64 if name == &name!(self) {
66 mark::hit!(extern_crate_self_as); 65 cov_mark::hit!(extern_crate_self_as);
67 return PerNs::types(self.module_id(self.root).into(), Visibility::Public); 66 return PerNs::types(self.module_id(self.root).into(), Visibility::Public);
68 } 67 }
69 self.extern_prelude 68 self.extern_prelude
@@ -77,7 +76,7 @@ impl DefMap {
77 original_module: LocalModuleId, 76 original_module: LocalModuleId,
78 visibility: &RawVisibility, 77 visibility: &RawVisibility,
79 ) -> Option<Visibility> { 78 ) -> Option<Visibility> {
80 match visibility { 79 let mut vis = match visibility {
81 RawVisibility::Module(path) => { 80 RawVisibility::Module(path) => {
82 let (result, remaining) = 81 let (result, remaining) =
83 self.resolve_path(db, original_module, &path, BuiltinShadowMode::Module); 82 self.resolve_path(db, original_module, &path, BuiltinShadowMode::Module);
@@ -86,15 +85,28 @@ impl DefMap {
86 } 85 }
87 let types = result.take_types()?; 86 let types = result.take_types()?;
88 match types { 87 match types {
89 ModuleDefId::ModuleId(m) => Some(Visibility::Module(m)), 88 ModuleDefId::ModuleId(m) => Visibility::Module(m),
90 _ => { 89 _ => {
91 // error: visibility needs to refer to module 90 // error: visibility needs to refer to module
92 None 91 return None;
93 } 92 }
94 } 93 }
95 } 94 }
96 RawVisibility::Public => Some(Visibility::Public), 95 RawVisibility::Public => Visibility::Public,
96 };
97
98 // In block expressions, `self` normally refers to the containing non-block module, and
99 // `super` to its parent (etc.). However, visibilities must only refer to a module in the
100 // DefMap they're written in, so we restrict them when that happens.
101 if let Visibility::Module(m) = vis {
102 if self.block_id() != m.block {
103 cov_mark::hit!(adjust_vis_in_block_def_map);
104 vis = Visibility::Module(self.module_id(self.root()));
105 log::debug!("visibility {:?} points outside DefMap, adjusting to {:?}", m, vis);
106 }
97 } 107 }
108
109 Some(vis)
98 } 110 }
99 111
100 // Returns Yes if we are sure that additions to `ItemMap` wouldn't change 112 // Returns Yes if we are sure that additions to `ItemMap` wouldn't change
@@ -144,7 +156,7 @@ impl DefMap {
144 } 156 }
145 } 157 }
146 158
147 pub(super) fn resolve_path_fp_with_macro_single( 159 fn resolve_path_fp_with_macro_single(
148 &self, 160 &self,
149 db: &dyn DefDatabase, 161 db: &dyn DefDatabase,
150 mode: ResolveMode, 162 mode: ResolveMode,
@@ -156,12 +168,12 @@ impl DefMap {
156 let mut curr_per_ns: PerNs = match path.kind { 168 let mut curr_per_ns: PerNs = match path.kind {
157 PathKind::DollarCrate(krate) => { 169 PathKind::DollarCrate(krate) => {
158 if krate == self.krate { 170 if krate == self.krate {
159 mark::hit!(macro_dollar_crate_self); 171 cov_mark::hit!(macro_dollar_crate_self);
160 PerNs::types(self.crate_root(db).into(), Visibility::Public) 172 PerNs::types(self.crate_root(db).into(), Visibility::Public)
161 } else { 173 } else {
162 let def_map = db.crate_def_map(krate); 174 let def_map = db.crate_def_map(krate);
163 let module = def_map.module_id(def_map.root); 175 let module = def_map.module_id(def_map.root);
164 mark::hit!(macro_dollar_crate_other); 176 cov_mark::hit!(macro_dollar_crate_other);
165 PerNs::types(module.into(), Visibility::Public) 177 PerNs::types(module.into(), Visibility::Public)
166 } 178 }
167 } 179 }
@@ -297,7 +309,7 @@ impl DefMap {
297 } 309 }
298 ModuleDefId::AdtId(AdtId::EnumId(e)) => { 310 ModuleDefId::AdtId(AdtId::EnumId(e)) => {
299 // enum variant 311 // enum variant
300 mark::hit!(can_import_enum_variant); 312 cov_mark::hit!(can_import_enum_variant);
301 let enum_data = db.enum_data(e); 313 let enum_data = db.enum_data(e);
302 match enum_data.variant(&segment) { 314 match enum_data.variant(&segment) {
303 Some(local_id) => { 315 Some(local_id) => {
@@ -372,10 +384,16 @@ impl DefMap {
372 } 384 }
373 } 385 }
374 }; 386 };
375 let from_extern_prelude = self 387 // Give precedence to names in outer `DefMap`s over the extern prelude; only check prelude
376 .extern_prelude 388 // from the crate DefMap.
377 .get(name) 389 let from_extern_prelude = match self.block {
378 .map_or(PerNs::none(), |&it| PerNs::types(it, Visibility::Public)); 390 Some(_) => PerNs::none(),
391 None => self
392 .extern_prelude
393 .get(name)
394 .map_or(PerNs::none(), |&it| PerNs::types(it, Visibility::Public)),
395 };
396
379 let from_prelude = self.resolve_in_prelude(db, name); 397 let from_prelude = self.resolve_in_prelude(db, name);
380 398
381 from_legacy_macro.or(from_scope_or_builtin).or(from_extern_prelude).or(from_prelude) 399 from_legacy_macro.or(from_scope_or_builtin).or(from_extern_prelude).or(from_prelude)