@@ -796,6 +796,14 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
796
796
)
797
797
}
798
798
799
+ /**
800
+ * Holds if there is multiple ways in which a type with `conditionRoot` at
801
+ * the root can satisfy a constraint with `constraintRoot` at the root.
802
+ */
803
+ predicate multipleConstraintImplementations ( Type conditionRoot , Type constraintRoot ) {
804
+ countConstraintImplementations ( conditionRoot , constraintRoot ) > 1
805
+ }
806
+
799
807
/**
800
808
* Holds if `baseMention` is a (transitive) base type mention of `sub`,
801
809
* and `t` is mentioned (implicitly) at `path` inside `baseMention`. For
@@ -902,14 +910,20 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
902
910
{
903
911
private import Input
904
912
913
+ /** Holds if the type tree has the type `type` and should satisfy `constraint`. */
914
+ pragma [ nomagic]
915
+ private predicate hasTypeConstraint ( HasTypeTree term , Type type , Type constraint ) {
916
+ type = term .getTypeAt ( TypePath:: nil ( ) ) and
917
+ relevantConstraint ( term , constraint )
918
+ }
919
+
905
920
private module IsInstantiationOfInput implements IsInstantiationOfInputSig< HasTypeTree > {
906
921
predicate potentialInstantiationOf ( HasTypeTree tt , TypeAbstraction abs , TypeMention cond ) {
907
922
exists ( Type constraint , Type type |
908
- type = tt .getTypeAt ( TypePath:: nil ( ) ) and
909
- relevantConstraint ( tt , constraint ) and
923
+ hasTypeConstraint ( tt , type , constraint ) and
910
924
rootTypesSatisfaction ( type , constraint , abs , cond , _) and
911
925
// We only need to check instantiations where there are multiple candidates.
912
- countConstraintImplementations ( type , constraint ) > 1
926
+ multipleConstraintImplementations ( type , constraint )
913
927
)
914
928
}
915
929
@@ -918,13 +932,6 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
918
932
}
919
933
}
920
934
921
- /** Holds if the type tree has the type `type` and should satisfy `constraint`. */
922
- pragma [ nomagic]
923
- private predicate hasTypeConstraint ( HasTypeTree term , Type type , Type constraint ) {
924
- type = term .getTypeAt ( TypePath:: nil ( ) ) and
925
- relevantConstraint ( term , constraint )
926
- }
927
-
928
935
/**
929
936
* Holds if `tt` satisfies `constraint` through `abs`, `sub`, and `constraintMention`.
930
937
*/
@@ -944,7 +951,7 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
944
951
// When there are multiple ways the type could implement the
945
952
// constraint we need to find the right implementation, which is the
946
953
// one where the type instantiates the precondition.
947
- if countConstraintImplementations ( type , constraint ) > 1
954
+ if multipleConstraintImplementations ( type , constraint )
948
955
then
949
956
IsInstantiationOf< HasTypeTree , IsInstantiationOfInput > :: isInstantiationOf ( tt , abs , sub )
950
957
else any ( )
@@ -989,7 +996,7 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
989
996
path = prefix0 .append ( suffix )
990
997
)
991
998
or
992
- tt . getTypeAt ( TypePath :: nil ( ) ) = constraint and
999
+ hasTypeConstraint ( tt , constraint , constraint ) and
993
1000
t = tt .getTypeAt ( path )
994
1001
}
995
1002
}
@@ -1229,11 +1236,8 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
1229
1236
predicate relevantAccessConstraint (
1230
1237
Access a , Declaration target , AccessPosition apos , TypePath path , Type constraint
1231
1238
) {
1232
- exists ( DeclarationPosition dpos |
1233
- accessDeclarationPositionMatch ( apos , dpos ) and
1234
- target = a .getTarget ( ) and
1235
- typeParameterConstraintHasTypeParameter ( target , dpos , path , _, constraint , _, _)
1236
- )
1239
+ target = a .getTarget ( ) and
1240
+ typeParameterConstraintHasTypeParameter ( target , apos , path , constraint , _, _)
1237
1241
}
1238
1242
1239
1243
private newtype TRelevantAccess =
@@ -1276,12 +1280,11 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
1276
1280
}
1277
1281
1278
1282
predicate satisfiesConstraintType (
1279
- Access a , AccessPosition apos , TypePath prefix , Type constraint , TypePath path , Type t
1283
+ Access a , Declaration target , AccessPosition apos , TypePath prefix , Type constraint ,
1284
+ TypePath path , Type t
1280
1285
) {
1281
- exists ( RelevantAccess at | at = MkRelevantAccess ( a , _, apos , prefix ) |
1282
- SatisfiesConstraint< RelevantAccess , SatisfiesConstraintInput > :: satisfiesConstraintType ( at ,
1283
- constraint , path , t )
1284
- )
1286
+ SatisfiesConstraint< RelevantAccess , SatisfiesConstraintInput > :: satisfiesConstraintType ( MkRelevantAccess ( a ,
1287
+ target , apos , prefix ) , constraint , path , t )
1285
1288
}
1286
1289
}
1287
1290
@@ -1370,37 +1373,38 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
1370
1373
}
1371
1374
1372
1375
/**
1373
- * Holds if `tp1` and `tp2` are distinct type parameters of `target`, the
1374
- * declared type at `dpos` mentions `tp1` at `path1`, `tp1` has a base
1375
- * type mention of type `constraint` that mentions `tp2` at the path
1376
- * `path2`.
1376
+ * Holds if the declared type of `target` contains a type parameter at
1377
+ * `apos` and `pathToConstrained` that must satisfy `constraint` and `tp`
1378
+ * occurs at `pathToTp` in `constraint`.
1377
1379
*
1378
- * For this example
1380
+ * For example, in
1379
1381
* ```csharp
1380
1382
* interface IFoo<A> { }
1381
1383
* T1 M<T1, T2>(T2 item) where T2 : IFoo<T1> { }
1382
1384
* ```
1383
- * with the method declaration being the target and the for the first
1384
- * parameter position , we have the following
1385
- * - `path1 = ""`,
1386
- * - `tp1 = T2 `,
1385
+ * with the method declaration being the target and with `apos`
1386
+ * corresponding to `item` , we have the following
1387
+ * - `pathToConstrained = ""`,
1388
+ * - `tp = T1 `,
1387
1389
* - `constraint = IFoo`,
1388
- * - `path2 = "A"`, and
1389
- * - `tp2 = T1`.
1390
+ * - `pathToTp = "A"`.
1390
1391
*/
1391
1392
pragma [ nomagic]
1392
1393
private predicate typeParameterConstraintHasTypeParameter (
1393
- Declaration target , DeclarationPosition dpos , TypePath path1 , TypeParameter tp1 ,
1394
- Type constraint , TypePath path2 , TypeParameter tp2
1394
+ Declaration target , AccessPosition apos , TypePath pathToConstrained , Type constraint ,
1395
+ TypePath pathToTp , TypeParameter tp
1395
1396
) {
1396
- tp1 = target .getTypeParameter ( _) and
1397
- tp2 = target .getTypeParameter ( _) and
1398
- tp1 != tp2 and
1399
- tp1 = target .getDeclaredType ( dpos , path1 ) and
1400
- exists ( TypeMention tm |
1401
- tm = getATypeParameterConstraint ( tp1 ) and
1402
- tm .resolveTypeAt ( path2 ) = tp2 and
1403
- constraint = resolveTypeMentionRoot ( tm )
1397
+ exists ( DeclarationPosition dpos , TypeParameter constrainedTp |
1398
+ accessDeclarationPositionMatch ( apos , dpos ) and
1399
+ constrainedTp = target .getTypeParameter ( _) and
1400
+ tp = target .getTypeParameter ( _) and
1401
+ constrainedTp != tp and
1402
+ constrainedTp = target .getDeclaredType ( dpos , pathToConstrained ) and
1403
+ exists ( TypeMention tm |
1404
+ tm = getATypeParameterConstraint ( constrainedTp ) and
1405
+ tm .resolveTypeAt ( pathToTp ) = tp and
1406
+ constraint = resolveTypeMentionRoot ( tm )
1407
+ )
1404
1408
)
1405
1409
}
1406
1410
@@ -1409,15 +1413,9 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
1409
1413
Access a , Declaration target , TypePath path , Type t , TypeParameter tp
1410
1414
) {
1411
1415
not exists ( getTypeArgument ( a , target , tp , _) ) and
1412
- target = a .getTarget ( ) and
1413
- exists (
1414
- Type constraint , AccessPosition apos , DeclarationPosition dpos , TypePath pathToTp ,
1415
- TypePath pathToTp2
1416
- |
1417
- accessDeclarationPositionMatch ( apos , dpos ) and
1418
- typeParameterConstraintHasTypeParameter ( target , dpos , pathToTp2 , _, constraint , pathToTp ,
1419
- tp ) and
1420
- AccessConstraint:: satisfiesConstraintType ( a , apos , pathToTp2 , constraint ,
1416
+ exists ( Type constraint , AccessPosition apos , TypePath pathToTp , TypePath pathToTp2 |
1417
+ typeParameterConstraintHasTypeParameter ( target , apos , pathToTp2 , constraint , pathToTp , tp ) and
1418
+ AccessConstraint:: satisfiesConstraintType ( a , target , apos , pathToTp2 , constraint ,
1421
1419
pathToTp .appendInverse ( path ) , t )
1422
1420
)
1423
1421
}
0 commit comments