@@ -767,12 +767,6 @@ impl<'a, Cx: TypeCx> PlaceCtxt<'a, Cx> {
767767 fn ctor_arity ( & self , ctor : & Constructor < Cx > ) -> usize {
768768 self . cx . ctor_arity ( ctor, self . ty )
769769 }
770- fn ctor_sub_tys (
771- & ' a self ,
772- ctor : & ' a Constructor < Cx > ,
773- ) -> impl Iterator < Item = Cx :: Ty > + ExactSizeIterator + Captures < ' a > {
774- self . cx . ctor_sub_tys ( ctor, self . ty )
775- }
776770 fn ctors_for_ty ( & self ) -> Result < ConstructorSet < Cx > , Cx :: Error > {
777771 self . cx . ctors_for_ty ( self . ty )
778772 }
@@ -828,6 +822,32 @@ impl fmt::Display for ValidityConstraint {
828822 }
829823}
830824
825+ /// Data about a place under investigation.
826+ struct PlaceInfo < Cx : TypeCx > {
827+ /// The type of the place.
828+ ty : Cx :: Ty ,
829+ /// Whether the place is known to contain valid data.
830+ validity : ValidityConstraint ,
831+ }
832+
833+ impl < Cx : TypeCx > PlaceInfo < Cx > {
834+ fn specialize < ' a > (
835+ & ' a self ,
836+ cx : & ' a Cx ,
837+ ctor : & ' a Constructor < Cx > ,
838+ ) -> impl Iterator < Item = Self > + ExactSizeIterator + Captures < ' a > {
839+ let ctor_sub_tys = cx. ctor_sub_tys ( ctor, & self . ty ) ;
840+ let ctor_sub_validity = self . validity . specialize ( ctor) ;
841+ ctor_sub_tys. map ( move |ty| PlaceInfo { ty, validity : ctor_sub_validity } )
842+ }
843+ }
844+
845+ impl < Cx : TypeCx > Clone for PlaceInfo < Cx > {
846+ fn clone ( & self ) -> Self {
847+ Self { ty : self . ty . clone ( ) , validity : self . validity }
848+ }
849+ }
850+
831851/// Represents a pattern-tuple under investigation.
832852// The three lifetimes are:
833853// - 'p coming from the input
@@ -1001,10 +1021,9 @@ struct Matrix<'p, Cx: TypeCx> {
10011021 /// each column must have the same type. Each column corresponds to a place within the
10021022 /// scrutinee.
10031023 rows : Vec < MatrixRow < ' p , Cx > > ,
1004- /// Track the type of each column/place.
1005- place_ty : SmallVec < [ Cx :: Ty ; 2 ] > ,
1006- /// Track for each column/place whether it contains a known valid value.
1007- place_validity : SmallVec < [ ValidityConstraint ; 2 ] > ,
1024+ /// Track info about each place. Each place corresponds to a column in `rows`, and their types
1025+ /// must match.
1026+ place_info : SmallVec < [ PlaceInfo < Cx > ; 2 ] > ,
10081027 /// Track whether the virtual wildcard row used to compute exhaustiveness is relevant. See top
10091028 /// of the file for details on relevancy.
10101029 wildcard_row_is_relevant : bool ,
@@ -1032,10 +1051,10 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> {
10321051 scrut_ty : Cx :: Ty ,
10331052 scrut_validity : ValidityConstraint ,
10341053 ) -> Self {
1054+ let place_info = PlaceInfo { ty : scrut_ty, validity : scrut_validity } ;
10351055 let mut matrix = Matrix {
10361056 rows : Vec :: with_capacity ( arms. len ( ) ) ,
1037- place_ty : smallvec ! [ scrut_ty] ,
1038- place_validity : smallvec ! [ scrut_validity] ,
1057+ place_info : smallvec ! [ place_info] ,
10391058 wildcard_row_is_relevant : true ,
10401059 } ;
10411060 for ( row_id, arm) in arms. iter ( ) . enumerate ( ) {
@@ -1051,11 +1070,11 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> {
10511070 matrix
10521071 }
10531072
1054- fn head_ty ( & self ) -> Option < & Cx :: Ty > {
1055- self . place_ty . first ( )
1073+ fn head_place ( & self ) -> Option < & PlaceInfo < Cx > > {
1074+ self . place_info . first ( )
10561075 }
10571076 fn column_count ( & self ) -> usize {
1058- self . place_ty . len ( )
1077+ self . place_info . len ( )
10591078 }
10601079
10611080 fn rows (
@@ -1083,18 +1102,13 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> {
10831102 ctor : & Constructor < Cx > ,
10841103 ctor_is_relevant : bool ,
10851104 ) -> Result < Matrix < ' p , Cx > , Cx :: Error > {
1086- let ctor_sub_tys = pcx. ctor_sub_tys ( ctor) ;
1087- let arity = ctor_sub_tys. len ( ) ;
1088- let specialized_place_ty = ctor_sub_tys. chain ( self . place_ty [ 1 ..] . iter ( ) . cloned ( ) ) . collect ( ) ;
1089- let ctor_sub_validity = self . place_validity [ 0 ] . specialize ( ctor) ;
1090- let specialized_place_validity = std:: iter:: repeat ( ctor_sub_validity)
1091- . take ( arity)
1092- . chain ( self . place_validity [ 1 ..] . iter ( ) . copied ( ) )
1093- . collect ( ) ;
1105+ let subfield_place_info = self . place_info [ 0 ] . specialize ( pcx. cx , ctor) ;
1106+ let arity = subfield_place_info. len ( ) ;
1107+ let specialized_place_info =
1108+ subfield_place_info. chain ( self . place_info [ 1 ..] . iter ( ) . cloned ( ) ) . collect ( ) ;
10941109 let mut matrix = Matrix {
10951110 rows : Vec :: new ( ) ,
1096- place_ty : specialized_place_ty,
1097- place_validity : specialized_place_validity,
1111+ place_info : specialized_place_info,
10981112 wildcard_row_is_relevant : self . wildcard_row_is_relevant && ctor_is_relevant,
10991113 } ;
11001114 for ( i, row) in self . rows ( ) . enumerate ( ) {
@@ -1127,11 +1141,11 @@ impl<'p, Cx: TypeCx> fmt::Debug for Matrix<'p, Cx> {
11271141 . map ( |row| row. iter ( ) . map ( |pat| format ! ( "{pat:?}" ) ) . collect ( ) )
11281142 . collect ( ) ;
11291143 pretty_printed_matrix
1130- . push ( self . place_validity . iter ( ) . map ( |validity | format ! ( "{validity}" ) ) . collect ( ) ) ;
1144+ . push ( self . place_info . iter ( ) . map ( |place | format ! ( "{}" , place . validity ) ) . collect ( ) ) ;
11311145
11321146 let column_count = self . column_count ( ) ;
11331147 assert ! ( self . rows. iter( ) . all( |row| row. len( ) == column_count) ) ;
1134- assert ! ( self . place_validity . len( ) == column_count) ;
1148+ assert ! ( self . place_info . len( ) == column_count) ;
11351149 let column_widths: Vec < usize > = ( 0 ..column_count)
11361150 . map ( |col| pretty_printed_matrix. iter ( ) . map ( |row| row[ col] . len ( ) ) . max ( ) . unwrap_or ( 0 ) )
11371151 . collect ( ) ;
@@ -1457,7 +1471,7 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>(
14571471 return Ok ( WitnessMatrix :: empty ( ) ) ;
14581472 }
14591473
1460- let Some ( ty ) = matrix. head_ty ( ) . cloned ( ) else {
1474+ let Some ( place ) = matrix. head_place ( ) else {
14611475 // The base case: there are no columns in the matrix. We are morally pattern-matching on ().
14621476 // A row is useful iff it has no (unguarded) rows above it.
14631477 let mut useful = true ; // Whether the next row is useful.
@@ -1477,18 +1491,17 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>(
14771491 } ;
14781492 } ;
14791493
1480- debug ! ( "ty: {ty:?}" ) ;
1481- let pcx = & PlaceCtxt { cx : mcx. tycx , ty : & ty } ;
1494+ let ty = & place. ty . clone ( ) ; // Clone it out so we can mutate `matrix` later.
1495+ let pcx = & PlaceCtxt { cx : mcx. tycx , ty } ;
1496+ debug ! ( "ty: {:?}" , pcx. ty) ;
14821497 let ctors_for_ty = pcx. ctors_for_ty ( ) ?;
14831498
1484- // Whether the place/column we are inspecting is known to contain valid data.
1485- let place_validity = matrix. place_validity [ 0 ] ;
14861499 // We treat match scrutinees of type `!` or `EmptyEnum` differently.
14871500 let is_toplevel_exception =
14881501 is_top_level && matches ! ( ctors_for_ty, ConstructorSet :: NoConstructors ) ;
14891502 // Whether empty patterns are counted as useful or not. We only warn an empty arm unreachable if
14901503 // it is guaranteed unreachable by the opsem (i.e. if the place is `known_valid`).
1491- let empty_arms_are_unreachable = place_validity . is_known_valid ( )
1504+ let empty_arms_are_unreachable = place . validity . is_known_valid ( )
14921505 && ( is_toplevel_exception
14931506 || mcx. tycx . is_exhaustive_patterns_feature_on ( )
14941507 || mcx. tycx . is_min_exhaustive_patterns_feature_on ( ) ) ;
0 commit comments