mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-30 05:45:12 +00:00
Merge #2455
2455: Add BuiltinShadowMode r=flodiebold a=edwin0cheng This PR try to fix #1905 by introduce an `BuiltinShadowMode` in name resolving functions. cc @flodiebold Co-authored-by: Edwin Cheng <edwin0cheng@gmail.com>
This commit is contained in:
commit
ec164fbb68
7 changed files with 139 additions and 32 deletions
|
@ -286,7 +286,7 @@ impl SourceAnalyzer {
|
||||||
|
|
||||||
let items = self
|
let items = self
|
||||||
.resolver
|
.resolver
|
||||||
.resolve_module_path(db, &path)
|
.resolve_module_path_in_items(db, &path)
|
||||||
.take_types()
|
.take_types()
|
||||||
.map(|it| PathResolution::Def(it.into()));
|
.map(|it| PathResolution::Def(it.into()));
|
||||||
types.or(values).or(items).or_else(|| {
|
types.or(values).or(items).or_else(|| {
|
||||||
|
|
|
@ -15,7 +15,7 @@ use rustc_hash::FxHashMap;
|
||||||
use crate::{
|
use crate::{
|
||||||
db::DefDatabase,
|
db::DefDatabase,
|
||||||
expr::{Expr, ExprId, Pat, PatId},
|
expr::{Expr, ExprId, Pat, PatId},
|
||||||
nameres::CrateDefMap,
|
nameres::{BuiltinShadowMode, CrateDefMap},
|
||||||
path::Path,
|
path::Path,
|
||||||
src::HasSource,
|
src::HasSource,
|
||||||
DefWithBodyId, HasModule, Lookup, ModuleId,
|
DefWithBodyId, HasModule, Lookup, ModuleId,
|
||||||
|
@ -83,7 +83,10 @@ impl Expander {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_path_as_macro(&self, db: &impl DefDatabase, path: &Path) -> Option<MacroDefId> {
|
fn resolve_path_as_macro(&self, db: &impl DefDatabase, path: &Path) -> Option<MacroDefId> {
|
||||||
self.crate_def_map.resolve_path(db, self.module.local_id, path).0.take_macros()
|
self.crate_def_map
|
||||||
|
.resolve_path(db, self.module.local_id, path, BuiltinShadowMode::Other)
|
||||||
|
.0
|
||||||
|
.take_macros()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -149,6 +149,15 @@ static BUILTIN_SCOPE: Lazy<FxHashMap<Name, Resolution>> = Lazy::new(|| {
|
||||||
.collect()
|
.collect()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/// Shadow mode for builtin type which can be shadowed by module.
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
|
pub enum BuiltinShadowMode {
|
||||||
|
// Prefer Module
|
||||||
|
Module,
|
||||||
|
// Prefer Other Types
|
||||||
|
Other,
|
||||||
|
}
|
||||||
|
|
||||||
/// Legacy macros can only be accessed through special methods like `get_legacy_macros`.
|
/// Legacy macros can only be accessed through special methods like `get_legacy_macros`.
|
||||||
/// Other methods will only resolve values, types and module scoped macros only.
|
/// Other methods will only resolve values, types and module scoped macros only.
|
||||||
impl ModuleScope {
|
impl ModuleScope {
|
||||||
|
@ -178,8 +187,20 @@ impl ModuleScope {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a name from current module scope, legacy macros are not included
|
/// Get a name from current module scope, legacy macros are not included
|
||||||
pub fn get(&self, name: &Name) -> Option<&Resolution> {
|
pub fn get(&self, name: &Name, shadow: BuiltinShadowMode) -> Option<&Resolution> {
|
||||||
self.items.get(name).or_else(|| BUILTIN_SCOPE.get(name))
|
match shadow {
|
||||||
|
BuiltinShadowMode::Module => self.items.get(name).or_else(|| BUILTIN_SCOPE.get(name)),
|
||||||
|
BuiltinShadowMode::Other => {
|
||||||
|
let item = self.items.get(name);
|
||||||
|
if let Some(res) = item {
|
||||||
|
if let Some(ModuleDefId::ModuleId(_)) = res.def.take_types() {
|
||||||
|
return BUILTIN_SCOPE.get(name).or(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
item.or_else(|| BUILTIN_SCOPE.get(name))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn traits<'a>(&'a self) -> impl Iterator<Item = TraitId> + 'a {
|
pub fn traits<'a>(&'a self) -> impl Iterator<Item = TraitId> + 'a {
|
||||||
|
@ -250,8 +271,10 @@ impl CrateDefMap {
|
||||||
db: &impl DefDatabase,
|
db: &impl DefDatabase,
|
||||||
original_module: LocalModuleId,
|
original_module: LocalModuleId,
|
||||||
path: &Path,
|
path: &Path,
|
||||||
|
shadow: BuiltinShadowMode,
|
||||||
) -> (PerNs, Option<usize>) {
|
) -> (PerNs, Option<usize>) {
|
||||||
let res = self.resolve_path_fp_with_macro(db, ResolveMode::Other, original_module, path);
|
let res =
|
||||||
|
self.resolve_path_fp_with_macro(db, ResolveMode::Other, original_module, path, shadow);
|
||||||
(res.resolved_def, res.segment_index)
|
(res.resolved_def, res.segment_index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ use crate::{
|
||||||
db::DefDatabase,
|
db::DefDatabase,
|
||||||
nameres::{
|
nameres::{
|
||||||
diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint,
|
diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint,
|
||||||
raw, CrateDefMap, ModuleData, Resolution, ResolveMode,
|
raw, BuiltinShadowMode, CrateDefMap, ModuleData, Resolution, ResolveMode,
|
||||||
},
|
},
|
||||||
path::{Path, PathKind},
|
path::{Path, PathKind},
|
||||||
per_ns::PerNs,
|
per_ns::PerNs,
|
||||||
|
@ -299,6 +299,7 @@ where
|
||||||
ResolveMode::Import,
|
ResolveMode::Import,
|
||||||
module_id,
|
module_id,
|
||||||
&import.path,
|
&import.path,
|
||||||
|
BuiltinShadowMode::Module,
|
||||||
);
|
);
|
||||||
|
|
||||||
(res.resolved_def, res.reached_fixedpoint)
|
(res.resolved_def, res.reached_fixedpoint)
|
||||||
|
@ -477,6 +478,7 @@ where
|
||||||
ResolveMode::Other,
|
ResolveMode::Other,
|
||||||
*module_id,
|
*module_id,
|
||||||
path,
|
path,
|
||||||
|
BuiltinShadowMode::Module,
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(def) = resolved_res.resolved_def.take_macros() {
|
if let Some(def) = resolved_res.resolved_def.take_macros() {
|
||||||
|
|
|
@ -16,7 +16,7 @@ use test_utils::tested_by;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
db::DefDatabase,
|
db::DefDatabase,
|
||||||
nameres::CrateDefMap,
|
nameres::{BuiltinShadowMode, CrateDefMap},
|
||||||
path::{Path, PathKind},
|
path::{Path, PathKind},
|
||||||
per_ns::PerNs,
|
per_ns::PerNs,
|
||||||
AdtId, EnumVariantId, LocalModuleId, ModuleDefId, ModuleId,
|
AdtId, EnumVariantId, LocalModuleId, ModuleDefId, ModuleId,
|
||||||
|
@ -68,7 +68,17 @@ impl CrateDefMap {
|
||||||
mode: ResolveMode,
|
mode: ResolveMode,
|
||||||
original_module: LocalModuleId,
|
original_module: LocalModuleId,
|
||||||
path: &Path,
|
path: &Path,
|
||||||
|
shadow: BuiltinShadowMode,
|
||||||
) -> ResolvePathResult {
|
) -> ResolvePathResult {
|
||||||
|
// if it is not the last segment, we prefer the module to the builtin
|
||||||
|
let prefer_module = |index| {
|
||||||
|
if index == path.segments.len() - 1 {
|
||||||
|
shadow
|
||||||
|
} else {
|
||||||
|
BuiltinShadowMode::Module
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let mut segments = path.segments.iter().enumerate();
|
let mut segments = path.segments.iter().enumerate();
|
||||||
let mut curr_per_ns: PerNs = match path.kind {
|
let mut curr_per_ns: PerNs = match path.kind {
|
||||||
PathKind::DollarCrate(krate) => {
|
PathKind::DollarCrate(krate) => {
|
||||||
|
@ -96,20 +106,20 @@ impl CrateDefMap {
|
||||||
if self.edition == Edition::Edition2015
|
if self.edition == Edition::Edition2015
|
||||||
&& (path.kind == PathKind::Abs || mode == ResolveMode::Import) =>
|
&& (path.kind == PathKind::Abs || mode == ResolveMode::Import) =>
|
||||||
{
|
{
|
||||||
let segment = match segments.next() {
|
let (idx, segment) = match segments.next() {
|
||||||
Some((_, segment)) => segment,
|
Some((idx, segment)) => (idx, segment),
|
||||||
None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
|
None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
|
||||||
};
|
};
|
||||||
log::debug!("resolving {:?} in crate root (+ extern prelude)", segment);
|
log::debug!("resolving {:?} in crate root (+ extern prelude)", segment);
|
||||||
self.resolve_name_in_crate_root_or_extern_prelude(&segment.name)
|
self.resolve_name_in_crate_root_or_extern_prelude(&segment.name, prefer_module(idx))
|
||||||
}
|
}
|
||||||
PathKind::Plain => {
|
PathKind::Plain => {
|
||||||
let segment = match segments.next() {
|
let (idx, segment) = match segments.next() {
|
||||||
Some((_, segment)) => segment,
|
Some((idx, segment)) => (idx, segment),
|
||||||
None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
|
None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
|
||||||
};
|
};
|
||||||
log::debug!("resolving {:?} in module", segment);
|
log::debug!("resolving {:?} in module", segment);
|
||||||
self.resolve_name_in_module(db, original_module, &segment.name)
|
self.resolve_name_in_module(db, original_module, &segment.name, prefer_module(idx))
|
||||||
}
|
}
|
||||||
PathKind::Super => {
|
PathKind::Super => {
|
||||||
if let Some(p) = self.modules[original_module].parent {
|
if let Some(p) = self.modules[original_module].parent {
|
||||||
|
@ -160,7 +170,7 @@ impl CrateDefMap {
|
||||||
Path { segments: path.segments[i..].to_vec(), kind: PathKind::Self_ };
|
Path { segments: path.segments[i..].to_vec(), kind: PathKind::Self_ };
|
||||||
log::debug!("resolving {:?} in other crate", path);
|
log::debug!("resolving {:?} in other crate", path);
|
||||||
let defp_map = db.crate_def_map(module.krate);
|
let defp_map = db.crate_def_map(module.krate);
|
||||||
let (def, s) = defp_map.resolve_path(db, module.local_id, &path);
|
let (def, s) = defp_map.resolve_path(db, module.local_id, &path, shadow);
|
||||||
return ResolvePathResult::with(
|
return ResolvePathResult::with(
|
||||||
def,
|
def,
|
||||||
ReachedFixedPoint::Yes,
|
ReachedFixedPoint::Yes,
|
||||||
|
@ -169,7 +179,7 @@ impl CrateDefMap {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Since it is a qualified path here, it should not contains legacy macros
|
// Since it is a qualified path here, it should not contains legacy macros
|
||||||
match self[module.local_id].scope.get(&segment.name) {
|
match self[module.local_id].scope.get(&segment.name, prefer_module(i)) {
|
||||||
Some(res) => res.def,
|
Some(res) => res.def,
|
||||||
_ => {
|
_ => {
|
||||||
log::debug!("path segment {:?} not found", segment.name);
|
log::debug!("path segment {:?} not found", segment.name);
|
||||||
|
@ -212,6 +222,7 @@ impl CrateDefMap {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
ResolvePathResult::with(curr_per_ns, ReachedFixedPoint::Yes, None)
|
ResolvePathResult::with(curr_per_ns, ReachedFixedPoint::Yes, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,6 +231,7 @@ impl CrateDefMap {
|
||||||
db: &impl DefDatabase,
|
db: &impl DefDatabase,
|
||||||
module: LocalModuleId,
|
module: LocalModuleId,
|
||||||
name: &Name,
|
name: &Name,
|
||||||
|
shadow: BuiltinShadowMode,
|
||||||
) -> PerNs {
|
) -> PerNs {
|
||||||
// Resolve in:
|
// Resolve in:
|
||||||
// - legacy scope of macro
|
// - legacy scope of macro
|
||||||
|
@ -228,23 +240,33 @@ impl CrateDefMap {
|
||||||
// - std prelude
|
// - std prelude
|
||||||
let from_legacy_macro =
|
let from_legacy_macro =
|
||||||
self[module].scope.get_legacy_macro(name).map_or_else(PerNs::none, PerNs::macros);
|
self[module].scope.get_legacy_macro(name).map_or_else(PerNs::none, PerNs::macros);
|
||||||
let from_scope = self[module].scope.get(name).map_or_else(PerNs::none, |res| res.def);
|
let from_scope =
|
||||||
|
self[module].scope.get(name, shadow).map_or_else(PerNs::none, |res| res.def);
|
||||||
let from_extern_prelude =
|
let from_extern_prelude =
|
||||||
self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it));
|
self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it));
|
||||||
let from_prelude = self.resolve_in_prelude(db, name);
|
let from_prelude = self.resolve_in_prelude(db, name, shadow);
|
||||||
|
|
||||||
from_legacy_macro.or(from_scope).or(from_extern_prelude).or(from_prelude)
|
from_legacy_macro.or(from_scope).or(from_extern_prelude).or(from_prelude)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_name_in_crate_root_or_extern_prelude(&self, name: &Name) -> PerNs {
|
fn resolve_name_in_crate_root_or_extern_prelude(
|
||||||
|
&self,
|
||||||
|
name: &Name,
|
||||||
|
shadow: BuiltinShadowMode,
|
||||||
|
) -> PerNs {
|
||||||
let from_crate_root =
|
let from_crate_root =
|
||||||
self[self.root].scope.get(name).map_or_else(PerNs::none, |res| res.def);
|
self[self.root].scope.get(name, shadow).map_or_else(PerNs::none, |res| res.def);
|
||||||
let from_extern_prelude = self.resolve_name_in_extern_prelude(name);
|
let from_extern_prelude = self.resolve_name_in_extern_prelude(name);
|
||||||
|
|
||||||
from_crate_root.or(from_extern_prelude)
|
from_crate_root.or(from_extern_prelude)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_in_prelude(&self, db: &impl DefDatabase, name: &Name) -> PerNs {
|
fn resolve_in_prelude(
|
||||||
|
&self,
|
||||||
|
db: &impl DefDatabase,
|
||||||
|
name: &Name,
|
||||||
|
shadow: BuiltinShadowMode,
|
||||||
|
) -> PerNs {
|
||||||
if let Some(prelude) = self.prelude {
|
if let Some(prelude) = self.prelude {
|
||||||
let keep;
|
let keep;
|
||||||
let def_map = if prelude.krate == self.krate {
|
let def_map = if prelude.krate == self.krate {
|
||||||
|
@ -254,7 +276,10 @@ impl CrateDefMap {
|
||||||
keep = db.crate_def_map(prelude.krate);
|
keep = db.crate_def_map(prelude.krate);
|
||||||
&keep
|
&keep
|
||||||
};
|
};
|
||||||
def_map[prelude.local_id].scope.get(name).map_or_else(PerNs::none, |res| res.def)
|
def_map[prelude.local_id]
|
||||||
|
.scope
|
||||||
|
.get(name, shadow)
|
||||||
|
.map_or_else(PerNs::none, |res| res.def)
|
||||||
} else {
|
} else {
|
||||||
PerNs::none()
|
PerNs::none()
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ use crate::{
|
||||||
db::DefDatabase,
|
db::DefDatabase,
|
||||||
expr::{ExprId, PatId},
|
expr::{ExprId, PatId},
|
||||||
generics::GenericParams,
|
generics::GenericParams,
|
||||||
nameres::CrateDefMap,
|
nameres::{BuiltinShadowMode, CrateDefMap},
|
||||||
path::{Path, PathKind},
|
path::{Path, PathKind},
|
||||||
per_ns::PerNs,
|
per_ns::PerNs,
|
||||||
AdtId, AstItemDef, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId, FunctionId,
|
AdtId, AstItemDef, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId, FunctionId,
|
||||||
|
@ -91,7 +91,7 @@ pub enum ValueNs {
|
||||||
impl Resolver {
|
impl Resolver {
|
||||||
/// Resolve known trait from std, like `std::futures::Future`
|
/// Resolve known trait from std, like `std::futures::Future`
|
||||||
pub fn resolve_known_trait(&self, db: &impl DefDatabase, path: &Path) -> Option<TraitId> {
|
pub fn resolve_known_trait(&self, db: &impl DefDatabase, path: &Path) -> Option<TraitId> {
|
||||||
let res = self.resolve_module_path(db, path).take_types()?;
|
let res = self.resolve_module_path(db, path, BuiltinShadowMode::Other).take_types()?;
|
||||||
match res {
|
match res {
|
||||||
ModuleDefId::TraitId(it) => Some(it),
|
ModuleDefId::TraitId(it) => Some(it),
|
||||||
_ => None,
|
_ => None,
|
||||||
|
@ -100,7 +100,7 @@ impl Resolver {
|
||||||
|
|
||||||
/// Resolve known struct from std, like `std::boxed::Box`
|
/// Resolve known struct from std, like `std::boxed::Box`
|
||||||
pub fn resolve_known_struct(&self, db: &impl DefDatabase, path: &Path) -> Option<StructId> {
|
pub fn resolve_known_struct(&self, db: &impl DefDatabase, path: &Path) -> Option<StructId> {
|
||||||
let res = self.resolve_module_path(db, path).take_types()?;
|
let res = self.resolve_module_path(db, path, BuiltinShadowMode::Other).take_types()?;
|
||||||
match res {
|
match res {
|
||||||
ModuleDefId::AdtId(AdtId::StructId(it)) => Some(it),
|
ModuleDefId::AdtId(AdtId::StructId(it)) => Some(it),
|
||||||
_ => None,
|
_ => None,
|
||||||
|
@ -109,26 +109,34 @@ impl Resolver {
|
||||||
|
|
||||||
/// Resolve known enum from std, like `std::result::Result`
|
/// Resolve known enum from std, like `std::result::Result`
|
||||||
pub fn resolve_known_enum(&self, db: &impl DefDatabase, path: &Path) -> Option<EnumId> {
|
pub fn resolve_known_enum(&self, db: &impl DefDatabase, path: &Path) -> Option<EnumId> {
|
||||||
let res = self.resolve_module_path(db, path).take_types()?;
|
let res = self.resolve_module_path(db, path, BuiltinShadowMode::Other).take_types()?;
|
||||||
match res {
|
match res {
|
||||||
ModuleDefId::AdtId(AdtId::EnumId(it)) => Some(it),
|
ModuleDefId::AdtId(AdtId::EnumId(it)) => Some(it),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// pub only for source-binder
|
fn resolve_module_path(
|
||||||
pub fn resolve_module_path(&self, db: &impl DefDatabase, path: &Path) -> PerNs {
|
&self,
|
||||||
|
db: &impl DefDatabase,
|
||||||
|
path: &Path,
|
||||||
|
shadow: BuiltinShadowMode,
|
||||||
|
) -> PerNs {
|
||||||
let (item_map, module) = match self.module() {
|
let (item_map, module) = match self.module() {
|
||||||
Some(it) => it,
|
Some(it) => it,
|
||||||
None => return PerNs::none(),
|
None => return PerNs::none(),
|
||||||
};
|
};
|
||||||
let (module_res, segment_index) = item_map.resolve_path(db, module, path);
|
let (module_res, segment_index) = item_map.resolve_path(db, module, path, shadow);
|
||||||
if segment_index.is_some() {
|
if segment_index.is_some() {
|
||||||
return PerNs::none();
|
return PerNs::none();
|
||||||
}
|
}
|
||||||
module_res
|
module_res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn resolve_module_path_in_items(&self, db: &impl DefDatabase, path: &Path) -> PerNs {
|
||||||
|
self.resolve_module_path(db, path, BuiltinShadowMode::Module)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn resolve_path_in_type_ns(
|
pub fn resolve_path_in_type_ns(
|
||||||
&self,
|
&self,
|
||||||
db: &impl DefDatabase,
|
db: &impl DefDatabase,
|
||||||
|
@ -163,7 +171,12 @@ impl Resolver {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Scope::ModuleScope(m) => {
|
Scope::ModuleScope(m) => {
|
||||||
let (module_def, idx) = m.crate_def_map.resolve_path(db, m.module_id, path);
|
let (module_def, idx) = m.crate_def_map.resolve_path(
|
||||||
|
db,
|
||||||
|
m.module_id,
|
||||||
|
path,
|
||||||
|
BuiltinShadowMode::Other,
|
||||||
|
);
|
||||||
let res = match module_def.take_types()? {
|
let res = match module_def.take_types()? {
|
||||||
ModuleDefId::AdtId(it) => TypeNs::AdtId(it),
|
ModuleDefId::AdtId(it) => TypeNs::AdtId(it),
|
||||||
ModuleDefId::EnumVariantId(it) => TypeNs::EnumVariantId(it),
|
ModuleDefId::EnumVariantId(it) => TypeNs::EnumVariantId(it),
|
||||||
|
@ -256,7 +269,12 @@ impl Resolver {
|
||||||
Scope::ImplBlockScope(_) | Scope::AdtScope(_) => continue,
|
Scope::ImplBlockScope(_) | Scope::AdtScope(_) => continue,
|
||||||
|
|
||||||
Scope::ModuleScope(m) => {
|
Scope::ModuleScope(m) => {
|
||||||
let (module_def, idx) = m.crate_def_map.resolve_path(db, m.module_id, path);
|
let (module_def, idx) = m.crate_def_map.resolve_path(
|
||||||
|
db,
|
||||||
|
m.module_id,
|
||||||
|
path,
|
||||||
|
BuiltinShadowMode::Other,
|
||||||
|
);
|
||||||
return match idx {
|
return match idx {
|
||||||
None => {
|
None => {
|
||||||
let value = match module_def.take_values()? {
|
let value = match module_def.take_values()? {
|
||||||
|
@ -310,7 +328,7 @@ impl Resolver {
|
||||||
|
|
||||||
pub fn resolve_path_as_macro(&self, db: &impl DefDatabase, path: &Path) -> Option<MacroDefId> {
|
pub fn resolve_path_as_macro(&self, db: &impl DefDatabase, path: &Path) -> Option<MacroDefId> {
|
||||||
let (item_map, module) = self.module()?;
|
let (item_map, module) = self.module()?;
|
||||||
item_map.resolve_path(db, module, path).0.take_macros()
|
item_map.resolve_path(db, module, path, BuiltinShadowMode::Other).0.take_macros()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn process_all_names(&self, db: &impl DefDatabase, f: &mut dyn FnMut(Name, ScopeDef)) {
|
pub fn process_all_names(&self, db: &impl DefDatabase, f: &mut dyn FnMut(Name, ScopeDef)) {
|
||||||
|
|
|
@ -3693,6 +3693,42 @@ fn main() {
|
||||||
assert_eq!(t, "Foo");
|
assert_eq!(t, "Foo");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn not_shadowing_primitive_by_module() {
|
||||||
|
let t = type_at(
|
||||||
|
r#"
|
||||||
|
//- /str.rs
|
||||||
|
fn foo() {}
|
||||||
|
|
||||||
|
//- /main.rs
|
||||||
|
mod str;
|
||||||
|
fn foo() -> &'static str { "" }
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
foo()<|>;
|
||||||
|
}"#,
|
||||||
|
);
|
||||||
|
assert_eq!(t, "&str");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn not_shadowing_module_by_primitive() {
|
||||||
|
let t = type_at(
|
||||||
|
r#"
|
||||||
|
//- /str.rs
|
||||||
|
fn foo() -> u32 {0}
|
||||||
|
|
||||||
|
//- /main.rs
|
||||||
|
mod str;
|
||||||
|
fn foo() -> &'static str { "" }
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
str::foo()<|>;
|
||||||
|
}"#,
|
||||||
|
);
|
||||||
|
assert_eq!(t, "u32");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn deref_trait() {
|
fn deref_trait() {
|
||||||
let t = type_at(
|
let t = type_at(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue