diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index 5fbc860a4b..e48f911f22 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -1162,9 +1162,39 @@ fn resolve_hir_path_qualifier( resolver: &Resolver, path: &Path, ) -> Option { - resolver - .resolve_path_in_type_ns_fully(db.upcast(), &path) - .map(|ty| match ty { + (|| { + let (ty, unresolved) = match path.type_anchor() { + Some(type_ref) => { + let (_, res) = TyLoweringContext::new(db, resolver, resolver.module().into()) + .lower_ty_ext(type_ref); + res.map(|ty_ns| (ty_ns, path.segments().first())) + } + None => { + 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() { + Some((ty, path.segments().last())) + } else { + None + } + } + None => Some((ty, None)), + } + } + }?; + + // If we are in a TypeNs for a Trait, and we have an unresolved name, try to resolve it as a type + // within the trait's associated types. + if let (Some(unresolved), &TypeNs::TraitId(trait_id)) = (&unresolved, &ty) { + if let Some(type_alias_id) = + db.trait_data(trait_id).associated_type_by_name(unresolved.name) + { + return Some(PathResolution::Def(ModuleDefId::from(type_alias_id).into())); + } + } + + let res = match ty { TypeNs::SelfType(it) => PathResolution::SelfType(it.into()), TypeNs::GenericParam(id) => PathResolution::TypeParam(id.into()), TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => { @@ -1175,11 +1205,28 @@ fn resolve_hir_path_qualifier( TypeNs::BuiltinType(it) => PathResolution::Def(BuiltinType::from(it).into()), TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()), TypeNs::TraitAliasId(it) => PathResolution::Def(TraitAlias::from(it).into()), - }) - .or_else(|| { - resolver - .resolve_module_path_in_items(db.upcast(), path.mod_path()?) - .take_types() - .map(|it| PathResolution::Def(it.into())) - }) + }; + match unresolved { + Some(unresolved) => resolver + .generic_def() + .and_then(|def| { + hir_ty::associated_type_shorthand_candidates( + db, + def, + res.in_type_ns()?, + |name, id| (name == unresolved.name).then_some(id), + ) + }) + .map(TypeAlias::from) + .map(Into::into) + .map(PathResolution::Def), + None => Some(res), + } + })() + .or_else(|| { + resolver + .resolve_module_path_in_items(db.upcast(), path.mod_path()?) + .take_types() + .map(|it| PathResolution::Def(it.into())) + }) }