181181//! we ignore all the patterns in the first column of `P` that involve other constructors.
182182//! This is where `S(c, P)` comes in:
183183//! `U(P, p) := U(S(c, P), S(c, p))`
184- //! This special case is handled in `is_useful_specialized`.
185184//!
186185//! For example, if `P` is:
187186//!
@@ -1116,8 +1115,8 @@ impl<'tcx> Constructor<'tcx> {
11161115 }
11171116 }
11181117
1119- /// Some constructors (namely IntRange and Slice) actually stand for a set of actual
1120- /// constructors (integers and fixed-sized slices). When specializing for these
1118+ /// Some constructors (namely Wildcard, IntRange and Slice) actually stand for a set of actual
1119+ /// constructors (like variants, integers or fixed-sized slices). When specializing for these
11211120 /// constructors, we want to be specialising for the actual underlying constructors.
11221121 /// Naively, we would simply return the list of constructors they correspond to. We instead are
11231122 /// more clever: if there are constructors that we know will behave the same wrt the current
@@ -1136,6 +1135,7 @@ impl<'tcx> Constructor<'tcx> {
11361135 debug ! ( "Constructor::split({:#?}, {:#?})" , self , pcx. matrix) ;
11371136
11381137 match self {
1138+ Wildcard => Constructor :: split_wildcard ( pcx) ,
11391139 // Fast-track if the range is trivial. In particular, we don't do the overlapping
11401140 // ranges check.
11411141 IntRange ( ctor_range)
@@ -1149,6 +1149,30 @@ impl<'tcx> Constructor<'tcx> {
11491149 }
11501150 }
11511151
1152+ /// For wildcards, there are two groups of constructors: there are the constructors actually
1153+ /// present in the matrix (`head_ctors`), and the constructors not present (`missing_ctors`).
1154+ /// Two constructors that are not in the matrix will either both be catched (by a wildcard), or
1155+ /// both not be catched. Therefore we can keep the missing constructors grouped together.
1156+ fn split_wildcard < ' p > ( pcx : PatCtxt < ' _ , ' p , ' tcx > ) -> SmallVec < [ Self ; 1 ] > {
1157+ // Missing constructors are those that are not matched by any non-wildcard patterns in the
1158+ // current column. We only fully construct them on-demand, because they're rarely used and
1159+ // can be big.
1160+ let missing_ctors = MissingConstructors :: new ( pcx) ;
1161+
1162+ if missing_ctors. is_empty ( ) {
1163+ // All the constructors are present in the matrix, so we just go through them all.
1164+ // We must also split them first.
1165+ // Since `all_ctors` never contains wildcards, this won't recurse more than once.
1166+ let ( all_ctors, _) = missing_ctors. into_inner ( ) ;
1167+ all_ctors. into_iter ( ) . flat_map ( |ctor| ctor. split ( pcx, None ) ) . collect ( )
1168+ } else {
1169+ // Some constructors are missing, thus we can specialize with the wildcard constructor,
1170+ // which will stand for those constructors that are missing, and behaves like any of
1171+ // them.
1172+ smallvec ! [ Wildcard ]
1173+ }
1174+ }
1175+
11521176 /// Returns whether `self` is covered by `other`, ie whether `self` is a subset of `other`. For
11531177 /// the simple cases, this is simply checking for equality. For the "grouped" constructors,
11541178 /// this checks for inclusion.
@@ -1617,8 +1641,8 @@ impl<'tcx> Usefulness<'tcx> {
16171641 match self {
16181642 UsefulWithWitness ( witnesses) => {
16191643 let new_witnesses = if ctor. is_wildcard ( ) {
1620- let missing_ctors = MissingConstructors :: new ( pcx, is_top_level ) ;
1621- let new_patterns = missing_ctors. report_patterns ( pcx) ;
1644+ let missing_ctors = MissingConstructors :: new ( pcx) ;
1645+ let new_patterns = missing_ctors. report_patterns ( pcx, is_top_level ) ;
16221646 witnesses
16231647 . into_iter ( )
16241648 . flat_map ( |witness| {
@@ -2217,16 +2241,15 @@ impl<'tcx> std::cmp::PartialEq for IntRange<'tcx> {
22172241struct MissingConstructors < ' tcx > {
22182242 all_ctors : Vec < Constructor < ' tcx > > ,
22192243 used_ctors : Vec < Constructor < ' tcx > > ,
2220- is_top_level : bool ,
22212244}
22222245
22232246impl < ' tcx > MissingConstructors < ' tcx > {
2224- fn new < ' p > ( pcx : PatCtxt < ' _ , ' p , ' tcx > , is_top_level : bool ) -> Self {
2247+ fn new < ' p > ( pcx : PatCtxt < ' _ , ' p , ' tcx > ) -> Self {
22252248 let used_ctors: Vec < Constructor < ' _ > > =
22262249 pcx. matrix . head_ctors ( pcx. cx ) . cloned ( ) . filter ( |c| !c. is_wildcard ( ) ) . collect ( ) ;
22272250 let all_ctors = all_constructors ( pcx) ;
22282251
2229- MissingConstructors { all_ctors, used_ctors, is_top_level }
2252+ MissingConstructors { all_ctors, used_ctors }
22302253 }
22312254
22322255 fn into_inner ( self ) -> ( Vec < Constructor < ' tcx > > , Vec < Constructor < ' tcx > > ) {
@@ -2244,7 +2267,11 @@ impl<'tcx> MissingConstructors<'tcx> {
22442267
22452268 /// List the patterns corresponding to the missing constructors. In some cases, instead of
22462269 /// listing all constructors of a given type, we prefer to simply report a wildcard.
2247- fn report_patterns < ' p > ( & self , pcx : PatCtxt < ' _ , ' p , ' tcx > ) -> SmallVec < [ Pat < ' tcx > ; 1 ] > {
2270+ fn report_patterns < ' p > (
2271+ & self ,
2272+ pcx : PatCtxt < ' _ , ' p , ' tcx > ,
2273+ is_top_level : bool ,
2274+ ) -> SmallVec < [ Pat < ' tcx > ; 1 ] > {
22482275 // There are 2 ways we can report a witness here.
22492276 // Commonly, we can report all the "free"
22502277 // constructors as witnesses, e.g., if we have:
@@ -2272,7 +2299,7 @@ impl<'tcx> MissingConstructors<'tcx> {
22722299 // `used_ctors` is empty.
22732300 // The exception is: if we are at the top-level, for example in an empty match, we
22742301 // sometimes prefer reporting the list of constructors instead of just `_`.
2275- let report_when_all_missing = self . is_top_level && !IntRange :: is_integral ( pcx. ty ) ;
2302+ let report_when_all_missing = is_top_level && !IntRange :: is_integral ( pcx. ty ) ;
22762303 if self . used_ctors . is_empty ( ) && !report_when_all_missing {
22772304 // All constructors are unused. Report only a wildcard
22782305 // rather than each individual constructor.
@@ -2407,103 +2434,26 @@ crate fn is_useful<'p, 'tcx>(
24072434
24082435 debug ! ( "is_useful_expand_first_col: ty={:#?}, expanding {:#?}" , pcx. ty, v. head( ) ) ;
24092436
2410- let constructor = v. head_ctor ( cx) ;
2411- let ret = if !constructor. is_wildcard ( ) {
2412- debug ! ( "is_useful - expanding constructor: {:#?}" , constructor) ;
2413- constructor
2414- . split ( pcx, Some ( hir_id) )
2415- . into_iter ( )
2416- . map ( |c| {
2417- is_useful_specialized (
2418- pcx,
2419- v,
2420- & c,
2421- witness_preference,
2422- hir_id,
2423- is_under_guard,
2424- is_top_level,
2425- )
2426- } )
2427- . find ( |result| result. is_useful ( ) )
2428- . unwrap_or ( NotUseful )
2429- } else {
2430- debug ! ( "is_useful - expanding wildcard" ) ;
2431-
2432- // `missing_ctors` is the set of constructors from the same type as the
2433- // first column of `matrix` that are matched only by wildcard patterns
2434- // from the first column.
2435- //
2436- // Therefore, if there is some pattern that is unmatched by `matrix`,
2437- // it will still be unmatched if the first constructor is replaced by
2438- // any of the constructors in `missing_ctors`
2439-
2440- // Missing constructors are those that are not matched by any non-wildcard patterns in the
2441- // current column. We only fully construct them on-demand, because they're rarely used and
2442- // can be big.
2443- let missing_ctors = MissingConstructors :: new ( pcx, is_top_level) ;
2444-
2445- debug ! ( "is_useful_missing_ctors.empty()={:#?}" , missing_ctors. is_empty( ) , ) ;
2446-
2447- if missing_ctors. is_empty ( ) {
2448- let ( all_ctors, _) = missing_ctors. into_inner ( ) ;
2449- all_ctors
2450- . into_iter ( )
2451- . flat_map ( |ctor| ctor. split ( pcx, None ) )
2452- . map ( |c| {
2453- is_useful_specialized (
2454- pcx,
2455- v,
2456- & c,
2457- witness_preference,
2458- hir_id,
2459- is_under_guard,
2460- is_top_level,
2461- )
2462- } )
2463- . find ( |result| result. is_useful ( ) )
2464- . unwrap_or ( NotUseful )
2465- } else {
2466- // Some constructors are missing, thus we can specialize with the wildcard constructor,
2467- // which will stand for those constructors that are missing, and behaves like any of
2468- // them.
2469- is_useful_specialized (
2470- pcx,
2471- v,
2472- constructor,
2473- witness_preference,
2474- hir_id,
2475- is_under_guard,
2476- is_top_level,
2477- )
2478- }
2479- } ;
2437+ let ret = v
2438+ . head_ctor ( cx)
2439+ . split ( pcx, Some ( hir_id) )
2440+ . into_iter ( )
2441+ . map ( |ctor| {
2442+ // We cache the result of `Fields::wildcards` because it is used a lot.
2443+ let ctor_wild_subpatterns = Fields :: wildcards ( pcx, & ctor) ;
2444+ let matrix = pcx. matrix . specialize_constructor ( pcx, & ctor, & ctor_wild_subpatterns) ;
2445+ // Unwrap is ok: v can always be specialized with its own constructor.
2446+ let v = v. specialize_constructor ( pcx, & ctor, & ctor_wild_subpatterns, true ) . unwrap ( ) ;
2447+ let usefulness =
2448+ is_useful ( pcx. cx , & matrix, & v, witness_preference, hir_id, is_under_guard, false ) ;
2449+ usefulness. apply_constructor ( pcx, & ctor, & ctor_wild_subpatterns, is_top_level)
2450+ } )
2451+ . find ( |result| result. is_useful ( ) )
2452+ . unwrap_or ( NotUseful ) ;
24802453 debug ! ( "is_useful::returns({:#?}, {:#?}) = {:?}" , matrix, v, ret) ;
24812454 ret
24822455}
24832456
2484- /// A shorthand for the `U(S(c, P), S(c, q))` operation from the paper. I.e., `is_useful` applied
2485- /// to the specialised version of both the pattern matrix `P` and the new pattern `q`.
2486- fn is_useful_specialized < ' p , ' tcx > (
2487- pcx : PatCtxt < ' _ , ' p , ' tcx > ,
2488- v : & PatStack < ' p , ' tcx > ,
2489- ctor : & Constructor < ' tcx > ,
2490- witness_preference : WitnessPreference ,
2491- hir_id : HirId ,
2492- is_under_guard : bool ,
2493- is_top_level : bool ,
2494- ) -> Usefulness < ' tcx > {
2495- debug ! ( "is_useful_specialized({:#?}, {:#?}, {:?})" , v, ctor, pcx. ty) ;
2496-
2497- // We cache the result of `Fields::wildcards` because it is used a lot.
2498- let ctor_wild_subpatterns = Fields :: wildcards ( pcx, ctor) ;
2499- let matrix = pcx. matrix . specialize_constructor ( pcx, ctor, & ctor_wild_subpatterns) ;
2500- // Unwrap is ok: v can always be specialized with its own constructor.
2501- let v = v. specialize_constructor ( pcx, ctor, & ctor_wild_subpatterns, true ) . unwrap ( ) ;
2502- let usefulness =
2503- is_useful ( pcx. cx , & matrix, & v, witness_preference, hir_id, is_under_guard, false ) ;
2504- usefulness. apply_constructor ( pcx, ctor, & ctor_wild_subpatterns, is_top_level)
2505- }
2506-
25072457/// Determines the constructor that the given pattern can be specialized to.
25082458/// Returns `None` in case of a catch-all, which can't be specialized.
25092459fn pat_constructor < ' p , ' tcx > (
0 commit comments