37
37
//! skipping some constructors as long as it doesn't change whether the resulting list of witnesses
38
38
//! is empty of not. We use this in the wildcard `_` case.
39
39
//!
40
- //! Splitting is implemented in the [`Constructor ::split`] function. We don't do splitting for
40
+ //! Splitting is implemented in the [`ConstructorSet ::split`] function. We don't do splitting for
41
41
//! or-patterns; instead we just try the alternatives one-by-one. For details on splitting
42
- //! wildcards, see [`Constructor ::split`]; for integer ranges, see
43
- //! [`IntRange::split`]; for slices, see [`Slice::split`].
42
+ //! wildcards, see [`ConstructorSet ::split`]; for integer ranges, see [`IntRange::split`]; for
43
+ //! slices, see [`Slice::split`].
44
44
//!
45
45
//! ## Opaque patterns
46
46
//!
@@ -678,8 +678,8 @@ pub(super) enum Constructor<'tcx> {
678
678
/// We use this for variants behind an unstable gate as well as
679
679
/// `#[doc(hidden)]` ones.
680
680
Hidden ,
681
- /// Fake extra constructor for constructors that are not seen in the matrix, as explained in the
682
- /// code for [`Constructor::split`] .
681
+ /// Fake extra constructor for constructors that are not seen in the matrix, as explained at the
682
+ /// top of the file .
683
683
Missing ,
684
684
}
685
685
@@ -761,104 +761,12 @@ impl<'tcx> Constructor<'tcx> {
761
761
}
762
762
}
763
763
764
- /// Some constructors (namely `Wildcard`, `IntRange` and `Slice`) actually stand for a set of
765
- /// actual constructors (like variants, integers or fixed-sized slices). When specializing for
766
- /// these constructors, we want to be specialising for the actual underlying constructors.
767
- /// Naively, we would simply return the list of constructors they correspond to. We instead are
768
- /// more clever: if there are constructors that we know will behave the same w.r.t. the current
769
- /// matrix, we keep them grouped. For example, all slices of a sufficiently large length will
770
- /// either be all useful or all non-useful with a given matrix.
771
- ///
772
- /// See the branches for details on how the splitting is done.
773
- ///
774
- /// This function may discard some irrelevant constructors if this preserves behavior. Eg. for
775
- /// the `_` case, we ignore the constructors already present in the column, unless all of them
776
- /// are.
777
- pub ( super ) fn split < ' a > (
778
- & self ,
779
- pcx : & PatCtxt < ' _ , ' _ , ' tcx > ,
780
- ctors : impl Iterator < Item = & ' a Constructor < ' tcx > > + Clone ,
781
- ) -> SmallVec < [ Self ; 1 ] >
782
- where
783
- ' tcx : ' a ,
784
- {
785
- match self {
786
- Wildcard => {
787
- let split_set = ConstructorSet :: for_ty ( pcx. cx , pcx. ty ) . split ( pcx, ctors) ;
788
- if !split_set. missing . is_empty ( ) {
789
- // We are splitting a wildcard in order to compute its usefulness. Some constructors are
790
- // not present in the column. The first thing we note is that specializing with any of
791
- // the missing constructors would select exactly the rows with wildcards. Moreover, they
792
- // would all return equivalent results. We can therefore group them all into a
793
- // fictitious `Missing` constructor.
794
- //
795
- // As an important optimization, this function will skip all the present constructors.
796
- // This is correct because specializing with any of the present constructors would
797
- // select a strict superset of the wildcard rows, and thus would only find witnesses
798
- // already found with the `Missing` constructor.
799
- // This does mean that diagnostics are incomplete: in
800
- // ```
801
- // match x {
802
- // Some(true) => {}
803
- // }
804
- // ```
805
- // we report `None` as missing but not `Some(false)`.
806
- //
807
- // When all the constructors are missing we can equivalently return the `Wildcard`
808
- // constructor on its own. The difference between `Wildcard` and `Missing` will then
809
- // only be in diagnostics.
810
-
811
- // If some constructors are missing, we typically want to report those constructors,
812
- // e.g.:
813
- // ```
814
- // enum Direction { N, S, E, W }
815
- // let Direction::N = ...;
816
- // ```
817
- // we can report 3 witnesses: `S`, `E`, and `W`.
818
- //
819
- // However, if the user didn't actually specify a constructor
820
- // in this arm, e.g., in
821
- // ```
822
- // let x: (Direction, Direction, bool) = ...;
823
- // let (_, _, false) = x;
824
- // ```
825
- // we don't want to show all 16 possible witnesses `(<direction-1>, <direction-2>,
826
- // true)` - we are satisfied with `(_, _, true)`. So if all constructors are missing we
827
- // prefer to report just a wildcard `_`.
828
- //
829
- // The exception is: if we are at the top-level, for example in an empty match, we
830
- // usually prefer to report the full list of constructors.
831
- let all_missing = split_set. present . is_empty ( ) ;
832
- let report_when_all_missing =
833
- pcx. is_top_level && !IntRange :: is_integral ( pcx. ty ) ;
834
- let ctor =
835
- if all_missing && !report_when_all_missing { Wildcard } else { Missing } ;
836
- smallvec ! [ ctor]
837
- } else {
838
- split_set. present
839
- }
840
- }
841
- // Fast-track if the range is trivial.
842
- IntRange ( this_range) if !this_range. is_singleton ( ) => {
843
- let column_ranges = ctors. filter_map ( |ctor| ctor. as_int_range ( ) ) . cloned ( ) ;
844
- this_range. split ( column_ranges) . map ( |( _, range) | IntRange ( range) ) . collect ( )
845
- }
846
- Slice ( this_slice @ Slice { kind : VarLen ( ..) , .. } ) => {
847
- let column_slices = ctors. filter_map ( |c| c. as_slice ( ) ) ;
848
- this_slice. split ( column_slices) . map ( |( _, slice) | Slice ( slice) ) . collect ( )
849
- }
850
- // Any other constructor can be used unchanged.
851
- _ => smallvec ! [ self . clone( ) ] ,
852
- }
853
- }
854
-
855
764
/// Returns whether `self` is covered by `other`, i.e. whether `self` is a subset of `other`.
856
765
/// For the simple cases, this is simply checking for equality. For the "grouped" constructors,
857
766
/// this checks for inclusion.
858
767
// We inline because this has a single call site in `Matrix::specialize_constructor`.
859
768
#[ inline]
860
769
pub ( super ) fn is_covered_by < ' p > ( & self , pcx : & PatCtxt < ' _ , ' p , ' tcx > , other : & Self ) -> bool {
861
- // This must be kept in sync with `is_covered_by_any`.
862
770
match ( self , other) {
863
771
// Wildcards cover anything
864
772
( _, Wildcard ) => true ,
@@ -1244,19 +1152,6 @@ impl ConstructorSet {
1244
1152
1245
1153
SplitConstructorSet { present, missing }
1246
1154
}
1247
-
1248
- /// Compute the set of constructors missing from this column.
1249
- /// This is only used for reporting to the user.
1250
- pub ( super ) fn compute_missing < ' a , ' tcx > (
1251
- & self ,
1252
- pcx : & PatCtxt < ' _ , ' _ , ' tcx > ,
1253
- ctors : impl Iterator < Item = & ' a Constructor < ' tcx > > + Clone ,
1254
- ) -> Vec < Constructor < ' tcx > >
1255
- where
1256
- ' tcx : ' a ,
1257
- {
1258
- self . split ( pcx, ctors) . missing
1259
- }
1260
1155
}
1261
1156
1262
1157
/// A value can be decomposed into a constructor applied to some fields. This struct represents
@@ -1697,7 +1592,17 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
1697
1592
self . reachable . set ( true )
1698
1593
}
1699
1594
pub ( super ) fn is_reachable ( & self ) -> bool {
1700
- self . reachable . get ( )
1595
+ if self . reachable . get ( ) {
1596
+ true
1597
+ } else if self . is_or_pat ( ) && self . iter_fields ( ) . any ( |f| f. is_reachable ( ) ) {
1598
+ // We always expand or patterns in the matrix, so we will never see the actual
1599
+ // or-pattern (the one with constructor `Or`) in the column. As such, it will not be
1600
+ // marked as reachable itself, only its children will. We recover this information here.
1601
+ self . set_reachable ( ) ;
1602
+ true
1603
+ } else {
1604
+ false
1605
+ }
1701
1606
}
1702
1607
1703
1608
/// Report the spans of subpatterns that were not reachable, if any.
@@ -1706,7 +1611,6 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
1706
1611
self . collect_unreachable_spans ( & mut spans) ;
1707
1612
spans
1708
1613
}
1709
-
1710
1614
fn collect_unreachable_spans ( & self , spans : & mut Vec < Span > ) {
1711
1615
// We don't look at subpatterns if we already reported the whole pattern as unreachable.
1712
1616
if !self . is_reachable ( ) {
0 commit comments