diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs index 10a8192b93..bd8ab80ead 100644 --- a/crates/hir-def/src/resolver.rs +++ b/crates/hir-def/src/resolver.rs @@ -169,33 +169,26 @@ impl Resolver { self.resolve_module_path(db, path, BuiltinShadowMode::Module) } - pub fn resolve_path_in_type_ns<'a>( - &'a self, - db: &'a dyn DefDatabase, - path: &'a Path, - ) -> impl Iterator, Option)> + 'a - { + pub fn resolve_path_in_type_ns( + &self, + db: &dyn DefDatabase, + path: &Path, + ) -> Option<(ModuleOrTypeNs, Option, Option)> { self.resolve_path_in_type_ns_with_prefix_info(db, path).map( - move |(resolution, remaining_segments, import, _)| { - (resolution, remaining_segments, import) - }, + |(resolution, remaining_segments, import, _)| (resolution, remaining_segments, import), ) } - pub fn resolve_path_in_type_ns_with_prefix_info<'a>( - &'a self, - db: &'a dyn DefDatabase, - path: &'a Path, - ) -> Box< - dyn Iterator< - Item = ( - ModuleOrTypeNs, - Option, - Option, - ResolvePathResultPrefixInfo, - ), - > + 'a, - > { + pub fn resolve_path_in_type_ns_with_prefix_info( + &self, + db: &dyn DefDatabase, + path: &Path, + ) -> Option<( + ModuleOrTypeNs, + Option, + Option, + ResolvePathResultPrefixInfo, + )> { let path = match path { Path::BarePath(mod_path) => mod_path, Path::Normal(it) => &it.mod_path, @@ -209,30 +202,29 @@ impl Resolver { LangItemTarget::Trait(it) => TypeNs::TraitId(it), LangItemTarget::Function(_) | LangItemTarget::ImplDef(_) - | LangItemTarget::Static(_) => return Box::new(iter::empty()), + | LangItemTarget::Static(_) => return None, }; - return Box::new(iter::once(( + return Some(( ModuleOrTypeNs::TypeNs(type_ns), seg.as_ref().map(|_| 1), None, ResolvePathResultPrefixInfo::default(), - ))); + )); } }; - let Some(first_name) = path.segments().first() else { return Box::new(iter::empty()) }; + let first_name = path.segments().first()?; let skip_to_mod = path.kind != PathKind::Plain; if skip_to_mod { - return Box::new(self.module_scope.resolve_path_in_type_ns(db, path).into_iter()); + return self.module_scope.resolve_path_in_module_or_type_ns(db, path); } let remaining_idx = || { if path.segments().len() == 1 { None } else { Some(1) } }; - let ns = self - .scopes() - .filter_map(move |scope| match scope { - Scope::ExprScope(_) | Scope::MacroDefScope(_) => None, + for scope in self.scopes() { + match scope { + Scope::ExprScope(_) | Scope::MacroDefScope(_) => continue, Scope::GenericParams { params, def } => { if let Some(id) = params.find_type_by_name(first_name, *def) { return Some(( @@ -242,7 +234,6 @@ impl Resolver { ResolvePathResultPrefixInfo::default(), )); } - None } &Scope::ImplDefScope(impl_) => { if *first_name == sym::Self_.clone() { @@ -253,7 +244,6 @@ impl Resolver { ResolvePathResultPrefixInfo::default(), )); } - None } &Scope::AdtScope(adt) => { if *first_name == sym::Self_.clone() { @@ -264,18 +254,33 @@ impl Resolver { ResolvePathResultPrefixInfo::default(), )); } - None } Scope::BlockScope(m) => { - if let Some(res) = m.resolve_path_in_type_ns(db, path) { + if let Some(res) = m.resolve_path_in_module_or_type_ns(db, path) { + let res = match res.0 { + ModuleOrTypeNs::TypeNs(_) => res, + ModuleOrTypeNs::ModuleNs(_) => { + if let Some(ModuleDefId::BuiltinType(builtin)) = BUILTIN_SCOPE + .get(first_name) + .and_then(|builtin| builtin.take_types()) + { + ( + ModuleOrTypeNs::TypeNs(TypeNs::BuiltinType(builtin)), + remaining_idx(), + None, + ResolvePathResultPrefixInfo::default(), + ) + } else { + res + } + } + }; return Some(res); } - None } - }) - .chain(self.module_scope.resolve_path_in_type_ns(db, path)); - - Box::new(ns) + } + } + self.module_scope.resolve_path_in_module_or_type_ns(db, path) } pub fn resolve_path_in_type_ns_fully( @@ -283,17 +288,11 @@ impl Resolver { db: &dyn DefDatabase, path: &Path, ) -> Option { - let (res, unresolved) = self - .resolve_path_in_type_ns(db, path) - .filter_map(|(res, unresolved, _)| match res { - ModuleOrTypeNs::TypeNs(it) => Some((it, unresolved)), - ModuleOrTypeNs::ModuleNs(_) => None, - }) - .next()?; - if unresolved.is_some() { - return None; + if let (ModuleOrTypeNs::TypeNs(res), None, _) = self.resolve_path_in_type_ns(db, path)? { + Some(res) + } else { + None } - Some(res) } pub fn resolve_visibility( @@ -1183,7 +1182,7 @@ impl ModuleItemMap { } } - fn resolve_path_in_type_ns( + fn resolve_path_in_module_or_type_ns( &self, db: &dyn DefDatabase, path: &ModPath, diff --git a/crates/hir-ty/src/lower/path.rs b/crates/hir-ty/src/lower/path.rs index 2064cad597..08917d70b6 100644 --- a/crates/hir-ty/src/lower/path.rs +++ b/crates/hir-ty/src/lower/path.rs @@ -333,15 +333,14 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> { } pub(crate) fn resolve_path_in_type_ns(&mut self) -> Option<(TypeNs, Option)> { - let (resolution, remaining_index, prefix_info) = self + let (resolution, remaining_index, _, prefix_info) = self .ctx .resolver - .resolve_path_in_type_ns_with_prefix_info(self.ctx.db.upcast(), self.path) - .filter_map(|(res, remaining_index, _, prefix_info)| match res { - ModuleOrTypeNs::TypeNs(type_ns) => Some((type_ns, remaining_index, prefix_info)), - ModuleOrTypeNs::ModuleNs(_) => None, - }) - .next()?; + .resolve_path_in_type_ns_with_prefix_info(self.ctx.db.upcast(), self.path)?; + + let ModuleOrTypeNs::TypeNs(resolution) = resolution else { + return None; + }; let segments = self.segments; if segments.is_empty() || matches!(self.path, Path::LangItem(..)) { diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index 586e55f42a..4d3b8f9f60 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -1365,23 +1365,6 @@ pub(crate) fn resolve_hir_path_as_attr_macro( .map(Into::into) } -fn resolve_path_in_module_or_type_ns( - db: &dyn HirDatabase, - resolver: &Resolver, - path: &Path, -) -> Option<(ModuleOrTypeNs, Option)> { - let mut types = resolver - .resolve_path_in_type_ns(db.upcast(), path) - .map(|(ty, remaining_idx, _)| (ty, remaining_idx)) - .peekable(); - let (ty, _) = types.peek()?; - match ty { - ModuleOrTypeNs::ModuleNs(_) => types - .find_or_first(|(ty, _)| matches!(ty, ModuleOrTypeNs::TypeNs(TypeNs::BuiltinType(_)))), - ModuleOrTypeNs::TypeNs(_) => types.next(), - } -} - fn resolve_hir_path_( db: &dyn HirDatabase, resolver: &Resolver, @@ -1404,7 +1387,7 @@ fn resolve_hir_path_( res.map(|ty_ns| (ModuleOrTypeNs::TypeNs(ty_ns), path.segments().first())) } None => { - let (ty, remaining_idx) = resolve_path_in_module_or_type_ns(db, resolver, 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() { @@ -1542,7 +1525,7 @@ fn resolve_hir_path_qualifier( res.map(|ty_ns| (ModuleOrTypeNs::TypeNs(ty_ns), path.segments().first())) } None => { - let (ty, remaining_idx) = resolve_path_in_module_or_type_ns(db, resolver, 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() {