Skip to content

Commit bb601e7

Browse files
committed
Add BuiltinShadowMode
1 parent 8b278b1 commit bb601e7

File tree

7 files changed

+157
-31
lines changed

7 files changed

+157
-31
lines changed

crates/ra_hir/src/source_binder.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ impl SourceAnalyzer {
286286

287287
let items = self
288288
.resolver
289-
.resolve_module_path(db, &path)
289+
.resolve_module_path_in_items(db, &path)
290290
.take_types()
291291
.map(|it| PathResolution::Def(it.into()));
292292
types.or(values).or(items).or_else(|| {

crates/ra_hir_def/src/body.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use rustc_hash::FxHashMap;
1515
use crate::{
1616
db::DefDatabase,
1717
expr::{Expr, ExprId, Pat, PatId},
18-
nameres::CrateDefMap,
18+
nameres::{BuiltinShadowMode, CrateDefMap},
1919
path::Path,
2020
src::HasSource,
2121
DefWithBodyId, HasModule, Lookup, ModuleId,
@@ -83,7 +83,10 @@ impl Expander {
8383
}
8484

8585
fn resolve_path_as_macro(&self, db: &impl DefDatabase, path: &Path) -> Option<MacroDefId> {
86-
self.crate_def_map.resolve_path(db, self.module.local_id, path).0.take_macros()
86+
self.crate_def_map
87+
.resolve_path(db, self.module.local_id, path, BuiltinShadowMode::Other)
88+
.0
89+
.take_macros()
8790
}
8891
}
8992

crates/ra_hir_def/src/nameres.rs

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,16 @@ static BUILTIN_SCOPE: Lazy<FxHashMap<Name, Resolution>> = Lazy::new(|| {
149149
.collect()
150150
});
151151

152+
/// Shadow mode for builtin type
153+
/// Builtin type can be shadowed by same name mode
154+
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
155+
pub enum BuiltinShadowMode {
156+
// Prefer Module
157+
Module,
158+
// Prefer Other Types
159+
Other,
160+
}
161+
152162
/// Legacy macros can only be accessed through special methods like `get_legacy_macros`.
153163
/// Other methods will only resolve values, types and module scoped macros only.
154164
impl ModuleScope {
@@ -178,8 +188,20 @@ impl ModuleScope {
178188
}
179189

180190
/// Get a name from current module scope, legacy macros are not included
181-
pub fn get(&self, name: &Name) -> Option<&Resolution> {
182-
self.items.get(name).or_else(|| BUILTIN_SCOPE.get(name))
191+
pub fn get(&self, name: &Name, shadow: BuiltinShadowMode) -> Option<&Resolution> {
192+
match shadow {
193+
BuiltinShadowMode::Module => self.items.get(name).or_else(|| BUILTIN_SCOPE.get(name)),
194+
BuiltinShadowMode::Other => {
195+
let item = self.items.get(name);
196+
if let Some(res) = item {
197+
if let Some(ModuleDefId::ModuleId(_)) = res.def.take_types() {
198+
return BUILTIN_SCOPE.get(name).or(item);
199+
}
200+
}
201+
202+
item.or_else(|| BUILTIN_SCOPE.get(name))
203+
}
204+
}
183205
}
184206

185207
pub fn traits<'a>(&'a self) -> impl Iterator<Item = TraitId> + 'a {
@@ -250,8 +272,10 @@ impl CrateDefMap {
250272
db: &impl DefDatabase,
251273
original_module: LocalModuleId,
252274
path: &Path,
275+
shadow: BuiltinShadowMode,
253276
) -> (PerNs, Option<usize>) {
254-
let res = self.resolve_path_fp_with_macro(db, ResolveMode::Other, original_module, path);
277+
let res =
278+
self.resolve_path_fp_with_macro(db, ResolveMode::Other, original_module, path, shadow);
255279
(res.resolved_def, res.segment_index)
256280
}
257281
}

crates/ra_hir_def/src/nameres/collector.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use crate::{
1919
db::DefDatabase,
2020
nameres::{
2121
diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint,
22-
raw, CrateDefMap, ModuleData, Resolution, ResolveMode,
22+
raw, BuiltinShadowMode, CrateDefMap, ModuleData, Resolution, ResolveMode,
2323
},
2424
path::{Path, PathKind},
2525
per_ns::PerNs,
@@ -299,6 +299,7 @@ where
299299
ResolveMode::Import,
300300
module_id,
301301
&import.path,
302+
BuiltinShadowMode::Module,
302303
);
303304

304305
(res.resolved_def, res.reached_fixedpoint)
@@ -477,6 +478,7 @@ where
477478
ResolveMode::Other,
478479
*module_id,
479480
path,
481+
BuiltinShadowMode::Module,
480482
);
481483

482484
if let Some(def) = resolved_res.resolved_def.take_macros() {

crates/ra_hir_def/src/nameres/path_resolution.rs

Lines changed: 57 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use test_utils::tested_by;
1616

1717
use crate::{
1818
db::DefDatabase,
19-
nameres::CrateDefMap,
19+
nameres::{BuiltinShadowMode, CrateDefMap},
2020
path::{Path, PathKind},
2121
per_ns::PerNs,
2222
AdtId, EnumVariantId, LocalModuleId, ModuleDefId, ModuleId,
@@ -68,8 +68,10 @@ impl CrateDefMap {
6868
mode: ResolveMode,
6969
original_module: LocalModuleId,
7070
path: &Path,
71+
shadow: BuiltinShadowMode,
7172
) -> ResolvePathResult {
72-
let mut segments = path.segments.iter().enumerate();
73+
let mut segments = path.segments.iter().enumerate().peekable();
74+
7375
let mut curr_per_ns: PerNs = match path.kind {
7476
PathKind::DollarCrate(krate) => {
7577
if krate == self.krate {
@@ -101,15 +103,24 @@ impl CrateDefMap {
101103
None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
102104
};
103105
log::debug!("resolving {:?} in crate root (+ extern prelude)", segment);
104-
self.resolve_name_in_crate_root_or_extern_prelude(&segment.name)
106+
107+
self.resolve_name_in_crate_root_or_extern_prelude(
108+
&segment.name,
109+
prefer_module(&mut segments, shadow),
110+
)
105111
}
106112
PathKind::Plain => {
107113
let segment = match segments.next() {
108114
Some((_, segment)) => segment,
109115
None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
110116
};
111117
log::debug!("resolving {:?} in module", segment);
112-
self.resolve_name_in_module(db, original_module, &segment.name)
118+
self.resolve_name_in_module(
119+
db,
120+
original_module,
121+
&segment.name,
122+
prefer_module(&mut segments, shadow),
123+
)
113124
}
114125
PathKind::Super => {
115126
if let Some(p) = self.modules[original_module].parent {
@@ -139,7 +150,7 @@ impl CrateDefMap {
139150
}
140151
};
141152

142-
for (i, segment) in segments {
153+
while let Some((i, segment)) = segments.next() {
143154
let curr = match curr_per_ns.take_types() {
144155
Some(r) => r,
145156
None => {
@@ -160,7 +171,7 @@ impl CrateDefMap {
160171
Path { segments: path.segments[i..].to_vec(), kind: PathKind::Self_ };
161172
log::debug!("resolving {:?} in other crate", path);
162173
let defp_map = db.crate_def_map(module.krate);
163-
let (def, s) = defp_map.resolve_path(db, module.local_id, &path);
174+
let (def, s) = defp_map.resolve_path(db, module.local_id, &path, shadow);
164175
return ResolvePathResult::with(
165176
def,
166177
ReachedFixedPoint::Yes,
@@ -169,7 +180,10 @@ impl CrateDefMap {
169180
}
170181

171182
// Since it is a qualified path here, it should not contains legacy macros
172-
match self[module.local_id].scope.get(&segment.name) {
183+
match self[module.local_id]
184+
.scope
185+
.get(&segment.name, prefer_module(&mut segments, shadow))
186+
{
173187
Some(res) => res.def,
174188
_ => {
175189
log::debug!("path segment {:?} not found", segment.name);
@@ -212,14 +226,30 @@ impl CrateDefMap {
212226
}
213227
};
214228
}
215-
ResolvePathResult::with(curr_per_ns, ReachedFixedPoint::Yes, None)
229+
return ResolvePathResult::with(curr_per_ns, ReachedFixedPoint::Yes, None);
230+
231+
// if it is not the last segment, we prefer builtin as module
232+
fn prefer_module<I>(
233+
segments: &mut std::iter::Peekable<I>,
234+
shadow: BuiltinShadowMode,
235+
) -> BuiltinShadowMode
236+
where
237+
I: Iterator,
238+
{
239+
if segments.peek().is_some() {
240+
BuiltinShadowMode::Module
241+
} else {
242+
shadow
243+
}
244+
}
216245
}
217246

218247
fn resolve_name_in_module(
219248
&self,
220249
db: &impl DefDatabase,
221250
module: LocalModuleId,
222251
name: &Name,
252+
shadow: BuiltinShadowMode,
223253
) -> PerNs {
224254
// Resolve in:
225255
// - legacy scope of macro
@@ -228,23 +258,33 @@ impl CrateDefMap {
228258
// - std prelude
229259
let from_legacy_macro =
230260
self[module].scope.get_legacy_macro(name).map_or_else(PerNs::none, PerNs::macros);
231-
let from_scope = self[module].scope.get(name).map_or_else(PerNs::none, |res| res.def);
261+
let from_scope =
262+
self[module].scope.get(name, shadow).map_or_else(PerNs::none, |res| res.def);
232263
let from_extern_prelude =
233264
self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it));
234-
let from_prelude = self.resolve_in_prelude(db, name);
265+
let from_prelude = self.resolve_in_prelude(db, name, shadow);
235266

236267
from_legacy_macro.or(from_scope).or(from_extern_prelude).or(from_prelude)
237268
}
238269

239-
fn resolve_name_in_crate_root_or_extern_prelude(&self, name: &Name) -> PerNs {
270+
fn resolve_name_in_crate_root_or_extern_prelude(
271+
&self,
272+
name: &Name,
273+
shadow: BuiltinShadowMode,
274+
) -> PerNs {
240275
let from_crate_root =
241-
self[self.root].scope.get(name).map_or_else(PerNs::none, |res| res.def);
276+
self[self.root].scope.get(name, shadow).map_or_else(PerNs::none, |res| res.def);
242277
let from_extern_prelude = self.resolve_name_in_extern_prelude(name);
243278

244279
from_crate_root.or(from_extern_prelude)
245280
}
246281

247-
fn resolve_in_prelude(&self, db: &impl DefDatabase, name: &Name) -> PerNs {
282+
fn resolve_in_prelude(
283+
&self,
284+
db: &impl DefDatabase,
285+
name: &Name,
286+
shadow: BuiltinShadowMode,
287+
) -> PerNs {
248288
if let Some(prelude) = self.prelude {
249289
let keep;
250290
let def_map = if prelude.krate == self.krate {
@@ -254,7 +294,10 @@ impl CrateDefMap {
254294
keep = db.crate_def_map(prelude.krate);
255295
&keep
256296
};
257-
def_map[prelude.local_id].scope.get(name).map_or_else(PerNs::none, |res| res.def)
297+
def_map[prelude.local_id]
298+
.scope
299+
.get(name, shadow)
300+
.map_or_else(PerNs::none, |res| res.def)
258301
} else {
259302
PerNs::none()
260303
}

crates/ra_hir_def/src/resolver.rs

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use crate::{
1414
db::DefDatabase,
1515
expr::{ExprId, PatId},
1616
generics::GenericParams,
17-
nameres::CrateDefMap,
17+
nameres::{BuiltinShadowMode, CrateDefMap},
1818
path::{Path, PathKind},
1919
per_ns::PerNs,
2020
AdtId, AstItemDef, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId, FunctionId,
@@ -91,7 +91,7 @@ pub enum ValueNs {
9191
impl Resolver {
9292
/// Resolve known trait from std, like `std::futures::Future`
9393
pub fn resolve_known_trait(&self, db: &impl DefDatabase, path: &Path) -> Option<TraitId> {
94-
let res = self.resolve_module_path(db, path).take_types()?;
94+
let res = self.resolve_module_path(db, path, BuiltinShadowMode::Other).take_types()?;
9595
match res {
9696
ModuleDefId::TraitId(it) => Some(it),
9797
_ => None,
@@ -100,7 +100,7 @@ impl Resolver {
100100

101101
/// Resolve known struct from std, like `std::boxed::Box`
102102
pub fn resolve_known_struct(&self, db: &impl DefDatabase, path: &Path) -> Option<StructId> {
103-
let res = self.resolve_module_path(db, path).take_types()?;
103+
let res = self.resolve_module_path(db, path, BuiltinShadowMode::Other).take_types()?;
104104
match res {
105105
ModuleDefId::AdtId(AdtId::StructId(it)) => Some(it),
106106
_ => None,
@@ -109,26 +109,34 @@ impl Resolver {
109109

110110
/// Resolve known enum from std, like `std::result::Result`
111111
pub fn resolve_known_enum(&self, db: &impl DefDatabase, path: &Path) -> Option<EnumId> {
112-
let res = self.resolve_module_path(db, path).take_types()?;
112+
let res = self.resolve_module_path(db, path, BuiltinShadowMode::Other).take_types()?;
113113
match res {
114114
ModuleDefId::AdtId(AdtId::EnumId(it)) => Some(it),
115115
_ => None,
116116
}
117117
}
118118

119-
/// pub only for source-binder
120-
pub fn resolve_module_path(&self, db: &impl DefDatabase, path: &Path) -> PerNs {
119+
fn resolve_module_path(
120+
&self,
121+
db: &impl DefDatabase,
122+
path: &Path,
123+
shadow: BuiltinShadowMode,
124+
) -> PerNs {
121125
let (item_map, module) = match self.module() {
122126
Some(it) => it,
123127
None => return PerNs::none(),
124128
};
125-
let (module_res, segment_index) = item_map.resolve_path(db, module, path);
129+
let (module_res, segment_index) = item_map.resolve_path(db, module, path, shadow);
126130
if segment_index.is_some() {
127131
return PerNs::none();
128132
}
129133
module_res
130134
}
131135

136+
pub fn resolve_module_path_in_items(&self, db: &impl DefDatabase, path: &Path) -> PerNs {
137+
self.resolve_module_path(db, path, BuiltinShadowMode::Module)
138+
}
139+
132140
pub fn resolve_path_in_type_ns(
133141
&self,
134142
db: &impl DefDatabase,
@@ -163,7 +171,12 @@ impl Resolver {
163171
}
164172
}
165173
Scope::ModuleScope(m) => {
166-
let (module_def, idx) = m.crate_def_map.resolve_path(db, m.module_id, path);
174+
let (module_def, idx) = m.crate_def_map.resolve_path(
175+
db,
176+
m.module_id,
177+
path,
178+
BuiltinShadowMode::Other,
179+
);
167180
let res = match module_def.take_types()? {
168181
ModuleDefId::AdtId(it) => TypeNs::AdtId(it),
169182
ModuleDefId::EnumVariantId(it) => TypeNs::EnumVariantId(it),
@@ -256,7 +269,12 @@ impl Resolver {
256269
Scope::ImplBlockScope(_) | Scope::AdtScope(_) => continue,
257270

258271
Scope::ModuleScope(m) => {
259-
let (module_def, idx) = m.crate_def_map.resolve_path(db, m.module_id, path);
272+
let (module_def, idx) = m.crate_def_map.resolve_path(
273+
db,
274+
m.module_id,
275+
path,
276+
BuiltinShadowMode::Other,
277+
);
260278
return match idx {
261279
None => {
262280
let value = match module_def.take_values()? {
@@ -310,7 +328,7 @@ impl Resolver {
310328

311329
pub fn resolve_path_as_macro(&self, db: &impl DefDatabase, path: &Path) -> Option<MacroDefId> {
312330
let (item_map, module) = self.module()?;
313-
item_map.resolve_path(db, module, path).0.take_macros()
331+
item_map.resolve_path(db, module, path, BuiltinShadowMode::Other).0.take_macros()
314332
}
315333

316334
pub fn process_all_names(&self, db: &impl DefDatabase, f: &mut dyn FnMut(Name, ScopeDef)) {

0 commit comments

Comments
 (0)