Skip to content

Commit cf98ecb

Browse files
committed
support tuple pointing
1 parent eb1e120 commit cf98ecb

File tree

3 files changed

+79
-15
lines changed

3 files changed

+79
-15
lines changed

compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2091,24 +2091,38 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
20912091
}
20922092
};
20932093

2094+
enum PointableType<'tcx> {
2095+
Adt(ty::AdtDef<'tcx>),
2096+
Tuple,
2097+
}
2098+
20942099
// We can only handle Adt types for now.
20952100
// TODO: We could support blanket impls here as well.
20962101
// TODO: We could support tuple impls here as well.
20972102
// TODO: We could potentially support array/vec/slice impls here as well.
20982103
// TODO: We could support ref impls here as well.
20992104
// Note that there is no point in supporting "primitive" types like char/i32,
21002105
// since we cannot refine such a span any more anyway.
2101-
let ty::Adt(impl_self_ty_path, impl_self_ty_args) = impl_self_ty.kind() else {
2102-
return Err(expr);
2106+
let (impl_self_ty, impl_self_ty_args) = match impl_self_ty.kind() {
2107+
ty::Adt(impl_self_ty_path, impl_self_ty_args) => (
2108+
PointableType::Adt(*impl_self_ty_path),
2109+
impl_self_ty_args.iter().collect::<Vec<_>>(),
2110+
),
2111+
ty::Tuple(impl_self_ty_args) => (
2112+
PointableType::Tuple,
2113+
impl_self_ty_args.iter().map(|t| ty::GenericArg::from(t)).collect::<Vec<_>>(),
2114+
),
2115+
_ => {
2116+
return Err(expr);
2117+
}
21032118
};
21042119

21052120
// We need to find which of the type's arguments are relevant to this obligation.
21062121
// For example, if we had an impl for `SomeTime<(A, C), B, Result<B, C>>` and the broken obligation
21072122
// was `B: Display` then we'd care about indexes `vec![1, 2]`, but if it was `C: PartialEq` then we'd
21082123
// care about index `vec![0, 2]`.
21092124
let relevant_ty_args_indices: Vec<usize> = impl_self_ty_args
2110-
.as_slice()
2111-
.iter()
2125+
.into_iter()
21122126
.enumerate()
21132127
.filter(|(_index, ty_arg)| {
21142128
relevant_impl_generics
@@ -2130,6 +2144,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
21302144
struct_fields,
21312145
_, // NOTE: "Rest" fields in structs are currently ignored by this function.
21322146
) => {
2147+
let PointableType::Adt(impl_self_ty_path) = impl_self_ty else {
2148+
// An Adt expression requires an Adt type and vice-versa.
2149+
return Err(expr);
2150+
};
21332151
// We can directly support `Variant` and `Struct` struct expressions:
21342152
let (struct_variant_def, struct_def_generics): (&ty::VariantDef, &ty::Generics) =
21352153
match struct_def_kind {
@@ -2233,6 +2251,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
22332251
..
22342252
},
22352253
)) => {
2254+
let PointableType::Adt(impl_self_ty_path) = impl_self_ty else {
2255+
// An Adt expression requires an Adt type and vice-versa.
2256+
return Err(expr);
2257+
};
2258+
22362259
let (struct_variant_def, struct_def_generics) = {
22372260
let mut struct_def_id = self.tcx.parent(*ctor_def_id);
22382261
if impl_self_ty_path.did() != struct_def_id {
@@ -2312,6 +2335,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
23122335
}
23132336
_ => Err(expr),
23142337
},
2338+
hir::ExprKind::Tup(elements) => {
2339+
if let &[single_index] = relevant_ty_args_indices.as_slice() {
2340+
if single_index < elements.len() {
2341+
return Ok(&elements[single_index]);
2342+
}
2343+
}
2344+
return Err(expr);
2345+
}
23152346
_ => Err(expr),
23162347
}
23172348
}

