Skip to content

Commit 539b6e4

Browse files
committed
wip
1 parent 299a00d commit 539b6e4

File tree

7 files changed

+76
-32
lines changed

7 files changed

+76
-32
lines changed

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

Lines changed: 6 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,11 @@ 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 Callable getStaticTarget() {
32+
result = TypeInference::resolveMethodCallTarget(this)
33+
or
34+
result = TypeInference::resolveCallTarget(this)
35+
}
3136

3237
override Expr getArg(int index) { result = this.getArgList().getArg(index) }
3338
}

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: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ module Impl {
6262
Function getStaticTarget() {
6363
result = TypeInference::resolveMethodCallTarget(this)
6464
or
65-
not exists(TypeInference::resolveMethodCallTarget(this)) and
6665
result = this.(CallExpr).getStaticTarget()
6766
}
6867

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()

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

Lines changed: 65 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ private import codeql.rust.frameworks.stdlib.Stdlib
1111
private import codeql.rust.frameworks.stdlib.Builtins as Builtins
1212
private import codeql.rust.elements.Call
1313
private import codeql.rust.elements.internal.CallImpl::Impl as CallImpl
14+
private import codeql.rust.elements.internal.CallExprImpl::Impl as CallExprImpl
1415

1516
class Type = T::Type;
1617

@@ -699,8 +700,6 @@ private module CallExprBaseMatchingInput implements MatchingInputSig {
699700
}
700701
}
701702

