diff options
| author | Dan Robertson <dan@dlrobertson.com> | 2019-01-13 14:23:32 +0000 |
|---|---|---|
| committer | Dan Robertson <dan@dlrobertson.com> | 2019-01-13 14:23:32 +0000 |
| commit | d6c19191b05c11c6a3f5cbf25178ec749f5a3414 (patch) | |
| tree | 5976d09bec43f7e815ec70f63d94291021e63dae | |
| parent | 0c91f3d97fe78d31c8cf3abb1858c65d73c6aa17 (diff) | |
| download | rust-d6c19191b05c11c6a3f5cbf25178ec749f5a3414.tar.gz rust-d6c19191b05c11c6a3f5cbf25178ec749f5a3414.zip | |
librustc_mir: Fix ICE with slice patterns
If a match arm does not include all fields in a structure and a later pattern includes a field that is an array, we will attempt to use the array type from the prior arm. When calculating the field type, treat a array of an unknown size as a TyErr.
| -rw-r--r-- | src/librustc_mir/hair/pattern/_match.rs | 9 | ||||
| -rw-r--r-- | src/test/ui/issues/issue-57472.rs | 35 | ||||
| -rw-r--r-- | src/test/ui/issues/issue-57472.stderr | 20 |
3 files changed, 63 insertions, 1 deletions
diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index b25d47b3901..188a1120442 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -1372,7 +1372,14 @@ fn constructor_sub_pattern_tys<'a, 'tcx: 'a>(cx: &MatchCheckCtxt<'a, 'tcx>, let is_visible = adt.is_enum() || field.vis.is_accessible_from(cx.module, cx.tcx); if is_visible { - field.ty(cx.tcx, substs) + let ty = field.ty(cx.tcx, substs); + match ty.sty { + // If the field type returned is an array of an unknown + // size return an TyErr. + ty::Array(_, len) if len.assert_usize(cx.tcx).is_none() => + cx.tcx.types.err, + _ => ty, + } } else { // Treat all non-visible fields as TyErr. They // can't appear in any other pattern from diff --git a/src/test/ui/issues/issue-57472.rs b/src/test/ui/issues/issue-57472.rs new file mode 100644 index 00000000000..1131006374c --- /dev/null +++ b/src/test/ui/issues/issue-57472.rs @@ -0,0 +1,35 @@ +#![crate_type="lib"] +#![deny(unreachable_patterns)] + +mod test_struct { + // Test the exact copy of the minimal example + // posted in the issue. + pub struct Punned { + foo: [u8; 1], + bar: [u8; 1], + } + + pub fn test(punned: Punned) { + match punned { + Punned { foo: [_], .. } => println!("foo"), + Punned { bar: [_], .. } => println!("bar"), + //~^ ERROR unreachable pattern [unreachable_patterns] + } + } +} + +mod test_union { + // Test the same thing using a union. + pub union Punned { + foo: [u8; 1], + bar: [u8; 1], + } + + pub fn test(punned: Punned) { + match punned { + Punned { foo: [_] } => println!("foo"), + Punned { bar: [_] } => println!("bar"), + //~^ ERROR unreachable pattern [unreachable_patterns] + } + } +} diff --git a/src/test/ui/issues/issue-57472.stderr b/src/test/ui/issues/issue-57472.stderr new file mode 100644 index 00000000000..b6dd7e24941 --- /dev/null +++ b/src/test/ui/issues/issue-57472.stderr @@ -0,0 +1,20 @@ +error: unreachable pattern + --> $DIR/issue-57472.rs:15:13 + | +LL | Punned { bar: [_], .. } => println!("bar"), + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +note: lint level defined here + --> $DIR/issue-57472.rs:2:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/issue-57472.rs:31:13 + | +LL | Punned { bar: [_] } => println!("bar"), + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + |
