From a5a7fcbde390ce3545613d7deeba25d0d400d818 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 5 Dec 2018 18:31:49 +0100 Subject: [PATCH 1/8] Don't depend on `Allocation` sizes for pattern length --- src/librustc_mir/hair/pattern/_match.rs | 161 +++++++++++++++++------- src/librustc_mir/hair/pattern/mod.rs | 44 ++++--- 2 files changed, 137 insertions(+), 68 deletions(-) diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index 4c77350f10ecd..601b08203fada 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -178,11 +178,11 @@ use super::{PatternFoldable, PatternFolder, compare_const_vals}; use rustc::hir::def_id::DefId; use rustc::hir::RangeEnd; -use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; -use rustc::ty::layout::{Integer, IntegerExt, VariantIdx}; +use rustc::ty::{self, Ty, TyCtxt, TypeFoldable, Const}; +use rustc::ty::layout::{Integer, IntegerExt, VariantIdx, Size}; use rustc::mir::Field; -use rustc::mir::interpret::ConstValue; +use rustc::mir::interpret::{ConstValue, Pointer, Scalar}; use rustc::util::common::ErrorReported; use syntax::attr::{SignedInt, UnsignedInt}; @@ -200,14 +200,54 @@ use std::u128; pub fn expand_pattern<'a, 'tcx>(cx: &MatchCheckCtxt<'a, 'tcx>, pat: Pattern<'tcx>) -> &'a Pattern<'tcx> { - cx.pattern_arena.alloc(LiteralExpander.fold_pattern(&pat)) + cx.pattern_arena.alloc(LiteralExpander { tcx: cx.tcx }.fold_pattern(&pat)) } -struct LiteralExpander; -impl<'tcx> PatternFolder<'tcx> for LiteralExpander { +struct LiteralExpander<'a, 'tcx> { + tcx: TyCtxt<'a, 'tcx, 'tcx> +} + +impl<'a, 'tcx> LiteralExpander<'a, 'tcx> { + /// Derefs `val` and potentially unsizes the value if `crty` is an array and `rty` a slice + fn fold_const_value_deref( + &mut self, + val: ConstValue<'tcx>, + rty: Ty<'tcx>, + crty: Ty<'tcx>, + ) -> ConstValue<'tcx> { + match (val, &crty.sty, &rty.sty) { + // the easy case, deref a reference + (ConstValue::Scalar(Scalar::Ptr(p)), x, y) if x == y => ConstValue::ByRef( + p.alloc_id, + self.tcx.alloc_map.lock().unwrap_memory(p.alloc_id), + p.offset, + ), + // unsize array to slice if pattern is array but match value or other patterns are slice + (ConstValue::Scalar(Scalar::Ptr(p)), ty::Array(t, n), ty::Slice(u)) => { + assert_eq!(t, u); + ConstValue::ScalarPair( + Scalar::Ptr(p), + n.val.try_to_scalar().unwrap(), + ) + }, + // fat pointers stay the same + (ConstValue::ScalarPair(..), _, _) => val, + // FIXME(oli-obk): this is reachable for `const FOO: &&&u32 = &&&42;` being used + _ => bug!("cannot deref {:#?}, {} -> {}", val, crty, rty), + } + } +} + +impl<'a, 'tcx> PatternFolder<'tcx> for LiteralExpander<'a, 'tcx> { fn fold_pattern(&mut self, pat: &Pattern<'tcx>) -> Pattern<'tcx> { match (&pat.ty.sty, &*pat.kind) { - (&ty::Ref(_, rty, _), &PatternKind::Constant { ref value }) => { + ( + &ty::Ref(_, rty, _), + &PatternKind::Constant { value: Const { + val, + ty: ty::TyS { sty: ty::Ref(_, crty, _), .. }, + } }, + ) => { Pattern { ty: pat.ty, span: pat.span, @@ -215,7 +255,11 @@ impl<'tcx> PatternFolder<'tcx> for LiteralExpander { subpattern: Pattern { ty: rty, span: pat.span, - kind: box PatternKind::Constant { value: value.clone() }, + kind: box PatternKind::Constant { value: Const::from_const_value( + self.tcx, + self.fold_const_value_deref(*val, rty, crty), + rty, + ) }, } } } @@ -732,15 +776,16 @@ fn max_slice_length<'p, 'a: 'p, 'tcx: 'a, I>( for row in patterns { match *row.kind { PatternKind::Constant { value } => { - if let Some(ptr) = value.to_ptr() { - let is_array_ptr = value.ty - .builtin_deref(true) - .and_then(|t| t.ty.builtin_index()) - .map_or(false, |t| t == cx.tcx.types.u8); - if is_array_ptr { - let alloc = cx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id); - max_fixed_len = cmp::max(max_fixed_len, alloc.bytes.len() as u64); - } + match (value.val, &value.ty.sty) { + (_, ty::Array(_, n)) => max_fixed_len = cmp::max( + max_fixed_len, + n.unwrap_usize(cx.tcx), + ), + (ConstValue::ScalarPair(_, n), ty::Slice(_)) => max_fixed_len = cmp::max( + max_fixed_len, + n.to_usize(&cx.tcx).unwrap(), + ), + _ => {}, } } PatternKind::Slice { ref prefix, slice: None, ref suffix } => { @@ -1358,18 +1403,44 @@ fn slice_pat_covered_by_constructor<'tcx>( ) -> Result { let data: &[u8] = match *ctor { ConstantValue(const_val) => { - let val = match const_val.val { - ConstValue::Unevaluated(..) | - ConstValue::ByRef(..) => bug!("unexpected ConstValue: {:?}", const_val), - ConstValue::Scalar(val) | ConstValue::ScalarPair(val, _) => val, - }; - if let Ok(ptr) = val.to_ptr() { - tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id).bytes.as_ref() - } else { - bug!("unexpected non-ptr ConstantValue") + match (const_val.val, &const_val.ty.sty) { + (ConstValue::ByRef(id, alloc, offset), ty::Array(t, n)) => { + if *t != tcx.types.u8 { + // FIXME(oli-obk): can't mix const patterns with slice patterns and get + // any sort of exhaustiveness/unreachable check yet + return Ok(false); + } + let ptr = Pointer::new(id, offset); + let n = n.assert_usize(tcx).unwrap(); + alloc.get_bytes(&tcx, ptr, Size::from_bytes(n)).unwrap() + }, + (ConstValue::ScalarPair(Scalar::Bits { .. }, n), ty::Slice(_)) => { + assert_eq!(n.to_usize(&tcx).unwrap(), 0); + &[] + }, + (ConstValue::ScalarPair(Scalar::Ptr(ptr), n), ty::Slice(t)) => { + if *t != tcx.types.u8 { + // FIXME(oli-obk): can't mix const patterns with slice patterns and get + // any sort of exhaustiveness/unreachable check yet + return Ok(false); + } + let n = n.to_usize(&tcx).unwrap(); + tcx.alloc_map + .lock() + .unwrap_memory(ptr.alloc_id) + .get_bytes(&tcx, ptr, Size::from_bytes(n)) + .unwrap() + }, + _ => bug!( + "slice_pat_covered_by_constructor: {:#?}, {:#?}, {:#?}, {:#?}", + ctor, prefix, slice, suffix, + ), } } - _ => bug!() + _ => bug!( + "slice_pat_covered_by_constructor not ConstValue: {:#?}, {:#?}, {:#?}, {:#?}", + ctor, prefix, slice, suffix, + ), }; let pat_len = prefix.len() + suffix.len(); @@ -1675,22 +1746,23 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>( // necessarily point to memory, they are usually just integers. The only time // they should be pointing to memory is when they are subslices of nonzero // slices - let (opt_ptr, n, ty) = match value.ty.builtin_deref(false).unwrap().ty.sty { - ty::TyKind::Array(t, n) => (value.to_ptr(), n.unwrap_usize(cx.tcx), t), - ty::TyKind::Slice(t) => { - match value.val { - ConstValue::ScalarPair(ptr, n) => ( - ptr.to_ptr().ok(), - n.to_bits(cx.tcx.data_layout.pointer_size).unwrap() as u64, - t, - ), - _ => span_bug!( - pat.span, - "slice pattern constant must be scalar pair but is {:?}", - value, - ), - } - }, + let (opt_ptr, n, ty) = match (value.val, &value.ty.sty) { + (ConstValue::ByRef(id, alloc, offset), ty::TyKind::Array(t, n)) => ( + Some(( + Pointer::new(id, offset), + alloc, + )), + n.unwrap_usize(cx.tcx), + t, + ), + (ConstValue::ScalarPair(ptr, n), ty::TyKind::Slice(t)) => ( + ptr.to_ptr().ok().map(|ptr| ( + ptr, + cx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id), + )), + n.to_bits(cx.tcx.data_layout.pointer_size).unwrap() as u64, + t, + ), _ => span_bug!( pat.span, "unexpected const-val {:?} with ctor {:?}", @@ -1702,8 +1774,7 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>( // convert a constant slice/array pattern to a list of patterns. match (n, opt_ptr) { (0, _) => Some(SmallVec::new()), - (_, Some(ptr)) => { - let alloc = cx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id); + (_, Some((ptr, alloc))) => { let layout = cx.tcx.layout_of(cx.param_env.and(ty)).ok()?; (0..n).map(|i| { let ptr = ptr.offset(layout.size * i, &cx.tcx).ok()?; diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index d695a64f62a08..ddd6a705b04d1 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -1259,34 +1259,32 @@ pub fn compare_const_vals<'a, 'tcx>( } } - if let ty::Ref(_, rty, _) = ty.value.sty { - if let ty::Str = rty.sty { - match (a.val, b.val) { - ( - ConstValue::ScalarPair( - Scalar::Ptr(ptr_a), - len_a, - ), - ConstValue::ScalarPair( - Scalar::Ptr(ptr_b), - len_b, - ), - ) if ptr_a.offset.bytes() == 0 && ptr_b.offset.bytes() == 0 => { - if let Ok(len_a) = len_a.to_bits(tcx.data_layout.pointer_size) { - if let Ok(len_b) = len_b.to_bits(tcx.data_layout.pointer_size) { - if len_a == len_b { - let map = tcx.alloc_map.lock(); - let alloc_a = map.unwrap_memory(ptr_a.alloc_id); - let alloc_b = map.unwrap_memory(ptr_b.alloc_id); - if alloc_a.bytes.len() as u128 == len_a { - return from_bool(alloc_a == alloc_b); - } + if let ty::Str = ty.value.sty { + match (a.val, b.val) { + ( + ConstValue::ScalarPair( + Scalar::Ptr(ptr_a), + len_a, + ), + ConstValue::ScalarPair( + Scalar::Ptr(ptr_b), + len_b, + ), + ) if ptr_a.offset.bytes() == 0 && ptr_b.offset.bytes() == 0 => { + if let Ok(len_a) = len_a.to_bits(tcx.data_layout.pointer_size) { + if let Ok(len_b) = len_b.to_bits(tcx.data_layout.pointer_size) { + if len_a == len_b { + let map = tcx.alloc_map.lock(); + let alloc_a = map.unwrap_memory(ptr_a.alloc_id); + let alloc_b = map.unwrap_memory(ptr_b.alloc_id); + if alloc_a.bytes.len() as u128 == len_a { + return from_bool(alloc_a == alloc_b); } } } } - _ => (), } + _ => (), } } From 8f2ce3d8391f411fb7f1264fef2639702f4cc44e Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 7 Dec 2018 18:56:05 +0100 Subject: [PATCH 2/8] Document and simplify pattern matching with constants as patterns --- src/librustc_mir/hair/pattern/_match.rs | 93 ++++++++++++++----------- 1 file changed, 51 insertions(+), 42 deletions(-) diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index 601b08203fada..2880ffa5891a5 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -209,10 +209,16 @@ struct LiteralExpander<'a, 'tcx> { impl<'a, 'tcx> LiteralExpander<'a, 'tcx> { /// Derefs `val` and potentially unsizes the value if `crty` is an array and `rty` a slice + /// + /// `crty` and `rty` can differ because you can use array constants in the presence of slice + /// patterns. So the pattern may end up being a slice, but the constant is an array. We convert + /// the array to a slice in that case fn fold_const_value_deref( &mut self, val: ConstValue<'tcx>, + // the pattern's pointee type rty: Ty<'tcx>, + // the constant's pointee type crty: Ty<'tcx>, ) -> ConstValue<'tcx> { match (val, &crty.sty, &rty.sty) { @@ -776,6 +782,7 @@ fn max_slice_length<'p, 'a: 'p, 'tcx: 'a, I>( for row in patterns { match *row.kind { PatternKind::Constant { value } => { + // extract the length of an array/slice from a constant match (value.val, &value.ty.sty) { (_, ty::Array(_, n)) => max_fixed_len = cmp::max( max_fixed_len, @@ -1393,53 +1400,55 @@ fn constructor_sub_pattern_tys<'a, 'tcx: 'a>(cx: &MatchCheckCtxt<'a, 'tcx>, } } -fn slice_pat_covered_by_constructor<'tcx>( +// checks whether a constant is equal to a user-written slice pattern. Only supports byte slices, +// meaning all other types will compare unequal and thus equal patterns often do not cause the +// second pattern to lint about unreachable match arms. +fn slice_pat_covered_by_const<'tcx>( tcx: TyCtxt<'_, 'tcx, '_>, _span: Span, - ctor: &Constructor, + const_val: &ty::Const<'tcx>, prefix: &[Pattern<'tcx>], slice: &Option>, suffix: &[Pattern<'tcx>] ) -> Result { - let data: &[u8] = match *ctor { - ConstantValue(const_val) => { - match (const_val.val, &const_val.ty.sty) { - (ConstValue::ByRef(id, alloc, offset), ty::Array(t, n)) => { - if *t != tcx.types.u8 { - // FIXME(oli-obk): can't mix const patterns with slice patterns and get - // any sort of exhaustiveness/unreachable check yet - return Ok(false); - } - let ptr = Pointer::new(id, offset); - let n = n.assert_usize(tcx).unwrap(); - alloc.get_bytes(&tcx, ptr, Size::from_bytes(n)).unwrap() - }, - (ConstValue::ScalarPair(Scalar::Bits { .. }, n), ty::Slice(_)) => { - assert_eq!(n.to_usize(&tcx).unwrap(), 0); - &[] - }, - (ConstValue::ScalarPair(Scalar::Ptr(ptr), n), ty::Slice(t)) => { - if *t != tcx.types.u8 { - // FIXME(oli-obk): can't mix const patterns with slice patterns and get - // any sort of exhaustiveness/unreachable check yet - return Ok(false); - } - let n = n.to_usize(&tcx).unwrap(); - tcx.alloc_map - .lock() - .unwrap_memory(ptr.alloc_id) - .get_bytes(&tcx, ptr, Size::from_bytes(n)) - .unwrap() - }, - _ => bug!( - "slice_pat_covered_by_constructor: {:#?}, {:#?}, {:#?}, {:#?}", - ctor, prefix, slice, suffix, - ), + let data: &[u8] = match (const_val.val, &const_val.ty.sty) { + (ConstValue::ByRef(id, alloc, offset), ty::Array(t, n)) => { + if *t != tcx.types.u8 { + // FIXME(oli-obk): can't mix const patterns with slice patterns and get + // any sort of exhaustiveness/unreachable check yet + return Ok(false); } - } + let ptr = Pointer::new(id, offset); + let n = n.assert_usize(tcx).unwrap(); + alloc.get_bytes(&tcx, ptr, Size::from_bytes(n)).unwrap() + }, + // a slice fat pointer to a zero length slice + (ConstValue::ScalarPair(Scalar::Bits { .. }, n), ty::Slice(t)) => { + if *t != tcx.types.u8 { + // FIXME(oli-obk): can't mix const patterns with slice patterns and get + // any sort of exhaustiveness/unreachable check yet + return Ok(false); + } + assert_eq!(n.to_usize(&tcx).unwrap(), 0); + &[] + }, + // + (ConstValue::ScalarPair(Scalar::Ptr(ptr), n), ty::Slice(t)) => { + if *t != tcx.types.u8 { + // FIXME(oli-obk): can't mix const patterns with slice patterns and get + // any sort of exhaustiveness/unreachable check yet + return Ok(false); + } + let n = n.to_usize(&tcx).unwrap(); + tcx.alloc_map + .lock() + .unwrap_memory(ptr.alloc_id) + .get_bytes(&tcx, ptr, Size::from_bytes(n)) + .unwrap() + }, _ => bug!( - "slice_pat_covered_by_constructor not ConstValue: {:#?}, {:#?}, {:#?}, {:#?}", - ctor, prefix, slice, suffix, + "slice_pat_covered_by_const: {:#?}, {:#?}, {:#?}, {:#?}", + const_val, prefix, slice, suffix, ), }; @@ -1837,9 +1846,9 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>( None } } - ConstantValue(..) => { - match slice_pat_covered_by_constructor( - cx.tcx, pat.span, constructor, prefix, slice, suffix + ConstantValue(cv) => { + match slice_pat_covered_by_const( + cx.tcx, pat.span, cv, prefix, slice, suffix ) { Ok(true) => Some(smallvec![]), Ok(false) => None, From 8a9414ae19ad16468935ca30930e45d1ae91aa59 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 7 Dec 2018 19:06:22 +0100 Subject: [PATCH 3/8] Add a few more tests of edge cases --- src/test/ui/pattern/slice-pattern-const-2.rs | 7 ++++++ src/test/ui/pattern/slice-pattern-const-3.rs | 7 ++++++ src/test/ui/pattern/slice-pattern-const.rs | 23 ++++++++++++++++++++ 3 files changed, 37 insertions(+) diff --git a/src/test/ui/pattern/slice-pattern-const-2.rs b/src/test/ui/pattern/slice-pattern-const-2.rs index 6f9501d025c26..15c23b39b01f2 100644 --- a/src/test/ui/pattern/slice-pattern-const-2.rs +++ b/src/test/ui/pattern/slice-pattern-const-2.rs @@ -21,4 +21,11 @@ fn main() { MAGIC_TEST => (), // this should warn _ => (), } + const FOO: [u32; 1] = [4]; + match [99] { + [0x00] => (), + [4] => (), + FOO => (), // this should warn + _ => (), + } } diff --git a/src/test/ui/pattern/slice-pattern-const-3.rs b/src/test/ui/pattern/slice-pattern-const-3.rs index e7a30cef57a8e..dbc61af16b560 100644 --- a/src/test/ui/pattern/slice-pattern-const-3.rs +++ b/src/test/ui/pattern/slice-pattern-const-3.rs @@ -21,4 +21,11 @@ fn main() { MAGIC_TEST => (), // this should warn _ => (), } + const FOO: [&str; 1] = ["boo"]; + match ["baa"] { + ["0x00"] => (), + ["boo"] => (), + FOO => (), // this should warn + _ => (), + } } diff --git a/src/test/ui/pattern/slice-pattern-const.rs b/src/test/ui/pattern/slice-pattern-const.rs index d353f6cddbd0d..e2589ddf81c64 100644 --- a/src/test/ui/pattern/slice-pattern-const.rs +++ b/src/test/ui/pattern/slice-pattern-const.rs @@ -21,4 +21,27 @@ fn main() { MAGIC_TEST => (), // this should warn _ => (), } + const FOO: [u8; 1] = [4]; + match [99] { + [0x00] => (), + [4] => (), + FOO => (), // this should warn + _ => (), + } + const BAR: &[u8; 1] = &[4]; + match &[99] { + [0x00] => (), + [4] => (), + BAR => (), // this should warn + b"a" => (), + _ => (), + } + + const BOO: &[u8; 0] = &[]; + match &[] { + [] => (), + BOO => (), // this should warn + b"" => (), + _ => (), + } } From 7d1b19cfe3552345d35c44745971c7df99a970bb Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 11 Dec 2018 09:05:06 +0100 Subject: [PATCH 4/8] Diagnostics improvement! --- src/test/run-pass/ctfe/references.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/run-pass/ctfe/references.rs b/src/test/run-pass/ctfe/references.rs index 946ed246bb05e..d5ab8dd7a2aac 100644 --- a/src/test/run-pass/ctfe/references.rs +++ b/src/test/run-pass/ctfe/references.rs @@ -28,9 +28,10 @@ fn main() { _ => panic!("c"), } + #[allow(unreachable_patterns)] match &43 { &42 => panic!(), - BOO => panic!(), + BOO => panic!(), // pattern is unreachable _ => println!("d"), } } From 46c1da6740982739a4cb3d2e9d553ac94ad38d22 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Thu, 13 Dec 2018 12:23:49 +0100 Subject: [PATCH 5/8] Doc comment format --- src/librustc_mir/hair/pattern/_match.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index 2880ffa5891a5..6ec82d8496da0 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -208,11 +208,11 @@ struct LiteralExpander<'a, 'tcx> { } impl<'a, 'tcx> LiteralExpander<'a, 'tcx> { - /// Derefs `val` and potentially unsizes the value if `crty` is an array and `rty` a slice + /// Derefs `val` and potentially unsizes the value if `crty` is an array and `rty` a slice. /// /// `crty` and `rty` can differ because you can use array constants in the presence of slice /// patterns. So the pattern may end up being a slice, but the constant is an array. We convert - /// the array to a slice in that case + /// the array to a slice in that case. fn fold_const_value_deref( &mut self, val: ConstValue<'tcx>, From 25a4f76d63e64784cc35396f2295197130ad1a85 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Thu, 13 Dec 2018 12:24:38 +0100 Subject: [PATCH 6/8] Fix indent --- src/librustc_mir/hair/pattern/_match.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index 6ec82d8496da0..1162f0ca86156 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -1847,9 +1847,7 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>( } } ConstantValue(cv) => { - match slice_pat_covered_by_const( - cx.tcx, pat.span, cv, prefix, slice, suffix - ) { + match slice_pat_covered_by_const(cx.tcx, pat.span, cv, prefix, slice, suffix) { Ok(true) => Some(smallvec![]), Ok(false) => None, Err(ErrorReported) => None From 5df6af49a7dbec08f210e258c3a66301f4fb3535 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Thu, 13 Dec 2018 12:54:49 +0100 Subject: [PATCH 7/8] Update tests to show diagnostics --- src/test/run-pass/ctfe/references.rs | 2 +- src/test/ui/pattern/const-pat-ice.rs | 13 +++++ src/test/ui/pattern/slice-pattern-const-2.rs | 10 ++-- .../ui/pattern/slice-pattern-const-2.stderr | 26 +++++++++ src/test/ui/pattern/slice-pattern-const-3.rs | 10 ++-- .../ui/pattern/slice-pattern-const-3.stderr | 14 +++++ src/test/ui/pattern/slice-pattern-const.rs | 18 +++--- .../ui/pattern/slice-pattern-const.stderr | 56 +++++++++++++++++++ 8 files changed, 129 insertions(+), 20 deletions(-) create mode 100644 src/test/ui/pattern/const-pat-ice.rs create mode 100644 src/test/ui/pattern/slice-pattern-const-2.stderr create mode 100644 src/test/ui/pattern/slice-pattern-const-3.stderr create mode 100644 src/test/ui/pattern/slice-pattern-const.stderr diff --git a/src/test/run-pass/ctfe/references.rs b/src/test/run-pass/ctfe/references.rs index d5ab8dd7a2aac..421f35438302b 100644 --- a/src/test/run-pass/ctfe/references.rs +++ b/src/test/run-pass/ctfe/references.rs @@ -31,7 +31,7 @@ fn main() { #[allow(unreachable_patterns)] match &43 { &42 => panic!(), - BOO => panic!(), // pattern is unreachable + BOO => panic!(), _ => println!("d"), } } diff --git a/src/test/ui/pattern/const-pat-ice.rs b/src/test/ui/pattern/const-pat-ice.rs new file mode 100644 index 0000000000000..6496a2ab69f5c --- /dev/null +++ b/src/test/ui/pattern/const-pat-ice.rs @@ -0,0 +1,13 @@ +// failure-status: 101 + +// This is a repro test for an ICE in our pattern handling of constants. + +const FOO: &&&u32 = &&&42; + +fn main() { + match unimplemented!() { + &&&42 => {}, + FOO => {}, + _ => {}, + } +} diff --git a/src/test/ui/pattern/slice-pattern-const-2.rs b/src/test/ui/pattern/slice-pattern-const-2.rs index 15c23b39b01f2..6cfef115d08dc 100644 --- a/src/test/ui/pattern/slice-pattern-const-2.rs +++ b/src/test/ui/pattern/slice-pattern-const-2.rs @@ -1,4 +1,4 @@ -// compile-pass +#![deny(unreachable_patterns)] fn main() { let s = &[0x00; 4][..]; //Slice of any value @@ -6,26 +6,26 @@ fn main() { match s { MAGIC_TEST => (), [0x00, 0x00, 0x00, 0x00] => (), - [4, 5, 6, 7] => (), // this should warn + [4, 5, 6, 7] => (), //~ ERROR unreachable pattern _ => (), } match s { [0x00, 0x00, 0x00, 0x00] => (), MAGIC_TEST => (), - [4, 5, 6, 7] => (), // this should warn + [4, 5, 6, 7] => (), //~ ERROR unreachable pattern _ => (), } match s { [0x00, 0x00, 0x00, 0x00] => (), [4, 5, 6, 7] => (), - MAGIC_TEST => (), // this should warn + MAGIC_TEST => (), // FIXME(oli-obk): this should warn, but currently does not _ => (), } const FOO: [u32; 1] = [4]; match [99] { [0x00] => (), [4] => (), - FOO => (), // this should warn + FOO => (), //~ ERROR unreachable pattern _ => (), } } diff --git a/src/test/ui/pattern/slice-pattern-const-2.stderr b/src/test/ui/pattern/slice-pattern-const-2.stderr new file mode 100644 index 0000000000000..95651ccc401e0 --- /dev/null +++ b/src/test/ui/pattern/slice-pattern-const-2.stderr @@ -0,0 +1,26 @@ +error: unreachable pattern + --> $DIR/slice-pattern-const-2.rs:9:9 + | +LL | [4, 5, 6, 7] => (), //~ ERROR unreachable pattern + | ^^^^^^^^^^^^ + | +note: lint level defined here + --> $DIR/slice-pattern-const-2.rs:1:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/slice-pattern-const-2.rs:15:9 + | +LL | [4, 5, 6, 7] => (), //~ ERROR unreachable pattern + | ^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/slice-pattern-const-2.rs:28:9 + | +LL | FOO => (), //~ ERROR unreachable pattern + | ^^^ + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/pattern/slice-pattern-const-3.rs b/src/test/ui/pattern/slice-pattern-const-3.rs index dbc61af16b560..8805c43ba0283 100644 --- a/src/test/ui/pattern/slice-pattern-const-3.rs +++ b/src/test/ui/pattern/slice-pattern-const-3.rs @@ -1,4 +1,4 @@ -// compile-pass +#![deny(unreachable_patterns)] fn main() { let s = &["0x00"; 4][..]; //Slice of any value @@ -6,26 +6,26 @@ fn main() { match s { MAGIC_TEST => (), ["0x00", "0x00", "0x00", "0x00"] => (), - ["4", "5", "6", "7"] => (), // this should warn + ["4", "5", "6", "7"] => (), // FIXME(oli-obk): this should warn, but currently does not _ => (), } match s { ["0x00", "0x00", "0x00", "0x00"] => (), MAGIC_TEST => (), - ["4", "5", "6", "7"] => (), // this should warn + ["4", "5", "6", "7"] => (), // FIXME(oli-obk): this should warn, but currently does not _ => (), } match s { ["0x00", "0x00", "0x00", "0x00"] => (), ["4", "5", "6", "7"] => (), - MAGIC_TEST => (), // this should warn + MAGIC_TEST => (), // FIXME(oli-obk): this should warn, but currently does not _ => (), } const FOO: [&str; 1] = ["boo"]; match ["baa"] { ["0x00"] => (), ["boo"] => (), - FOO => (), // this should warn + FOO => (), //~ ERROR unreachable pattern _ => (), } } diff --git a/src/test/ui/pattern/slice-pattern-const-3.stderr b/src/test/ui/pattern/slice-pattern-const-3.stderr new file mode 100644 index 0000000000000..531bbbc84d038 --- /dev/null +++ b/src/test/ui/pattern/slice-pattern-const-3.stderr @@ -0,0 +1,14 @@ +error: unreachable pattern + --> $DIR/slice-pattern-const-3.rs:28:9 + | +LL | FOO => (), //~ ERROR unreachable pattern + | ^^^ + | +note: lint level defined here + --> $DIR/slice-pattern-const-3.rs:1:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/pattern/slice-pattern-const.rs b/src/test/ui/pattern/slice-pattern-const.rs index e2589ddf81c64..f0a04513f91fb 100644 --- a/src/test/ui/pattern/slice-pattern-const.rs +++ b/src/test/ui/pattern/slice-pattern-const.rs @@ -1,4 +1,4 @@ -//compile-pass +#![deny(unreachable_patterns)] fn main() { let s = &[0x00; 4][..]; //Slice of any value @@ -6,33 +6,33 @@ fn main() { match s { MAGIC_TEST => (), [0x00, 0x00, 0x00, 0x00] => (), - [84, 69, 83, 84] => (), // this should warn + [84, 69, 83, 84] => (), //~ ERROR unreachable pattern _ => (), } match s { [0x00, 0x00, 0x00, 0x00] => (), MAGIC_TEST => (), - [84, 69, 83, 84] => (), // this should warn + [84, 69, 83, 84] => (), //~ ERROR unreachable pattern _ => (), } match s { [0x00, 0x00, 0x00, 0x00] => (), [84, 69, 83, 84] => (), - MAGIC_TEST => (), // this should warn + MAGIC_TEST => (), //~ ERROR unreachable pattern _ => (), } const FOO: [u8; 1] = [4]; match [99] { [0x00] => (), [4] => (), - FOO => (), // this should warn + FOO => (), //~ ERROR unreachable pattern _ => (), } const BAR: &[u8; 1] = &[4]; match &[99] { [0x00] => (), [4] => (), - BAR => (), // this should warn + BAR => (), //~ ERROR unreachable pattern b"a" => (), _ => (), } @@ -40,8 +40,8 @@ fn main() { const BOO: &[u8; 0] = &[]; match &[] { [] => (), - BOO => (), // this should warn - b"" => (), - _ => (), + BOO => (), //~ ERROR unreachable pattern + b"" => (), //~ ERROR unreachable pattern + _ => (), //~ ERROR unreachable pattern } } diff --git a/src/test/ui/pattern/slice-pattern-const.stderr b/src/test/ui/pattern/slice-pattern-const.stderr new file mode 100644 index 0000000000000..412e0158c01c7 --- /dev/null +++ b/src/test/ui/pattern/slice-pattern-const.stderr @@ -0,0 +1,56 @@ +error: unreachable pattern + --> $DIR/slice-pattern-const.rs:9:9 + | +LL | [84, 69, 83, 84] => (), //~ ERROR unreachable pattern + | ^^^^^^^^^^^^^^^^ + | +note: lint level defined here + --> $DIR/slice-pattern-const.rs:1:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/slice-pattern-const.rs:15:9 + | +LL | [84, 69, 83, 84] => (), //~ ERROR unreachable pattern + | ^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/slice-pattern-const.rs:21:9 + | +LL | MAGIC_TEST => (), //~ ERROR unreachable pattern + | ^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/slice-pattern-const.rs:28:9 + | +LL | FOO => (), //~ ERROR unreachable pattern + | ^^^ + +error: unreachable pattern + --> $DIR/slice-pattern-const.rs:35:9 + | +LL | BAR => (), //~ ERROR unreachable pattern + | ^^^ + +error: unreachable pattern + --> $DIR/slice-pattern-const.rs:43:9 + | +LL | BOO => (), //~ ERROR unreachable pattern + | ^^^ + +error: unreachable pattern + --> $DIR/slice-pattern-const.rs:44:9 + | +LL | b"" => (), //~ ERROR unreachable pattern + | ^^^ + +error: unreachable pattern + --> $DIR/slice-pattern-const.rs:45:9 + | +LL | _ => (), //~ ERROR unreachable pattern + | ^ + +error: aborting due to 8 previous errors + From 1c2a29e29a56d449111a1f39beb901983e8b7ebc Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Thu, 13 Dec 2018 12:54:57 +0100 Subject: [PATCH 8/8] Expand on a few comments --- src/librustc_mir/hair/pattern/_match.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index 1162f0ca86156..5cfcc16162ee2 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -1416,6 +1416,8 @@ fn slice_pat_covered_by_const<'tcx>( if *t != tcx.types.u8 { // FIXME(oli-obk): can't mix const patterns with slice patterns and get // any sort of exhaustiveness/unreachable check yet + // This solely means that we don't lint about unreachable patterns, even if some + // are definitely unreachable. return Ok(false); } let ptr = Pointer::new(id, offset); @@ -1427,6 +1429,8 @@ fn slice_pat_covered_by_const<'tcx>( if *t != tcx.types.u8 { // FIXME(oli-obk): can't mix const patterns with slice patterns and get // any sort of exhaustiveness/unreachable check yet + // This solely means that we don't lint about unreachable patterns, even if some + // are definitely unreachable. return Ok(false); } assert_eq!(n.to_usize(&tcx).unwrap(), 0); @@ -1437,6 +1441,8 @@ fn slice_pat_covered_by_const<'tcx>( if *t != tcx.types.u8 { // FIXME(oli-obk): can't mix const patterns with slice patterns and get // any sort of exhaustiveness/unreachable check yet + // This solely means that we don't lint about unreachable patterns, even if some + // are definitely unreachable. return Ok(false); } let n = n.to_usize(&tcx).unwrap();