mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-01 23:12:02 +00:00
Lower generic arguments for GATs in associated type bindings
This commit is contained in:
parent
63cba43b48
commit
5fc18ad6fa
@ -808,7 +808,15 @@ impl<'a> TyLoweringContext<'a> {
|
||||
// handle defaults. In expression or pattern path segments without
|
||||
// explicitly specified type arguments, missing type arguments are inferred
|
||||
// (i.e. defaults aren't used).
|
||||
if !infer_args || had_explicit_args {
|
||||
// Generic parameters for associated types are not supposed to have defaults, so we just
|
||||
// ignore them.
|
||||
let is_assoc_ty = if let GenericDefId::TypeAliasId(id) = def {
|
||||
let container = id.lookup(self.db.upcast()).container;
|
||||
matches!(container, ItemContainerId::TraitId(_))
|
||||
} else {
|
||||
false
|
||||
};
|
||||
if !is_assoc_ty && (!infer_args || had_explicit_args) {
|
||||
let defaults = self.db.generic_defaults(def);
|
||||
assert_eq!(total_len, defaults.len());
|
||||
let parent_from = item_len - substs.len();
|
||||
@ -997,9 +1005,28 @@ impl<'a> TyLoweringContext<'a> {
|
||||
None => return SmallVec::new(),
|
||||
Some(t) => t,
|
||||
};
|
||||
// FIXME: `substs_from_path_segment()` pushes `TyKind::Error` for every parent
|
||||
// generic params. It's inefficient to splice the `Substitution`s, so we may want
|
||||
// that method to optionally take parent `Substitution` as we already know them at
|
||||
// this point (`super_trait_ref.substitution`).
|
||||
let substitution = self.substs_from_path_segment(
|
||||
// FIXME: This is hack. We shouldn't really build `PathSegment` directly.
|
||||
PathSegment { name: &binding.name, args_and_bindings: binding.args.as_deref() },
|
||||
Some(associated_ty.into()),
|
||||
false, // this is not relevant
|
||||
Some(super_trait_ref.self_type_parameter(Interner)),
|
||||
);
|
||||
let self_params = generics(self.db.upcast(), associated_ty.into()).len_self();
|
||||
let substitution = Substitution::from_iter(
|
||||
Interner,
|
||||
substitution
|
||||
.iter(Interner)
|
||||
.take(self_params)
|
||||
.chain(super_trait_ref.substitution.iter(Interner)),
|
||||
);
|
||||
let projection_ty = ProjectionTy {
|
||||
associated_ty_id: to_assoc_type_id(associated_ty),
|
||||
substitution: super_trait_ref.substitution,
|
||||
substitution,
|
||||
};
|
||||
let mut preds: SmallVec<[_; 1]> = SmallVec::with_capacity(
|
||||
binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(),
|
||||
|
@ -4083,3 +4083,40 @@ fn f<'a>(v: &dyn Trait<Assoc<i32> = &'a i32>) {
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gats_in_associated_type_binding() {
|
||||
check_infer_with_mismatches(
|
||||
r#"
|
||||
trait Trait {
|
||||
type Assoc<T>;
|
||||
fn get<U>(&self) -> Self::Assoc<U>;
|
||||
}
|
||||
|
||||
fn f<T>(t: T)
|
||||
where
|
||||
T: Trait<Assoc<i32> = u32>,
|
||||
T: Trait<Assoc<isize> = usize>,
|
||||
{
|
||||
let a = t.get::<i32>();
|
||||
let a = t.get::<isize>();
|
||||
let a = t.get::<()>();
|
||||
}
|
||||
|
||||
"#,
|
||||
expect![[r#"
|
||||
48..52 'self': &Self
|
||||
84..85 't': T
|
||||
164..252 '{ ...>(); }': ()
|
||||
174..175 'a': u32
|
||||
178..179 't': T
|
||||
178..192 't.get::<i32>()': u32
|
||||
202..203 'a': usize
|
||||
206..207 't': T
|
||||
206..222 't.get:...ize>()': usize
|
||||
232..233 'a': Trait::Assoc<(), T>
|
||||
236..237 't': T
|
||||
236..249 't.get::<()>()': Trait::Assoc<(), T>
|
||||
"#]],
|
||||
)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user