diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index 6c7bbc4489..7b5990a47c 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs @@ -360,13 +360,23 @@ impl Ty { }, Some(TypeNs::GenericParam(param_id)) => { let predicates = ctx.db.generic_predicates_for_param(param_id); - predicates + let mut traits_: Vec<_> = predicates .iter() .filter_map(|pred| match &pred.value { GenericPredicate::Implemented(tr) => Some(tr.trait_), _ => None, }) - .collect() + .collect(); + // Handle `Self::Type` referring to own associated type in trait definitions + if let GenericDefId::TraitId(trait_id) = param_id.parent { + let generics = generics(ctx.db.upcast(), trait_id.into()); + if generics.params.types[param_id.local_id].provenance + == TypeParamProvenance::TraitSelf + { + traits_.push(trait_id); + } + } + traits_ } _ => return Ty::Unknown, }; diff --git a/crates/ra_hir_ty/src/tests/regression.rs b/crates/ra_hir_ty/src/tests/regression.rs index 3402e0cb5a..d69115a2f5 100644 --- a/crates/ra_hir_ty/src/tests/regression.rs +++ b/crates/ra_hir_ty/src/tests/regression.rs @@ -451,8 +451,7 @@ pub mod str { "#, ); - // should be Option, but currently not because of Chalk ambiguity problem - assert_eq!("(Option<{unknown}>, Option<{unknown}>)", super::type_at_pos(&db, pos)); + assert_eq!("(Option, Option)", super::type_at_pos(&db, pos)); } #[test] diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs index 22ae6ca909..d088bf3096 100644 --- a/crates/ra_hir_ty/src/tests/traits.rs +++ b/crates/ra_hir_ty/src/tests/traits.rs @@ -1803,7 +1803,7 @@ fn test() where T::Item: Trait2, T: Trait, U: Trait<()> { } #[test] -fn unselected_projection_on_trait_self() { +fn unselected_projection_on_impl_self() { assert_snapshot!(infer( r#" //- /main.rs @@ -1843,6 +1843,30 @@ impl Trait for S2 { "###); } +#[test] +fn unselected_projection_on_trait_self() { + let t = type_at( + r#" +//- /main.rs +trait Trait { + type Item; + + fn f(&self) -> Self::Item { loop {} } +} + +struct S; +impl Trait for S { + type Item = u32; +} + +fn test() { + S.f()<|>; +} +"#, + ); + assert_eq!(t, "u32"); +} + #[test] fn trait_impl_self_ty() { let t = type_at(