Skip to content

Commit ba28e19

Browse files
committedOct 29, 2022
Auto merge of rust-lang#13505 - lowr:feat/gats, r=flodiebold
Clean up tests and add documentation for GATs related stuff This is a follow-up PR for rust-lang#13494. - addresses rust-lang/rust-analyzer#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)
2 parents ebce5e9 + e0f09cd commit ba28e19

File tree

2 files changed

+41
-64
lines changed

2 files changed

+41
-64
lines changed
 

‎crates/hir-ty/src/lib.rs

+13
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,20 @@ pub type PlaceholderIndex = chalk_ir::PlaceholderIndex;
8181
pub type VariableKind = chalk_ir::VariableKind<Interner>;
8282
pub type VariableKinds = chalk_ir::VariableKinds<Interner>;
8383
pub type CanonicalVarKinds = chalk_ir::CanonicalVarKinds<Interner>;
84+
/// Represents generic parameters and an item bound by them. When the item has parent, the binders
85+
/// also contain the generic parameters for its parent. See chalk's documentation for details.
86+
///
87+
/// One thing to keep in mind when working with `Binders` (and `Substitution`s, which represent
88+
/// generic arguments) in rust-analyzer is that the ordering within *is* significant - the generic
89+
/// parameters/arguments for an item MUST come before those for its parent. This is to facilitate
90+
/// the integration with chalk-solve, which mildly puts constraints as such. See #13335 for its
91+
/// motivation in detail.
8492
pub type Binders<T> = chalk_ir::Binders<T>;
93+
/// Interned list of generic arguments for an item. When an item has parent, the `Substitution` for
94+
/// it contains generic arguments for both its parent and itself. See chalk's documentation for
95+
/// details.
96+
///
97+
/// See `Binders` for the constraint on the ordering.
8598
pub type Substitution = chalk_ir::Substitution<Interner>;
8699
pub type GenericArg = chalk_ir::GenericArg<Interner>;
87100
pub type GenericArgData = chalk_ir::GenericArgData<Interner>;

‎crates/hir-ty/src/tests/traits.rs

