Skip to content

Commit b39f74f

Browse files
authored
Unrolled build for #150979
Rollup merge of #150979 - typeck-pat, r=lcnr Avoid ICEs after bad patterns, for the other syntactic variants This PR introduces changes equivalent to the ones in #126320, but also for struct and tuple patterns, instead of tuple struct patterns only. Fixes #150507.
2 parents a6acf0f + 1028c7a commit b39f74f

File tree

3 files changed

+128
-9
lines changed

3 files changed

+128
-9
lines changed

compiler/rustc_hir_typeck/src/pat.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1512,11 +1512,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
15121512
pat_info: PatInfo<'tcx>,
15131513
) -> Ty<'tcx> {
15141514
// Type-check the path.
1515-
let _ = self.demand_eqtype_pat(pat.span, expected, pat_ty, &pat_info.top_info);
1515+
let had_err = self.demand_eqtype_pat(pat.span, expected, pat_ty, &pat_info.top_info);
15161516

15171517
// Type-check subpatterns.
15181518
match self.check_struct_pat_fields(pat_ty, pat, variant, fields, has_rest_pat, pat_info) {
1519-
Ok(()) => pat_ty,
1519+
Ok(()) => match had_err {
1520+
Ok(()) => pat_ty,
1521+
Err(guar) => Ty::new_error(self.tcx, guar),
1522+
},
15201523
Err(guar) => Ty::new_error(self.tcx, guar),
15211524
}
15221525
}
@@ -1764,8 +1767,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
17641767
};
17651768

17661769
// Type-check the tuple struct pattern against the expected type.
1767-
let diag = self.demand_eqtype_pat_diag(pat.span, expected, pat_ty, &pat_info.top_info);
1768-
let had_err = diag.map_err(|diag| diag.emit());
1770+
let had_err = self.demand_eqtype_pat(pat.span, expected, pat_ty, &pat_info.top_info);
17691771

17701772
// Type-check subpatterns.
17711773
if subpats.len() == variant.fields.len()
@@ -1989,11 +1991,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
19891991
if let Err(reported) = self.demand_eqtype_pat(span, expected, pat_ty, &pat_info.top_info) {
19901992
// Walk subpatterns with an expected type of `err` in this case to silence
19911993
// further errors being emitted when using the bindings. #50333
1992-
let element_tys_iter = (0..max_len).map(|_| Ty::new_error(tcx, reported));
19931994
for (_, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
19941995
self.check_pat(elem, Ty::new_error(tcx, reported), pat_info);
19951996
}
1996-
Ty::new_tup_from_iter(tcx, element_tys_iter)
1997+
Ty::new_error(tcx, reported)
19971998
} else {
19981999
for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
19992000
self.check_pat(elem, element_tys[i], pat_info);

tests/ui/pattern/type_mismatch.rs

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//! This test used to ICE: rust-lang/rust#109812
1+
//! These tests used to ICE: rust-lang/rust#109812, rust-lang/rust#150507
22
//! Instead of actually analyzing the erroneous patterns,
33
//! we instead stop after typeck where errors are already
44
//! reported.
@@ -8,12 +8,21 @@
88
enum Either {
99
One(X),
1010
Two(X),
11+
Three { a: X },
1112
}
1213

1314
struct X(Y);
1415

1516
struct Y;
1617

18+
struct Z(*const i32);
19+
unsafe impl Send for Z {}
20+
21+
enum Meow {
22+
A { a: Z },
23+
B(Z),
24+
}
25+
1726
fn consume_fnmut(_: impl FnMut()) {}
1827

1928
fn move_into_fnmut() {
@@ -25,6 +34,58 @@ fn move_into_fnmut() {
2534

2635
let X(mut _t) = x;
2736
});
37+
38+
consume_fnmut(|| {
39+
let Either::Three { a: ref mut _t } = x;
40+
//~^ ERROR: mismatched types
41+
42+
let X(mut _t) = x;
43+
});
44+
}
45+
46+
fn tuple_against_array() {
47+
let variant: [();1] = [()];
48+
49+
|| match variant {
50+
(2,) => (),
51+
//~^ ERROR: mismatched types
52+
_ => {}
53+
};
54+
55+
|| {
56+
let ((2,) | _) = variant;
57+
//~^ ERROR: mismatched types
58+
};
59+
}
60+
61+
// Reproducer that triggers the compatibility lint more reliably, instead of relying on the fact
62+
// that at the time of writing, an unresolved integer type variable does not implement any
63+
// auto-traits.
64+
//
65+
// The @_ makes this example also reproduce ICE #150507 before PR #138961
66+
fn arcane() {
67+
let variant: [();1] = [()];
68+
69+
|| {
70+
match variant {
71+
(Z(y@_),) => {}
72+
//~^ ERROR: mismatched types
73+
}
74+
};
75+
76+
|| {
77+
match variant {
78+
Meow::A { a: Z(y@_) } => {}
79+
//~^ ERROR: mismatched types
80+
}
81+
};
82+
83+
|| {
84+
match variant {
85+
Meow::B(Z(y@_)) => {}
86+
//~^ ERROR: mismatched types
87+
}
88+
};
2889
}
2990

