Skip to content

Commit 930ed67

Browse files
committed
wip
1 parent 22a255b commit 930ed67

File tree

2 files changed

+87
-326
lines changed

2 files changed

+87
-326
lines changed

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

Lines changed: 87 additions & 23 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();
14961516

1497-
private Type getReceiverTypeAt(TypePath path) { result = inferType(this.getReceiver(), path) }
1517+
Type getArgumentTypeAt(ArgumentPosition pos, TypePath path) {
1518+
result = inferType(this.getArgument(pos), path)
1519+
}
1520+
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,29 @@ 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() { CallExprImpl::getResolvedFunction(this).(Function).hasSelfParam() }
1710+
1711+
pragma[nomagic]
1712+
override predicate hasNameAndArity(string name, int arity) {
1713+
name = CallExprImpl::getFunctionPath(this).getText() and
1714+
arity = this.getArgList().getNumberOfArgs() - 1
1715+
}
1716+
1717+
override Expr getArgument(ArgumentPosition pos) {
1718+
pos.isSelf() and
1719+
result = this.getArg(0)
1720+
or
1721+
result = this.getArgList().getArg(pos.asPosition() + 1)
1722+
}
1723+
1724+
Type getTypeAt(TypePath path) { result = getCallExprQualifierType(this, path) }
1725+
1726+
override predicate supportsAutoDerefAndBorrow() { none() }
16751727
}
16761728

16771729
private newtype TMethodCallCand =
@@ -1733,7 +1785,11 @@ private module MethodCallResolution {
17331785
private Function resolveCallTargetCand(ImplOrTraitItemNode i) {
17341786
exists(string name |
17351787
IsInstantiationOf<MethodCallCand, FunctionType, MethodCallReceiverIsInstantiationOfInput>::isInstantiationOf(this,
1736-
i, _) and
1788+
i, _)
1789+
or
1790+
IsInstantiationOf<MethodCallCallExpr, TypeMentionTypeTree, MethodCallCallExprIsInstantiationOfInput>::isInstantiationOf(mc_,
1791+
i, _)
1792+
|
17371793
mc_.hasNameAndArity(name, _) and
17381794
result = getMethodSuccessor(i, name, _) and
17391795
if i.(Impl).hasTrait()
@@ -1827,6 +1883,28 @@ private module MethodCallResolution {
18271883
}
18281884
}
18291885

1886+
/**
1887+
* A configuration for matching the type of a receiver against the type of
1888+
* a `self` parameter.
1889+
*/
1890+
private module MethodCallCallExprIsInstantiationOfInput implements
1891+
IsInstantiationOfInputSig<MethodCallCallExpr, TypeMentionTypeTree>
1892+
{
1893+
pragma[nomagic]
1894+
predicate potentialInstantiationOf(
1895+
MethodCallCallExpr ce, TypeAbstraction abs, TypeMentionTypeTree constraint
1896+
) {
1897+
abs =
1898+
any(ImplItemNode impl |
1899+
CallExprImpl::getResolvedFunction(ce) = impl.getASuccessor(_) and
1900+
constraint = impl.getSelfPath()
1901+
)
1902+
}
1903+
// predicate relevantTypeMention(FunctionType constraint) {
1904+
// methodInfo(_, _, _, _, constraint, _, _)
1905+
// }
1906+
}
1907+
18301908
/**
18311909
* A configuration for anti-matching the type of a receiver against the type of
18321910
* a `self` parameter in an inherent method.
@@ -2073,6 +2151,8 @@ private module FunctionCallResolution {
20732151

20742152
/** A function call, `f(x)`. */
20752153
final class FunctionCall extends CallExpr {
2154+
FunctionCall() { not this instanceof MethodCallResolution::MethodCall }
2155+
20762156
/**
20772157
* Gets the item that this function call resolves to using path resolution,
20782158
* if any.
@@ -2412,26 +2492,10 @@ private module FunctionCallMatchingInput implements MatchingInputSig {
24122492
result = this and apos.isReturn()
24132493
}
24142494

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-
24312495
pragma[nomagic]
24322496
Type getInferredType(AccessPosition apos, TypePath path) {
24332497
apos.asArgumentPosition().isSelf() and
2434-
result = this.getQualifierType(path)
2498+
result = getCallExprQualifierType(this, path)
24352499
or
24362500
result = inferType(this.getNodeAt(apos), path)
24372501
}

0 commit comments

Comments
 (0)