Skip to content

Commit 77fa7b4

Browse files
committed
wip
1 parent 7662edf commit 77fa7b4

File tree

2 files changed

+120
-106
lines changed

2 files changed

+120
-106
lines changed

rust/ql/lib/codeql/rust/internal/PathResolution.qll

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1427,34 +1427,43 @@ signature predicate relevantTraitVisibleSig(Element element, Trait trait);
14271427
* at a given element.
14281428
*/
14291429
module TraitIsVisible<relevantTraitVisibleSig/2 relevantTraitVisible> {
1430-
/** Holds if the trait might be looked up in `encl`. */
1431-
private predicate traitLookup(ItemNode encl, Element element, Trait trait) {
1432-
// lookup in immediately enclosing item
1433-
relevantTraitVisible(element, trait) and
1434-
encl.getADescendant() = element
1430+
private newtype TNode =
1431+
TTrait(Trait t) or
1432+
TItemNode(ItemNode i) or
1433+
TElement(Element e) { relevantTraitVisible(e, _) }
1434+
1435+
private predicate isTrait(TNode n) { n instanceof TTrait }
1436+
1437+
private predicate step(TNode n1, TNode n2) {
1438+
exists(Trait t1, ItemNode i2 |
1439+
n1 = TTrait(t1) and
1440+
n2 = TItemNode(i2) and
1441+
t1 = i2.getASuccessor(_, _)
1442+
)
14351443
or
1436-
// lookup in an outer scope, but only if the trait is not declared in inner scope
1437-
exists(ItemNode mid |
1438-
traitLookup(mid, element, trait) and
1439-
not trait = mid.getASuccessor(_, _) and
1440-
encl = getOuterScope(mid)
1444+
exists(ItemNode i1, ItemNode i2 |
1445+
n1 = TItemNode(i1) and
1446+
n2 = TItemNode(i2) and
1447+
i1 = getOuterScope(i2)
1448+
)
1449+
or
1450+
exists(ItemNode i1, Element e2 |
1451+
n1 = TItemNode(i1) and
1452+
n2 = TElement(e2) and
1453+
i1.getADescendant() = e2
14411454
)
14421455
}
14431456

1457+
private predicate isElement(TNode n) { n instanceof TElement }
1458+
1459+
private predicate traitIsVisibleTC(TNode trait, TNode element) =
1460+
doublyBoundedFastTC(step/2, isTrait/1, isElement/1)(trait, element)
1461+
14441462
/** Holds if the trait `trait` is visible at `element`. */
14451463
pragma[nomagic]
14461464
predicate traitIsVisible(Element element, Trait trait) {
1447-
exists(ItemNode encl | traitLookup(encl, element, trait) and trait = encl.getASuccessor(_, _))
1448-
}
1449-
1450-
/** Holds if the trait `trait` is _not_ visible at `element`. */
1451-
pragma[nomagic]
1452-
predicate traitIsNotVisible(Element element, Trait trait) {
1453-
exists(ItemNode top |
1454-
traitLookup(top, element, trait) and
1455-
not exists(getOuterScope(top)) and
1456-
not trait = top.getASuccessor(_, _)
1457-
)
1465+
traitIsVisibleTC(TTrait(trait), TElement(element)) and
1466+
relevantTraitVisible(element, trait)
14581467
}
14591468
}
14601469

rust/ql/lib/codeql/rust/internal/TypeInference.qll

Lines changed: 90 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1025,6 +1025,7 @@ private class FunctionPositionType extends TFunctionPositionType {
10251025
this.asInheritedFunctionPositionType(f, pos, _, i)
10261026
}
10271027

1028+
pragma[nomagic]
10281029
private Type getTypeAt0(TypePath path) {
10291030
exists(Function f, FunctionPosition pos | this.asFunctionPositionType(f, pos, _) |
10301031
pos.asArgumentPosition().isSelf() and
@@ -1047,13 +1048,18 @@ private class FunctionPositionType extends TFunctionPositionType {
10471048
not result instanceof TSelfTypeParameter
10481049
or
10491050
exists(TypePath prefix, TypePath suffix |
1050-
parentType.getTypeAt0(prefix) = TSelfTypeParameter(_) and
1051+
parentType.hasSelfTypeParameterAt(prefix) and
10511052
result = resolveImplOrTraitType(i, suffix) and
10521053
path = prefix.append(suffix)
10531054
)
10541055
)
10551056
}
10561057

1058+
pragma[nomagic]
1059+
private predicate hasSelfTypeParameterAt(TypePath path) {
1060+
this.getTypeAt0(path) = TSelfTypeParameter(_)
1061+
}
1062+
10571063
Type getTypeAt(TypePath path) {
10581064
// For methods belonging to a `trait`, we use the type of the trait itself
10591065
// instead of the implicit `Self` type parameter, as otherwise any type will
@@ -1113,6 +1119,50 @@ private module MethodCallResolution {
11131119
)
11141120
}
11151121

1122+
pragma[nomagic]
1123+
private predicate methodCandidateImplTrait(string name, int arity, Trait trait) {
1124+
exists(ImplItemNode i |
1125+
methodCandidate(_, name, arity, i, _) and
1126+
trait = i.resolveTraitTy()
1127+
)
1128+
}
1129+
1130+
pragma[nomagic]
1131+
private predicate methodCallTraitCandidate(Element mc, Trait trait) {
1132+
exists(string name, int arity |
1133+
mc.(MethodCall).isMethodCall(name, arity) and
1134+
methodCandidateImplTrait(name, arity, trait)
1135+
)
1136+
}
1137+
1138+
private predicate methodCallVisibleTraitCandidate(MethodCall mc, Trait trait) {
1139+
TraitIsVisible<methodCallTraitCandidate/2>::traitIsVisible(mc, trait)
1140+
}
1141+
1142+
bindingset[mc, impl]
1143+
pragma[inline_late]
1144+
private predicate methodCallVisibleImplTraitCandidate(MethodCall mc, ImplItemNode impl) {
1145+
methodCallVisibleTraitCandidate(mc, impl.resolveTraitTy())
1146+
}
1147+
1148+
pragma[nomagic]
1149+
private predicate methodCallCandidate(
1150+
MethodCall mc, Type type, ImplOrTraitItemNode i, FunctionPositionType self
1151+
) {
1152+
exists(string name, int arity |
1153+
mc.isMethodCall(name, arity) and
1154+
methodCandidate(type, name, arity, i, self) //and
1155+
|
1156+
// not CertainTypeInference::inferCertainType(mc.getReceiver(), TypePath::nil()) != type
1157+
not exists(i.(ImplItemNode).resolveTraitTy())
1158+
or
1159+
methodCallVisibleImplTraitCandidate(mc, i)
1160+
or
1161+
mc instanceof IndexExpr and
1162+
i.(ImplItemNode).resolveTraitTy() instanceof IndexTrait
1163+
)
1164+
}
1165+
11161166
/**
11171167
* A method call.
11181168
*
@@ -1139,9 +1189,9 @@ private module MethodCallResolution {
11391189

11401190
abstract Expr getArgument(ArgumentPosition pos);
11411191

1142-
private Type getReceiverTypeAt(TypePath path) {
1143-
result = inferType(this.getArgument(any(ArgumentPosition pos | pos.isSelf())), path)
1144-
}
1192+
Expr getReceiver() { result = this.getArgument(any(ArgumentPosition pos | pos.isSelf())) }
1193+
1194+
private Type getReceiverTypeAt(TypePath path) { result = inferType(this.getReceiver(), path) }
11451195

11461196
/**
11471197
* Same as `getACandidateReceiverTypeAt`, but without borrows.
@@ -1167,48 +1217,29 @@ private module MethodCallResolution {
11671217
}
11681218

11691219
pragma[nomagic]
1170-
private predicate isMethodCall0(Type rootType, string name, int arity, string derefChainBorrow) {
1171-
rootType = this.getACandidateReceiverTypeAt(TypePath::nil(), derefChainBorrow) and
1220+
private predicate isMethodCall0(Type type, string name, int arity, string derefChainBorrow) {
1221+
type = this.getACandidateReceiverTypeAt(TypePath::nil(), derefChainBorrow) and
11721222
this.isMethodCall(name, arity)
11731223
}
11741224

1175-
pragma[nomagic]
1176-
predicate hasTraitImplCandidate(
1177-
ImplItemNode i, FunctionPositionType self, string derefChainBorrow, Trait trait
1178-
) {
1179-
exists(Type rootType, string name, int arity |
1180-
this.isMethodCall0(rootType, name, arity, derefChainBorrow) and
1181-
methodCandidate(rootType, name, arity, i, self) and
1182-
trait = i.resolveTraitTy()
1183-
)
1184-
}
1185-
11861225
pragma[nomagic]
11871226
private predicate isNotCandidate(
11881227
ImplOrTraitItemNode i, FunctionPositionType self, string derefChainBorrow
11891228
) {
11901229
IsInstantiationOf<MethodCallCand, FunctionPositionType, MethodCallIsInstantiationOfInput>::isNotInstantiationOf(MkMethodCallCand(this,
11911230
derefChainBorrow), i, self)
1192-
or
1193-
exists(Trait trait |
1194-
this.hasTraitImplCandidate(i, self, derefChainBorrow, trait) and
1195-
TraitIsVisible<relevantTraitVisible1/2>::traitIsNotVisible(this, trait)
1196-
|
1197-
not this instanceof IndexExpr or
1198-
not trait instanceof IndexTrait
1199-
)
12001231
}
12011232

12021233
pragma[nomagic]
12031234
private Type getACandidateReceiverTypeAtNoBorrowNoMatch(TypePath path, string derefChain) {
12041235
result = this.getACandidateReceiverTypeAtNoBorrow(path, derefChain) and
1205-
exists(Type rootType, string name, int arity, string derefChainBorrow |
1236+
exists(Type type, string name, int arity, string derefChainBorrow |
12061237
derefChainBorrow = derefChain + ";" and
12071238
not derefChain.matches("%.ref") and // no need to try a borrow if the last thing we did was a deref
1208-
this.isMethodCall0(rootType, name, arity, derefChainBorrow)
1239+
this.isMethodCall0(type, name, arity, derefChainBorrow)
12091240
|
12101241
forall(ImplOrTraitItemNode i, FunctionPositionType self |
1211-
methodCandidate(rootType, name, arity, i, self)
1242+
methodCallCandidate(this, type, i, self)
12121243
|
12131244
this.isNotCandidate(i, self, derefChainBorrow)
12141245
)
@@ -1218,12 +1249,12 @@ private module MethodCallResolution {
12181249
pragma[nomagic]
12191250
private Type getACandidateReceiverTypeAtNoMatch(TypePath path, string derefChain) {
12201251
result = this.getACandidateReceiverTypeAtNoBorrowNoMatch(path, derefChain) and
1221-
exists(Type rootType, string name, int arity, string derefChainBorrow |
1252+
exists(Type type, string name, int arity, string derefChainBorrow |
12221253
derefChainBorrow = derefChain + ";borrow" and
1223-
this.isMethodCall0(rootType, name, arity, derefChainBorrow)
1254+
this.isMethodCall0(type, name, arity, derefChainBorrow)
12241255
|
12251256
forall(ImplOrTraitItemNode i, FunctionPositionType self |
1226-
methodCandidate(rootType, name, arity, i, self)
1257+
methodCallCandidate(this, type, i, self)
12271258
|
12281259
this.isNotCandidate(i, self, derefChainBorrow)
12291260
)
@@ -1281,22 +1312,18 @@ private module MethodCallResolution {
12811312
}
12821313
}
12831314

1284-
private predicate relevantTraitVisible1(Element mc, Trait trait) {
1285-
mc.(MethodCall).hasTraitImplCandidate(_, _, _, trait)
1286-
}
1287-
1288-
private class MethodCallMethodCallExpr extends MethodCall, MethodCallExpr {
1315+
private class MethodCallMethodCallExpr extends MethodCall instanceof MethodCallExpr {
12891316
pragma[nomagic]
12901317
override predicate isMethodCall(string name, int arity) {
1291-
name = this.getIdentifier().getText() and
1292-
arity = this.getArgList().getNumberOfArgs()
1318+
name = super.getIdentifier().getText() and
1319+
arity = super.getArgList().getNumberOfArgs()
12931320
}
12941321

12951322
override Expr getArgument(ArgumentPosition pos) {
12961323
pos.isSelf() and
1297-
result = this.getReceiver()
1324+
result = MethodCallExpr.super.getReceiver()
12981325
or
1299-
result = this.getArgList().getArg(pos.asPosition())
1326+
result = super.getArgList().getArg(pos.asPosition())
13001327
}
13011328
}
13021329

@@ -1323,15 +1350,15 @@ private module MethodCallResolution {
13231350

13241351
/** A method call tagged with a candidate receiver type. */
13251352
private class MethodCallCand extends MkMethodCallCand {
1326-
MethodCall mc;
1353+
MethodCall mc_;
13271354
string derefChainBorrow;
13281355

1329-
MethodCallCand() { this = MkMethodCallCand(mc, derefChainBorrow) }
1356+
MethodCallCand() { this = MkMethodCallCand(mc_, derefChainBorrow) }
13301357

1331-
MethodCall getMethodCall() { result = mc }
1358+
MethodCall getMethodCall() { result = mc_ }
13321359

13331360
Type getTypeAt(TypePath path) {
1334-
exists(Type t | t = mc.getACandidateReceiverTypeAt(path, derefChainBorrow) |
1361+
exists(Type t | t = mc_.getACandidateReceiverTypeAt(path, derefChainBorrow) |
13351362
not exists(getATraitBound(t)) and
13361363
result = t
13371364
or
@@ -1340,8 +1367,9 @@ private module MethodCallResolution {
13401367
}
13411368

13421369
pragma[nomagic]
1343-
predicate isMethodCall(Type rootType, string name, int arity) {
1344-
rootType = this.getTypeAt(TypePath::nil()) and
1370+
predicate isMethodCall(MethodCall mc, Type type, string name, int arity) {
1371+
type = this.getTypeAt(TypePath::nil()) and
1372+
mc = mc_ and
13451373
mc.isMethodCall(name, arity)
13461374
}
13471375

@@ -1358,10 +1386,10 @@ private module MethodCallResolution {
13581386
*/
13591387
pragma[nomagic]
13601388
private predicate hasNoInherentTarget() {
1361-
exists(Type rootType, string name, int arity |
1362-
this.isMethodCall(rootType, name, arity) and
1389+
exists(Type type, string name, int arity |
1390+
this.isMethodCall(_, type, name, arity) and
13631391
forall(Impl impl |
1364-
methodCandidate(rootType, name, arity, impl, _) and
1392+
methodCandidate(type, name, arity, impl, _) and
13651393
not impl.hasTrait()
13661394
|
13671395
this.isNotInherentTarget(impl)
@@ -1373,7 +1401,7 @@ private module MethodCallResolution {
13731401
private Function resolveCallTargetCand(ImplOrTraitItemNode i, string name) {
13741402
IsInstantiationOf<MethodCallCand, FunctionPositionType, MethodCallIsInstantiationOfInput>::isInstantiationOf(this,
13751403
i, _) and
1376-
mc.isMethodCall(name, _) and
1404+
mc_.isMethodCall(name, _) and
13771405
result = getMethodSuccessor(i, name, _) and
13781406
if i.(Impl).hasTrait()
13791407
then
@@ -1394,54 +1422,31 @@ private module MethodCallResolution {
13941422
FunctionOverloading::functionResolutionDependsOnArgument(i, name, result, pos,
13951423
pragma[only_bind_into](path), type) and
13961424
pos.isPositional() and
1397-
inferType(mc.getArgument(pos.asArgumentPosition()), pragma[only_bind_into](path)) = type
1425+
inferType(mc_.getArgument(pos.asArgumentPosition()), pragma[only_bind_into](path)) = type
13981426
)
13991427
)
14001428
}
14011429

1402-
string toString() { result = mc.toString() + " [" + derefChainBorrow + "]" }
1430+
string toString() { result = mc_.toString() + " [" + derefChainBorrow + "]" }
14031431

1404-
Location getLocation() { result = mc.getLocation() }
1432+
Location getLocation() { result = mc_.getLocation() }
14051433
}
14061434

14071435
private module MethodCallIsInstantiationOfInput implements
14081436
IsInstantiationOfInputSig<MethodCallCand, FunctionPositionType>
14091437
{
1410-
pragma[nomagic]
1411-
private predicate methodCallCandidate(
1412-
MethodCallCand mcc, MethodCall mc, ImplOrTraitItemNode i, FunctionPositionType constraint
1413-
) {
1414-
exists(Type rootType, string name, int arity |
1415-
mcc.isMethodCall(rootType, name, arity) and
1416-
methodCandidate(rootType, name, arity, i, constraint) and
1417-
mc = mcc.getMethodCall()
1418-
)
1419-
}
1420-
1421-
private predicate relevantTraitVisible(Element mc, Trait trait) {
1422-
trait = any(ImplItemNode impl | methodCallCandidate(_, mc, impl, _)).resolveTraitTy()
1423-
}
1424-
14251438
pragma[nomagic]
14261439
predicate potentialInstantiationOf(
14271440
MethodCallCand mcc, TypeAbstraction abs, FunctionPositionType constraint
14281441
) {
1429-
exists(MethodCall mc | methodCallCandidate(mcc, mc, abs, constraint) |
1430-
not exists(abs.(ImplItemNode).resolveTraitTy())
1431-
or
1432-
// If the `impl` block implements a trait, that trait must be visible in
1433-
// order for the `impl` to be valid.
1434-
exists(Trait trait | pragma[only_bind_into](trait) = abs.(ImplItemNode).resolveTraitTy() |
1435-
TraitIsVisible<relevantTraitVisible/2>::traitIsVisible(mc, pragma[only_bind_into](trait))
1436-
or
1437-
mc instanceof IndexExpr and
1438-
trait instanceof IndexTrait
1439-
)
1442+
exists(MethodCall mc, Type type, string name, int arity |
1443+
mcc.isMethodCall(mc, type, name, arity) and
1444+
methodCallCandidate(mc, type, abs, constraint)
14401445
)
14411446
}
14421447

14431448
predicate relevantTypeMention(FunctionPositionType constraint) {
1444-
methodCandidate(_, _, _, _, constraint)
1449+
methodCallCandidate(_, _, _, constraint)
14451450
}
14461451
}
14471452
}
@@ -2033,10 +2038,10 @@ private module OperationResolution {
20332038
}
20342039

20352040
pragma[nomagic]
2036-
predicate isOperation(Type rootType, Trait trait, string name, int arity) {
2041+
predicate isOperation(Type type, Trait trait, string name, int arity) {
20372042
name = this.(Call).getMethodName() and
20382043
arity = this.(Call).getNumberOfArguments() and
2039-
rootType = this.getTypeAt(TypePath::nil()) and
2044+
type = this.getTypeAt(TypePath::nil()) and
20402045
trait = this.(Call).getTrait()
20412046
}
20422047

@@ -2089,9 +2094,9 @@ private module OperationResolution {
20892094

20902095
pragma[nomagic]
20912096
predicate potentialInstantiationOf(Op op, TypeAbstraction abs, FunctionPositionType constraint) {
2092-
exists(Type rootType, Trait trait, string name, int arity |
2093-
op.isOperation(rootType, trait, name, arity) and
2094-
MethodCallResolution::methodCandidate(rootType, name, arity, abs, constraint)
2097+
exists(Type type, Trait trait, string name, int arity |
2098+
op.isOperation(type, trait, name, arity) and
2099+
MethodCallResolution::methodCandidate(type, name, arity, abs, constraint)
20952100
|
20962101
trait = abs.(ImplItemNode).resolveTraitTy()
20972102
or

0 commit comments

Comments
 (0)