Skip to content

Commit f4c3754

Browse files
committed
wip
1 parent 0bddecd commit f4c3754

File tree

5 files changed

+61
-48
lines changed

5 files changed

+61
-48
lines changed

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

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,7 @@ module Impl {
2828
*/
2929
class CallExprBase extends Generated::CallExprBase {
3030
/** Gets the static target of this call, if any. */
31-
final Callable getStaticTarget() {
32-
result = TypeInference::resolveMethodCallTarget(this)
33-
or
34-
result = TypeInference::resolveCallTarget(this)
35-
}
31+
final Function getStaticTarget() { result = TypeInference::resolveCallTarget(this) }
3632

3733
override Expr getArg(int index) { result = this.getArgList().getArg(index) }
3834
}

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

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,11 +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-
result = this.(CallExpr).getStaticTarget()
66-
}
62+
Function getStaticTarget() { result = TypeInference::resolveCallTarget(this) }
6763

6864
/** Gets a runtime target of this call, if any. */
6965
pragma[nomagic]

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

Lines changed: 58 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -770,9 +770,7 @@ private module CallExprBaseMatchingInput implements MatchingInputSig {
770770
Declaration getTarget() {
771771
result = resolveMethodCallTarget(this) // mutual recursion; resolving method calls requires resolving types and vice versa
772772
or
773-
result = resolveCallTargetSimple(this)
774-
or
775-
result = resolveCallTargetComplex(this) // mutual recursion
773+
result = resolveFunctionCallTarget(this) // potential mutual recursion; resolving some associated function calls requires resolving types
776774
}
777775
}
778776

