Skip to content

Commit 3720a8c

Browse files
committed
Type inference: Performance tweaks
1 parent 78a4f9c commit 3720a8c

1 file changed

Lines changed: 86 additions & 21 deletions

File tree

shared/typeinference/codeql/typeinference/internal/TypeInference.qll

Lines changed: 86 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ overlay[local?]
7070
module;
7171

7272
private import codeql.util.Location
73+
private import codeql.util.Strings
7374

7475
/** Provides the input to `Make1`. */
7576
signature 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

Comments
 (0)