Skip to content

Commit 8da8b10

Browse files
committed
wip4
1 parent d9a2a65 commit 8da8b10

File tree

1 file changed

+85
-81
lines changed

1 file changed

+85
-81
lines changed

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

Lines changed: 85 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1238,7 +1238,8 @@ private module MethodCallResolution {
12381238
derefChain = ""
12391239
or
12401240
exists(TypePath path0, Type t0, string derefChain0 |
1241-
t0 = this.getACandidateReceiverTypeAtNoMatch(path0, derefChain0)
1241+
this.noCandidateReceiverTypeAt(derefChain0) and
1242+
t0 = this.getACandidateReceiverTypeAtNoBorrow(path0, derefChain0)
12421243
|
12431244
path0.isCons(TRefTypeParameter(), path) and
12441245
result = t0 and
@@ -1252,23 +1253,29 @@ private module MethodCallResolution {
12521253
)
12531254
}
12541255

1256+
/**
1257+
* Holds if the method inside `i` with matching name and arity can be ruled out
1258+
* as a candidate for the receiver type represented by `derefChainBorrow`.
1259+
*/
12551260
pragma[nomagic]
12561261
private predicate isNotCandidate(ImplOrTraitItemNode i, string derefChainBorrow) {
12571262
IsInstantiationOf<MethodCallCand, FunctionType, MethodCallIsInstantiationOfInput>::isNotInstantiationOf(MkMethodCallCand(this,
12581263
derefChainBorrow), i, _)
12591264
or
1260-
// not MethodCallIsInstantiationOfInput::potentialInstantiationOf(mcc, abs, constraint)
12611265
exists(Type rootType, TypePath selfRootPath, Type selfRootType |
12621266
rootType = this.getACandidateReceiverTypeAtSubstituteTraitBounds(derefChainBorrow) and
1263-
// mcc.isMethodCall(mc, selfPath, selfType, name, arity) and
12641267
methodCallCandidate(this, i, _, rootType, selfRootPath, selfRootType) and
12651268
selfRootType !=
12661269
this.getACandidateReceiverTypeAtSubstituteTraitBounds(selfRootPath, derefChainBorrow)
12671270
)
12681271
}
12691272

1273+
/**
1274+
* Holds if the candidate receiver type represented by `derefChain` does not
1275+
* have a matching method target.
1276+
*/
12701277
pragma[nomagic]
1271-
private predicate getACandidateReceiverTypeAtNoBorrowNoMatch0(string derefChain) {
1278+
private predicate noCandidateReceiverTypeAtNoBorrow(string derefChain) {
12721279
exists(Type rootType, string derefChainBorrow |
12731280
derefChainBorrow = derefChain + ";" and
12741281
not derefChain.matches("%.ref") and // no need to try a borrow if the last thing we did was a deref
@@ -1280,43 +1287,36 @@ private module MethodCallResolution {
12801287
)
12811288
}
12821289

1283-
pragma[nomagic]
1284-
private Type getACandidateReceiverTypeAtNoBorrowNoMatch(TypePath path, string derefChain) {
1285-
result = this.getACandidateReceiverTypeAtNoBorrow(path, derefChain) and
1286-
this.getACandidateReceiverTypeAtNoBorrowNoMatch0(derefChain)
1287-
}
1288-
12891290
pragma[nomagic]
12901291
private predicate hasRefCandidate(ImplOrTraitItemNode i) {
12911292
methodCallCandidate(this, i, _, TRefType(), _, _)
12921293
}
12931294

1295+
/**
1296+
* Holds if the candidate receiver type represented by `derefChain;borrow` does not
1297+
* have a matching method target.
1298+
*/
12941299
pragma[nomagic]
1295-
private predicate getACandidateReceiverTypeAtNoMatch0(string derefChain) {
1300+
private predicate noCandidateReceiverTypeAt(string derefChain) {
12961301
exists(string derefChainBorrow |
12971302
derefChainBorrow = derefChain + ";borrow" and
1298-
this.getACandidateReceiverTypeAtNoBorrowNoMatch0(derefChain)
1303+
this.noCandidateReceiverTypeAtNoBorrow(derefChain)
12991304
|
13001305
forall(ImplOrTraitItemNode i | this.hasRefCandidate(i) |
13011306
this.isNotCandidate(i, derefChainBorrow)
13021307
)
13031308
)
13041309
}
13051310

1306-
pragma[nomagic]
1307-
private Type getACandidateReceiverTypeAtNoMatch(TypePath path, string derefChain) {
1308-
result = this.getACandidateReceiverTypeAtNoBorrowNoMatch(path, derefChain) and
1309-
this.getACandidateReceiverTypeAtNoMatch0(derefChain)
1310-
}
1311-
13121311
/**
13131312
* Gets a [candidate receiver type][1] of this method call at `path`.
13141313
*
13151314
* The type is obtained by repeatedly dereferencing the receiver expression's type,
13161315
* as long as the method cannot be resolved in an earlier candidate type, and possibly
13171316
* applying a borrow at the end.
13181317
*
1319-
* The string `derefChainBorrow` encodes the above, separated by a semi-colon.
1318+
* The string `derefChainBorrow` encodes the sequences of dereferences and whether a
1319+
* borrow has been applied.
13201320
*
13211321
* [1]: https://doc.rust-lang.org/reference/expressions/method-call-expr.html#r-expr.method.candidate-receivers
13221322
*/
@@ -1326,19 +1326,24 @@ private module MethodCallResolution {
13261326
result = this.getACandidateReceiverTypeAtNoBorrow(path, derefChain) and
13271327
derefChainBorrow = derefChain + ";"
13281328
or
1329-
exists(TypePath path0, Type t0 |
1330-
t0 = this.getACandidateReceiverTypeAtNoBorrowNoMatch(path0, derefChain) and
1331-
derefChainBorrow = derefChain + ";borrow"
1332-
|
1329+
this.noCandidateReceiverTypeAtNoBorrow(derefChain) and
1330+
derefChainBorrow = derefChain + ";borrow" and
1331+
(
13331332
path.isEmpty() and
13341333
result = TRefType()
13351334
or
1336-
path = TypePath::cons(TRefTypeParameter(), path0) and
1337-
result = t0
1335+
exists(TypePath suffix |
1336+
result = this.getACandidateReceiverTypeAtNoBorrow(suffix, derefChain) and
1337+
path = TypePath::cons(TRefTypeParameter(), suffix)
1338+
)
13381339
)
13391340
)
13401341
}
13411342

1343+
/**
1344+
* Same as `getACandidateReceiverTypeAt`, but with traits substituted in for types
1345+
* with trait bounds.
1346+
*/
13421347
pragma[nomagic]
13431348
Type getACandidateReceiverTypeAtSubstituteTraitBounds(TypePath path, string derefChainBorrow) {
13441349
result = substituteTraitBounds(this.getACandidateReceiverTypeAt(path, derefChainBorrow))
@@ -1427,19 +1432,16 @@ private module MethodCallResolution {
14271432
mc.isMethodCall(name, arity)
14281433
}
14291434

1435+
/**
1436+
* Holds if the inherent method inside `i` with matching name and arity can be
1437+
* ruled out as a candidate for this call.
1438+
*/
14301439
pragma[nomagic]
1431-
private predicate isNotInherentTarget(Impl impl) {
1440+
private predicate isNotInherentCandidate(Impl impl) {
14321441
IsInstantiationOf<MethodCallCand, FunctionType, MethodCallIsNotInstantiationOfInput>::isNotInstantiationOf(this,
14331442
impl, _)
14341443
}
14351444

1436-
// pragma[nomagic]
1437-
// private predicate blah(
1438-
// Type type, Impl i, FunctionType self, TypePath selfRootPath, Type selfRootType
1439-
// ) {
1440-
// not i.hasTrait() and
1441-
// mc_.blah(type, i, self, selfPath, selfType, derefChainBorrow)
1442-
// }
14431445
/**
14441446
* Holds if this method call has no inherent target, i.e., it does not
14451447
* resolve to a method in an `impl` block for the type of the receiver.
@@ -1452,14 +1454,7 @@ private module MethodCallResolution {
14521454
methodInfo(_, name, arity, i, self, rootType, selfRootPath, selfRootType) and
14531455
not i.hasTrait()
14541456
|
1455-
// this.blah(type, i, self, selfPath, selfType)
1456-
// or
1457-
this.isNotInherentTarget(i)
1458-
// forall(Impl impl |
1459-
// methodInfo(type, name, arity, impl, _, _, _) and
1460-
// not impl.hasTrait()
1461-
// |
1462-
// this.isNotInherentTarget(impl)
1457+
this.isNotInherentCandidate(i)
14631458
)
14641459
)
14651460
}
@@ -1518,6 +1513,10 @@ private module MethodCallResolution {
15181513
Location getLocation() { result = mc_.getLocation() }
15191514
}
15201515

1516+
/**
1517+
* A configuration for matching the type of a receiver against the type of
1518+
* a `self` parameter.
1519+
*/
15211520
private module MethodCallIsInstantiationOfInput implements
15221521
IsInstantiationOfInputSig<MethodCallCand, FunctionType>
15231522
{
@@ -1528,7 +1527,6 @@ private module MethodCallResolution {
15281527
exists(MethodCall mc, string name, int arity, TypePath selfRootPath, Type selfRootType |
15291528
mcc.isMethodCall(mc, selfRootPath, selfRootType, name, arity) and
15301529
methodCallCandidate(mc, abs, constraint, _, selfRootPath, selfRootType)
1531-
// mc = Debug::getRelevantLocatable()
15321530
)
15331531
}
15341532

@@ -1537,6 +1535,10 @@ private module MethodCallResolution {
15371535
}
15381536
}
15391537

1538+
/**
1539+
* A configuration for anti-matching the type of a receiver against the type of
1540+
* a `self` parameter in an inherent method.
1541+
*/
15401542
private module MethodCallIsNotInstantiationOfInput implements
15411543
IsInstantiationOfInputSig<MethodCallCand, FunctionType>
15421544
{
@@ -1548,7 +1550,6 @@ private module MethodCallResolution {
15481550
exists(MethodCall mc, string name, int arity, Type rootType |
15491551
mcc.isMethodCall(mc, TypePath::nil(), rootType, name, arity) and
15501552
methodCallCandidate(mc, abs, constraint, rootType, _, _)
1551-
// mc = Debug::getRelevantLocatable()
15521553
)
15531554
}
15541555

@@ -1772,7 +1773,7 @@ private module FunctionCallResolution {
17721773
result = CallExprImpl::getResolvedFunction(this)
17731774
}
17741775

1775-
private ItemNode getPathResolutionResolvedFunctionOrImplementation(ItemNode resolved) {
1776+
ItemNode getPathResolutionResolvedFunctionOrImplementation(ItemNode resolved) {
17761777
resolved = this.getPathResolutionResolvedFunction() and
17771778
(
17781779
result = resolved
@@ -1781,43 +1782,21 @@ private module FunctionCallResolution {
17811782
)
17821783
}
17831784

1784-
// The `Self` type is supplied explicitly as a type qualifier, e.g. `Foo::<Bar>::baz()`
1785-
pragma[nomagic]
1786-
Type getQualifierType(TypePath path) {
1787-
exists(PathExpr pe, TypeMention tm |
1788-
pe = this.getFunction() and
1789-
tm = pe.getPath().getQualifier() and
1790-
result = tm.resolveTypeAt(path) and
1791-
not resolvePath(tm) instanceof Trait
1792-
)
1793-
}
1794-
17951785
pragma[nomagic]
17961786
Type getTypeAt(TypePath path) {
17971787
result = substituteTraitBounds(inferType(this.getArg(0), path))
17981788
}
17991789

18001790
pragma[nomagic]
1801-
Function getATraitCandidateMethod0(
1802-
TraitItemNode trait, ImplOrTraitItemNode i, FunctionType self, Function resolved
1803-
) {
1804-
exists(TypePath selfRootPath, Type selfRootType |
1805-
result = this.getPathResolutionResolvedFunctionOrImplementation(resolved) and
1806-
trait = this.(Call).getTrait() and
1807-
MethodCallResolution::methodInfo(result, _, _, i, self, _, selfRootPath, selfRootType) and
1808-
this.getTypeAt(selfRootPath) = selfRootType
1791+
private Function getACandidateTraitMethod() {
1792+
exists(TraitItemNode trait, ImplOrTraitItemNode i, FunctionType self, Function resolved |
1793+
FunctionMethodCallIsInstantiationOfInput::potentialInstantiationOf(this, trait, i, self,
1794+
resolved, result) and
1795+
IsInstantiationOf<FunctionCall, FunctionType, FunctionMethodCallIsInstantiationOfInput>::isInstantiationOf(this,
1796+
i, self)
18091797
)
18101798
}
18111799

1812-
pragma[nomagic]
1813-
private Function getATraitCandidateMethod(
1814-
TraitItemNode trait, ImplOrTraitItemNode i, FunctionType self, Function resolved
1815-
) {
1816-
result = this.getATraitCandidateMethod0(trait, i, self, resolved) and
1817-
IsInstantiationOf<FunctionCall, FunctionType, FunctionMethodCallIsInstantiationOfInput>::isInstantiationOf(this,
1818-
i, self)
1819-
}
1820-
18211800
pragma[nomagic]
18221801
private Function getAnAmbigousCandidate(FunctionTypePosition pos, TypePath path, Type type) {
18231802
exists(TraitItemNode trait, Function resolved |
@@ -1827,7 +1806,7 @@ private module FunctionCallResolution {
18271806
)
18281807
or
18291808
(
1830-
result = this.getATraitCandidateMethod(_, _, _, _)
1809+
result = this.getACandidateTraitMethod()
18311810
or
18321811
not this.(Call).hasTrait() and
18331812
result = this.getPathResolutionResolvedFunction()
@@ -1857,20 +1836,17 @@ private module FunctionCallResolution {
18571836
/**
18581837
* Gets the target of this call, where resolution does not rely on type inference.
18591838
*/
1860-
// inline to reduce non-linear recursion
1861-
pragma[inline]
1839+
pragma[nomagic]
18621840
private ItemNode resolveUnambigousFunctionCallTarget() {
18631841
(
1864-
result = this.getATraitCandidateMethod(_, _, _, _)
1842+
result = this.getACandidateTraitMethod()
18651843
or
18661844
not this.(Call).hasTrait() and
18671845
result = this.getPathResolutionResolvedFunction()
18681846
) and
18691847
not functionResolutionDependsOnArgument(_, result, _, _, _)
18701848
}
18711849

1872-
// inline to reduce non-linear recursion
1873-
pragma[inline]
18741850
ItemNode resolveCallTarget() {
18751851
result = this.resolveUnambigousFunctionCallTarget()
18761852
or
@@ -1881,11 +1857,24 @@ private module FunctionCallResolution {
18811857
private module FunctionMethodCallIsInstantiationOfInput implements
18821858
IsInstantiationOfInputSig<FunctionCall, FunctionType>
18831859
{
1860+
pragma[nomagic]
1861+
additional predicate potentialInstantiationOf(
1862+
FunctionCall call, TraitItemNode trait, ImplOrTraitItemNode i, FunctionType self,
1863+
Function resolved, Function f
1864+
) {
1865+
exists(TypePath selfRootPath, Type selfRootType |
1866+
f = call.getPathResolutionResolvedFunctionOrImplementation(resolved) and
1867+
trait = call.(Call).getTrait() and
1868+
MethodCallResolution::methodInfo(f, _, _, i, self, _, selfRootPath, selfRootType) and
1869+
call.getTypeAt(selfRootPath) = selfRootType
1870+
)
1871+
}
1872+
18841873
pragma[nomagic]
18851874
predicate potentialInstantiationOf(
18861875
FunctionCall call, TypeAbstraction abs, FunctionType constraint
18871876
) {
1888-
exists(call.getATraitCandidateMethod0(_, abs, constraint, _))
1877+
potentialInstantiationOf(call, _, abs, constraint, _, _)
18891878
}
18901879

18911880
predicate relevantTypeMention(FunctionType constraint) {
@@ -2069,6 +2058,22 @@ private module FunctionCallMatchingInput implements MatchingInputSig {
20692058
result = this and apos.isReturn()
20702059
}
20712060

2061+
/**
2062+
* Gets the type qualifier of this function call, if any.
2063+
*
2064+
* For example, the type qualifier of `Foo::<Bar>::baz()` is `Foo::<Bar>`,
2065+
* but only when `Foo` is not a trait.
2066+
*/
2067+
pragma[nomagic]
2068+
private Type getQualifierType(TypePath path) {
2069+
exists(PathExpr pe, TypeMention tm |
2070+
pe = this.getFunction() and
2071+
tm = pe.getPath().getQualifier() and
2072+
result = tm.resolveTypeAt(path) and
2073+
not resolvePath(tm) instanceof Trait
2074+
)
2075+
}
2076+
20722077
pragma[nomagic]
20732078
Type getInferredType(AccessPosition apos, TypePath path) {
20742079
apos.asArgumentPosition().isSelf() and
@@ -2101,7 +2106,6 @@ private Type inferCallExprType(AstNode n, TypePath path) {
21012106
private module OperationResolution {
21022107
/** An operation, `x + y`. */
21032108
final class Op extends Operation {
2104-
// Op() { none() }
21052109
pragma[nomagic]
21062110
private Type getTypeAt0(TypePath path) {
21072111
if this.(Call).implicitBorrowAt(any(ArgumentPosition pos | pos.isSelf()), true)
@@ -2162,7 +2166,7 @@ private module OperationResolution {
21622166
TypePath selfRootPath, Type selfRootType
21632167
) {
21642168
MethodCallResolution::methodInfo(_, name, arity, abs, constraint, _, selfRootPath,
2165-
selfRootType) and //and
2169+
selfRootType) and
21662170
(
21672171
trait = abs.(ImplItemNode).resolveTraitTy()
21682172
or

0 commit comments

Comments
 (0)