Skip to content

Commit a64ef1c

Browse files
committed
Rust: Disambiguate calls to associated functions
1 parent ae8af42 commit a64ef1c

File tree

5 files changed

+151
-56
lines changed

5 files changed

+151
-56
lines changed

rust/ql/lib/codeql/rust/elements/internal/CallExprBaseImpl.qll

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ private import codeql.rust.elements.Resolvable
1313
*/
1414
module Impl {
1515
private import rust
16+
private import codeql.rust.internal.TypeInference as TypeInference
1617

1718
pragma[nomagic]
1819
Resolvable getCallResolvable(CallExprBase call) {
@@ -27,7 +28,7 @@ module Impl {
2728
*/
2829
class CallExprBase extends Generated::CallExprBase {
2930
/** Gets the static target of this call, if any. */
30-
Callable getStaticTarget() { none() } // overridden by subclasses, but cannot be made abstract
31+
final Function getStaticTarget() { result = TypeInference::resolveCallTarget(this) }
3132

3233
override Expr getArg(int index) { result = this.getArgList().getArg(index) }
3334
}

rust/ql/lib/codeql/rust/elements/internal/CallExprImpl.qll

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ private import codeql.rust.elements.PathExpr
1414
module Impl {
1515
private import rust
1616
private import codeql.rust.internal.PathResolution as PathResolution
17-
private import codeql.rust.internal.TypeInference as TypeInference
1817

1918
pragma[nomagic]
2019
Path getFunctionPath(CallExpr ce) { result = ce.getFunction().(PathExpr).getPath() }
@@ -37,15 +36,6 @@ module Impl {
3736
class CallExpr extends Generated::CallExpr {
3837
override string toStringImpl() { result = this.getFunction().toAbbreviatedString() + "(...)" }
3938

40-
override Callable getStaticTarget() {
41-
// If this call is to a trait method, e.g., `Trait::foo(bar)`, then check
42-
// if type inference can resolve it to the correct trait implementation.
43-
result = TypeInference::resolveMethodCallTarget(this)
44-
or
45-
not exists(TypeInference::resolveMethodCallTarget(this)) and
46-
result = getResolvedFunction(this)
47-
}
48-
4939
/** Gets the struct that this call resolves to, if any. */
5040
Struct getStruct() { result = getResolvedFunction(this) }
5141

rust/ql/lib/codeql/rust/elements/internal/CallImpl.qll

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,7 @@ module Impl {
5959
Expr getReceiver() { result = this.getArgument(TSelfArgumentPosition()) }
6060

6161
/** Gets the static target of this call, if any. */
62-
Function getStaticTarget() {
63-
result = TypeInference::resolveMethodCallTarget(this)
64-
or
65-
not exists(TypeInference::resolveMethodCallTarget(this)) and
66-
result = this.(CallExpr).getStaticTarget()
67-
}
62+
Function getStaticTarget() { result = TypeInference::resolveCallTarget(this) }
6863

6964
/** Gets a runtime target of this call, if any. */
7065
pragma[nomagic]
@@ -79,18 +74,23 @@ module Impl {
7974
}
8075

8176
/** Holds if the call expression dispatches to a method. */
82-
private predicate callIsMethodCall(CallExpr call, Path qualifier, string methodName) {
77+
private predicate callIsMethodCall(
78+
CallExpr call, Path qualifier, string methodName, boolean selfIsRef
79+
) {
8380
exists(Path path, Function f |
8481
path = call.getFunction().(PathExpr).getPath() and
8582
f = resolvePath(path) and
86-
f.getParamList().hasSelfParam() and
8783
qualifier = path.getQualifier() and
88-
path.getSegment().getIdentifier().getText() = methodName
84+
path.getSegment().getIdentifier().getText() = methodName and
85+
exists(SelfParam self |
86+
self = f.getParamList().getSelfParam() and
87+
if self.isRef() then selfIsRef = true else selfIsRef = false
88+
)
8989
)
9090
}
9191

9292
private class CallExprCall extends Call instanceof CallExpr {
93-
CallExprCall() { not callIsMethodCall(this, _, _) }
93+
CallExprCall() { not callIsMethodCall(this, _, _, _) }
9494

9595
override string getMethodName() { none() }
9696

@@ -103,11 +103,19 @@ module Impl {
103103
}
104104
}
105105

106-
private class CallExprMethodCall extends Call instanceof CallExpr {
106+
class CallExprMethodCall extends Call instanceof CallExpr {
107107
Path qualifier;
108108
string methodName;
109+
boolean selfIsRef;
110+
111+
CallExprMethodCall() { callIsMethodCall(this, qualifier, methodName, selfIsRef) }
109112

110-
CallExprMethodCall() { callIsMethodCall(this, qualifier, methodName) }
113+
/**
114+
* Holds if this call must have an explicit borrow for the `self` argument,
115+
* because the corresponding parameter is `&self`. Explicit borrows are not
116+
* needed when using method call syntax.
117+
*/
118+
predicate hasExplicitSelfBorrow() { selfIsRef = true }
111119

112120
override string getMethodName() { result = methodName }
113121

rust/ql/lib/codeql/rust/elements/internal/MethodCallExprImpl.qll

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66

77
private import rust
88
private import codeql.rust.elements.internal.generated.MethodCallExpr
9-
private import codeql.rust.internal.PathResolution
10-
private import codeql.rust.internal.TypeInference
119

1210
/**
1311
* INTERNAL: This module contains the customizable definition of `MethodCallExpr` and should not
@@ -23,8 +21,6 @@ module Impl {
2321
* ```
2422
*/
2523
class MethodCallExpr extends Generated::MethodCallExpr {
26-
override Function getStaticTarget() { result = resolveMethodCallTarget(this) }
27-
2824
private string toStringPart(int index) {
2925
index = 0 and
3026
result = this.getReceiver().toAbbreviatedString()

0 commit comments

Comments
 (0)