@@ -827,30 +827,33 @@ private boolean exhausts(JCExpression selector, List<JCCase> cases) {
827
827
}
828
828
}
829
829
Set <PatternDescription > patterns = patternSet ;
830
- boolean genericPatternsExpanded = false ;
830
+ boolean useHashes = true ;
831
831
try {
832
832
boolean repeat = true ;
833
833
while (repeat ) {
834
834
Set <PatternDescription > updatedPatterns ;
835
835
updatedPatterns = reduceBindingPatterns (selector .type , patterns );
836
- updatedPatterns = reduceNestedPatterns (updatedPatterns );
836
+ updatedPatterns = reduceNestedPatterns (updatedPatterns , useHashes );
837
837
updatedPatterns = reduceRecordPatterns (updatedPatterns );
838
838
updatedPatterns = removeCoveredRecordPatterns (updatedPatterns );
839
839
repeat = !updatedPatterns .equals (patterns );
840
840
if (checkCovered (selector .type , patterns )) {
841
841
return true ;
842
842
}
843
- if (!repeat && ! genericPatternsExpanded ) {
843
+ if (!repeat ) {
844
844
//there may be situation like:
845
- //class B extends S1, S2
845
+ //class B permits S1, S2
846
846
//patterns: R(S1, B), R(S2, S2)
847
- //this should be joined to R(B, S2),
847
+ //this might be joined to R(B, S2), as B could be rewritten to S2
848
848
//but hashing in reduceNestedPatterns will not allow that
849
- //attempt to once expand all types to their transitive permitted types,
850
- //on all depth of nesting:
851
- updatedPatterns = expandGenericPatterns (updatedPatterns );
852
- genericPatternsExpanded = true ;
853
- repeat = !updatedPatterns .equals (patterns );
849
+ //disable the use of hashing, and use subtyping in
850
+ //reduceNestedPatterns to handle situations like this:
851
+ repeat = useHashes ;
852
+ useHashes = false ;
853
+ } else {
854
+ //if a reduction happened, make sure hashing in reduceNestedPatterns
855
+ //is enabled, as the hashing speeds up the process significantly:
856
+ useHashes = true ;
854
857
}
855
858
patterns = updatedPatterns ;
856
859
}
@@ -1023,8 +1026,15 @@ private List<ClassSymbol> baseClasses(TypeSymbol root) {
1023
1026
* simplify the pattern. If that succeeds, the original found sub-set
1024
1027
* of patterns is replaced with a new set of patterns of the form:
1025
1028
* $record($prefix$, $resultOfReduction, $suffix$)
1029
+ *
1030
+ * useHashes: when true, patterns will be subject to exact equivalence;
1031
+ * when false, two binding patterns will be considered equivalent
1032
+ * if one of them is more generic than the other one;
1033
+ * when false, the processing will be significantly slower,
1034
+ * as pattern hashes cannot be used to speed up the matching process
1026
1035
*/
1027
- private Set <PatternDescription > reduceNestedPatterns (Set <PatternDescription > patterns ) {
1036
+ private Set <PatternDescription > reduceNestedPatterns (Set <PatternDescription > patterns ,
1037
+ boolean useHashes ) {
1028
1038
/* implementation note:
1029
1039
* finding a sub-set of patterns that only differ in a single
1030
1040
* column is time-consuming task, so this method speeds it up by:
@@ -1049,13 +1059,13 @@ private Set<PatternDescription> reduceNestedPatterns(Set<PatternDescription> pat
1049
1059
mismatchingCandidate < nestedPatternsCount ;
1050
1060
mismatchingCandidate ++) {
1051
1061
int mismatchingCandidateFin = mismatchingCandidate ;
1052
- var groupByHashes =
1062
+ var groupEquivalenceCandidates =
1053
1063
current
1054
1064
.stream ()
1055
1065
//error recovery, ignore patterns with incorrect number of nested patterns:
1056
1066
.filter (pd -> pd .nested .length == nestedPatternsCount )
1057
- .collect (groupingBy (pd -> pd .hashCode (mismatchingCandidateFin )));
1058
- for (var candidates : groupByHashes .values ()) {
1067
+ .collect (groupingBy (pd -> useHashes ? pd .hashCode (mismatchingCandidateFin ) : 0 ));
1068
+ for (var candidates : groupEquivalenceCandidates .values ()) {
1059
1069
var candidatesArr = candidates .toArray (RecordPattern []::new );
1060
1070
1061
1071
for (int firstCandidate = 0 ;
@@ -1076,24 +1086,35 @@ private Set<PatternDescription> reduceNestedPatterns(Set<PatternDescription> pat
1076
1086
RecordPattern rpOther = candidatesArr [nextCandidate ];
1077
1087
if (rpOne .recordType .tsym == rpOther .recordType .tsym ) {
1078
1088
for (int i = 0 ; i < rpOne .nested .length ; i ++) {
1079
- if (i != mismatchingCandidate &&
1080
- !rpOne .nested [i ].equals (rpOther .nested [i ])) {
1081
- continue NEXT_PATTERN ;
1089
+ if (i != mismatchingCandidate ) {
1090
+ if (!rpOne .nested [i ].equals (rpOther .nested [i ])) {
1091
+ if (useHashes ||
1092
+ //when not using hashes,
1093
+ //check if rpOne.nested[i] is
1094
+ //a subtype of rpOther.nested[i]:
1095
+ !(rpOne .nested [i ] instanceof BindingPattern bpOne ) ||
1096
+ !(rpOther .nested [i ] instanceof BindingPattern bpOther ) ||
1097
+ !types .isSubtype (types .erasure (bpOne .type ), types .erasure (bpOther .type ))) {
1098
+ continue NEXT_PATTERN ;
1099
+ }
1100
+ }
1082
1101
}
1083
1102
}
1084
1103
join .append (rpOther );
1085
1104
}
1086
1105
}
1087
1106
1088
1107
var nestedPatterns = join .stream ().map (rp -> rp .nested [mismatchingCandidateFin ]).collect (Collectors .toSet ());
1089
- var updatedPatterns = reduceNestedPatterns (nestedPatterns );
1108
+ var updatedPatterns = reduceNestedPatterns (nestedPatterns , useHashes );
1090
1109
1091
1110
updatedPatterns = reduceRecordPatterns (updatedPatterns );
1092
1111
updatedPatterns = removeCoveredRecordPatterns (updatedPatterns );
1093
1112
updatedPatterns = reduceBindingPatterns (rpOne .fullComponentTypes ()[mismatchingCandidateFin ], updatedPatterns );
1094
1113
1095
1114
if (!nestedPatterns .equals (updatedPatterns )) {
1096
- current .removeAll (join );
1115
+ if (useHashes ) {
1116
+ current .removeAll (join );
1117
+ }
1097
1118
1098
1119
for (PatternDescription nested : updatedPatterns ) {
1099
1120
PatternDescription [] newNested =
@@ -1169,40 +1190,6 @@ private PatternDescription reduceRecordPattern(PatternDescription pattern) {
1169
1190
return pattern ;
1170
1191
}
1171
1192
1172
- private Set <PatternDescription > expandGenericPatterns (Set <PatternDescription > patterns ) {
1173
- var newPatterns = new HashSet <PatternDescription >(patterns );
1174
- boolean modified ;
1175
- do {
1176
- modified = false ;
1177
- for (PatternDescription pd : patterns ) {
1178
- if (pd instanceof RecordPattern rpOne ) {
1179
- for (int i = 0 ; i < rpOne .nested .length ; i ++) {
1180
- Set <PatternDescription > toExpand = Set .of (rpOne .nested [i ]);
1181
- Set <PatternDescription > expanded = expandGenericPatterns (toExpand );
1182
- if (expanded != toExpand ) {
1183
- expanded .removeAll (toExpand );
1184
- for (PatternDescription exp : expanded ) {
1185
- PatternDescription [] newNested = Arrays .copyOf (rpOne .nested , rpOne .nested .length );
1186
- newNested [i ] = exp ;
1187
- modified |= newPatterns .add (new RecordPattern (rpOne .recordType (), rpOne .fullComponentTypes (), newNested ));
1188
- }
1189
- }
1190
- }
1191
- } else if (pd instanceof BindingPattern bp ) {
1192
- Set <Symbol > permittedSymbols = allPermittedSubTypes (bp .type .tsym , cs -> true );
1193
-
1194
- if (!permittedSymbols .isEmpty ()) {
1195
- for (Symbol permitted : permittedSymbols ) {
1196
- //TODO infer.instantiatePatternType(selectorType, csym); (?)
1197
- modified |= newPatterns .add (new BindingPattern (permitted .type ));
1198
- }
1199
- }
1200
- }
1201
- }
1202
- } while (modified );
1203
- return newPatterns ;
1204
- }
1205
-
1206
1193
private Set <PatternDescription > removeCoveredRecordPatterns (Set <PatternDescription > patterns ) {
1207
1194
Set <Symbol > existingBindings = patterns .stream ()
1208
1195
.filter (pd -> pd instanceof BindingPattern )
0 commit comments