@@ -828,6 +828,8 @@ struct PlaceInfo<Cx: TypeCx> {
828
828
ty : Cx :: Ty ,
829
829
/// Whether the place is known to contain valid data.
830
830
validity : ValidityConstraint ,
831
+ /// Whether the place is the scrutinee itself or a subplace of it.
832
+ is_scrutinee : bool ,
831
833
}
832
834
833
835
impl < Cx : TypeCx > PlaceInfo < Cx > {
@@ -838,13 +840,17 @@ impl<Cx: TypeCx> PlaceInfo<Cx> {
838
840
) -> impl Iterator < Item = Self > + ExactSizeIterator + Captures < ' a > {
839
841
let ctor_sub_tys = cx. ctor_sub_tys ( ctor, & self . ty ) ;
840
842
let ctor_sub_validity = self . validity . specialize ( ctor) ;
841
- ctor_sub_tys. map ( move |ty| PlaceInfo { ty, validity : ctor_sub_validity } )
843
+ ctor_sub_tys. map ( move |ty| PlaceInfo {
844
+ ty,
845
+ validity : ctor_sub_validity,
846
+ is_scrutinee : false ,
847
+ } )
842
848
}
843
849
}
844
850
845
851
impl < Cx : TypeCx > Clone for PlaceInfo < Cx > {
846
852
fn clone ( & self ) -> Self {
847
- Self { ty : self . ty . clone ( ) , validity : self . validity }
853
+ Self { ty : self . ty . clone ( ) , validity : self . validity , is_scrutinee : self . is_scrutinee }
848
854
}
849
855
}
850
856
@@ -1051,7 +1057,7 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> {
1051
1057
scrut_ty : Cx :: Ty ,
1052
1058
scrut_validity : ValidityConstraint ,
1053
1059
) -> Self {
1054
- let place_info = PlaceInfo { ty : scrut_ty, validity : scrut_validity } ;
1060
+ let place_info = PlaceInfo { ty : scrut_ty, validity : scrut_validity, is_scrutinee : true } ;
1055
1061
let mut matrix = Matrix {
1056
1062
rows : Vec :: with_capacity ( arms. len ( ) ) ,
1057
1063
place_info : smallvec ! [ place_info] ,
@@ -1446,11 +1452,10 @@ fn collect_overlapping_range_endpoints<'p, Cx: TypeCx>(
1446
1452
/// - unspecialization, where we lift the results from the previous step into results for this step
1447
1453
/// (using `apply_constructor` and by updating `row.useful` for each parent row).
1448
1454
/// This is all explained at the top of the file.
1449
- #[ instrument( level = "debug" , skip( mcx, is_top_level ) , ret) ]
1455
+ #[ instrument( level = "debug" , skip( mcx) , ret) ]
1450
1456
fn compute_exhaustiveness_and_usefulness < ' a , ' p , Cx : TypeCx > (
1451
1457
mcx : UsefulnessCtxt < ' a , Cx > ,
1452
1458
matrix : & mut Matrix < ' p , Cx > ,
1453
- is_top_level : bool ,
1454
1459
) -> Result < WitnessMatrix < Cx > , Cx :: Error > {
1455
1460
debug_assert ! ( matrix. rows( ) . all( |r| r. len( ) == matrix. column_count( ) ) ) ;
1456
1461
@@ -1488,7 +1493,7 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>(
1488
1493
1489
1494
// We treat match scrutinees of type `!` or `EmptyEnum` differently.
1490
1495
let is_toplevel_exception =
1491
- is_top_level && matches ! ( ctors_for_ty, ConstructorSet :: NoConstructors ) ;
1496
+ place . is_scrutinee && matches ! ( ctors_for_ty, ConstructorSet :: NoConstructors ) ;
1492
1497
// Whether empty patterns are counted as useful or not. We only warn an empty arm unreachable if
1493
1498
// it is guaranteed unreachable by the opsem (i.e. if the place is `known_valid`).
1494
1499
let empty_arms_are_unreachable = place. validity . is_known_valid ( )
@@ -1517,7 +1522,7 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>(
1517
1522
1518
1523
// Decide what constructors to report.
1519
1524
let is_integers = matches ! ( ctors_for_ty, ConstructorSet :: Integers { .. } ) ;
1520
- let always_report_all = is_top_level && !is_integers;
1525
+ let always_report_all = place . is_scrutinee && !is_integers;
1521
1526
// Whether we should report "Enum::A and Enum::C are missing" or "_ is missing".
1522
1527
let report_individual_missing_ctors = always_report_all || !all_missing;
1523
1528
// Which constructors are considered missing. We ensure that `!missing_ctors.is_empty() =>
@@ -1538,7 +1543,7 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>(
1538
1543
let ctor_is_relevant = matches ! ( ctor, Constructor :: Missing ) || missing_ctors. is_empty ( ) ;
1539
1544
let mut spec_matrix = matrix. specialize_constructor ( pcx, & ctor, ctor_is_relevant) ?;
1540
1545
let mut witnesses = ensure_sufficient_stack ( || {
1541
- compute_exhaustiveness_and_usefulness ( mcx, & mut spec_matrix, false )
1546
+ compute_exhaustiveness_and_usefulness ( mcx, & mut spec_matrix)
1542
1547
} ) ?;
1543
1548
1544
1549
// Transform witnesses for `spec_matrix` into witnesses for `matrix`.
@@ -1613,8 +1618,7 @@ pub fn compute_match_usefulness<'p, Cx: TypeCx>(
1613
1618
) -> Result < UsefulnessReport < ' p , Cx > , Cx :: Error > {
1614
1619
let cx = UsefulnessCtxt { tycx } ;
1615
1620
let mut matrix = Matrix :: new ( arms, scrut_ty, scrut_validity) ;
1616
- let non_exhaustiveness_witnesses =
1617
- compute_exhaustiveness_and_usefulness ( cx, & mut matrix, true ) ?;
1621
+ let non_exhaustiveness_witnesses = compute_exhaustiveness_and_usefulness ( cx, & mut matrix) ?;
1618
1622
1619
1623
let non_exhaustiveness_witnesses: Vec < _ > = non_exhaustiveness_witnesses. single_column ( ) ;
1620
1624
let arm_usefulness: Vec < _ > = arms
0 commit comments