Skip to content

Commit 61661fd

Browse files
committed
wip
1 parent 7803df5 commit 61661fd

File tree

4 files changed

+58
-41
lines changed

4 files changed

+58
-41
lines changed

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

Lines changed: 57 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -882,7 +882,7 @@ private module ArgIsInstantiationOf<
882882
}
883883

884884
/**
885-
* Provides logic for resolving method calls.
885+
* Provides logic for resolving calls to methods.
886886
*
887887
* When resolving a method call, a list of [candidate receiver types][1] is constructed
888888
*
@@ -915,7 +915,7 @@ private module ArgIsInstantiationOf<
915915
*
916916
* [1]: https://doc.rust-lang.org/reference/expressions/method-call-expr.html#r-expr.method.candidate-receivers
917917
*/
918-
private module MethodCallResolution {
918+
private module MethodResolution {
919919
/**
920920
* Holds if `root` is a valid complex [`self` root type][1], with type
921921
* parameter `tp`.
@@ -1169,7 +1169,7 @@ private module MethodCallResolution {
11691169
derefChain = ""
11701170
or
11711171
exists(TypePath path0, Type t0, string derefChain0 |
1172-
this.hasNoCompatibleTarget(derefChain0) and
1172+
this.hasNoCompatibleTarget(derefChain0, _) and
11731173
t0 = this.getACandidateReceiverTypeAtNoBorrow(path0, derefChain0)
11741174
|
11751175
path0.isCons(TRefTypeParameter(), path) and
@@ -1216,9 +1216,13 @@ private module MethodCallResolution {
12161216
* have a matching method target.
12171217
*/
12181218
pragma[nomagic]
1219-
private predicate hasNoCompatibleTargetNoBorrow(string derefChain) {
1220-
this.supportsAutoDerefAndBorrow() and
1221-
exists(TypePath strippedTypePath, Type strippedType, string derefChainBorrow |
1219+
predicate hasNoCompatibleTargetNoBorrow(string derefChain, string derefChainBorrow) {
1220+
(
1221+
//
1222+
this.supportsAutoDerefAndBorrow() or
1223+
derefChain = ""
1224+
) and
1225+
exists(TypePath strippedTypePath, Type strippedType |
12221226
derefChainBorrow = derefChain + ";" and
12231227
not derefChain.matches("%.ref") and // no need to try a borrow if the last thing we did was a deref
12241228
strippedType = this.getComplexStrippedType(strippedTypePath, derefChainBorrow)
@@ -1237,10 +1241,10 @@ private module MethodCallResolution {
12371241
* have a matching method target.
12381242
*/
12391243
pragma[nomagic]
1240-
private predicate hasNoCompatibleTarget(string derefChain) {
1241-
exists(TypePath strippedTypePath, Type strippedType, string derefChainBorrow |
1244+
predicate hasNoCompatibleTarget(string derefChain, string derefChainBorrow) {
1245+
exists(TypePath strippedTypePath, Type strippedType |
12421246
derefChainBorrow = derefChain + ";borrow" and
1243-
this.hasNoCompatibleTargetNoBorrow(derefChain) and
1247+
this.hasNoCompatibleTargetNoBorrow(derefChain, _) and
12441248
strippedType = this.getComplexStrippedType(strippedTypePath, derefChainBorrow)
12451249
|
12461250
// todo: also check that all blanket implementation candidates are incompatible
@@ -1270,7 +1274,7 @@ private module MethodCallResolution {
12701274
result = this.getACandidateReceiverTypeAtNoBorrow(path, derefChain) and
12711275
derefChainBorrow = derefChain + ";"
12721276
or
1273-
this.hasNoCompatibleTargetNoBorrow(derefChain) and
1277+
this.hasNoCompatibleTargetNoBorrow(derefChain, _) and
12741278
derefChainBorrow = derefChain + ";borrow" and
12751279
(
12761280
path.isEmpty() and
@@ -1429,6 +1433,13 @@ private module MethodCallResolution {
14291433
result = mc_.getACandidateReceiverTypeAtSubstituteLookupTraits(path, derefChainBorrow)
14301434
}
14311435

1436+
pragma[nomagic]
1437+
predicate hasNoCompatibleTarget() {
1438+
mc_.hasNoCompatibleTarget(_, derefChainBorrow)
1439+
or
1440+
mc_.hasNoCompatibleTargetNoBorrow(_, derefChainBorrow)
1441+
}
1442+
14321443
pragma[nomagic]
14331444
predicate hasSignature(
14341445
MethodCall mc, TypePath strippedTypePath, Type strippedType, string name, int arity
@@ -1531,7 +1542,11 @@ private module MethodCallResolution {
15311542
) {
15321543
exists(MethodCall mc, string name, int arity |
15331544
mcc.hasSignature(mc, _, _, name, arity) and
1534-
methodCallBlanketCandidate(mc, m, _, _, blanketPath, blanketTypeParam)
1545+
methodCallBlanketCandidate(mc, m, _, _, blanketPath, blanketTypeParam) and
1546+
// Only apply blanket implementations when no other implementations are possible;
1547+
// this is to account for codebases that use the (unstable) specialization feature
1548+
// (https://rust-lang.github.io/rfcs/1210-impl-specialization.html)
1549+
mcc.hasNoCompatibleTarget()
15351550
)
15361551
}
15371552
}
@@ -1544,23 +1559,36 @@ private module MethodCallResolution {
15441559
IsInstantiationOfInputSig<MethodCallCand, FunctionType>
15451560
{
15461561
pragma[nomagic]
1547-
predicate potentialInstantiationOf(
1548-
MethodCallCand mcc, TypeAbstraction abs, FunctionType constraint
1562+
additional predicate potentialInstantiationOf0(
1563+
MethodCallCand mcc, ImplOrTraitItemNode i, FunctionType selfType
15491564
) {
15501565
exists(
15511566
MethodCall mc, Method m, string name, int arity, TypePath strippedTypePath,
15521567
Type strippedType
15531568
|
15541569
mcc.hasSignature(mc, strippedTypePath, strippedType, name, arity)
15551570
|
1556-
methodCallNonBlanketCandidate(mc, m, abs, constraint, strippedTypePath, strippedType)
1571+
methodCallNonBlanketCandidate(mc, m, i, selfType, strippedTypePath, strippedType)
15571572
or
1558-
methodCallBlanketCandidate(mc, m, abs, constraint, _, _) and
1573+
methodCallBlanketCandidate(mc, m, i, selfType, _, _) and
15591574
BlanketImplementation::SatisfiesBlanketConstraint<MethodCallCand, SatisfiesBlanketConstraintInput>::satisfiesBlanketConstraint(mcc,
15601575
m)
15611576
)
15621577
}
15631578

1579+
pragma[nomagic]
1580+
predicate potentialInstantiationOf(
1581+
MethodCallCand mcc, TypeAbstraction abs, FunctionType constraint
1582+
) {
1583+
potentialInstantiationOf0(mcc, abs, constraint) and
1584+
if abs.(Impl).hasTrait()
1585+
then
1586+
// inherent methods take precedence over trait methods, so only allow
1587+
// trait methods when there are no matching inherent methods
1588+
mcc.hasNoInherentTarget()
1589+
else any()
1590+
}
1591+
15641592
predicate relevantTypeMention(FunctionType constraint) {
15651593
methodInfo(_, _, _, _, constraint, _, _)
15661594
}
@@ -1597,7 +1625,7 @@ private module MethodCallResolution {
15971625
predicate potentialInstantiationOf(
15981626
MethodCallCand mcc, TypeAbstraction abs, FunctionType constraint
15991627
) {
1600-
MethodCallReceiverIsInstantiationOfInput::potentialInstantiationOf(mcc, abs, constraint) and
1628+
MethodCallReceiverIsInstantiationOfInput::potentialInstantiationOf0(mcc, abs, constraint) and
16011629
abs = any(Impl i | not i.hasTrait())
16021630
}
16031631

@@ -1674,7 +1702,7 @@ private module MethodCallMatchingInput implements MatchingWithEnvironmentInputSi
16741702

16751703
class AccessEnvironment = string;
16761704

1677-
final private class MethodCallFinal = MethodCallResolution::MethodCall;
1705+
final private class MethodCallFinal = MethodResolution::MethodCall;
16781706

16791707
class Access extends MethodCallFinal {
16801708
Access() {
@@ -1764,8 +1792,10 @@ private Type inferMethodCallExprType(AstNode n, TypePath path) {
17641792
MethodCallMatchingInput::Access a, MethodCallMatchingInput::AccessPosition apos,
17651793
string derefChainBorrow, TypePath path0
17661794
|
1767-
result = inferMethodCallExprType0(a, apos, n, derefChainBorrow, path0)
1795+
result = inferMethodCallExprType0(a, apos, n, derefChainBorrow, path0) //and
17681796
|
1797+
// todo
1798+
// not apos.asArgumentPosition().isSelf()
17691799
(
17701800
not apos.asArgumentPosition().isSelf()
17711801
or
@@ -1786,10 +1816,10 @@ private Type inferMethodCallExprType(AstNode n, TypePath path) {
17861816
}
17871817

17881818
/**
1789-
* Provides logic for resolving associated function calls. This includes
1819+
* Provides logic for resolving calls to associated functions. This includes
17901820
* "calls" to tuple variants and tuple structs.
17911821
*/
1792-
private module AssocFunctionCallResolution {
1822+
private module AssocFunctionResolution {
17931823
private import FunctionOverloading
17941824

17951825
/**
@@ -2131,7 +2161,7 @@ private module AssocFunctionCallMatchingInput implements MatchingInputSig {
21312161
}
21322162
}
21332163

2134-
class Access extends AssocFunctionCallResolution::AssocFunctionCall {
2164+
class Access extends AssocFunctionResolution::AssocFunctionCall {
21352165
pragma[nomagic]
21362166
Type getTypeArgument(TypeArgumentPosition apos, TypePath path) {
21372167
result = getCallExprTypeArgument(this, apos).resolveTypeAt(path)
@@ -2218,7 +2248,7 @@ private module OperationMatchingInput implements MatchingInputSig {
22182248
}
22192249
}
22202250

2221-
class Access extends MethodCallResolution::MethodCallOperation {
2251+
class Access extends MethodResolution::MethodCallOperation {
22222252
Type getTypeArgument(TypeArgumentPosition apos, TypePath path) { none() }
22232253

22242254
pragma[nomagic]
@@ -2247,7 +2277,7 @@ private Type getFieldExprLookupType(FieldExpr fe, string name) {
22472277
exists(TypePath path |
22482278
result = inferType(fe.getContainer(), path) and
22492279
name = fe.getIdentifier().getText() and
2250-
MethodCallResolution::isComplexRootStripped(path, result)
2280+
MethodResolution::isComplexRootStripped(path, result)
22512281
)
22522282
}
22532283

@@ -2885,21 +2915,21 @@ private module Cached {
28852915
/** Holds if `receiver` is the receiver of a method call with an implicit dereference. */
28862916
cached
28872917
predicate receiverHasImplicitDeref(AstNode receiver) {
2888-
any(MethodCallResolution::MethodCall mc).receiverHasImplicitDeref(receiver)
2918+
any(MethodResolution::MethodCall mc).receiverHasImplicitDeref(receiver)
28892919
}
28902920

28912921
/** Holds if `receiver` is the receiver of a method call with an implicit borrow. */
28922922
cached
28932923
predicate receiverHasImplicitBorrow(AstNode receiver) {
2894-
any(MethodCallResolution::MethodCall mc).receiverHasImplicitBorrow(receiver)
2924+
any(MethodResolution::MethodCall mc).receiverHasImplicitBorrow(receiver)
28952925
}
28962926

28972927
/** Gets a function that `call` resolves to, if any. */
28982928
cached
28992929
Function resolveCallTarget(Call call) {
2900-
result = call.(MethodCallResolution::MethodCall).resolveCallTarget(_)
2930+
result = call.(MethodResolution::MethodCall).resolveCallTarget(_)
29012931
or
2902-
result = call.(AssocFunctionCallResolution::AssocFunctionCall).resolveCallTarget()
2932+
result = call.(AssocFunctionResolution::AssocFunctionCall).resolveCallTarget()
29032933
}
29042934

29052935
/**

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +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-
| invalid/main.rs:91:17:91:30 | S1.duplicate() |
98
| main.rs:1821:13:1821:63 | ... .partial_cmp(...) |
109
| main.rs:2336:9:2336:34 | ...::my_from2(...) |
1110
| main.rs:2337:9:2337:33 | ...::my_from2(...) |

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,6 @@ mod impl_specialization {
8888
pub fn test_basic_blanket() {
8989
// this call should target the specialized implementation of Duplicatable for S1,
9090
// not the blanket implementation
91-
let x = S1.duplicate(); // $ target=S1::duplicate $ SPURIOUS: target=Clone1duplicate
91+
let x = S1.duplicate(); // $ target=S1::duplicate
9292
}
9393
}

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

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3697,22 +3697,14 @@ inferType
36973697
| main.rs:1724:13:1727:13 | Vec2 {...} | | main.rs:1604:5:1609:5 | Vec2 |
36983698
| main.rs:1725:20:1725:23 | self | | main.rs:1604:5:1609:5 | Vec2 |
36993699
| main.rs:1725:20:1725:25 | self.x | | {EXTERNAL LOCATION} | i64 |
3700-
| main.rs:1725:20:1725:33 | ... \| ... | | {EXTERNAL LOCATION} | NonZero |
37013700
| main.rs:1725:20:1725:33 | ... \| ... | | {EXTERNAL LOCATION} | i64 |
3702-
| main.rs:1725:20:1725:33 | ... \| ... | T | {EXTERNAL LOCATION} | i64 |
37033701
| main.rs:1725:29:1725:31 | rhs | | main.rs:1604:5:1609:5 | Vec2 |
3704-
| main.rs:1725:29:1725:33 | rhs.x | | {EXTERNAL LOCATION} | NonZero |
37053702
| main.rs:1725:29:1725:33 | rhs.x | | {EXTERNAL LOCATION} | i64 |
3706-
| main.rs:1725:29:1725:33 | rhs.x | T | {EXTERNAL LOCATION} | i64 |
37073703
| main.rs:1726:20:1726:23 | self | | main.rs:1604:5:1609:5 | Vec2 |
37083704
| main.rs:1726:20:1726:25 | self.y | | {EXTERNAL LOCATION} | i64 |
3709-
| main.rs:1726:20:1726:33 | ... \| ... | | {EXTERNAL LOCATION} | NonZero |
37103705
| main.rs:1726:20:1726:33 | ... \| ... | | {EXTERNAL LOCATION} | i64 |
3711-
| main.rs:1726:20:1726:33 | ... \| ... | T | {EXTERNAL LOCATION} | i64 |
37123706
| main.rs:1726:29:1726:31 | rhs | | main.rs:1604:5:1609:5 | Vec2 |
3713-
| main.rs:1726:29:1726:33 | rhs.y | | {EXTERNAL LOCATION} | NonZero |
37143707
| main.rs:1726:29:1726:33 | rhs.y | | {EXTERNAL LOCATION} | i64 |
3715-
| main.rs:1726:29:1726:33 | rhs.y | T | {EXTERNAL LOCATION} | i64 |
37163708
| main.rs:1732:25:1732:33 | SelfParam | | file://:0:0:0:0 | & |
37173709
| main.rs:1732:25:1732:33 | SelfParam | &T | main.rs:1604:5:1609:5 | Vec2 |
37183710
| main.rs:1732:36:1732:38 | rhs | | main.rs:1604:5:1609:5 | Vec2 |
@@ -4058,13 +4050,9 @@ inferType
40584050
| main.rs:1881:26:1881:30 | 33i64 | | {EXTERNAL LOCATION} | i64 |
40594051
| main.rs:1881:26:1881:38 | ... & ... | | {EXTERNAL LOCATION} | i64 |
40604052
| main.rs:1881:34:1881:38 | 34i64 | | {EXTERNAL LOCATION} | i64 |
4061-
| main.rs:1882:13:1882:21 | i64_bitor | | {EXTERNAL LOCATION} | NonZero |
40624053
| main.rs:1882:13:1882:21 | i64_bitor | | {EXTERNAL LOCATION} | i64 |
4063-
| main.rs:1882:13:1882:21 | i64_bitor | T | {EXTERNAL LOCATION} | i64 |
40644054
| main.rs:1882:25:1882:29 | 35i64 | | {EXTERNAL LOCATION} | i64 |
4065-
| main.rs:1882:25:1882:37 | ... \| ... | | {EXTERNAL LOCATION} | NonZero |
40664055
| main.rs:1882:25:1882:37 | ... \| ... | | {EXTERNAL LOCATION} | i64 |
4067-
| main.rs:1882:25:1882:37 | ... \| ... | T | {EXTERNAL LOCATION} | i64 |
40684056
| main.rs:1882:33:1882:37 | 36i64 | | {EXTERNAL LOCATION} | i64 |
40694057
| main.rs:1883:13:1883:22 | i64_bitxor | | {EXTERNAL LOCATION} | i64 |
40704058
| main.rs:1883:26:1883:30 | 37i64 | | {EXTERNAL LOCATION} | i64 |

0 commit comments

Comments
 (0)