Skip to content

Commit

Permalink
Auto merge of #13505 - lowr:feat/gats, r=flodiebold
Browse files Browse the repository at this point in the history
Clean up tests and add documentation for GATs related stuff

This is a follow-up PR for #13494.

- addresses #13494 (comment)
- documents the ordering constraint on `Binders` and `Substitution` (which is not really follow-up for the previous PR, but it was introduced to support GATs and I strongly feel it's worth it)
  • Loading branch information
bors committed Oct 29, 2022
2 parents ebce5e9 + e0f09cd commit ba28e19
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 64 deletions.
13 changes: 13 additions & 0 deletions crates/hir-ty/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,20 @@ pub type PlaceholderIndex = chalk_ir::PlaceholderIndex;
pub type VariableKind = chalk_ir::VariableKind<Interner>;
pub type VariableKinds = chalk_ir::VariableKinds<Interner>;
pub type CanonicalVarKinds = chalk_ir::CanonicalVarKinds<Interner>;
/// Represents generic parameters and an item bound by them. When the item has parent, the binders
/// also contain the generic parameters for its parent. See chalk's documentation for details.
///
/// One thing to keep in mind when working with `Binders` (and `Substitution`s, which represent
/// generic arguments) in rust-analyzer is that the ordering within *is* significant - the generic
/// parameters/arguments for an item MUST come before those for its parent. This is to facilitate
/// the integration with chalk-solve, which mildly puts constraints as such. See #13335 for its
/// motivation in detail.
pub type Binders<T> = chalk_ir::Binders<T>;
/// Interned list of generic arguments for an item. When an item has parent, the `Substitution` for
/// it contains generic arguments for both its parent and itself. See chalk's documentation for
/// details.
///
/// See `Binders` for the constraint on the ordering.
pub type Substitution = chalk_ir::Substitution<Interner>;
pub type GenericArg = chalk_ir::GenericArg<Interner>;
pub type GenericArgData = chalk_ir::GenericArgData<Interner>;
Expand Down
92 changes: 28 additions & 64 deletions crates/hir-ty/src/tests/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3966,7 +3966,7 @@ fn g(t: &(dyn T + Send)) {

#[test]
fn gats_in_path() {
check_infer_with_mismatches(
check_types(
r#"
//- minicore: deref
use core::ops::Deref;
Expand All @@ -3976,32 +3976,22 @@ trait PointerFamily {
fn f<P: PointerFamily>(p: P::Pointer<i32>) {
let a = *p;
//^ i32
}
fn g<P: PointerFamily>(p: <P as PointerFamily>::Pointer<i32>) {
let a = *p;
//^ i32
}
"#,
expect![[r#"
110..111 'p': PointerFamily::Pointer<i32, P>
130..149 '{ ... *p; }': ()
140..141 'a': i32
144..146 '*p': i32
145..146 'p': PointerFamily::Pointer<i32, P>
173..174 'p': PointerFamily::Pointer<i32, P>
212..231 '{ ... *p; }': ()
222..223 'a': i32
226..228 '*p': i32
227..228 'p': PointerFamily::Pointer<i32, P>
"#]],
);
}

#[test]
fn gats_with_impl_trait() {
// FIXME: the last function (`fn h()`) is not valid Rust as of this writing because you cannot
// specify the same associated type multiple times even if their arguments are different.
// Reconsider how to treat these invalid types.
check_infer_with_mismatches(
// FIXME: the last function (`fn i()`) is not valid Rust as of this writing because you cannot
// specify the same associated type multiple times even if their arguments are different (c.f.
// `fn h()`, which is valid). Reconsider how to treat these invalid types.
check_types(
r#"
//- minicore: deref
use core::ops::Deref;
Expand All @@ -4012,45 +4002,30 @@ trait Trait {
}
fn f<T>(v: impl Trait) {
v.get::<i32>().deref();
v.get::<T>().deref();
let a = v.get::<i32>().deref();
//^ &i32
let a = v.get::<T>().deref();
//^ &T
}
fn g<T>(v: impl Trait<Assoc<T> = &'a T>) {
fn g<'a, T: 'a>(v: impl Trait<Assoc<T> = &'a T>) {
let a = v.get::<T>();
//^ &T
let a = v.get::<()>();
//^ Trait::Assoc<(), impl Trait<Assoc<T> = &T>>
}
fn h<'a>(v: impl Trait<Assoc<i32> = &'a i32> + Trait<Assoc<i64> = &'a i64>) {
let a = v.get::<i32>();
//^ &i32
let a = v.get::<i64>();
//^ &i64
}
fn h(v: impl Trait<Assoc<i32> = &'a i32, Assoc<i64> = &'a i64> {
fn i<'a>(v: impl Trait<Assoc<i32> = &'a i32, Assoc<i64> = &'a i64>) {
let a = v.get::<i32>();
//^ &i32
let a = v.get::<i64>();
//^ &i64
}
"#,
expect![[r#"
90..94 'self': &Self
126..127 'v': impl Trait
141..198 '{ ...f(); }': ()
147..148 'v': impl Trait
147..161 'v.get::<i32>()': Trait::Assoc<i32, impl Trait>
147..169 'v.get:...eref()': &i32
175..176 'v': impl Trait
175..187 'v.get::<T>()': Trait::Assoc<T, impl Trait>
175..195 'v.get:...eref()': &T
207..208 'v': impl Trait<Assoc<T> = &T>
240..296 '{ ...>(); }': ()
250..251 'a': &T
254..255 'v': impl Trait<Assoc<T> = &T>
254..266 'v.get::<T>()': &T
276..277 'a': Trait::Assoc<(), impl Trait<Assoc<T> = &T>>
280..281 'v': impl Trait<Assoc<T> = &T>
280..293 'v.get::<()>()': Trait::Assoc<(), impl Trait<Assoc<T> = &T>>
302..303 'v': impl Trait<Assoc<i32> = &i32, Assoc<i64> = &i64>
360..419 '{ ...>(); }': ()
370..371 'a': &i32
374..375 'v': impl Trait<Assoc<i32> = &i32, Assoc<i64> = &i64>
374..388 'v.get::<i32>()': &i32
398..399 'a': &i64
402..403 'v': impl Trait<Assoc<i32> = &i32, Assoc<i64> = &i64>
402..416 'v.get::<i64>()': &i64
"#]],
);
}

Expand Down Expand Up @@ -4086,7 +4061,7 @@ fn f<'a>(v: &dyn Trait<Assoc<i32> = &'a i32>) {

#[test]
fn gats_in_associated_type_binding() {
check_infer_with_mismatches(
check_types(
r#"
trait Trait {
type Assoc<T>;
Expand All @@ -4099,24 +4074,13 @@ where
T: Trait<Assoc<isize> = usize>,
{
let a = t.get::<i32>();
//^ u32
let a = t.get::<isize>();
//^ usize
let a = t.get::<()>();
//^ Trait::Assoc<(), T>
}
"#,
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>
"#]],
)
);
}

0 comments on commit ba28e19

Please sign in to comment.