@@ -717,7 +717,7 @@ use std::fmt;
717
717
718
718
use crate :: constructor:: { Constructor , ConstructorSet } ;
719
719
use crate :: pat:: { DeconstructedPat , WitnessPat } ;
720
- use crate :: { Captures , MatchArm , MatchCtxt , TypeCx , TypedArena } ;
720
+ use crate :: { Captures , MatchArm , MatchCtxt , TypeCx } ;
721
721
722
722
use self :: ValidityConstraint :: * ;
723
723
@@ -984,11 +984,13 @@ struct Matrix<'p, Cx: TypeCx> {
984
984
/// each column must have the same type. Each column corresponds to a place within the
985
985
/// scrutinee.
986
986
rows : Vec < MatrixRow < ' p , Cx > > ,
987
- /// Stores an extra fictitious row full of wildcards. Mostly used to keep track of the type of
988
- /// each column. This must obey the same invariants as the real rows.
989
- wildcard_row : PatStack < ' p , Cx > ,
987
+ /// Track the type of each column/place.
988
+ place_ty : SmallVec < [ Cx :: Ty ; 2 ] > ,
990
989
/// Track for each column/place whether it contains a known valid value.
991
990
place_validity : SmallVec < [ ValidityConstraint ; 2 ] > ,
991
+ /// Track whether the virtual wildcard row used to compute exhaustiveness is relevant. See top
992
+ /// of the file for details on relevancy.
993
+ wildcard_row_is_relevant : bool ,
992
994
}
993
995
994
996
impl < ' p , Cx : TypeCx > Matrix < ' p , Cx > {
@@ -1007,17 +1009,15 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> {
1007
1009
1008
1010
/// Build a new matrix from an iterator of `MatchArm`s.
1009
1011
fn new (
1010
- wildcard_arena : & ' p TypedArena < DeconstructedPat < ' p , Cx > > ,
1011
1012
arms : & [ MatchArm < ' p , Cx > ] ,
1012
1013
scrut_ty : Cx :: Ty ,
1013
1014
scrut_validity : ValidityConstraint ,
1014
1015
) -> Self {
1015
- let wild_pattern = wildcard_arena. alloc ( DeconstructedPat :: wildcard ( scrut_ty) ) ;
1016
- let wildcard_row = PatStack :: from_pattern ( wild_pattern) ;
1017
1016
let mut matrix = Matrix {
1018
1017
rows : Vec :: with_capacity ( arms. len ( ) ) ,
1019
- wildcard_row ,
1018
+ place_ty : smallvec ! [ scrut_ty ] ,
1020
1019
place_validity : smallvec ! [ scrut_validity] ,
1020
+ wildcard_row_is_relevant : true ,
1021
1021
} ;
1022
1022
for ( row_id, arm) in arms. iter ( ) . enumerate ( ) {
1023
1023
let v = MatrixRow {
@@ -1032,10 +1032,10 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> {
1032
1032
}
1033
1033
1034
1034
fn head_ty ( & self ) -> Option < Cx :: Ty > {
1035
- self . wildcard_row . head_opt ( ) . map ( |pat| pat . ty ( ) )
1035
+ self . place_ty . first ( ) . copied ( )
1036
1036
}
1037
1037
fn column_count ( & self ) -> usize {
1038
- self . wildcard_row . len ( )
1038
+ self . place_ty . len ( )
1039
1039
}
1040
1040
1041
1041
fn rows (
@@ -1063,14 +1063,20 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> {
1063
1063
ctor : & Constructor < Cx > ,
1064
1064
ctor_is_relevant : bool ,
1065
1065
) -> Matrix < ' p , Cx > {
1066
- let wildcard_row = self . wildcard_row . pop_head_constructor ( pcx, ctor, ctor_is_relevant) ;
1067
- let new_validity = self . place_validity [ 0 ] . specialize ( ctor) ;
1068
- let new_place_validity = std:: iter:: repeat ( new_validity)
1066
+ let ctor_sub_tys = pcx. ctor_sub_tys ( ctor) ;
1067
+ let specialized_place_ty =
1068
+ ctor_sub_tys. iter ( ) . chain ( self . place_ty [ 1 ..] . iter ( ) ) . copied ( ) . collect ( ) ;
1069
+ let ctor_sub_validity = self . place_validity [ 0 ] . specialize ( ctor) ;
1070
+ let specialized_place_validity = std:: iter:: repeat ( ctor_sub_validity)
1069
1071
. take ( ctor. arity ( pcx) )
1070
1072
. chain ( self . place_validity [ 1 ..] . iter ( ) . copied ( ) )
1071
1073
. collect ( ) ;
1072
- let mut matrix =
1073
- Matrix { rows : Vec :: new ( ) , wildcard_row, place_validity : new_place_validity } ;
1074
+ let mut matrix = Matrix {
1075
+ rows : Vec :: new ( ) ,
1076
+ place_ty : specialized_place_ty,
1077
+ place_validity : specialized_place_validity,
1078
+ wildcard_row_is_relevant : self . wildcard_row_is_relevant && ctor_is_relevant,
1079
+ } ;
1074
1080
for ( i, row) in self . rows ( ) . enumerate ( ) {
1075
1081
if ctor. is_covered_by ( pcx, row. head ( ) . ctor ( ) ) {
1076
1082
let new_row = row. pop_head_constructor ( pcx, ctor, ctor_is_relevant, i) ;
@@ -1335,7 +1341,7 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>(
1335
1341
) -> WitnessMatrix < Cx > {
1336
1342
debug_assert ! ( matrix. rows( ) . all( |r| r. len( ) == matrix. column_count( ) ) ) ;
1337
1343
1338
- if !matrix. wildcard_row . relevant && matrix. rows ( ) . all ( |r| !r. pats . relevant ) {
1344
+ if !matrix. wildcard_row_is_relevant && matrix. rows ( ) . all ( |r| !r. pats . relevant ) {
1339
1345
// Here we know that nothing will contribute further to exhaustiveness or usefulness. This
1340
1346
// is purely an optimization: skipping this check doesn't affect correctness. See the top of
1341
1347
// the file for details.
@@ -1356,7 +1362,7 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>(
1356
1362
}
1357
1363
// No (unguarded) rows, so the match is not exhaustive. We return a new witness unless
1358
1364
// irrelevant.
1359
- return if matrix. wildcard_row . relevant {
1365
+ return if matrix. wildcard_row_is_relevant {
1360
1366
WitnessMatrix :: unit_witness ( )
1361
1367
} else {
1362
1368
// We choose to not report anything here; see at the top for details.
@@ -1466,7 +1472,7 @@ pub fn compute_match_usefulness<'p, Cx: TypeCx>(
1466
1472
scrut_ty : Cx :: Ty ,
1467
1473
scrut_validity : ValidityConstraint ,
1468
1474
) -> UsefulnessReport < ' p , Cx > {
1469
- let mut matrix = Matrix :: new ( cx . wildcard_arena , arms, scrut_ty, scrut_validity) ;
1475
+ let mut matrix = Matrix :: new ( arms, scrut_ty, scrut_validity) ;
1470
1476
let non_exhaustiveness_witnesses = compute_exhaustiveness_and_usefulness ( cx, & mut matrix, true ) ;
1471
1477
1472
1478
let non_exhaustiveness_witnesses: Vec < _ > = non_exhaustiveness_witnesses. single_column ( ) ;
0 commit comments