Avoid ICEs after bad patterns, for the other syntactic variants
This commit is contained in:
parent
1279939b38
commit
1028c7a66a
3 changed files with 128 additions and 9 deletions
|
|
@ -1512,11 +1512,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
pat_info: PatInfo<'tcx>,
|
||||
) -> Ty<'tcx> {
|
||||
// Type-check the path.
|
||||
let _ = self.demand_eqtype_pat(pat.span, expected, pat_ty, &pat_info.top_info);
|
||||
let had_err = self.demand_eqtype_pat(pat.span, expected, pat_ty, &pat_info.top_info);
|
||||
|
||||
// Type-check subpatterns.
|
||||
match self.check_struct_pat_fields(pat_ty, pat, variant, fields, has_rest_pat, pat_info) {
|
||||
Ok(()) => pat_ty,
|
||||
Ok(()) => match had_err {
|
||||
Ok(()) => pat_ty,
|
||||
Err(guar) => Ty::new_error(self.tcx, guar),
|
||||
},
|
||||
Err(guar) => Ty::new_error(self.tcx, guar),
|
||||
}
|
||||
}
|
||||
|
|
@ -1764,8 +1767,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
};
|
||||
|
||||
// Type-check the tuple struct pattern against the expected type.
|
||||
let diag = self.demand_eqtype_pat_diag(pat.span, expected, pat_ty, &pat_info.top_info);
|
||||
let had_err = diag.map_err(|diag| diag.emit());
|
||||
let had_err = self.demand_eqtype_pat(pat.span, expected, pat_ty, &pat_info.top_info);
|
||||
|
||||
// Type-check subpatterns.
|
||||
if subpats.len() == variant.fields.len()
|
||||
|
|
@ -1989,11 +1991,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
if let Err(reported) = self.demand_eqtype_pat(span, expected, pat_ty, &pat_info.top_info) {
|
||||
// Walk subpatterns with an expected type of `err` in this case to silence
|
||||
// further errors being emitted when using the bindings. #50333
|
||||
let element_tys_iter = (0..max_len).map(|_| Ty::new_error(tcx, reported));
|
||||
for (_, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
|
||||
self.check_pat(elem, Ty::new_error(tcx, reported), pat_info);
|
||||
}
|
||||
Ty::new_tup_from_iter(tcx, element_tys_iter)
|
||||
Ty::new_error(tcx, reported)
|
||||
} else {
|
||||
for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) {
|
||||
self.check_pat(elem, element_tys[i], pat_info);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
//! This test used to ICE: rust-lang/rust#109812
|
||||
//! These tests used to ICE: rust-lang/rust#109812, rust-lang/rust#150507
|
||||
//! Instead of actually analyzing the erroneous patterns,
|
||||
//! we instead stop after typeck where errors are already
|
||||
//! reported.
|
||||
|
|
@ -8,12 +8,21 @@
|
|||
enum Either {
|
||||
One(X),
|
||||
Two(X),
|
||||
Three { a: X },
|
||||
}
|
||||
|
||||
struct X(Y);
|
||||
|
||||
struct Y;
|
||||
|
||||
struct Z(*const i32);
|
||||
unsafe impl Send for Z {}
|
||||
|
||||
enum Meow {
|
||||
A { a: Z },
|
||||
B(Z),
|
||||
}
|
||||
|
||||
fn consume_fnmut(_: impl FnMut()) {}
|
||||
|
||||
fn move_into_fnmut() {
|
||||
|
|
@ -25,6 +34,58 @@ fn move_into_fnmut() {
|
|||
|
||||
let X(mut _t) = x;
|
||||
});
|
||||
|
||||
consume_fnmut(|| {
|
||||
let Either::Three { a: ref mut _t } = x;
|
||||
//~^ ERROR: mismatched types
|
||||
|
||||
let X(mut _t) = x;
|
||||
});
|
||||
}
|
||||
|
||||
fn tuple_against_array() {
|
||||
let variant: [();1] = [()];
|
||||
|
||||
|| match variant {
|
||||
(2,) => (),
|
||||
//~^ ERROR: mismatched types
|
||||
_ => {}
|
||||
};
|
||||
|
||||
|| {
|
||||
let ((2,) | _) = variant;
|
||||
//~^ ERROR: mismatched types
|
||||
};
|
||||
}
|
||||
|
||||
// Reproducer that triggers the compatibility lint more reliably, instead of relying on the fact
|
||||
// that at the time of writing, an unresolved integer type variable does not implement any
|
||||
// auto-traits.
|
||||
//
|
||||
// The @_ makes this example also reproduce ICE #150507 before PR #138961
|
||||
fn arcane() {
|
||||
let variant: [();1] = [()];
|
||||
|
||||
|| {
|
||||
match variant {
|
||||
(Z(y@_),) => {}
|
||||
//~^ ERROR: mismatched types
|
||||
}
|
||||
};
|
||||
|
||||
|| {
|
||||
match variant {
|
||||
Meow::A { a: Z(y@_) } => {}
|
||||
//~^ ERROR: mismatched types
|
||||
}
|
||||
};
|
||||
|
||||
|| {
|
||||
match variant {
|
||||
Meow::B(Z(y@_)) => {}
|
||||
//~^ ERROR: mismatched types
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,68 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/type_mismatch.rs:23:13
|
||||
--> $DIR/type_mismatch.rs:32:13
|
||||
|
|
||||
LL | let Either::Two(ref mut _t) = x;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `X`
|
||||
| |
|
||||
| expected `X`, found `Either`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/type_mismatch.rs:39:13
|
||||
|
|
||||
LL | let Either::Three { a: ref mut _t } = x;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `X`
|
||||
| |
|
||||
| expected `X`, found `Either`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/type_mismatch.rs:50:9
|
||||
|
|
||||
LL | || match variant {
|
||||
| ------- this expression has type `[(); 1]`
|
||||
LL | (2,) => (),
|
||||
| ^^^^ expected `[(); 1]`, found `(_,)`
|
||||
|
|
||||
= note: expected array `[(); 1]`
|
||||
found tuple `(_,)`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/type_mismatch.rs:56:14
|
||||
|
|
||||
LL | let ((2,) | _) = variant;
|
||||
| ^^^^ ------- this expression has type `[(); 1]`
|
||||
| |
|
||||
| expected `[(); 1]`, found `(_,)`
|
||||
|
|
||||
= note: expected array `[(); 1]`
|
||||
found tuple `(_,)`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/type_mismatch.rs:71:13
|
||||
|
|
||||
LL | match variant {
|
||||
| ------- this expression has type `[(); 1]`
|
||||
LL | (Z(y@_),) => {}
|
||||
| ^^^^^^^^^ expected `[(); 1]`, found `(_,)`
|
||||
|
|
||||
= note: expected array `[(); 1]`
|
||||
found tuple `(_,)`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/type_mismatch.rs:78:13
|
||||
|
|
||||
LL | match variant {
|
||||
| ------- this expression has type `[(); 1]`
|
||||
LL | Meow::A { a: Z(y@_) } => {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ expected `[(); 1]`, found `Meow`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/type_mismatch.rs:85:13
|
||||
|
|
||||
LL | match variant {
|
||||
| ------- this expression has type `[(); 1]`
|
||||
LL | Meow::B(Z(y@_)) => {}
|
||||
| ^^^^^^^^^^^^^^^ expected `[(); 1]`, found `Meow`
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue