Skip to content

Commit 6ff0fc0

Browse files
committed
wip
1 parent 22a255b commit 6ff0fc0

File tree

3 files changed

+92
-468
lines changed

3 files changed

+92
-468
lines changed

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

Lines changed: 92 additions & 159 deletions
Original file line numberDiff line numberDiff line change
@@ -1238,6 +1238,22 @@ private Type substituteLookupTraits(Type t) {
12381238
result = TTrait(getALookupTrait(t))
12391239
}
12401240

1241+
/**
1242+
* Gets the type qualifier of function call `ce`, if any.
1243+
*
1244+
* For example, the type qualifier of `Foo::<i32>::default()` is `Foo::<i32>`,
1245+
* but only when `Foo` is not a trait.
1246+
*/
1247+
pragma[nomagic]
1248+
private Type getCallExprQualifierType(CallExpr ce, TypePath path) {
1249+
exists(PathExpr pe, TypeMention tm |
1250+
pe = ce.getFunction() and
1251+
tm = pe.getPath().getQualifier() and
1252+
result = tm.resolveTypeAt(path) and
1253+
not resolvePath(tm) instanceof Trait
1254+
)
1255+
}
1256+
12411257
/**
12421258
* Provides logic for resolving method calls.
12431259
*
@@ -1403,6 +1419,10 @@ private module MethodCallResolution {
14031419
exists(string name, int arity |
14041420
mc.(MethodCall).hasNameAndArity(name, arity) and
14051421
methodTraitInfo(name, arity, trait)
1422+
|
1423+
not mc.(Call).hasTrait()
1424+
or
1425+
trait = mc.(Call).getTrait()
14061426
)
14071427
}
14081428

@@ -1492,9 +1512,15 @@ private module MethodCallResolution {
14921512

14931513
abstract Expr getArgument(ArgumentPosition pos);
14941514

1495-
Expr getReceiver() { result = this.getArgument(any(ArgumentPosition pos | pos.isSelf())) }
1515+
abstract predicate supportsAutoDerefAndBorrow();
1516+
1517+
Type getArgumentTypeAt(ArgumentPosition pos, TypePath path) {
1518+
result = inferType(this.getArgument(pos), path)
1519+
}
14961520

1497-
private Type getReceiverTypeAt(TypePath path) { result = inferType(this.getReceiver(), path) }
1521+
private Type getReceiverTypeAt(TypePath path) {
1522+
result = this.getArgumentTypeAt(any(ArgumentPosition pos | pos.isSelf()), path)
1523+
}
14981524

14991525
/**
15001526
* Same as `getACandidateReceiverTypeAt`, but without borrows.
@@ -1541,7 +1567,7 @@ private module MethodCallResolution {
15411567
}
15421568

15431569
pragma[nomagic]
1544-
private Type getComplexstrippedType(TypePath strippedTypePath, string derefChainBorrow) {
1570+
private Type getComplexStrippedType(TypePath strippedTypePath, string derefChainBorrow) {
15451571
result =
15461572
this.getACandidateReceiverTypeAtSubstituteLookupTraits(strippedTypePath, derefChainBorrow) and
15471573
isComplexRootStripped(strippedTypePath, result)
@@ -1553,10 +1579,11 @@ private module MethodCallResolution {
15531579
*/
15541580
pragma[nomagic]
15551581
private predicate hasNoCompatibleTargetNoBorrow(string derefChain) {
1582+
this.supportsAutoDerefAndBorrow() and
15561583
exists(TypePath strippedTypePath, Type strippedType, string derefChainBorrow |
15571584
derefChainBorrow = derefChain + ";" and
15581585
not derefChain.matches("%.ref") and // no need to try a borrow if the last thing we did was a deref
1559-
strippedType = this.getComplexstrippedType(strippedTypePath, derefChainBorrow)
1586+
strippedType = this.getComplexStrippedType(strippedTypePath, derefChainBorrow)
15601587
|
15611588
// todo: also check that all blanket implementation candidates are incompatible
15621589
forall(ImplOrTraitItemNode i |
@@ -1576,7 +1603,7 @@ private module MethodCallResolution {
15761603
exists(TypePath strippedTypePath, Type strippedType, string derefChainBorrow |
15771604
derefChainBorrow = derefChain + ";borrow" and
15781605
this.hasNoCompatibleTargetNoBorrow(derefChain) and
1579-
strippedType = this.getComplexstrippedType(strippedTypePath, derefChainBorrow)
1606+
strippedType = this.getComplexStrippedType(strippedTypePath, derefChainBorrow)
15801607
|
15811608
// todo: also check that all blanket implementation candidates are incompatible
15821609
forall(ImplOrTraitItemNode i |
@@ -1656,6 +1683,8 @@ private module MethodCallResolution {
16561683
or
16571684
result = super.getArgList().getArg(pos.asPosition())
16581685
}
1686+
1687+
override predicate supportsAutoDerefAndBorrow() { any() }
16591688
}
16601689

16611690
private class MethodCallIndexExpr extends MethodCall, IndexExpr {
@@ -1672,6 +1701,36 @@ private module MethodCallResolution {
16721701
pos.asPosition() = 0 and
16731702
result = this.getIndex()
16741703
}
1704+
1705+
override predicate supportsAutoDerefAndBorrow() { any() }
1706+
}
1707+
1708+
private class MethodCallCallExpr extends MethodCall, CallExpr {
1709+
MethodCallCallExpr() {
1710+
not exists(Function f |
1711+
f = CallExprImpl::getResolvedFunction(this) and
1712+
not f.hasSelfParam()
1713+
)
1714+
}
1715+
1716+
pragma[nomagic]
1717+
override predicate hasNameAndArity(string name, int arity) {
1718+
name = CallExprImpl::getFunctionPath(this).getText() and
1719+
arity = this.getArgList().getNumberOfArgs() - 1
1720+
}
1721+
1722+
override Expr getArgument(ArgumentPosition pos) {
1723+
pos.isSelf() and
1724+
result = this.getArg(0)
1725+
or
1726+
result = this.getArgList().getArg(pos.asPosition() + 1)
1727+
}
1728+
1729+
Type getTypeAt(TypePath path) {
1730+
result = substituteLookupTraits(getCallExprQualifierType(this, path))
1731+
}
1732+
1733+
override predicate supportsAutoDerefAndBorrow() { none() }
16751734
}
16761735

16771736
private newtype TMethodCallCand =
@@ -1733,7 +1792,11 @@ private module MethodCallResolution {
17331792
private Function resolveCallTargetCand(ImplOrTraitItemNode i) {
17341793
exists(string name |
17351794
IsInstantiationOf<MethodCallCand, FunctionType, MethodCallReceiverIsInstantiationOfInput>::isInstantiationOf(this,
1736-
i, _) and
1795+
i, _)
1796+
or
1797+
IsInstantiationOf<MethodCallCallExpr, TypeMentionTypeTree, MethodCallCallExprIsInstantiationOfInput>::isInstantiationOf(mc_,
1798+
i, _)
1799+
|
17371800
mc_.hasNameAndArity(name, _) and
17381801
result = getMethodSuccessor(i, name, _) and
17391802
if i.(Impl).hasTrait()
@@ -1827,6 +1890,26 @@ private module MethodCallResolution {
18271890
}
18281891
}
18291892

1893+
/**
1894+
* A configuration for matching the type qualifier of a function call against
1895+
* the type being implemented in an `impl` block.
1896+
*/
1897+
private module MethodCallCallExprIsInstantiationOfInput implements
1898+
IsInstantiationOfInputSig<MethodCallCallExpr, TypeMentionTypeTree>
1899+
{
1900+
pragma[nomagic]
1901+
predicate potentialInstantiationOf(
1902+
MethodCallCallExpr ce, TypeAbstraction abs, TypeMentionTypeTree constraint
1903+
) {
1904+
exists(getCallExprQualifierType(ce, _)) and
1905+
abs =
1906+
any(ImplItemNode impl |
1907+
CallExprImpl::getResolvedFunction(ce) = impl.getASuccessor(_) and
1908+
constraint = impl.getSelfPath()
1909+
)
1910+
}
1911+
}
1912+
18301913
/**
18311914
* A configuration for anti-matching the type of a receiver against the type of
18321915
* a `self` parameter in an inherent method.
@@ -2078,38 +2161,13 @@ private module FunctionCallResolution {
20782161
* if any.
20792162
*/
20802163
ItemNode getPathResolutionResolvedFunction() {
2081-
result = CallExprImpl::getResolvedFunction(this)
2082-
}
2083-
2084-
pragma[nomagic]
2085-
Type getTypeAt(TypePath path) {
2086-
result = substituteLookupTraits(inferType(this.getArg(0), path))
2087-
}
2088-
2089-
pragma[nomagic]
2090-
predicate hasSignature(
2091-
TypePath strippedTypePath, Type strippedType, TraitItemNode trait, Function resolved
2092-
) {
2093-
this.getTypeAt(strippedTypePath) = strippedType and
2094-
resolved = this.getPathResolutionResolvedFunction() and
2095-
trait = this.(Call).getTrait() and
2096-
MethodCallResolution::isComplexRootStripped(strippedTypePath, strippedType)
2097-
}
2098-
2099-
pragma[nomagic]
2100-
private Function getATargetMethodCand() {
2101-
exists(ImplOrTraitItemNode i, FunctionType self |
2102-
FunctionMethodCallIsInstantiationOfInput::potentialInstantiationOf(this, i, self, result) and
2103-
IsInstantiationOf<FunctionCall, FunctionType, FunctionMethodCallIsInstantiationOfInput>::isInstantiationOf(this,
2104-
i, self)
2105-
)
2164+
result = CallExprImpl::getResolvedFunction(this) and
2165+
not result.(Function).hasSelfParam()
21062166
}
21072167

21082168
pragma[nomagic]
21092169
private Function getAnAmbigousCandidate(FunctionTypePosition pos, TypePath path, Type type) {
21102170
(
2111-
result = this.getATargetMethodCand()
2112-
or
21132171
not this.(Call).hasTrait() and
21142172
result = this.getPathResolutionResolvedFunction()
21152173
) and
@@ -2149,8 +2207,6 @@ private module FunctionCallResolution {
21492207
pragma[nomagic]
21502208
private ItemNode resolveUnambigousFunctionCallTarget() {
21512209
(
2152-
result = this.getATargetMethodCand()
2153-
or
21542210
not this.(Call).hasTrait() and
21552211
result = this.getPathResolutionResolvedFunction()
21562212
) and
@@ -2163,113 +2219,6 @@ private module FunctionCallResolution {
21632219
result = this.resolveAmbigousFunctionCallTarget()
21642220
}
21652221
}
2166-
2167-
private module SatisfiesBlanketConstraintInput implements
2168-
BlanketImplementation::SatisfiesBlanketConstraintInputSig<FunctionCall>
2169-
{
2170-
pragma[nomagic]
2171-
private predicate hasSignature(FunctionCall call, string name, int arity) {
2172-
name = CallExprImpl::getFunctionPath(call).getText() and
2173-
arity = call.getNumberOfArgs() - 1
2174-
}
2175-
2176-
pragma[nomagic]
2177-
private predicate hasBlanketCandidate(
2178-
FunctionCall call, Trait trait, Function m, TypePath blanketPath, TypeParam blanketTypeParam
2179-
) {
2180-
not exists(call.getPathResolutionResolvedFunction()) and
2181-
exists(string name, int arity, ImplItemNode impl |
2182-
hasSignature(call, name, arity) and
2183-
MethodCallResolution::methodInfoBlanket(m, name, arity, impl, trait, _, blanketPath,
2184-
blanketTypeParam)
2185-
)
2186-
}
2187-
2188-
pragma[nomagic]
2189-
private predicate functionCallTraitCandidate(Element mc, Trait trait) {
2190-
hasBlanketCandidate(mc, trait, _, _, _)
2191-
}
2192-
2193-
pragma[nomagic]
2194-
predicate hasBlanketCandidate(
2195-
FunctionCall call, Function m, TypePath blanketPath, TypeParam blanketTypeParam
2196-
) {
2197-
exists(Trait trait |
2198-
hasBlanketCandidate(call, trait, m, blanketPath, blanketTypeParam) and
2199-
TraitIsVisible<functionCallTraitCandidate/2>::traitIsVisible(call, trait)
2200-
)
2201-
}
2202-
}
2203-
2204-
/**
2205-
* A configuration for matching the type of the first argument in a function call
2206-
* against the type of a `self` parameter.
2207-
*/
2208-
private module FunctionMethodCallIsInstantiationOfInput implements
2209-
IsInstantiationOfInputSig<FunctionCall, FunctionType>
2210-
{
2211-
pragma[nomagic]
2212-
private predicate methodInfo(
2213-
TypePath strippedTypePath, Type strippedType, TraitItemNode trait, Function f,
2214-
Function traitFunction
2215-
) {
2216-
exists(ImplOrTraitItemNode i |
2217-
MethodCallResolution::methodInfo(f, _, _, i, _, strippedTypePath, strippedType) and
2218-
not i.(ImplItemNode).isBlanketImplementation() and
2219-
traitFunction = trait.getAnAssocItem() and
2220-
(
2221-
f.implements(traitFunction)
2222-
or
2223-
f = traitFunction
2224-
)
2225-
)
2226-
}
2227-
2228-
pragma[nomagic]
2229-
private predicate methodInfoTypeParam(
2230-
TypePath strippedTypePath, TraitItemNode trait, Function f, Function traitFunction
2231-
) {
2232-
MethodCallResolution::methodInfoTypeParam(f, _, _, _, _, strippedTypePath, _) and
2233-
traitFunction = trait.getAnAssocItem() and
2234-
(
2235-
f.implements(traitFunction)
2236-
or
2237-
f = traitFunction
2238-
)
2239-
}
2240-
2241-
pragma[nomagic]
2242-
additional predicate potentialInstantiationOf(
2243-
FunctionCall call, ImplOrTraitItemNode i, FunctionType selfType, Function f
2244-
) {
2245-
(
2246-
exists(
2247-
TraitItemNode trait, Function resolved, TypePath strippedTypePath, Type strippedType
2248-
|
2249-
call.hasSignature(strippedTypePath, strippedType, trait, resolved)
2250-
|
2251-
methodInfo(strippedTypePath, strippedType, trait, f, resolved)
2252-
or
2253-
methodInfoTypeParam(strippedTypePath, trait, f, resolved)
2254-
)
2255-
or
2256-
BlanketImplementation::SatisfiesBlanketConstraint<FunctionCall, SatisfiesBlanketConstraintInput>::satisfiesBlanketConstraint(call,
2257-
f)
2258-
) and
2259-
MethodCallResolution::methodInfo(f, _, _, i, selfType, _, _)
2260-
}
2261-
2262-
pragma[nomagic]
2263-
predicate potentialInstantiationOf(
2264-
FunctionCall call, TypeAbstraction abs, FunctionType constraint
2265-
) {
2266-
potentialInstantiationOf(call, abs, constraint, _)
2267-
}
2268-
2269-
predicate relevantTypeMention(FunctionType constraint) {
2270-
MethodCallResolution::methodInfo(_, _, _, _, constraint, _, _)
2271-
}
2272-
}
22732222
}
22742223

22752224
/**
@@ -2412,26 +2361,10 @@ private module FunctionCallMatchingInput implements MatchingInputSig {
24122361
result = this and apos.isReturn()
24132362
}
24142363

2415-
/**
2416-
* Gets the type qualifier of this function call, if any.
2417-
*
2418-
* For example, the type qualifier of `Foo::<i32>::default()` is `Foo::<i32>`,
2419-
* but only when `Foo` is not a trait.
2420-
*/
2421-
pragma[nomagic]
2422-
private Type getQualifierType(TypePath path) {
2423-
exists(PathExpr pe, TypeMention tm |
2424-
pe = this.getFunction() and
2425-
tm = pe.getPath().getQualifier() and
2426-
result = tm.resolveTypeAt(path) and
2427-
not resolvePath(tm) instanceof Trait
2428-
)
2429-
}
2430-
24312364
pragma[nomagic]
24322365
Type getInferredType(AccessPosition apos, TypePath path) {
24332366
apos.asArgumentPosition().isSelf() and
2434-
result = this.getQualifierType(path)
2367+
result = getCallExprQualifierType(this, path)
24352368
or
24362369
result = inferType(this.getNodeAt(apos), path)
24372370
}

rust/ql/test/library-tests/type-inference/CONSISTENCY/PathResolutionConsistency.expected

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,6 @@ multipleCallTargets
55
| dereference.rs:184:17:184:30 | ... .foo() |
66
| dereference.rs:186:17:186:25 | S.bar(...) |
77
| dereference.rs:187:17:187:29 | S.bar(...) |
8-
| main.rs:540:26:540:42 | x.common_method() |
9-
| main.rs:541:26:541:45 | ...::common_method(...) |
10-
| main.rs:547:26:547:56 | ...::common_method(...) |
11-
| main.rs:551:26:551:49 | ...::common_method(...) |
12-
| main.rs:552:26:552:56 | ...::common_method(...) |
13-
| main.rs:556:26:556:37 | ...::m(...) |
148
| main.rs:1809:13:1809:63 | ... .partial_cmp(...) |
159
| main.rs:2324:9:2324:34 | ...::my_from2(...) |
1610
| main.rs:2325:9:2325:33 | ...::my_from2(...) |

0 commit comments

Comments
 (0)