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`.
This commit is contained in:
Florian Diebold 2020-04-12 12:29:03 +02:00
parent c388130f5f
commit d88d67819b
3 changed files with 38 additions and 5 deletions

View file

@ -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,
};

View file

@ -451,8 +451,7 @@ pub mod str {
"#,
);
// should be Option<char>, but currently not because of Chalk ambiguity problem
assert_eq!("(Option<{unknown}>, Option<{unknown}>)", super::type_at_pos(&db, pos));
assert_eq!("(Option<char>, Option<char>)", super::type_at_pos(&db, pos));
}
#[test]

View file

@ -1803,7 +1803,7 @@ fn test<T, U>() where T::Item: Trait2, T: Trait<U::Item>, 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(