@@ -137,7 +137,7 @@ namespace {
137
137
cache.insert (getType ().getPointer ());
138
138
139
139
SmallVector<Space, 4 > spaces;
140
- decompose (DC, getType (), spaces);
140
+ decomposeDisjuncts (DC, getType (), {} , spaces);
141
141
size_t acc = 0 ;
142
142
for (auto &sp : spaces) {
143
143
// Decomposed pattern spaces grow with the sum of the subspaces.
@@ -317,14 +317,14 @@ namespace {
317
317
318
318
// (_ : Ty1) <= (_ : Ty2) iff D(Ty1) == D(Ty2)
319
319
if (canDecompose (this ->getType ())) {
320
- Space or1Space = decompose (DC, this ->getType ());
320
+ Space or1Space = decompose (DC, this ->getType (), {} );
321
321
if (or1Space.isSubspace (other, DC)) {
322
322
return true ;
323
323
}
324
324
}
325
325
326
326
if (canDecompose (other.getType ())) {
327
- Space or2Space = decompose (DC, other.getType ());
327
+ Space or2Space = decompose (DC, other.getType (), {} );
328
328
return this ->isSubspace (or2Space, DC);
329
329
}
330
330
@@ -342,13 +342,13 @@ namespace {
342
342
if (!canDecompose (this ->getType ())) {
343
343
return false ;
344
344
}
345
- Space or1Space = decompose (DC, this ->getType ());
345
+ Space or1Space = decompose (DC, this ->getType (), {} );
346
346
return or1Space.isSubspace (other, DC);
347
347
}
348
348
PAIRCASE (SpaceKind::Type, SpaceKind::Constructor): {
349
349
// (_ : Ty1) <= H(p1 | ... | pn) iff D(Ty1) <= H(p1 | ... | pn)
350
350
if (canDecompose (this ->getType ())) {
351
- Space or1Space = decompose (DC, this ->getType ());
351
+ Space or1Space = decompose (DC, this ->getType (), {} );
352
352
return or1Space.isSubspace (other, DC);
353
353
}
354
354
// An undecomposable type is always larger than its constructor space.
@@ -466,7 +466,7 @@ namespace {
466
466
}
467
467
PAIRCASE (SpaceKind::Type, SpaceKind::Constructor): {
468
468
if (canDecompose (this ->getType ())) {
469
- auto decomposition = decompose (DC, this ->getType ());
469
+ auto decomposition = decompose (DC, this ->getType (), {} );
470
470
return decomposition.minus (other, DC, minusCount);
471
471
} else {
472
472
return *this ;
@@ -480,8 +480,38 @@ namespace {
480
480
// decomposable.
481
481
return *this ;
482
482
483
+ PAIRCASE (SpaceKind::Type, SpaceKind::Disjunct): {
484
+ // Optimize for the common case of a type minus a disjunct of
485
+ // constructor subspaces. This form of subtraction is guaranteed to
486
+ // happen very early on, and we can eliminate a huge part of the
487
+ // pattern space by only decomposing the parts of the type space that
488
+ // aren't actually covered by the disjunction.
489
+ if (canDecompose (this ->getType ())) {
490
+ llvm::StringSet<> otherConstructors;
491
+ for (auto s : other.getSpaces ()) {
492
+ // Filter for constructor spaces with no payloads.
493
+ if (s.getKind () != SpaceKind::Constructor) {
494
+ continue ;
495
+ }
496
+
497
+ if (!s.getSpaces ().empty ()) {
498
+ continue ;
499
+ }
500
+
501
+ otherConstructors.insert (s.Head .getBaseIdentifier ().str ());
502
+ }
503
+
504
+ auto decomposition = decompose (DC, this ->getType (),
505
+ otherConstructors);
506
+ return decomposition.minus (other, DC, minusCount);
507
+ } else {
508
+ // If the type isn't decomposable then there's no way we can
509
+ // subtract from it. Report the total space as uncovered.
510
+ return *this ;
511
+ }
512
+ }
513
+
483
514
PAIRCASE (SpaceKind::Empty, SpaceKind::Disjunct):
484
- PAIRCASE (SpaceKind::Type, SpaceKind::Disjunct):
485
515
PAIRCASE (SpaceKind::Constructor, SpaceKind::Disjunct):
486
516
PAIRCASE (SpaceKind::Disjunct, SpaceKind::Disjunct):
487
517
PAIRCASE (SpaceKind::BooleanConstant, SpaceKind::Disjunct):
@@ -628,7 +658,7 @@ namespace {
628
658
}
629
659
630
660
if (canDecompose (other.getType ())) {
631
- auto decomposition = decompose (DC, other.getType ());
661
+ auto decomposition = decompose (DC, other.getType (), {} );
632
662
return this ->minus (decomposition, DC, minusCount);
633
663
}
634
664
return *this ;
@@ -640,7 +670,7 @@ namespace {
640
670
641
671
PAIRCASE (SpaceKind::Type, SpaceKind::BooleanConstant): {
642
672
if (canDecompose (this ->getType ())) {
643
- auto orSpace = decompose (DC, this ->getType ());
673
+ auto orSpace = decompose (DC, this ->getType (), {} );
644
674
return orSpace.minus (other, DC, minusCount);
645
675
} else {
646
676
return *this ;
@@ -778,9 +808,16 @@ namespace {
778
808
}
779
809
};
780
810
781
- // Decompose a type into its component spaces.
782
- static void decompose (const DeclContext *DC, Type tp,
783
- SmallVectorImpl<Space> &arr) {
811
+ // Decompose a type into its component spaces, ignoring any enum
812
+ // cases that have no payloads and are also in the `voidList`. Membership
813
+ // there means the space is guaranteed by the subtraction procedure to be
814
+ // covered, so there's no reason to include it. Note that this *only*
815
+ // works for constructor spaces with no payloads as these cannot be
816
+ // overloaded and there is no further recursive structure to subtract
817
+ // into.
818
+ static void decomposeDisjuncts (const DeclContext *DC, Type tp,
819
+ const llvm::StringSet<> &voidList,
820
+ SmallVectorImpl<Space> &arr) {
784
821
assert (canDecompose (tp) && " Non-decomposable type?" );
785
822
786
823
if (tp->isBool ()) {
@@ -797,6 +834,14 @@ namespace {
797
834
return Space ();
798
835
}
799
836
837
+ // If we're guaranteed a match from a subtraction, don't include
838
+ // the space at all. See the `Type - Disjunct` case of
839
+ // subtraction for when this optimization applies.
840
+ if (!eed->hasAssociatedValues () &&
841
+ voidList.contains (eed->getBaseIdentifier ().str ())) {
842
+ return Space ();
843
+ }
844
+
800
845
// .e(a: X, b: X) -> (a: X, b: X)
801
846
// .f((a: X, b: X)) -> ((a: X, b: X)
802
847
auto eedTy = tp->getCanonicalType ()->getTypeOfMember (
@@ -838,9 +883,11 @@ namespace {
838
883
}
839
884
}
840
885
841
- static Space decompose (const DeclContext *DC, Type type) {
886
+ static Space decompose (const DeclContext *DC,
887
+ Type type,
888
+ const llvm::StringSet<> &voidList) {
842
889
SmallVector<Space, 4 > spaces;
843
- decompose (DC, type, spaces);
890
+ decomposeDisjuncts (DC, type, voidList , spaces);
844
891
return Space::forDisjunct (spaces);
845
892
}
846
893
@@ -1034,7 +1081,7 @@ namespace {
1034
1081
if (uncovered.getKind () == SpaceKind::Type) {
1035
1082
if (Space::canDecompose (uncovered.getType ())) {
1036
1083
SmallVector<Space, 4 > spaces;
1037
- Space::decompose (DC, uncovered.getType (), spaces);
1084
+ Space::decomposeDisjuncts (DC, uncovered.getType (), {} , spaces);
1038
1085
diagnoseMissingCases (RequiresDefault::No, Space::forDisjunct (spaces),
1039
1086
unknownCase);
1040
1087
} else {
0 commit comments