src/test/ui/tuple/blame-trait-error.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ struct GenericBurrito<Spiciness, Filling> {
4343
impl<X, Y: T3> T2 for GenericBurrito<X, Y> {}
4444
struct NotSpicy;
4545

46+
impl<A: T3, B: T3> T2 for (A, B) {}
47+
4648
fn want<V: T1>(_x: V) {}
4749

4850
fn example<Q>(q: Q) {
@@ -60,6 +62,9 @@ fn example<Q>(q: Q) {
6062

6163
want(Wrapper { value: GenericBurrito { spiciness: NotSpicy, filling: q } });
6264
//~^ ERROR the trait bound `Q: T3` is not satisfied [E0277]
65+
66+
want(Wrapper { value: (3, q) });
67+
//~^ ERROR the trait bound `Q: T3` is not satisfied [E0277]
6368
}
6469

6570
fn main() {}

src/test/ui/tuple/blame-trait-error.stderr

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0277]: the trait bound `Q: T3` is not satisfied
2-
--> $DIR/blame-trait-error.rs:49:60
2+
--> $DIR/blame-trait-error.rs:51:60
33
|
44
LL | want(Wrapper { value: Burrito { spicy: false, filling: q } });
55
| ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q`
@@ -15,7 +15,7 @@ note: required for `Wrapper<Burrito<Q>>` to implement `T1`
1515
LL | impl<B: T2> T1 for Wrapper<B> {}
1616
| ^^ ^^^^^^^^^^
1717
note: required by a bound in `want`
18-
--> $DIR/blame-trait-error.rs:46:12
18+
--> $DIR/blame-trait-error.rs:48:12
1919
|
2020
LL | fn want<V: T1>(_x: V) {}
2121
| ^^ required by this bound in `want`
@@ -25,7 +25,7 @@ LL | fn example<Q: T3>(q: Q) {
2525
| ++++
2626

2727
error[E0277]: the trait bound `Q: T3` is not satisfied
28-
--> $DIR/blame-trait-error.rs:52:84
28+
--> $DIR/blame-trait-error.rs:54:84
2929
|
3030
LL | want(Wrapper { value: BurritoKinds::SmallBurrito { spicy: true, small_filling: q } });
3131
| ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q`
@@ -41,7 +41,7 @@ note: required for `Wrapper<BurritoKinds<Q>>` to implement `T1`
4141
LL | impl<B: T2> T1 for Wrapper<B> {}
4242
| ^^ ^^^^^^^^^^
4343
note: required by a bound in `want`
44-
--> $DIR/blame-trait-error.rs:46:12
44+
--> $DIR/blame-trait-error.rs:48:12
4545
|
4646
LL | fn want<V: T1>(_x: V) {}
4747
| ^^ required by this bound in `want`
@@ -51,7 +51,7 @@ LL | fn example<Q: T3>(q: Q) {
5151
| ++++
5252

5353
error[E0277]: the trait bound `Q: T3` is not satisfied
54-
--> $DIR/blame-trait-error.rs:55:39
54+
--> $DIR/blame-trait-error.rs:57:39
5555
|
5656
LL | want(Wrapper { value: Taco(false, q) });
5757
| ---- ^ the trait `T3` is not implemented for `Q`
@@ -69,7 +69,7 @@ note: required for `Wrapper<Taco<Q>>` to implement `T1`
6969
LL | impl<B: T2> T1 for Wrapper<B> {}
7070
| ^^ ^^^^^^^^^^
7171
note: required by a bound in `want`
72-
--> $DIR/blame-trait-error.rs:46:12
72+
--> $DIR/blame-trait-error.rs:48:12
7373
|
7474
LL | fn want<V: T1>(_x: V) {}
7575
| ^^ required by this bound in `want`
@@ -79,7 +79,7 @@ LL | fn example<Q: T3>(q: Q) {
7979
| ++++
8080

8181
error[E0277]: the trait bound `Q: T3` is not satisfied
82-
--> $DIR/blame-trait-error.rs:58:53
82+
--> $DIR/blame-trait-error.rs:60:53
8383
|
8484
LL | want(Wrapper { value: TacoKinds::OneTaco(false, q) });
8585
| ---- ^ the trait `T3` is not implemented for `Q`
@@ -97,7 +97,7 @@ note: required for `Wrapper<TacoKinds<Q>>` to implement `T1`
9797
LL | impl<B: T2> T1 for Wrapper<B> {}
9898
| ^^ ^^^^^^^^^^
9999
note: required by a bound in `want`
100-
--> $DIR/blame-trait-error.rs:46:12
100+
--> $DIR/blame-trait-error.rs:48:12
101101
|
102102
LL | fn want<V: T1>(_x: V) {}
103103
| ^^ required by this bound in `want`
@@ -107,7 +107,7 @@ LL | fn example<Q: T3>(q: Q) {
107107
| ++++
108108

109109
error[E0277]: the trait bound `Q: T3` is not satisfied
110-
--> $DIR/blame-trait-error.rs:61:74
110+
--> $DIR/blame-trait-error.rs:63:74
111111
|
112112
LL | want(Wrapper { value: GenericBurrito { spiciness: NotSpicy, filling: q } });
113113
| ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q`
@@ -123,7 +123,7 @@ note: required for `Wrapper<GenericBurrito<NotSpicy, Q>>` to implement `T1`
123123
LL | impl<B: T2> T1 for Wrapper<B> {}
124124
| ^^ ^^^^^^^^^^
125125
note: required by a bound in `want`
126-
--> $DIR/blame-trait-error.rs:46:12
126+
--> $DIR/blame-trait-error.rs:48:12
127127
|
128128
LL | fn want<V: T1>(_x: V) {}
129129
| ^^ required by this bound in `want`
@@ -132,6 +132,34 @@ help: consider restricting type parameter `Q`
132132
LL | fn example<Q: T3>(q: Q) {
133133
| ++++
134134

135-
error: aborting due to 5 previous errors
135+
error[E0277]: the trait bound `Q: T3` is not satisfied
136+
--> $DIR/blame-trait-error.rs:66:31
137+
|
138+
LL | want(Wrapper { value: (3, q) });
139+
| ---- ^ the trait `T3` is not implemented for `Q`
140+
| |
141+
| required by a bound introduced by this call
142+
|
143+
note: required for `(i32, Q)` to implement `T2`
144+
--> $DIR/blame-trait-error.rs:46:20
145+
|
146+
LL | impl<A: T3, B: T3> T2 for (A, B) {}
147+
| ^^ ^^^^^^
148+
note: required for `Wrapper<(i32, Q)>` to implement `T1`
149+
--> $DIR/blame-trait-error.rs:12:13
150+
|
151+
LL | impl<B: T2> T1 for Wrapper<B> {}
152+
| ^^ ^^^^^^^^^^
153+
note: required by a bound in `want`
154+
--> $DIR/blame-trait-error.rs:48:12
155+
|
156+
LL | fn want<V: T1>(_x: V) {}
157+
| ^^ required by this bound in `want`
158+
help: consider restricting type parameter `Q`
159+
|
160+
LL | fn example<Q: T3>(q: Q) {
161+
| ++++
162+
163+
error: aborting due to 6 previous errors
136164

137165
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)