3091
fn main() {}
Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,68 @@
11
error[E0308]: mismatched types
2-
--> $DIR/type_mismatch.rs:23:13
2+
--> $DIR/type_mismatch.rs:32:13
33
|
44
LL | let Either::Two(ref mut _t) = x;
55
| ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `X`
66
| |
77
| expected `X`, found `Either`
88

9-
error: aborting due to 1 previous error
9+
error[E0308]: mismatched types
10+
--> $DIR/type_mismatch.rs:39:13
11+
|
12+
LL | let Either::Three { a: ref mut _t } = x;
13+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `X`
14+
| |
15+
| expected `X`, found `Either`
16+
17+
error[E0308]: mismatched types
18+
--> $DIR/type_mismatch.rs:50:9
19+
|
20+
LL | || match variant {
21+
| ------- this expression has type `[(); 1]`
22+
LL | (2,) => (),
23+
| ^^^^ expected `[(); 1]`, found `(_,)`
24+
|
25+
= note: expected array `[(); 1]`
26+
found tuple `(_,)`
27+
28+
error[E0308]: mismatched types
29+
--> $DIR/type_mismatch.rs:56:14
30+
|
31+
LL | let ((2,) | _) = variant;
32+
| ^^^^ ------- this expression has type `[(); 1]`
33+
| |
34+
| expected `[(); 1]`, found `(_,)`
35+
|
36+
= note: expected array `[(); 1]`
37+
found tuple `(_,)`
38+
39+
error[E0308]: mismatched types
40+
--> $DIR/type_mismatch.rs:71:13
41+
|
42+
LL | match variant {
43+
| ------- this expression has type `[(); 1]`
44+
LL | (Z(y@_),) => {}
45+
| ^^^^^^^^^ expected `[(); 1]`, found `(_,)`
46+
|
47+
= note: expected array `[(); 1]`
48+
found tuple `(_,)`
49+
50+
error[E0308]: mismatched types
51+
--> $DIR/type_mismatch.rs:78:13
52+
|
53+
LL | match variant {
54+
| ------- this expression has type `[(); 1]`
55+
LL | Meow::A { a: Z(y@_) } => {}
56+
| ^^^^^^^^^^^^^^^^^^^^^ expected `[(); 1]`, found `Meow`
57+
58+
error[E0308]: mismatched types
59+
--> $DIR/type_mismatch.rs:85:13
60+
|
61+
LL | match variant {
62+
| ------- this expression has type `[(); 1]`
63+
LL | Meow::B(Z(y@_)) => {}
64+
| ^^^^^^^^^^^^^^^ expected `[(); 1]`, found `Meow`
65+
66+
error: aborting due to 7 previous errors
1067

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

0 commit comments

Comments
 (0)