mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 21:05:02 +00:00
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:
parent
c388130f5f
commit
d88d67819b
3 changed files with 38 additions and 5 deletions
|
@ -360,13 +360,23 @@ impl Ty {
|
||||||
},
|
},
|
||||||
Some(TypeNs::GenericParam(param_id)) => {
|
Some(TypeNs::GenericParam(param_id)) => {
|
||||||
let predicates = ctx.db.generic_predicates_for_param(param_id);
|
let predicates = ctx.db.generic_predicates_for_param(param_id);
|
||||||
predicates
|
let mut traits_: Vec<_> = predicates
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|pred| match &pred.value {
|
.filter_map(|pred| match &pred.value {
|
||||||
GenericPredicate::Implemented(tr) => Some(tr.trait_),
|
GenericPredicate::Implemented(tr) => Some(tr.trait_),
|
||||||
_ => None,
|
_ => 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,
|
_ => return Ty::Unknown,
|
||||||
};
|
};
|
||||||
|
|
|
@ -451,8 +451,7 @@ pub mod str {
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
|
|
||||||
// should be Option<char>, but currently not because of Chalk ambiguity problem
|
assert_eq!("(Option<char>, Option<char>)", super::type_at_pos(&db, pos));
|
||||||
assert_eq!("(Option<{unknown}>, Option<{unknown}>)", super::type_at_pos(&db, pos));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -1803,7 +1803,7 @@ fn test<T, U>() where T::Item: Trait2, T: Trait<U::Item>, U: Trait<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn unselected_projection_on_trait_self() {
|
fn unselected_projection_on_impl_self() {
|
||||||
assert_snapshot!(infer(
|
assert_snapshot!(infer(
|
||||||
r#"
|
r#"
|
||||||
//- /main.rs
|
//- /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]
|
#[test]
|
||||||
fn trait_impl_self_ty() {
|
fn trait_impl_self_ty() {
|
||||||
let t = type_at(
|
let t = type_at(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue