Skip to content

Commit f43cd30

Browse files
committed
always make tuple elements a coercion site
1 parent 9171ba2 commit f43cd30

File tree

10 files changed

+42
-53
lines changed

10 files changed

+42
-53
lines changed

compiler/rustc_hir_typeck/src/expr.rs

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1939,27 +1939,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
19391939

19401940
fn check_expr_tuple(
19411941
&self,
1942-
elts: &'tcx [hir::Expr<'tcx>],
1942+
elements: &'tcx [hir::Expr<'tcx>],
19431943
expected: Expectation<'tcx>,
19441944
expr: &'tcx hir::Expr<'tcx>,
19451945
) -> Ty<'tcx> {
1946-
let flds = expected.only_has_type(self).and_then(|ty| {
1947-
let ty = self.try_structurally_resolve_type(expr.span, ty);
1948-
match ty.kind() {
1949-
ty::Tuple(flds) => Some(&flds[..]),
1950-
_ => None,
1951-
}
1946+
let mut expectations = expected
1947+
.only_has_type(self)
1948+
.and_then(|ty| self.try_structurally_resolve_type(expr.span, ty).tuple())
1949+
.unwrap_or_default()
1950+
.iter();
1951+
1952+
let elements = elements.iter().map(|e| {
1953+
let ty = expectations.next().unwrap_or_else(|| self.next_ty_var(e.span));
1954+
self.check_expr_coercible_to_type(e, ty, None);
1955+
ty
19521956
});
19531957

1954-
let elt_ts_iter = elts.iter().enumerate().map(|(i, e)| match flds {
1955-
Some(fs) if i < fs.len() => {
1956-
let ety = fs[i];
1957-
self.check_expr_coercible_to_type(e, ety, None);
1958-
ety
1959-
}
1960-
_ => self.check_expr_with_expectation(e, NoExpectation),
1961-
});
1962-
let tuple = Ty::new_tup_from_iter(self.tcx, elt_ts_iter);
1958+
let tuple = Ty::new_tup_from_iter(self.tcx, elements);
1959+
19631960
if let Err(guar) = tuple.error_reported() {
19641961
Ty::new_error(self.tcx, guar)
19651962
} else {

compiler/rustc_middle/src/ty/sty.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1560,7 +1560,8 @@ impl<'tcx> Ty<'tcx> {
15601560
}
15611561
}
15621562

1563-
/// Iterates over tuple fields.
1563+
/// Returns a list of tuple fields.
1564+
///
15641565
/// Panics when called on anything but a tuple.
15651566
#[inline]
15661567
pub fn tuple_fields(self) -> &'tcx List<Ty<'tcx>> {
@@ -1570,6 +1571,15 @@ impl<'tcx> Ty<'tcx> {
15701571
}
15711572
}
15721573

1574+
/// Returns a list of tuple type arguments, or `None` if `self` isn't a tuple.
1575+
#[inline]
1576+
pub fn tuple(self) -> Option<&'tcx List<Ty<'tcx>>> {
1577+
match self.kind() {
1578+
Tuple(args) => Some(args),
1579+
_ => None,
1580+
}
1581+
}
1582+
15731583
/// If the type contains variants, returns the valid range of variant indices.
15741584
//
15751585
// FIXME: This requires the optimized MIR in the case of coroutines.

tests/ui/loops/loop-break-value.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,10 +232,10 @@ LL | break (break, break);
232232
| || |
233233
| || expected because of this `break`
234234
| |expected because of this `break`
235-
| expected `()`, found `(!, !)`
235+
| expected `()`, found `(_, _)`
236236
|
237237
= note: expected unit type `()`
238-
found tuple `(!, !)`
238+
found tuple `(_, _)`
239239

240240
error[E0308]: mismatched types
241241
--> $DIR/loop-break-value.rs:89:15

tests/ui/never_type/diverging-tuple-parts-39485.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@ error[E0308]: mismatched types
2222
LL | fn f() -> isize {
2323
| ----- expected `isize` because of return type
2424
LL | (return 1, return 2)
25-
| ^^^^^^^^^^^^^^^^^^^^ expected `isize`, found `(!, !)`
25+
| ^^^^^^^^^^^^^^^^^^^^ expected `isize`, found `(_, _)`
2626
|
2727
= note: expected type `isize`
28-
found tuple `(!, !)`
28+
found tuple `(_, _)`
2929

3030
error: aborting due to 2 previous errors
3131

tests/ui/never_type/issue-10176.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ fn f() -> isize { //~ NOTE expected `isize` because of return type
22
(return 1, return 2)
33
//~^ ERROR mismatched types
44
//~| NOTE expected type `isize`
5-
//~| NOTE found tuple `(!, !)`
6-
//~| NOTE expected `isize`, found `(!, !)`
5+
//~| NOTE found tuple `(_, _)`
6+
//~| NOTE expected `isize`, found `(_, _)`
77
}
88

99
fn main() {}

tests/ui/never_type/issue-10176.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ error[E0308]: mismatched types
44
LL | fn f() -> isize {
55
| ----- expected `isize` because of return type
66
LL | (return 1, return 2)
7-
| ^^^^^^^^^^^^^^^^^^^^ expected `isize`, found `(!, !)`
7+
| ^^^^^^^^^^^^^^^^^^^^ expected `isize`, found `(_, _)`
88
|
99
= note: expected type `isize`
10-
found tuple `(!, !)`
10+
found tuple `(_, _)`
1111

1212
error: aborting due to 1 previous error
1313

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
fn main() {
22
let _tmp = [
33
("C200B40A82", 3),
4-
("C200B40A83", 4) //~ ERROR: expected function, found `(&'static str, {integer})` [E0618]
4+
("C200B40A83", 4) //~ ERROR: expected function, found `(&str, {integer})` [E0618]
55
("C200B40A8537", 5),
66
];
77
}

tests/ui/tuple/array-diagnostics.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0618]: expected function, found `(&'static str, {integer})`
1+
error[E0618]: expected function, found `(&str, {integer})`
22
--> $DIR/array-diagnostics.rs:4:9
33
|
44
LL | ("C200B40A83", 4)

tests/ui/tuple/coercion.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,17 @@
55
fn main() {
66
let _: ((),) = (loop {},);
77

8-
((),) = (loop {},); //~ error: mismatched types
8+
((),) = (loop {},);
99

1010
let x = (loop {},);
11-
let _: ((),) = x; //~ error: mismatched types
11+
let _: ((),) = x;
1212

1313
let _: (&[u8],) = (&[],);
1414

15+
// This one can't work without a redesign on the coercion system.
16+
// We currently only eagerly add never-to-any coercions, not any others.
17+
// Thus, because we don't have an expectation when typechecking `&[]`,
18+
// we don't add a coercion => this doesn't work.
1519
let y = (&[],);
1620
let _: (&[u8],) = y; //~ error: mismatched types
1721
}

tests/ui/tuple/coercion.stderr

Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,5 @@
11
error[E0308]: mismatched types
2-
--> $DIR/coercion.rs:8:6
3-
|
4-
LL | ((),) = (loop {},);
5-
| ^^ ---------- this expression has type `(!,)`
6-
| |
7-
| expected `!`, found `()`
8-
|
9-
= note: expected type `!`
10-
found unit type `()`
11-
12-
error[E0308]: mismatched types
13-
--> $DIR/coercion.rs:11:20
14-
|
15-
LL | let _: ((),) = x;
16-
| ----- ^ expected `((),)`, found `(!,)`
17-
| |
18-
| expected due to this
19-
|
20-
= note: expected tuple `((),)`
21-
found tuple `(!,)`
22-
23-
error[E0308]: mismatched types
24-
--> $DIR/coercion.rs:16:23
2+
--> $DIR/coercion.rs:20:23
253
|
264
LL | let _: (&[u8],) = y;
275
| -------- ^ expected `(&[u8],)`, found `(&[_; 0],)`
@@ -31,6 +9,6 @@ LL | let _: (&[u8],) = y;
319
= note: expected tuple `(&[u8],)`
3210
found tuple `(&[_; 0],)`
3311

34-
error: aborting due to 3 previous errors
12+
error: aborting due to 1 previous error
3513

3614
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)