@@ -866,6 +866,101 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
866
866
867
867
private import BaseTypes
868
868
869
+ signature module SatisfiesConstraintSig< HasTypeTreeSig TypeTree> {
870
+ /** Holds if it is relevant to know if `term` satisfies `constraint`. */
871
+ predicate relevantConstraint ( TypeTree term , Type constraint ) ;
872
+ }
873
+
874
+ module SatisfiesConstraint< HasTypeTreeSig TypeTree, SatisfiesConstraintSig< TypeTree > Input> {
875
+ import Input
876
+
877
+ private module IsInstantiationOfInput implements IsInstantiationOfInputSig< TypeTree > {
878
+ predicate potentialInstantiationOf ( TypeTree tt , TypeAbstraction abs , TypeMention cond ) {
879
+ exists ( Type constraint , Type type |
880
+ type = tt .getTypeAt ( TypePath:: nil ( ) ) and
881
+ relevantConstraint ( tt , constraint ) and
882
+ rootTypesSatisfaction ( type , constraint , abs , cond , _) and
883
+ // We only need to check instantiations where there are multiple candidates.
884
+ countConstraintImplementations ( type , constraint ) > 1
885
+ )
886
+ }
887
+
888
+ predicate relevantTypeMention ( TypeMention constraint ) {
889
+ rootTypesSatisfaction ( _, _, _, constraint , _)
890
+ }
891
+ }
892
+
893
+ /** Holds if the type tree has the type `type` and should satisfy `constraint`. */
894
+ private predicate hasTypeConstraint ( TypeTree term , Type type , Type constraint ) {
895
+ type = term .getTypeAt ( TypePath:: nil ( ) ) and
896
+ relevantConstraint ( term , constraint )
897
+ }
898
+
899
+ /**
900
+ * Holds if `tt` satisfies `constraint` through `abs`, `sub`, and `constraintMention`.
901
+ */
902
+ pragma [ nomagic]
903
+ private predicate hasConstraintMention (
904
+ TypeTree tt , TypeAbstraction abs , TypeMention sub , Type constraint ,
905
+ TypeMention constraintMention
906
+ ) {
907
+ exists ( Type type | hasTypeConstraint ( tt , type , constraint ) |
908
+ not exists ( countConstraintImplementations ( type , constraint ) ) and
909
+ conditionSatisfiesConstraintTypeAt ( abs , sub , constraintMention , _, _) and
910
+ resolveTypeMentionRoot ( sub ) = abs .getATypeParameter ( ) and
911
+ constraint = resolveTypeMentionRoot ( constraintMention )
912
+ or
913
+ countConstraintImplementations ( type , constraint ) > 0 and
914
+ rootTypesSatisfaction ( type , constraint , abs , sub , constraintMention ) and
915
+ // When there are multiple ways the type could implement the
916
+ // constraint we need to find the right implementation, which is the
917
+ // one where the type instantiates the precondition.
918
+ if countConstraintImplementations ( type , constraint ) > 1
919
+ then IsInstantiationOf< TypeTree , IsInstantiationOfInput > :: isInstantiationOf ( tt , abs , sub )
920
+ else any ( )
921
+ )
922
+ }
923
+
924
+ pragma [ nomagic]
925
+ private predicate satisfiesConstraintTypeMention0 (
926
+ TypeTree tt , Type constraint , TypeAbstraction abs , TypeMention sub , TypePath path , Type t
927
+ ) {
928
+ exists ( TypeMention constraintMention |
929
+ hasConstraintMention ( tt , abs , sub , constraint , constraintMention ) and
930
+ conditionSatisfiesConstraintTypeAt ( abs , sub , constraintMention , path , t )
931
+ )
932
+ }
933
+
934
+ pragma [ nomagic]
935
+ private predicate satisfiesConstraintTypeMention1 (
936
+ TypeTree tt , Type constraint , TypePath path , TypePath pathToTypeParamInSub
937
+ ) {
938
+ exists ( TypeAbstraction abs , TypeMention sub , TypeParameter tp |
939
+ satisfiesConstraintTypeMention0 ( tt , constraint , abs , sub , path , tp ) and
940
+ tp = abs .getATypeParameter ( ) and
941
+ sub .resolveTypeAt ( pathToTypeParamInSub ) = tp
942
+ )
943
+ }
944
+
945
+ /**
946
+ * Holds if the type tree at `tt` satisfies the constraint `constraint`
947
+ * with the type `t` at `path`.
948
+ */
949
+ pragma [ nomagic]
950
+ predicate satisfiesConstraintTypeMention ( TypeTree tt , Type constraint , TypePath path , Type t ) {
951
+ exists ( TypeAbstraction abs |
952
+ satisfiesConstraintTypeMention0 ( tt , constraint , abs , _, path , t ) and
953
+ not t = abs .getATypeParameter ( )
954
+ )
955
+ or
956
+ exists ( TypePath prefix0 , TypePath pathToTypeParamInSub , TypePath suffix |
957
+ satisfiesConstraintTypeMention1 ( tt , constraint , prefix0 , pathToTypeParamInSub ) and
958
+ tt .getTypeAt ( pathToTypeParamInSub .appendInverse ( suffix ) ) = t and
959
+ path = prefix0 .append ( suffix )
960
+ )
961
+ }
962
+ }
963
+
869
964
/** Provides the input to `Matching`. */
870
965
signature module MatchingInputSig {
871
966
/**
@@ -1129,11 +1224,8 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
1129
1224
adjustedAccessType ( a , apos , target , path .appendInverse ( suffix ) , result )
1130
1225
}
1131
1226
1132
- /** Holds if this relevant access has the type `type` and should satisfy `constraint`. */
1133
- predicate hasTypeConstraint ( Type type , Type constraint ) {
1134
- adjustedAccessType ( a , apos , target , path , type ) and
1135
- relevantAccessConstraint ( a , target , apos , path , constraint )
1136
- }
1227
+ /** Holds if this relevant access should satisfy `constraint`. */
1228
+ Type getConstraint ( ) { relevantAccessConstraint ( a , target , apos , path , result ) }
1137
1229
1138
1230
string toString ( ) {
1139
1231
result = a .toString ( ) + ", " + apos .toString ( ) + ", " + path .toString ( )
@@ -1142,94 +1234,18 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
1142
1234
Location getLocation ( ) { result = a .getLocation ( ) }
1143
1235
}
1144
1236
1145
- private module IsInstantiationOfInput implements IsInstantiationOfInputSig< RelevantAccess > {
1146
- predicate potentialInstantiationOf (
1147
- RelevantAccess at , TypeAbstraction abs , TypeMention cond
1148
- ) {
1149
- exists ( Type constraint , Type type |
1150
- at .hasTypeConstraint ( type , constraint ) and
1151
- rootTypesSatisfaction ( type , constraint , abs , cond , _) and
1152
- // We only need to check instantiations where there are multiple candidates.
1153
- countConstraintImplementations ( type , constraint ) > 1
1154
- )
1155
- }
1156
-
1157
- predicate relevantTypeMention ( TypeMention constraint ) {
1158
- rootTypesSatisfaction ( _, _, _, constraint , _)
1237
+ private module SatisfiesConstraintInput implements SatisfiesConstraintSig< RelevantAccess > {
1238
+ predicate relevantConstraint ( RelevantAccess at , Type constraint ) {
1239
+ constraint = at .getConstraint ( )
1159
1240
}
1160
1241
}
1161
1242
1162
- /**
1163
- * Holds if `at` satisfies `constraint` through `abs`, `sub`, and `constraintMention`.
1164
- */
1165
- pragma [ nomagic]
1166
- private predicate hasConstraintMention (
1167
- RelevantAccess at , TypeAbstraction abs , TypeMention sub , Type constraint ,
1168
- TypeMention constraintMention
1169
- ) {
1170
- exists ( Type type | at .hasTypeConstraint ( type , constraint ) |
1171
- not exists ( countConstraintImplementations ( type , constraint ) ) and
1172
- conditionSatisfiesConstraintTypeAt ( abs , sub , constraintMention , _, _) and
1173
- resolveTypeMentionRoot ( sub ) = abs .getATypeParameter ( ) and
1174
- constraint = resolveTypeMentionRoot ( constraintMention )
1175
- or
1176
- countConstraintImplementations ( type , constraint ) > 0 and
1177
- rootTypesSatisfaction ( type , constraint , abs , sub , constraintMention ) and
1178
- // When there are multiple ways the type could implement the
1179
- // constraint we need to find the right implementation, which is the
1180
- // one where the type instantiates the precondition.
1181
- if countConstraintImplementations ( type , constraint ) > 1
1182
- then
1183
- IsInstantiationOf< RelevantAccess , IsInstantiationOfInput > :: isInstantiationOf ( at , abs ,
1184
- sub )
1185
- else any ( )
1186
- )
1187
- }
1188
-
1189
- pragma [ nomagic]
1190
- predicate satisfiesConstraintTypeMention0 (
1191
- RelevantAccess at , Access a , AccessPosition apos , TypePath prefix , Type constraint ,
1192
- TypeAbstraction abs , TypeMention sub , TypePath path , Type t
1193
- ) {
1194
- exists ( TypeMention constraintMention |
1195
- at = MkRelevantAccess ( a , _, apos , prefix ) and
1196
- hasConstraintMention ( at , abs , sub , constraint , constraintMention ) and
1197
- conditionSatisfiesConstraintTypeAt ( abs , sub , constraintMention , path , t )
1198
- )
1199
- }
1200
-
1201
- pragma [ nomagic]
1202
- predicate satisfiesConstraintTypeMention1 (
1203
- RelevantAccess at , Access a , AccessPosition apos , TypePath prefix , Type constraint ,
1204
- TypePath path , TypePath pathToTypeParamInSub
1205
- ) {
1206
- exists ( TypeAbstraction abs , TypeMention sub , TypeParameter tp |
1207
- satisfiesConstraintTypeMention0 ( at , a , apos , prefix , constraint , abs , sub , path , tp ) and
1208
- tp = abs .getATypeParameter ( ) and
1209
- sub .resolveTypeAt ( pathToTypeParamInSub ) = tp
1210
- )
1211
- }
1212
-
1213
- /**
1214
- * Holds if the type at `a`, `apos`, and `path` satisfies the constraint
1215
- * `constraint` with the type `t` at `path`.
1216
- */
1217
- pragma [ nomagic]
1218
1243
predicate satisfiesConstraintTypeMention (
1219
1244
Access a , AccessPosition apos , TypePath prefix , Type constraint , TypePath path , Type t
1220
1245
) {
1221
- exists ( TypeAbstraction abs |
1222
- satisfiesConstraintTypeMention0 ( _, a , apos , prefix , constraint , abs , _, path , t ) and
1223
- not t = abs .getATypeParameter ( )
1224
- )
1225
- or
1226
- exists (
1227
- RelevantAccess at , TypePath prefix0 , TypePath pathToTypeParamInSub , TypePath suffix
1228
- |
1229
- satisfiesConstraintTypeMention1 ( at , a , apos , prefix , constraint , prefix0 ,
1230
- pathToTypeParamInSub ) and
1231
- at .getTypeAt ( pathToTypeParamInSub .appendInverse ( suffix ) ) = t and
1232
- path = prefix0 .append ( suffix )
1246
+ exists ( RelevantAccess at | at = MkRelevantAccess ( a , _, apos , prefix ) |
1247
+ SatisfiesConstraint< RelevantAccess , SatisfiesConstraintInput > :: satisfiesConstraintTypeMention ( at ,
1248
+ constraint , path , t )
1233
1249
)
1234
1250
}
1235
1251
}
0 commit comments