Skip to content

Commit d88d678

Browse files
committed
Handle Self::Type in trait definitions when referring to own associated type
It was implemented for other generic parameters for the trait, but not for `Self`.
1 parent c388130 commit d88d678

File tree

3 files changed

+38
-5
lines changed

3 files changed

+38
-5
lines changed

crates/ra_hir_ty/src/lower.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -360,13 +360,23 @@ impl Ty {
360360
},
361361
Some(TypeNs::GenericParam(param_id)) => {
362362
let predicates = ctx.db.generic_predicates_for_param(param_id);
363-
predicates
363+
let mut traits_: Vec<_> = predicates
364364
.iter()
365365
.filter_map(|pred| match &pred.value {
366366
GenericPredicate::Implemented(tr) => Some(tr.trait_),
367367
_ => None,
368368
})
369-
.collect()
369+
.collect();
370+
// Handle `Self::Type` referring to own associated type in trait definitions
371+
if let GenericDefId::TraitId(trait_id) = param_id.parent {
372+
let generics = generics(ctx.db.upcast(), trait_id.into());
373+
if generics.params.types[param_id.local_id].provenance
374+
== TypeParamProvenance::TraitSelf
375+
{
376+
traits_.push(trait_id);
377+
}
378+
}
379+
traits_
370380
}
371381
_ => return Ty::Unknown,
372382
};

crates/ra_hir_ty/src/tests/regression.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -451,8 +451,7 @@ pub mod str {
451451
"#,
452452
);
453453

454-
// should be Option<char>, but currently not because of Chalk ambiguity problem
455-
assert_eq!("(Option<{unknown}>, Option<{unknown}>)", super::type_at_pos(&db, pos));
454+
assert_eq!("(Option<char>, Option<char>)", super::type_at_pos(&db, pos));
456455
}
457456

458457
#[test]

crates/ra_hir_ty/src/tests/traits.rs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1803,7 +1803,7 @@ fn test<T, U>() where T::Item: Trait2, T: Trait<U::Item>, U: Trait<()> {
18031803
}
18041804

18051805
#[test]
1806-
fn unselected_projection_on_trait_self() {
1806+
fn unselected_projection_on_impl_self() {
18071807
assert_snapshot!(infer(
18081808
r#"
18091809
//- /main.rs
@@ -1843,6 +1843,30 @@ impl Trait for S2 {
18431843
"###);
18441844
}
18451845

1846+
#[test]
1847+
fn unselected_projection_on_trait_self() {
1848+
let t = type_at(
1849+
r#"
1850+
//- /main.rs
1851+
trait Trait {
1852+
type Item;
1853+
1854+
fn f(&self) -> Self::Item { loop {} }
1855+
}
1856+
1857+
struct S;
1858+
impl Trait for S {
1859+
type Item = u32;
1860+
}
1861+
1862+
fn test() {
1863+
S.f()<|>;
1864+
}
1865+
"#,
1866+
);
1867+
assert_eq!(t, "u32");
1868+
}
1869+
18461870
#[test]
18471871
fn trait_impl_self_ty() {
18481872
let t = type_at(

0 commit comments

Comments
 (0)