@@ -796,6 +796,14 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
796796 )
797797 }
798798
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+
799807 /**
800808 * Holds if `baseMention` is a (transitive) base type mention of `sub`,
801809 * and `t` is mentioned (implicitly) at `path` inside `baseMention`. For
@@ -902,14 +910,20 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
902910 {
903911 private import Input
904912
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+
905920 private module IsInstantiationOfInput implements IsInstantiationOfInputSig< HasTypeTree > {
906921 predicate potentialInstantiationOf ( HasTypeTree tt , TypeAbstraction abs , TypeMention cond ) {
907922 exists ( Type constraint , Type type |
908- type = tt .getTypeAt ( TypePath:: nil ( ) ) and
909- relevantConstraint ( tt , constraint ) and
923+ hasTypeConstraint ( tt , type , constraint ) and
910924 rootTypesSatisfaction ( type , constraint , abs , cond , _) and
911925 // We only need to check instantiations where there are multiple candidates.
912- countConstraintImplementations ( type , constraint ) > 1
926+ multipleConstraintImplementations ( type , constraint )
913927 )
914928 }
915929
@@ -918,13 +932,6 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
918932 }
919933 }
920934
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-
928935 /**
929936 * Holds if `tt` satisfies `constraint` through `abs`, `sub`, and `constraintMention`.
930937 */
@@ -944,7 +951,7 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
944951 // When there are multiple ways the type could implement the
945952 // constraint we need to find the right implementation, which is the
946953 // one where the type instantiates the precondition.
947- if countConstraintImplementations ( type , constraint ) > 1
954+ if multipleConstraintImplementations ( type , constraint )
948955 then
949956 IsInstantiationOf< HasTypeTree , IsInstantiationOfInput > :: isInstantiationOf ( tt , abs , sub )
950957 else any ( )
@@ -989,7 +996,7 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
989996 path = prefix0 .append ( suffix )
990997 )
991998 or
992- tt . getTypeAt ( TypePath :: nil ( ) ) = constraint and
999+ hasTypeConstraint ( tt , constraint , constraint ) and
9931000 t = tt .getTypeAt ( path )
9941001 }
9951002 }
@@ -1229,11 +1236,8 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
12291236 predicate relevantAccessConstraint (
12301237 Access a , Declaration target , AccessPosition apos , TypePath path , Type constraint
12311238 ) {
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 , _, _)
12371241 }
12381242
12391243 private newtype TRelevantAccess =
@@ -1276,12 +1280,11 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
12761280 }
12771281
12781282 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
12801285 ) {
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 )
12851288 }
12861289 }
12871290
@@ -1370,37 +1373,38 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
13701373 }
13711374
13721375 /**
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`.
13771379 *
1378- * For this example
1380+ * For example, in
13791381 * ```csharp
13801382 * interface IFoo<A> { }
13811383 * T1 M<T1, T2>(T2 item) where T2 : IFoo<T1> { }
13821384 * ```
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 `,
13871389 * - `constraint = IFoo`,
1388- * - `path2 = "A"`, and
1389- * - `tp2 = T1`.
1390+ * - `pathToTp = "A"`.
13901391 */
13911392 pragma [ nomagic]
13921393 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
13951396 ) {
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+ )
14041408 )
14051409 }
14061410
@@ -1409,15 +1413,9 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
14091413 Access a , Declaration target , TypePath path , Type t , TypeParameter tp
14101414 ) {
14111415 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 ,
14211419 pathToTp .appendInverse ( path ) , t )
14221420 )
14231421 }
0 commit comments