@@ -717,7 +717,7 @@ use std::fmt;
717717
718718use crate :: constructor:: { Constructor , ConstructorSet } ;
719719use crate :: pat:: { DeconstructedPat , WitnessPat } ;
720- use crate :: { Captures , MatchArm , MatchCtxt , TypeCx , TypedArena } ;
720+ use crate :: { Captures , MatchArm , MatchCtxt , TypeCx } ;
721721
722722use self :: ValidityConstraint :: * ;
723723
@@ -874,11 +874,12 @@ impl<'p, Cx: TypeCx> PatStack<'p, Cx> {
874874 & self ,
875875 pcx : & PlaceCtxt < ' _ , ' p , Cx > ,
876876 ctor : & Constructor < Cx > ,
877+ ctor_sub_tys : & [ Cx :: Ty ] ,
877878 ctor_is_relevant : bool ,
878879 ) -> PatStack < ' p , Cx > {
879880 // We pop the head pattern and push the new fields extracted from the arguments of
880881 // `self.head()`.
881- let mut new_pats = self . head ( ) . specialize ( pcx, ctor) ;
882+ let mut new_pats = self . head ( ) . specialize ( pcx, ctor, ctor_sub_tys ) ;
882883 new_pats. extend_from_slice ( & self . pats [ 1 ..] ) ;
883884 // `ctor` is relevant for this row if it is the actual constructor of this row, or if the
884885 // row has a wildcard and `ctor` is relevant for wildcards.
@@ -950,11 +951,12 @@ impl<'p, Cx: TypeCx> MatrixRow<'p, Cx> {
950951 & self ,
951952 pcx : & PlaceCtxt < ' _ , ' p , Cx > ,
952953 ctor : & Constructor < Cx > ,
954+ ctor_sub_tys : & [ Cx :: Ty ] ,
953955 ctor_is_relevant : bool ,
954956 parent_row : usize ,
955957 ) -> MatrixRow < ' p , Cx > {
956958 MatrixRow {
957- pats : self . pats . pop_head_constructor ( pcx, ctor, ctor_is_relevant) ,
959+ pats : self . pats . pop_head_constructor ( pcx, ctor, ctor_sub_tys , ctor_is_relevant) ,
958960 parent_row,
959961 is_under_guard : self . is_under_guard ,
960962 useful : false ,
@@ -984,11 +986,13 @@ struct Matrix<'p, Cx: TypeCx> {
984986 /// each column must have the same type. Each column corresponds to a place within the
985987 /// scrutinee.
986988 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 > ,
989+ /// Track the type of each column/place.
990+ place_ty : SmallVec < [ Cx :: Ty ; 2 ] > ,
990991 /// Track for each column/place whether it contains a known valid value.
991992 place_validity : SmallVec < [ ValidityConstraint ; 2 ] > ,
993+ /// Track whether the virtual wildcard row used to compute exhaustiveness is relevant. See top
994+ /// of the file for details on relevancy.
995+ wildcard_row_is_relevant : bool ,
992996}
993997
994998impl < ' p , Cx : TypeCx > Matrix < ' p , Cx > {
@@ -1007,17 +1011,15 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> {
10071011
10081012 /// Build a new matrix from an iterator of `MatchArm`s.
10091013 fn new (
1010- wildcard_arena : & ' p TypedArena < DeconstructedPat < ' p , Cx > > ,
10111014 arms : & [ MatchArm < ' p , Cx > ] ,
10121015 scrut_ty : Cx :: Ty ,
10131016 scrut_validity : ValidityConstraint ,
10141017 ) -> Self {
1015- let wild_pattern = wildcard_arena. alloc ( DeconstructedPat :: wildcard ( scrut_ty) ) ;
1016- let wildcard_row = PatStack :: from_pattern ( wild_pattern) ;
10171018 let mut matrix = Matrix {
10181019 rows : Vec :: with_capacity ( arms. len ( ) ) ,
1019- wildcard_row ,
1020+ place_ty : smallvec ! [ scrut_ty ] ,
10201021 place_validity : smallvec ! [ scrut_validity] ,
1022+ wildcard_row_is_relevant : true ,
10211023 } ;
10221024 for ( row_id, arm) in arms. iter ( ) . enumerate ( ) {
10231025 let v = MatrixRow {
@@ -1032,10 +1034,10 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> {
10321034 }
10331035
10341036 fn head_ty ( & self ) -> Option < Cx :: Ty > {
1035- self . wildcard_row . head_opt ( ) . map ( |pat| pat . ty ( ) )
1037+ self . place_ty . first ( ) . copied ( )
10361038 }
10371039 fn column_count ( & self ) -> usize {
1038- self . wildcard_row . len ( )
1040+ self . place_ty . len ( )
10391041 }
10401042
10411043 fn rows (
@@ -1063,17 +1065,24 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> {
10631065 ctor : & Constructor < Cx > ,
10641066 ctor_is_relevant : bool ,
10651067 ) -> 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)
1068+ let ctor_sub_tys = pcx. ctor_sub_tys ( ctor) ;
1069+ let specialized_place_ty =
1070+ ctor_sub_tys. iter ( ) . chain ( self . place_ty [ 1 ..] . iter ( ) ) . copied ( ) . collect ( ) ;
1071+ let ctor_sub_validity = self . place_validity [ 0 ] . specialize ( ctor) ;
1072+ let specialized_place_validity = std:: iter:: repeat ( ctor_sub_validity)
10691073 . take ( ctor. arity ( pcx) )
10701074 . chain ( self . place_validity [ 1 ..] . iter ( ) . copied ( ) )
10711075 . collect ( ) ;
1072- let mut matrix =
1073- Matrix { rows : Vec :: new ( ) , wildcard_row, place_validity : new_place_validity } ;
1076+ let mut matrix = Matrix {
1077+ rows : Vec :: new ( ) ,
1078+ place_ty : specialized_place_ty,
1079+ place_validity : specialized_place_validity,
1080+ wildcard_row_is_relevant : self . wildcard_row_is_relevant && ctor_is_relevant,
1081+ } ;
10741082 for ( i, row) in self . rows ( ) . enumerate ( ) {
10751083 if ctor. is_covered_by ( pcx, row. head ( ) . ctor ( ) ) {
1076- let new_row = row. pop_head_constructor ( pcx, ctor, ctor_is_relevant, i) ;
1084+ let new_row =
1085+ row. pop_head_constructor ( pcx, ctor, ctor_sub_tys, ctor_is_relevant, i) ;
10771086 matrix. expand_and_push ( new_row) ;
10781087 }
10791088 }
@@ -1335,7 +1344,7 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>(
13351344) -> WitnessMatrix < Cx > {
13361345 debug_assert ! ( matrix. rows( ) . all( |r| r. len( ) == matrix. column_count( ) ) ) ;
13371346
1338- if !matrix. wildcard_row . relevant && matrix. rows ( ) . all ( |r| !r. pats . relevant ) {
1347+ if !matrix. wildcard_row_is_relevant && matrix. rows ( ) . all ( |r| !r. pats . relevant ) {
13391348 // Here we know that nothing will contribute further to exhaustiveness or usefulness. This
13401349 // is purely an optimization: skipping this check doesn't affect correctness. See the top of
13411350 // the file for details.
@@ -1356,7 +1365,7 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>(
13561365 }
13571366 // No (unguarded) rows, so the match is not exhaustive. We return a new witness unless
13581367 // irrelevant.
1359- return if matrix. wildcard_row . relevant {
1368+ return if matrix. wildcard_row_is_relevant {
13601369 WitnessMatrix :: unit_witness ( )
13611370 } else {
13621371 // We choose to not report anything here; see at the top for details.
@@ -1466,7 +1475,7 @@ pub fn compute_match_usefulness<'p, Cx: TypeCx>(
14661475 scrut_ty : Cx :: Ty ,
14671476 scrut_validity : ValidityConstraint ,
14681477) -> UsefulnessReport < ' p , Cx > {
1469- let mut matrix = Matrix :: new ( cx . wildcard_arena , arms, scrut_ty, scrut_validity) ;
1478+ let mut matrix = Matrix :: new ( arms, scrut_ty, scrut_validity) ;
14701479 let non_exhaustiveness_witnesses = compute_exhaustiveness_and_usefulness ( cx, & mut matrix, true ) ;
14711480
14721481 let non_exhaustiveness_witnesses: Vec < _ > = non_exhaustiveness_witnesses. single_column ( ) ;
0 commit comments