+28-64
Original file line numberDiff line numberDiff line change
@@ -3966,7 +3966,7 @@ fn g(t: &(dyn T + Send)) {
39663966

39673967
#[test]
39683968
fn gats_in_path() {
3969-
check_infer_with_mismatches(
3969+
check_types(
39703970
r#"
39713971
//- minicore: deref
39723972
use core::ops::Deref;
@@ -3976,32 +3976,22 @@ trait PointerFamily {
39763976
39773977
fn f<P: PointerFamily>(p: P::Pointer<i32>) {
39783978
let a = *p;
3979+
//^ i32
39793980
}
39803981
fn g<P: PointerFamily>(p: <P as PointerFamily>::Pointer<i32>) {
39813982
let a = *p;
3983+
//^ i32
39823984
}
39833985
"#,
3984-
expect![[r#"
3985-
110..111 'p': PointerFamily::Pointer<i32, P>
3986-
130..149 '{ ... *p; }': ()
3987-
140..141 'a': i32
3988-
144..146 '*p': i32
3989-
145..146 'p': PointerFamily::Pointer<i32, P>
3990-
173..174 'p': PointerFamily::Pointer<i32, P>
3991-
212..231 '{ ... *p; }': ()
3992-
222..223 'a': i32
3993-
226..228 '*p': i32
3994-
227..228 'p': PointerFamily::Pointer<i32, P>
3995-
"#]],
39963986
);
39973987
}
39983988

39993989
#[test]
40003990
fn gats_with_impl_trait() {
4001-
// FIXME: the last function (`fn h()`) is not valid Rust as of this writing because you cannot
4002-
// specify the same associated type multiple times even if their arguments are different.
4003-
// Reconsider how to treat these invalid types.
4004-
check_infer_with_mismatches(
3991+
// FIXME: the last function (`fn i()`) is not valid Rust as of this writing because you cannot
3992+
// specify the same associated type multiple times even if their arguments are different (c.f.
3993+
// `fn h()`, which is valid). Reconsider how to treat these invalid types.
3994+
check_types(
40053995
r#"
40063996
//- minicore: deref
40073997
use core::ops::Deref;
@@ -4012,45 +4002,30 @@ trait Trait {
40124002
}
40134003
40144004
fn f<T>(v: impl Trait) {
4015-
v.get::<i32>().deref();
4016-
v.get::<T>().deref();
4005+
let a = v.get::<i32>().deref();
4006+
//^ &i32
4007+
let a = v.get::<T>().deref();
4008+
//^ &T
40174009
}
4018-
fn g<T>(v: impl Trait<Assoc<T> = &'a T>) {
4010+
fn g<'a, T: 'a>(v: impl Trait<Assoc<T> = &'a T>) {
40194011
let a = v.get::<T>();
4012+
//^ &T
40204013
let a = v.get::<()>();
4014+
//^ Trait::Assoc<(), impl Trait<Assoc<T> = &T>>
4015+
}
4016+
fn h<'a>(v: impl Trait<Assoc<i32> = &'a i32> + Trait<Assoc<i64> = &'a i64>) {
4017+
let a = v.get::<i32>();
4018+
//^ &i32
4019+
let a = v.get::<i64>();
4020+
//^ &i64
40214021
}
4022-
fn h(v: impl Trait<Assoc<i32> = &'a i32, Assoc<i64> = &'a i64> {
4022+
fn i<'a>(v: impl Trait<Assoc<i32> = &'a i32, Assoc<i64> = &'a i64>) {
40234023
let a = v.get::<i32>();
4024+
//^ &i32
40244025
let a = v.get::<i64>();
4026+
//^ &i64
40254027
}
40264028
"#,
4027-
expect![[r#"
4028-
90..94 'self': &Self
4029-
126..127 'v': impl Trait
4030-
141..198 '{ ...f(); }': ()
4031-
147..148 'v': impl Trait
4032-
147..161 'v.get::<i32>()': Trait::Assoc<i32, impl Trait>
4033-
147..169 'v.get:...eref()': &i32
4034-
175..176 'v': impl Trait
4035-
175..187 'v.get::<T>()': Trait::Assoc<T, impl Trait>
4036-
175..195 'v.get:...eref()': &T
4037-
207..208 'v': impl Trait<Assoc<T> = &T>
4038-
240..296 '{ ...>(); }': ()
4039-
250..251 'a': &T
4040-
254..255 'v': impl Trait<Assoc<T> = &T>
4041-
254..266 'v.get::<T>()': &T
4042-
276..277 'a': Trait::Assoc<(), impl Trait<Assoc<T> = &T>>
4043-
280..281 'v': impl Trait<Assoc<T> = &T>
4044-
280..293 'v.get::<()>()': Trait::Assoc<(), impl Trait<Assoc<T> = &T>>
4045-
302..303 'v': impl Trait<Assoc<i32> = &i32, Assoc<i64> = &i64>
4046-
360..419 '{ ...>(); }': ()
4047-
370..371 'a': &i32
4048-
374..375 'v': impl Trait<Assoc<i32> = &i32, Assoc<i64> = &i64>
4049-
374..388 'v.get::<i32>()': &i32
4050-
398..399 'a': &i64
4051-
402..403 'v': impl Trait<Assoc<i32> = &i32, Assoc<i64> = &i64>
4052-
402..416 'v.get::<i64>()': &i64
4053-
"#]],
40544029
);
40554030
}
40564031

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

40874062
#[test]
40884063
fn gats_in_associated_type_binding() {
4089-
check_infer_with_mismatches(
4064+
check_types(
40904065
r#"
40914066
trait Trait {
40924067
type Assoc<T>;
@@ -4099,24 +4074,13 @@ where
40994074
T: Trait<Assoc<isize> = usize>,
41004075
{
41014076
let a = t.get::<i32>();
4077+
//^ u32
41024078
let a = t.get::<isize>();
4079+
//^ usize
41034080
let a = t.get::<()>();
4081+
//^ Trait::Assoc<(), T>
41044082
}
41054083
41064084
"#,
4107-
expect![[r#"
4108-
48..52 'self': &Self
4109-
84..85 't': T
4110-
164..252 '{ ...>(); }': ()
4111-
174..175 'a': u32
4112-
178..179 't': T
4113-
178..192 't.get::<i32>()': u32
4114-
202..203 'a': usize
4115-
206..207 't': T
4116-
206..222 't.get:...ize>()': usize
4117-
232..233 'a': Trait::Assoc<(), T>
4118-
236..237 't': T
4119-
236..249 't.get::<()>()': Trait::Assoc<(), T>
4120-
"#]],
4121-
)
4085+
);
41224086
}

0 commit comments

Comments
 (0)