@@ -1224,12 +1222,22 @@ private Type inferForLoopExprType(AstNode n, TypePath path) {
12241222
final class MethodCall extends Call {
12251223
MethodCall() { exists(this.getReceiver()) }
12261224

1225+
private Type getReceiverTypeAt(TypePath path) {
1226+
result = inferType(super.getReceiver(), path)
1227+
or
1228+
exists(PathExpr pe, TypeMention tm |
1229+
pe = this.(CallExpr).getFunction() and
1230+
tm = pe.getPath().getQualifier() and
1231+
result = tm.resolveTypeAt(path)
1232+
)
1233+
}
1234+
12271235
/** Gets the type of the receiver of the method call at `path`. */
12281236
Type getTypeAt(TypePath path) {
12291237
if this.receiverImplicitlyBorrowed()
12301238
then
12311239
exists(TypePath path0, Type t0 |
1232-
t0 = inferType(super.getReceiver(), path0) and
1240+
t0 = this.getReceiverTypeAt(path0) and
12331241
(
12341242
path0.isCons(TRefTypeParameter(), path)
12351243
or
@@ -1257,10 +1265,14 @@ final class MethodCall extends Call {
12571265
t0.(StructType).asItemNode() instanceof StringStruct and
12581266
result.(StructType).asItemNode() instanceof Builtins::Str
12591267
)
1260-
else result = inferType(super.getReceiver(), path)
1268+
else result = this.getReceiverTypeAt(path)
12611269
}
12621270
}
12631271

1272+
final private class FunctionCallExpr extends CallExpr {
1273+
FunctionCallExpr() { not this instanceof MethodCall }
1274+
}
1275+
12641276
/**
12651277
* Holds if a method for `type` with the name `name` and the arity `arity`
12661278
* exists in `impl`.
@@ -1500,15 +1512,28 @@ private Function getTraitMethod(ImplTraitReturnType trait, string name) {
15001512
result = getMethodSuccessor(trait.getImplTraitTypeRepr(), name)
15011513
}
15021514

1515+
pragma[nomagic]
1516+
private Function resolveMethodCallTarget(MethodCall mc) {
1517+
// The method comes from an `impl` block targeting the type of the receiver.
1518+
result = getMethodFromImpl(mc)
1519+
or
1520+
// The type of the receiver is a type parameter and the method comes from a
1521+
// trait bound on the type parameter.
1522+
result = getTypeParameterMethod(mc.getTypeAt(TypePath::nil()), mc.getMethodName())
1523+
or
1524+
// The type of the receiver is an `impl Trait` type.
1525+
result = getTraitMethod(mc.getTypeAt(TypePath::nil()), mc.getMethodName())
1526+
}
1527+
15031528
pragma[nomagic]
15041529
private predicate assocFuncResolutionDependsOnArgument(Function f, Impl impl, int pos) {
15051530
methodResolutionDependsOnArgument(impl, _, f, pos, _, _)
15061531
}
15071532

1508-
private class AssocFuncCallExpr extends CallExpr {
1533+
private class AssocFunctionCallExpr extends FunctionCallExpr {
15091534
private int pos;
15101535

1511-
AssocFuncCallExpr() {
1536+
AssocFunctionCallExpr() {
15121537
assocFuncResolutionDependsOnArgument(CallExprImpl::getResolvedFunction(this), _, pos)
15131538
}
15141539

@@ -1524,11 +1549,11 @@ private class AssocFuncCallExpr extends CallExpr {
15241549
}
15251550

15261551
private module AssocFuncIsInstantiationOfInput implements
1527-
IsInstantiationOfInputSig<AssocFuncCallExpr>
1552+
IsInstantiationOfInputSig<AssocFunctionCallExpr>
15281553
{
15291554
pragma[nomagic]
15301555
predicate potentialInstantiationOf(
1531-
AssocFuncCallExpr ce, TypeAbstraction impl, TypeMention constraint
1556+
AssocFunctionCallExpr ce, TypeAbstraction impl, TypeMention constraint
15321557
) {
15331558
exists(Function cand |
15341559
cand = ce.getACandidate(impl) and
@@ -1537,21 +1562,34 @@ private module AssocFuncIsInstantiationOfInput implements
15371562
}
15381563
}
15391564

1565+
/**
1566+
* Gets the target of `call`, where resolution does not rely on type inference.
1567+
*/
15401568
pragma[nomagic]
1541-
ItemNode resolveCallTargetSimple(CallExpr ce) {
1542-
result = CallExprImpl::getResolvedFunction(ce) and
1569+
private ItemNode resolveFunctionCallTargetSimple(FunctionCallExpr call) {
1570+
result = CallExprImpl::getResolvedFunction(call) and
15431571
not assocFuncResolutionDependsOnArgument(result, _, _)
15441572
}
15451573

1574+
/**
1575+
* Gets the target of `call`, where resolution relies on type inference.
1576+
*/
15461577
pragma[nomagic]
1547-
Function resolveCallTargetComplex(AssocFuncCallExpr ce) {
1578+
private Function resolveFunctionCallTargetComplex(AssocFunctionCallExpr call) {
15481579
exists(Impl impl |
1549-
IsInstantiationOf<AssocFuncCallExpr, AssocFuncIsInstantiationOfInput>::isInstantiationOf(ce,
1580+
IsInstantiationOf<AssocFunctionCallExpr, AssocFuncIsInstantiationOfInput>::isInstantiationOf(call,
15501581
impl, _) and
1551-
result = getMethodSuccessor(impl, ce.getACandidate(_).getName().getText())
1582+
result = getMethodSuccessor(impl, call.getACandidate(_).getName().getText())
15521583
)
15531584
}
15541585

1586+
pragma[inline]
1587+
private ItemNode resolveFunctionCallTarget(FunctionCallExpr call) {
1588+
result = resolveFunctionCallTargetSimple(call)
1589+
or
1590+
result = resolveFunctionCallTargetComplex(call)
1591+
}
1592+
15551593
cached
15561594
private module Cached {
15571595
private import codeql.rust.internal.CachedStages
@@ -1580,26 +1618,12 @@ private module Cached {
15801618
)
15811619
}
15821620

1583-
/** Gets a method that the method call `mc` resolves to, if any. */
1584-
cached
1585-
Function resolveMethodCallTarget(MethodCall mc) {
1586-
// The method comes from an `impl` block targeting the type of the receiver.
1587-
result = getMethodFromImpl(mc)
1588-
or
1589-
// The type of the receiver is a type parameter and the method comes from a
1590-
// trait bound on the type parameter.
1591-
result = getTypeParameterMethod(mc.getTypeAt(TypePath::nil()), mc.getMethodName())
1592-
or
1593-
// The type of the receiver is an `impl Trait` type.
1594-
result = getTraitMethod(mc.getTypeAt(TypePath::nil()), mc.getMethodName())
1595-
}
1596-
1597-
/** Gets a method that the method call `mc` resolves to, if any. */
1621+
/** Gets a function that `call` resolves to, if any. */
15981622
cached
1599-
Function resolveCallTarget(CallExpr ce) {
1600-
result = resolveCallTargetSimple(ce)
1623+
Function resolveCallTarget(Call call) {
1624+
result = resolveMethodCallTarget(call)
16011625
or
1602-
result = resolveCallTargetComplex(ce)
1626+
result = resolveFunctionCallTarget(call)
16031627
}
16041628

16051629
pragma[inline]
@@ -1736,8 +1760,8 @@ private module Debug {
17361760
private Locatable getRelevantLocatable() {
17371761
exists(string filepath, int startline, int startcolumn, int endline, int endcolumn |
17381762
result.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) and
1739-
filepath.matches("%/sqlx.rs") and
1740-
startline = [56 .. 60]
1763+
filepath.matches("%/main.rs") and
1764+
startline = 120
17411765
)
17421766
}
17431767

rust/ql/test/library-tests/type-inference/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ mod trait_impl {
117117
let a = x.trait_method(); // $ type=a:bool method=MyThing::trait_method
118118

119119
let y = MyThing { field: false };
120-
let b = MyTrait::trait_method(y); // $ type=b:bool method=MyThing::trait_method $ SPURIOUS: method=trait_method
120+
let b = MyTrait::trait_method(y); // $ type=b:bool method=MyThing::trait_method
121121
}
122122
}
123123

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

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -273,14 +273,11 @@ inferType
273273
| main.rs:117:17:117:17 | x | | main.rs:99:5:102:5 | MyThing |
274274
| main.rs:117:17:117:32 | x.trait_method() | | {EXTERNAL LOCATION} | bool |
275275
| main.rs:119:13:119:13 | y | | main.rs:99:5:102:5 | MyThing |
276-
| main.rs:119:13:119:13 | y | | main.rs:104:5:106:5 | trait MyTrait |
277276
| main.rs:119:17:119:40 | MyThing {...} | | main.rs:99:5:102:5 | MyThing |
278-
| main.rs:119:17:119:40 | MyThing {...} | | main.rs:104:5:106:5 | trait MyTrait |
279277
| main.rs:119:34:119:38 | false | | {EXTERNAL LOCATION} | bool |
280278
| main.rs:120:13:120:13 | b | | {EXTERNAL LOCATION} | bool |
281279
| main.rs:120:17:120:40 | ...::trait_method(...) | | {EXTERNAL LOCATION} | bool |
282280
| main.rs:120:39:120:39 | y | | main.rs:99:5:102:5 | MyThing |
283-
| main.rs:120:39:120:39 | y | | main.rs:104:5:106:5 | trait MyTrait |
284281
| main.rs:137:15:137:18 | SelfParam | | main.rs:125:5:128:5 | MyThing |
285282
| main.rs:137:15:137:18 | SelfParam | A | main.rs:130:5:131:14 | S1 |
286283
| main.rs:137:27:139:9 | { ... } | | main.rs:130:5:131:14 | S1 |

0 commit comments

Comments
 (0)