From 9ad20442e8af42815fde41c03188764ac516cf18 Mon Sep 17 00:00:00 2001 From: Andrew Cann Date: Mon, 28 Nov 2016 18:38:27 +0800 Subject: [PATCH] Start enabling empty types in pattern matching. Remove the assumption at the start of is_useful that any suitably-long array of wildcard patterns is useful relative the any empty vector. Instead we just continue to recurse column-wise over the matrix. This assumption is false in the presence of empty types. eg. in the simplest case: let x: ! = ...; match x { // This pattern should not be considered useful by the algorithm _ => ... } --- src/librustc_const_eval/_match.rs | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/src/librustc_const_eval/_match.rs b/src/librustc_const_eval/_match.rs index 6d04975f533..e1894544657 100644 --- a/src/librustc_const_eval/_match.rs +++ b/src/librustc_const_eval/_match.rs @@ -510,19 +510,24 @@ pub fn is_useful<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>, -> Usefulness<'tcx> { let &Matrix(ref rows) = matrix; debug!("is_useful({:?}, {:?})", matrix, v); - if rows.is_empty() { - return match witness { - ConstructWitness => UsefulWithWitness(vec![Witness( - repeat(cx.wild_pattern).take(v.len()).cloned().collect() - )]), - LeaveOutWitness => Useful - }; - } - if rows[0].is_empty() { - return NotUseful; - } - let &Matrix(ref rows) = matrix; + // The base case. We are pattern-matching on () and the return value is + // based on whether our matrix has a row or not. + // NOTE: This could potentially be optimized by checking rows.is_empty() + // first and then, if v is non-empty, the return value is based on whether + // the type of the tuple we're checking is inhabited or not. + if v.is_empty() { + return if rows.is_empty() { + match witness { + ConstructWitness => UsefulWithWitness(vec![Witness(vec![])]), + LeaveOutWitness => Useful, + } + } + else { + NotUseful + } + }; + assert!(rows.iter().all(|r| r.len() == v.len()));