702-
private import codeql.rust.elements.internal.CallExprImpl::Impl as CallExprImpl
703-
704703
final class Access extends Call {
705704
pragma[nomagic]
706705
Type getTypeArgument(TypeArgumentPosition apos, TypePath path) {
@@ -746,7 +745,9 @@ private module CallExprBaseMatchingInput implements MatchingInputSig {
746745
Declaration getTarget() {
747746
result = resolveMethodCallTarget(this) // mutual recursion; resolving method calls requires resolving types and vice versa
748747
or
749-
result = CallExprImpl::getResolvedFunction(this)
748+
result = resolveCallTargetSimple(this)
749+
or
750+
result = resolveCallTargetComplex(this) // mutual recursion
750751
}
751752
}
752753

@@ -1290,7 +1291,7 @@ private predicate implSiblingCandidate(
12901291
// siblings).
12911292
not exists(impl.getAttributeMacroExpansion()) and
12921293
// We use this for resolving methods, so exclude traits that do not have methods.
1293-
exists(Function f | f = trait.getASuccessor(_) and f.getParamList().hasSelfParam()) and
1294+
exists(Function f | f = trait.getASuccessor(_)) and
12941295
selfTy = impl.getSelfTy() and
12951296
rootType = selfTy.resolveType()
12961297
}
@@ -1439,6 +1440,58 @@ private Function getTraitMethod(ImplTraitReturnType trait, string name) {
14391440
result = getMethodSuccessor(trait.getImplTraitTypeRepr(), name)
14401441
}
14411442

1443+
pragma[nomagic]
1444+
private predicate assocFuncResolutionDependsOnArgument(Function f, Impl impl, int pos) {
1445+
methodResolutionDependsOnArgument(impl, _, f, pos, _, _)
1446+
}
1447+
1448+
private class AssocFuncCallExpr extends CallExpr {
1449+
private int pos;
1450+
1451+
AssocFuncCallExpr() {
1452+
assocFuncResolutionDependsOnArgument(CallExprImpl::getResolvedFunction(this), _, pos)
1453+
}
1454+
1455+
Function getACandidate(Impl impl) {
1456+
result = CallExprImpl::getResolvedFunction(this) and
1457+
assocFuncResolutionDependsOnArgument(result, impl, pos)
1458+
}
1459+
1460+
int getPosition() { result = pos }
1461+
1462+
/** Gets the type of the receiver of the associated function call at `path`. */
1463+
Type getTypeAt(TypePath path) { result = inferType(this.getArg(pos), path) }
1464+
}
1465+
1466+
private module AssocFuncIsInstantiationOfInput implements
1467+
IsInstantiationOfInputSig<AssocFuncCallExpr>
1468+
{
1469+
pragma[nomagic]
1470+
predicate potentialInstantiationOf(
1471+
AssocFuncCallExpr ce, TypeAbstraction impl, TypeMention constraint
1472+
) {
1473+
exists(Function cand |
1474+
cand = ce.getACandidate(impl) and
1475+
constraint = cand.getParam(ce.getPosition()).getTypeRepr()
1476+
)
1477+
}
1478+
}
1479+
1480+
pragma[nomagic]
1481+
ItemNode resolveCallTargetSimple(CallExpr ce) {
1482+
result = CallExprImpl::getResolvedFunction(ce) and
1483+
not assocFuncResolutionDependsOnArgument(result, _, _)
1484+
}
1485+
1486+
pragma[nomagic]
1487+
Function resolveCallTargetComplex(AssocFuncCallExpr ce) {
1488+
exists(Impl impl |
1489+
IsInstantiationOf<AssocFuncCallExpr, AssocFuncIsInstantiationOfInput>::isInstantiationOf(ce,
1490+
impl, _) and
1491+
result = getMethodSuccessor(impl, ce.getACandidate(_).getName().getText())
1492+
)
1493+
}
1494+
14421495
cached
14431496
private module Cached {
14441497
private import codeql.rust.internal.CachedStages
@@ -1481,6 +1534,14 @@ private module Cached {
14811534
result = getTraitMethod(mc.getTypeAt(TypePath::nil()), mc.getMethodName())
14821535
}
14831536

1537+
/** Gets a method that the method call `mc` resolves to, if any. */
1538+
cached
1539+
Function resolveCallTarget(CallExpr ce) {
1540+
result = resolveCallTargetSimple(ce)
1541+
or
1542+
result = resolveCallTargetComplex(ce)
1543+
}
1544+
14841545
pragma[inline]
14851546
private Type inferRootTypeDeref(AstNode n) {
14861547
result = inferType(n) and

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2094,11 +2094,11 @@ mod method_determined_by_argument_type {
20942094
S(1i64).my_add(3i64); // $ MISSING: method=S::my_add2
20952095
S(1i64).my_add(&3i64); // $ method=S::my_add3
20962096

2097-
let x = i64::my_from(73i64); // $ method=MyFrom<i64>::my_from $ SPURIOUS: method=MyFrom<bool>::my_from
2098-
let y = i64::my_from(true); // $ method=MyFrom<bool>::my_from $ SPURIOUS: method=MyFrom<i64>::my_from
2097+
let x = i64::my_from(73i64); // $ method=MyFrom<i64>::my_from
2098+
let y = i64::my_from(true); // $ method=MyFrom<bool>::my_from
20992099
let z: i64 = MyFrom::my_from(73i64); // $ MISSING: method=MyFrom<i64>::my_from $ SPURIOUS: method=MyFrom::my_from
2100-
i64::my_from2(73i64, 0i64); // $ method=MyFrom2<i64>::my_from2 $ SPURIOUS: method=MyFrom2<bool>::my_from2
2101-
i64::my_from2(true, 0i64); // $ method=MyFrom2<bool>::my_from2 $ SPURIOUS: method=MyFrom2<i64>::my_from2
2100+
i64::my_from2(73i64, 0i64); // $ method=MyFrom2<i64>::my_from2
2101+
i64::my_from2(true, 0i64); // $ method=MyFrom2<bool>::my_from2
21022102
MyFrom2::my_from2(73i64, 0i64); // $ MISSING: method=MyFrom2<i64>::my_from2 $ SPURIOUS: method=MyFrom2::my_from2
21032103
}
21042104
}

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

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3209,23 +3209,19 @@ inferType
32093209
| main.rs:2095:25:2095:28 | 3i64 | | {EXTERNAL LOCATION} | i64 |
32103210
| main.rs:2097:13:2097:13 | x | | {EXTERNAL LOCATION} | i64 |
32113211
| main.rs:2097:17:2097:35 | ...::my_from(...) | | {EXTERNAL LOCATION} | i64 |
3212-
| main.rs:2097:30:2097:34 | 73i64 | | {EXTERNAL LOCATION} | bool |
32133212
| main.rs:2097:30:2097:34 | 73i64 | | {EXTERNAL LOCATION} | i64 |
32143213
| main.rs:2098:13:2098:13 | y | | {EXTERNAL LOCATION} | i64 |
32153214
| main.rs:2098:17:2098:34 | ...::my_from(...) | | {EXTERNAL LOCATION} | i64 |
32163215
| main.rs:2098:30:2098:33 | true | | {EXTERNAL LOCATION} | bool |
3217-
| main.rs:2098:30:2098:33 | true | | {EXTERNAL LOCATION} | i64 |
32183216
| main.rs:2099:13:2099:13 | z | | {EXTERNAL LOCATION} | i64 |
32193217
| main.rs:2099:13:2099:13 | z | | main.rs:2045:5:2048:5 | trait MyFrom |
32203218
| main.rs:2099:22:2099:43 | ...::my_from(...) | | {EXTERNAL LOCATION} | i64 |
32213219
| main.rs:2099:22:2099:43 | ...::my_from(...) | | main.rs:2045:5:2048:5 | trait MyFrom |
32223220
| main.rs:2099:38:2099:42 | 73i64 | | {EXTERNAL LOCATION} | bool |
32233221
| main.rs:2099:38:2099:42 | 73i64 | | {EXTERNAL LOCATION} | i64 |
3224-
| main.rs:2100:23:2100:27 | 73i64 | | {EXTERNAL LOCATION} | bool |
32253222
| main.rs:2100:23:2100:27 | 73i64 | | {EXTERNAL LOCATION} | i64 |
32263223
| main.rs:2100:30:2100:33 | 0i64 | | {EXTERNAL LOCATION} | i64 |
32273224
| main.rs:2101:23:2101:26 | true | | {EXTERNAL LOCATION} | bool |
3228-
| main.rs:2101:23:2101:26 | true | | {EXTERNAL LOCATION} | i64 |
32293225
| main.rs:2101:29:2101:32 | 0i64 | | {EXTERNAL LOCATION} | i64 |
32303226
| main.rs:2102:27:2102:31 | 73i64 | | {EXTERNAL LOCATION} | bool |
32313227
| main.rs:2102:27:2102:31 | 73i64 | | {EXTERNAL LOCATION} | i64 |
@@ -3444,10 +3440,8 @@ inferType
34443440
| main.rs:2188:32:2188:32 | 3 | | {EXTERNAL LOCATION} | u16 |
34453441
| main.rs:2191:13:2191:17 | vals5 | | {EXTERNAL LOCATION} | Vec |
34463442
| main.rs:2191:13:2191:17 | vals5 | A | {EXTERNAL LOCATION} | Global |
3447-
| main.rs:2191:13:2191:17 | vals5 | T | {EXTERNAL LOCATION} | u8 |
34483443
| main.rs:2191:21:2191:43 | ...::from(...) | | {EXTERNAL LOCATION} | Vec |
34493444
| main.rs:2191:21:2191:43 | ...::from(...) | A | {EXTERNAL LOCATION} | Global |
3450-
| main.rs:2191:21:2191:43 | ...::from(...) | T | {EXTERNAL LOCATION} | u8 |
34513445
| main.rs:2191:31:2191:42 | [...] | | file://:0:0:0:0 | [] |
34523446
| main.rs:2191:31:2191:42 | [...] | [T;...] | {EXTERNAL LOCATION} | i32 |
34533447
| main.rs:2191:31:2191:42 | [...] | [T;...] | {EXTERNAL LOCATION} | u32 |
@@ -3457,10 +3451,8 @@ inferType
34573451
| main.rs:2191:38:2191:38 | 2 | | {EXTERNAL LOCATION} | u32 |
34583452
| main.rs:2191:41:2191:41 | 3 | | {EXTERNAL LOCATION} | i32 |
34593453
| main.rs:2191:41:2191:41 | 3 | | {EXTERNAL LOCATION} | u32 |
3460-
| main.rs:2192:13:2192:13 | u | | {EXTERNAL LOCATION} | u8 |
34613454
| main.rs:2192:18:2192:22 | vals5 | | {EXTERNAL LOCATION} | Vec |
34623455
| main.rs:2192:18:2192:22 | vals5 | A | {EXTERNAL LOCATION} | Global |
3463-
| main.rs:2192:18:2192:22 | vals5 | T | {EXTERNAL LOCATION} | u8 |
34643456
| main.rs:2194:13:2194:17 | vals6 | | {EXTERNAL LOCATION} | Vec |
34653457
| main.rs:2194:13:2194:17 | vals6 | A | {EXTERNAL LOCATION} | Global |
34663458
| main.rs:2194:13:2194:17 | vals6 | T | file://:0:0:0:0 | & |
@@ -3640,3 +3632,4 @@ inferType
36403632
| main.rs:2283:41:2283:59 | ...::Foo {...} | | main.rs:72:5:72:21 | Foo |
36413633
| main.rs:2299:5:2299:15 | ...::f(...) | | {EXTERNAL LOCATION} | trait Future |
36423634
testFailures
3635+
| main.rs:120:17:120:40 | ...::trait_method(...) | Unexpected result: method=trait_method |

0 commit comments

Comments
 (0)