@@ -70,6 +70,7 @@ overlay[local?]
7070module ;
7171
7272private import codeql.util.Location
73+ private import codeql.util.Strings
7374
7475/** Provides the input to `Make1`. */
7576signature module InputSig1< LocationSig Location> {
@@ -1261,30 +1262,58 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
12611262 module MatchingWithEnvironment< MatchingWithEnvironmentInputSig Input> {
12621263 private import Input
12631264
1265+ private Type getTypeArgumentNonPseudo ( Access a , int pos , TypePath path ) {
1266+ result = a .getTypeArgument ( pos , path ) and
1267+ not result instanceof PseudoType
1268+ }
1269+
12641270 /**
12651271 * Gets the type of the type argument at `path` in `a` that corresponds to
12661272 * the type parameter `tp` in `target`, if any.
12671273 *
12681274 * Note that this predicate crucially does not depend on type inference,
1269- * and hence can appear in negated position, e.g., as in
1270- * `directTypeMatch`.
1275+ * and hence can appear in negated position, e.g., as in `directTypeMatch`.
12711276 */
12721277 bindingset [ a, target]
12731278 pragma [ inline_late]
12741279 Type getTypeArgument ( Access a , Declaration target , TypeParameter tp , TypePath path ) {
12751280 exists ( int pos |
1276- result = a .getTypeArgument ( pos , path ) and
1277- tp = target .getTypeParameter ( pos ) and
1278- not result instanceof PseudoType
1281+ result = getTypeArgumentNonPseudo ( a , pos , path ) and
1282+ tp = target .getTypeParameter ( pos )
1283+ )
1284+ }
1285+
1286+ bindingset [ a, target]
1287+ pragma [ inline_late]
1288+ private predicate hasNotTypeArgument0 ( Access a , Declaration target , TypeParameter tp ) {
1289+ exists ( int pos |
1290+ tp = target .getTypeParameter ( pragma [ only_bind_into ] ( pos ) ) and
1291+ not exists ( getTypeArgumentNonPseudo ( a , pos , _) )
12791292 )
12801293 }
12811294
1295+ bindingset [ target, tp]
1296+ pragma [ inline_late]
1297+ private predicate hasNotTypeArgument1 ( Declaration target , TypeParameter tp ) {
1298+ not tp = target .getTypeParameter ( _)
1299+ }
1300+
1301+ /**
1302+ * A join-order optimized version of `not exists(getTypeArgument(a, target, tp, _)`.
1303+ */
1304+ pragma [ inline]
1305+ private predicate hasNotTypeArgument ( Access a , Declaration target , TypeParameter tp ) {
1306+ hasNotTypeArgument0 ( a , target , tp )
1307+ or
1308+ hasNotTypeArgument1 ( target , tp )
1309+ }
1310+
12821311 pragma [ nomagic]
12831312 private predicate directTypeMatch0 (
12841313 Access a , DeclarationPosition dpos , AccessEnvironment e , Declaration target ,
12851314 TypePath pathToTypeParam , TypeParameter tp
12861315 ) {
1287- not exists ( getTypeArgument ( a , target , tp , _ ) ) and
1316+ hasNotTypeArgument ( a , target , tp ) and
12881317 tp = target .getDeclaredType ( dpos , pathToTypeParam ) and
12891318 target = a .getTarget ( e )
12901319 }
@@ -1359,12 +1388,18 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
13591388 t = a .getInferredType ( e , apos , TypePath:: nil ( ) )
13601389 }
13611390
1391+ private predicate relevantAccessTarget (
1392+ Access a , AccessPosition apos , AccessEnvironment e , Declaration target
1393+ ) {
1394+ exists ( Type t |
1395+ accessTargetsWithArgRootType ( a , e , target , apos , t ) and
1396+ argRootTypeSatisfiesTargetTypeCand ( t , target , apos , _, _)
1397+ )
1398+ }
1399+
13621400 private newtype TRelevantAccess =
13631401 MkRelevantAccess ( Access a , AccessPosition apos , AccessEnvironment e ) {
1364- exists ( Declaration target , Type t |
1365- accessTargetsWithArgRootType ( a , e , target , apos , t ) and
1366- argRootTypeSatisfiesTargetTypeCand ( t , target , apos , _, _)
1367- )
1402+ relevantAccessTarget ( a , apos , e , _)
13681403 }
13691404
13701405 private class RelevantAccess extends MkRelevantAccess {
@@ -1374,7 +1409,12 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
13741409
13751410 RelevantAccess ( ) { this = MkRelevantAccess ( a , apos , e ) }
13761411
1377- RelevantTarget getTarget ( ) { result = MkRelevantTarget ( a .getTarget ( e ) , apos ) }
1412+ RelevantTarget getTarget ( ) {
1413+ exists ( Declaration target |
1414+ relevantAccessTarget ( a , apos , e , target ) and
1415+ result = MkRelevantTarget ( target , apos )
1416+ )
1417+ }
13781418
13791419 pragma [ nomagic]
13801420 Type getTypeAt ( TypePath path ) { result = a .getInferredType ( e , apos , path ) }
@@ -1395,6 +1435,18 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
13951435 private module SatisfiesParameterConstraint =
13961436 SatisfiesConstraint< RelevantAccess , RelevantTarget , SatisfiesParameterConstraintInput > ;
13971437
1438+ private module InverseAppend2Input implements InverseAppend2InputSig {
1439+ class C1 = Declaration ;
1440+
1441+ class C2 = AccessPosition ;
1442+
1443+ class Result = TypeParameter ;
1444+
1445+ predicate prefixCandidate ( string prefix , C1 c1 , C2 c2 , Result res ) {
1446+ argRootTypeSatisfiesTargetTypeCand ( _, c1 , c2 , res , prefix )
1447+ }
1448+ }
1449+
13981450 /**
13991451 * Holds if the (transitive) base type `t` at `path` of `a` in environment `e`
14001452 * for some `AccessPosition` matches the type parameter `tp`, which is used in
@@ -1431,13 +1483,12 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
14311483 predicate baseTypeMatch (
14321484 Access a , AccessEnvironment e , Declaration target , TypePath path , Type t , TypeParameter tp
14331485 ) {
1434- exists ( AccessPosition apos , TypePath pathToTp |
1435- argRootTypeSatisfiesTargetTypeCand ( _, target , pragma [ only_bind_into ] ( apos ) , tp , pathToTp ) and
1486+ exists ( AccessPosition apos , TypePath pathFull |
14361487 SatisfiesParameterConstraint:: satisfiesConstraint ( MkRelevantAccess ( a ,
14371488 pragma [ only_bind_into ] ( apos ) , e ) ,
1438- MkRelevantTarget ( target , pragma [ only_bind_into ] ( apos ) ) , pathToTp . appendInverse ( path ) ,
1439- t ) and
1440- not exists ( getTypeArgument ( a , target , tp , _ ) )
1489+ MkRelevantTarget ( target , pragma [ only_bind_into ] ( apos ) ) , pathFull , t ) and
1490+ InverseAppend2 < InverseAppend2Input > :: inverseAppend ( pathFull , _ , path , target , apos , tp ) and
1491+ hasNotTypeArgument ( a , target , tp )
14411492 )
14421493 }
14431494 }
@@ -1591,15 +1642,29 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
15911642 constrainedTp != tp
15921643 }
15931644
1645+ private module InverseAppend3Input implements InverseAppend3InputSig {
1646+ class C1 = Declaration ;
1647+
1648+ class C2 = TypeParameter ;
1649+
1650+ class C3 = TypeMention ;
1651+
1652+ class Result = TypeParameter ;
1653+
1654+ predicate prefixCandidate ( string prefix , C1 c1 , C2 c2 , C3 c3 , Result res ) {
1655+ typeParameterConstraintHasTypeParameter ( c1 , c2 , c3 , prefix , res )
1656+ }
1657+ }
1658+
15941659 pragma [ nomagic]
15951660 private predicate typeConstraintBaseTypeMatch (
15961661 Access a , AccessEnvironment e , Declaration target , TypePath path , Type t , TypeParameter tp
15971662 ) {
1598- not exists ( getTypeArgument ( a , target , tp , _ ) ) and
1599- exists ( TypeMention constraint , TypeParameter constrainedTp , TypePath pathToTp |
1600- typeParameterConstraintHasTypeParameter ( target , constrainedTp , constraint , pathToTp , tp ) and
1601- AccessConstraint :: satisfiesConstraint ( a , e , target , constrainedTp , constraint ,
1602- pathToTp . appendInverse ( path ) , t )
1663+ hasNotTypeArgument ( a , target , tp ) and
1664+ exists ( TypeParameter constrainedTp , TypeMention constraint , TypePath pathFull |
1665+ AccessConstraint :: satisfiesConstraint ( a , e , target , constrainedTp , constraint , pathFull , t ) and
1666+ InverseAppend3 < InverseAppend3Input > :: inverseAppend ( pathFull , _ , path , target ,
1667+ constrainedTp , constraint , tp )
16031668 )
16041669 }
16051670
0 commit comments