diff options
Diffstat (limited to 'crates/hir_def/src/nameres/path_resolution.rs')
-rw-r--r-- | crates/hir_def/src/nameres/path_resolution.rs | 46 |
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 @@ | |||
13 | use base_db::Edition; | 13 | use base_db::Edition; |
14 | use hir_expand::name; | 14 | use hir_expand::name; |
15 | use hir_expand::name::Name; | 15 | use hir_expand::name::Name; |
16 | use test_utils::mark; | ||
17 | 16 | ||
18 | use crate::{ | 17 | use crate::{ |
19 | db::DefDatabase, | 18 | db::DefDatabase, |
@@ -63,7 +62,7 @@ impl ResolvePathResult { | |||
63 | impl DefMap { | 62 | impl 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) |