Skip to content

Commit 43e48d9

Browse files
committed
wip3
1 parent 43c075e commit 43e48d9

File tree

9 files changed

+118
-92
lines changed

9 files changed

+118
-92
lines changed

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

Lines changed: 72 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -838,10 +838,13 @@ private predicate functionInfoBlanket(
838838
Function f, string name, int arity, ImplItemNode impl, Trait trait, FunctionTypePosition pos,
839839
FunctionType t, TypePath blanketPath, TypeParam blanketTypeParam
840840
) {
841-
functionInfo(f, name, arity, impl, pos, t) and
842-
TTypeParamTypeParameter(blanketTypeParam) = t.getTypeAt(blanketPath) and
843-
MethodResolution::isBlanketLike(impl, blanketTypeParam) and
844-
trait = impl.resolveTraitTy()
841+
exists(TypePath path0 |
842+
functionInfo(f, name, arity, impl, pos, t) and
843+
TTypeParamTypeParameter(blanketTypeParam) = t.getTypeAt(blanketPath) and
844+
blanketPath = any(string s) + path0 and
845+
BlanketImplementation::isBlanket(impl, path0, blanketTypeParam) and
846+
trait = impl.resolveTraitTy()
847+
)
845848
}
846849

847850
/**
@@ -881,6 +884,30 @@ private module ArgIsInstantiationOf<
881884
}
882885
}
883886

887+
/**
888+
* Holds if `root` is a valid complex [`self` root type][1], with type
889+
* parameter `tp`.
890+
*
891+
* [1]: https://doc.rust-lang.org/stable/reference/items/associated-items.html?highlight=self#r-items.associated.fn.method.self-ty
892+
*/
893+
pragma[nomagic]
894+
predicate complexSelfRoot(Type root, TypeParameter tp) {
895+
tp = root.(RefType).getPositionalTypeParameter(_)
896+
or
897+
exists(Struct s |
898+
root = TStruct(s) and
899+
tp = root.getPositionalTypeParameter(0)
900+
|
901+
s instanceof BoxStruct
902+
or
903+
s instanceof RcStruct
904+
or
905+
s instanceof ArcStruct
906+
or
907+
s instanceof PinStruct
908+
)
909+
}
910+
884911
/**
885912
* Provides logic for resolving calls to methods.
886913
*
@@ -916,30 +943,6 @@ private module ArgIsInstantiationOf<
916943
* [1]: https://doc.rust-lang.org/reference/expressions/method-call-expr.html#r-expr.method.candidate-receivers
917944
*/
918945
private module MethodResolution {
919-
/**
920-
* Holds if `root` is a valid complex [`self` root type][1], with type
921-
* parameter `tp`.
922-
*
923-
* [1]: https://doc.rust-lang.org/stable/reference/items/associated-items.html?highlight=self#r-items.associated.fn.method.self-ty
924-
*/
925-
pragma[nomagic]
926-
private predicate complexSelfRoot(Type root, TypeParameter tp) {
927-
tp = root.(RefType).getPositionalTypeParameter(_)
928-
or
929-
exists(Struct s |
930-
root = TStruct(s) and
931-
tp = root.getPositionalTypeParameter(0)
932-
|
933-
s instanceof BoxStruct
934-
or
935-
s instanceof RcStruct
936-
or
937-
s instanceof ArcStruct
938-
or
939-
s instanceof PinStruct
940-
)
941-
}
942-
943946
/**
944947
* Holds if the type path `path` pointing to `type` is stripped of any leading
945948
* complex root type allowed for `self` parameters, such as `&`, `Box`, `Rc`,
@@ -991,17 +994,6 @@ private module MethodResolution {
991994
methodInfo(m, name, arity, i, selfType, strippedTypePath, TTypeParamTypeParameter(tp))
992995
}
993996

994-
predicate isBlanketLike(ImplItemNode i, TypeParam tp) {
995-
tp = i.getBlanketImplementationTypeParam()
996-
// or
997-
// exists(TypeMention tm, Type root, TypeParameter tp0 |
998-
// tm = i.(Impl).getSelfTy() and
999-
// complexSelfRoot(root, tp0) and
1000-
// tm.resolveType() = root and
1001-
// tm.resolveTypeAt(TypePath::singleton(tp0)) = TTypeParamTypeParameter(tp)
1002-
// )
1003-
}
1004-
1005997
/**
1006998
* Same as `methodInfo`, but restricted to non-blanket implementations, and
1007999
* allowing for any `strippedType` when the corresponding type inside `m` is
@@ -1016,7 +1008,7 @@ private module MethodResolution {
10161008
methodInfo(m, name, arity, i, selfType, strippedTypePath, strippedType) or
10171009
methodInfoTypeParam(m, name, arity, i, selfType, strippedTypePath, _)
10181010
) and
1019-
not isBlanketLike(i, _)
1011+
not BlanketImplementation::isBlanket(i, _, _)
10201012
}
10211013

10221014
/**
@@ -1242,7 +1234,7 @@ private module MethodResolution {
12421234
forall(ImplOrTraitItemNode i |
12431235
methodCallNonBlanketCandidate(this, _, i, _, strippedTypePath, strippedType)
12441236
or
1245-
CallExprImpl::getResolvedFunction(this) = i.(ImplItemNode).getASuccessor(_)
1237+
this.(MethodCallCallExpr).hasTypeQualifiedCandidate(i)
12461238
|
12471239
this.hasIncompatibleTarget(i, derefChainBorrow)
12481240
)
@@ -1265,7 +1257,7 @@ private module MethodResolution {
12651257
forall(ImplOrTraitItemNode i |
12661258
methodCallNonBlanketCandidate(this, _, i, _, strippedTypePath, strippedType)
12671259
or
1268-
CallExprImpl::getResolvedFunction(this) = i.(ImplItemNode).getASuccessor(_)
1260+
this.(MethodCallCallExpr).hasTypeQualifiedCandidate(i)
12691261
|
12701262
this.hasIncompatibleTarget(i, derefChainBorrow)
12711263
)
@@ -1371,6 +1363,20 @@ private module MethodResolution {
13711363
forall(ItemNode i | i = CallExprImpl::getResolvedFunction(this) | i instanceof Method)
13721364
}
13731365

1366+
/**
1367+
* Holds if this call has a type qualifier, and we are able to resolve,
1368+
* using path resolution, the function to a member of `impl`.
1369+
*
1370+
* When this is the case, we still want to check that the type qualifier
1371+
* is an instance of the type being implemented, which is done in
1372+
* `MethodCallCallExprIsInstantiationOfInput`.
1373+
*/
1374+
pragma[nomagic]
1375+
predicate hasTypeQualifiedCandidate(ImplItemNode impl) {
1376+
exists(getCallExprTypeQualifier(this, _)) and
1377+
CallExprImpl::getResolvedFunction(this) = impl.getASuccessor(_)
1378+
}
1379+
13741380
pragma[nomagic]
13751381
override predicate hasNameAndArity(string name, int arity) {
13761382
name = CallExprImpl::getFunctionPath(this).getText() and
@@ -1492,14 +1498,19 @@ private module MethodResolution {
14921498
)
14931499
}
14941500

1501+
pragma[nomagic]
1502+
private predicate argIsInstanceOf(ImplOrTraitItemNode i) {
1503+
IsInstantiationOf<MethodCallCallExpr, TypeMentionTypeTree, MethodCallCallExprIsInstantiationOfInput>::isInstantiationOf(mc_,
1504+
i, _)
1505+
}
1506+
14951507
pragma[nomagic]
14961508
private predicate argIsInstanceOf(ImplOrTraitItemNode i, string name, int arity) {
14971509
(
14981510
ArgIsInstantiationOf<MethodCallCand, MethodCallReceiverIsInstantiationOfInput>::argIsInstanceOf(this,
14991511
i, _)
15001512
or
1501-
IsInstantiationOf<MethodCallCallExpr, TypeMentionTypeTree, MethodCallCallExprIsInstantiationOfInput>::isInstantiationOf(mc_,
1502-
i, _)
1513+
this.argIsInstanceOf(i)
15031514
) and
15041515
mc_.hasNameAndArity(name, arity)
15051516
}
@@ -1553,11 +1564,11 @@ private module MethodResolution {
15531564
{
15541565
pragma[nomagic]
15551566
predicate hasBlanketCandidate(
1556-
MethodCallCand mcc, Function m, TypePath blanketPath, TypeParam blanketTypeParam
1567+
MethodCallCand mcc, ImplItemNode impl, TypePath blanketPath, TypeParam blanketTypeParam
15571568
) {
15581569
exists(MethodCall mc, string name, int arity |
15591570
mcc.hasSignature(mc, _, _, name, arity) and
1560-
methodCallBlanketCandidate(mc, m, _, _, blanketPath, blanketTypeParam) and
1571+
methodCallBlanketCandidate(mc, _, impl, _, blanketPath, blanketTypeParam) and
15611572
// Only apply blanket implementations when no other implementations are possible;
15621573
// this is to account for codebases that use the (unstable) specialization feature
15631574
// (https://rust-lang.github.io/rfcs/1210-impl-specialization.html)
@@ -1587,7 +1598,7 @@ private module MethodResolution {
15871598
or
15881599
methodCallBlanketCandidate(mc, m, i, selfType, _, _) and
15891600
BlanketImplementation::SatisfiesBlanketConstraint<MethodCallCand, SatisfiesBlanketConstraintInput>::satisfiesBlanketConstraint(mcc,
1590-
m)
1601+
i)
15911602
)
15921603
}
15931604

@@ -1620,8 +1631,7 @@ private module MethodResolution {
16201631
private predicate potentialInstantiationOf0(
16211632
MethodCallCallExpr ce, ImplItemNode impl, TypeMentionTypeTree constraint
16221633
) {
1623-
exists(getCallExprTypeQualifier(ce, _)) and
1624-
CallExprImpl::getResolvedFunction(ce) = impl.getASuccessor(_) and
1634+
ce.hasTypeQualifiedCandidate(impl) and
16251635
constraint = impl.getSelfPath()
16261636
}
16271637

@@ -1634,7 +1644,7 @@ private module MethodResolution {
16341644
then
16351645
// inherent methods take precedence over trait methods, so only allow
16361646
// trait methods when there are no matching inherent methods
1637-
MkMethodCallCand(ce, "").(MethodCallCand).hasNoInherentTarget()
1647+
MkMethodCallCand(ce, _).(MethodCallCand).hasNoInherentTarget()
16381648
else any()
16391649
}
16401650

@@ -1914,10 +1924,10 @@ private module AssocFunctionResolution {
19141924

19151925
pragma[nomagic]
19161926
private predicate functionCallBlanketCandidate(
1917-
AssocFunctionCall fc, AssocFunction f, FunctionTypePosition pos, TypePath blanketPath,
1918-
TypeParam blanketTypeParam
1927+
AssocFunctionCall fc, AssocFunction f, ImplItemNode impl, FunctionTypePosition pos,
1928+
TypePath blanketPath, TypeParam blanketTypeParam
19191929
) {
1920-
exists(string name, int arity, ImplItemNode impl, Trait trait, FunctionType t |
1930+
exists(string name, int arity, Trait trait, FunctionType t |
19211931
fc.hasNameAndArity(name, arity) and
19221932
exists(getTypeAt(fc, pos, blanketPath)) and
19231933
functionInfoBlanketRelevantPos(f, name, arity, impl, trait, pos, t, blanketPath,
@@ -1928,7 +1938,7 @@ private module AssocFunctionResolution {
19281938

19291939
private newtype TAssocFunctionCallAndPos =
19301940
MkAssocFunctionCallAndPos(AssocFunctionCall fc, FunctionTypePosition pos) {
1931-
functionCallBlanketCandidate(fc, _, pos, _, _)
1941+
functionCallBlanketCandidate(fc, _, _, pos, _, _)
19321942
}
19331943

19341944
class AssocFunctionCallAndPos extends MkAssocFunctionCallAndPos {
@@ -1949,11 +1959,12 @@ private module AssocFunctionResolution {
19491959
{
19501960
pragma[nomagic]
19511961
predicate hasBlanketCandidate(
1952-
AssocFunctionCallAndPos fcp, Function f, TypePath blanketPath, TypeParam blanketTypeParam
1962+
AssocFunctionCallAndPos fcp, ImplItemNode impl, TypePath blanketPath,
1963+
TypeParam blanketTypeParam
19531964
) {
19541965
exists(AssocFunctionCall fc, FunctionTypePosition pos |
19551966
fcp = MkAssocFunctionCallAndPos(fc, pos) and
1956-
functionCallBlanketCandidate(fc, f, pos, blanketPath, blanketTypeParam)
1967+
functionCallBlanketCandidate(fc, _, impl, pos, blanketPath, blanketTypeParam)
19571968
)
19581969
}
19591970
}
@@ -1969,11 +1980,11 @@ private module AssocFunctionResolution {
19691980
predicate potentialInstantiationOf(
19701981
AssocFunctionCallAndPos fcp, TypeAbstraction abs, FunctionType constraint
19711982
) {
1972-
exists(Function f, FunctionTypePosition pos |
1983+
exists(FunctionTypePosition pos |
19731984
BlanketImplementation::SatisfiesBlanketConstraint<AssocFunctionCallAndPos, SatisfiesBlanketConstraintInput>::satisfiesBlanketConstraint(fcp,
1974-
f) and
1985+
abs) and
19751986
fcp = MkAssocFunctionCallAndPos(_, pos) and
1976-
functionInfoBlanketRelevantPos(f, _, _, abs, _, pos, constraint, _, _)
1987+
functionInfoBlanketRelevantPos(_, _, _, abs, _, pos, constraint, _, _)
19771988
)
19781989
}
19791990

@@ -3079,8 +3090,8 @@ module Debug {
30793090
Locatable getRelevantLocatable() {
30803091
exists(string filepath, int startline, int startcolumn, int endline, int endcolumn |
30813092
result.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) and
3082-
filepath.matches("%/sqlx.rs") and
3083-
startline = 246
3093+
filepath.matches("%/test_futures_io.rs") and
3094+
startline = 45
30843095
)
30853096
}
30863097

rust/ql/lib/codeql/rust/internal/typeinference/BlanketImplementation.qll

Lines changed: 44 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,28 @@
88
private import rust
99
private import codeql.rust.internal.PathResolution
1010
private import codeql.rust.internal.Type
11+
private import codeql.rust.internal.TypeMention
1112
private import codeql.rust.internal.TypeInference
1213

14+
pragma[nomagic]
15+
private predicate isBlanketLike(ImplItemNode i, TypePath path, TypeParam tp) {
16+
exists(TypeMention tm, Type root, TypeParameter tp0 |
17+
tm = i.(Impl).getSelfTy() and
18+
complexSelfRoot(root, tp0) and
19+
tm.resolveType() = root and
20+
tm.resolveTypeAt(path) = TTypeParamTypeParameter(tp) and
21+
path = TypePath::singleton(tp0) and
22+
hasFirstNonTrivialTraitBound(tp, _)
23+
)
24+
}
25+
26+
predicate isBlanket(ImplItemNode i, TypePath path, TypeParam tp) {
27+
tp = i.getBlanketImplementationTypeParam() and
28+
path.isEmpty()
29+
or
30+
isBlanketLike(i, path, tp)
31+
}
32+
1333
/**
1434
* Holds if `tp` is the type parameter of a blanket implementation and
1535
* `traitBound` is the first non-trivial trait bound of `tp`.
@@ -33,24 +53,30 @@ private predicate hasFirstNonTrivialTraitBound(TypeParamItemNode tp, Trait trait
3353

3454
signature module SatisfiesBlanketConstraintInputSig<HasTypeTreeSig ArgumentType> {
3555
/**
36-
* Holds if a call with argument type `at` may potentially target `f`, which
37-
* is defined in a blanket implementation with type parameter `blanketTypeParam`.
56+
* Holds if a call with argument type `at` may potentially target a function belonging
57+
* to blanket implementation `impl` with type parameter `blanketTypeParam`.
3858
*
39-
* `blanketPath` points to the type `blanketTypeParam` inside the type of
40-
* `f`'s parameter at the matching position.
59+
* `blanketPath` points to the type `blanketTypeParam` inside the type of the parameter
60+
* at the matching position.
4161
*/
4262
predicate hasBlanketCandidate(
43-
ArgumentType at, Function f, TypePath blanketPath, TypeParam blanketTypeParam
63+
ArgumentType at, ImplItemNode impl, TypePath blanketPath, TypeParam blanketTypeParam
4464
);
4565
}
4666

4767
module SatisfiesBlanketConstraint<
4868
HasTypeTreeSig ArgumentType, SatisfiesBlanketConstraintInputSig<ArgumentType> Input>
4969
{
70+
private predicate hasBlanketCandidate(
71+
ArgumentType at, ImplItemNode impl, TypePath blanketPath, TypeParam blanketTypeParam
72+
) {
73+
Input::hasBlanketCandidate(at, impl, blanketPath, blanketTypeParam) and
74+
exists(at.getTypeAt(blanketPath))
75+
}
76+
5077
private newtype TArgumentTypeAndBlanketOffset =
5178
MkArgumentTypeAndBlanketOffset(ArgumentType at, TypePath blanketPath) {
52-
Input::hasBlanketCandidate(at, _, blanketPath, _) and
53-
exists(at.getTypeAt(blanketPath))
79+
hasBlanketCandidate(at, _, blanketPath, _)
5480
}
5581

5682
private class ArgumentTypeAndBlanketOffset extends MkArgumentTypeAndBlanketOffset {
@@ -71,11 +97,11 @@ module SatisfiesBlanketConstraint<
7197
{
7298
pragma[nomagic]
7399
additional predicate relevantConstraint(
74-
ArgumentTypeAndBlanketOffset ato, Function f, Trait traitBound
100+
ArgumentTypeAndBlanketOffset ato, ImplItemNode impl, Trait traitBound
75101
) {
76102
exists(ArgumentType at, TypePath blanketPath, TypeParam blanketTypeParam |
77103
ato = MkArgumentTypeAndBlanketOffset(at, blanketPath) and
78-
Input::hasBlanketCandidate(at, f, blanketPath, blanketTypeParam) and
104+
hasBlanketCandidate(at, impl, blanketPath, blanketTypeParam) and
79105
hasFirstNonTrivialTraitBound(blanketTypeParam, traitBound)
80106
)
81107
}
@@ -90,21 +116,21 @@ module SatisfiesBlanketConstraint<
90116

91117
/**
92118
* Holds if the argument type `at` satisfies the first non-trivial blanket
93-
* constraint of the function `f`, if such a constraint exists.
119+
* constraint of `impl`, if such a constraint exists.
94120
*/
95121
pragma[nomagic]
96-
predicate satisfiesBlanketConstraint(ArgumentType at, Function f) {
122+
predicate satisfiesBlanketConstraint(ArgumentType at, ImplItemNode impl) {
97123
exists(ArgumentTypeAndBlanketOffset ato, Trait traitBound |
98124
ato = MkArgumentTypeAndBlanketOffset(at, _) and
99-
SatisfiesBlanketConstraintInput::relevantConstraint(ato, f, traitBound) and
125+
SatisfiesBlanketConstraintInput::relevantConstraint(ato, impl, traitBound) and
100126
SatisfiesConstraint<ArgumentTypeAndBlanketOffset, SatisfiesBlanketConstraintInput>::satisfiesConstraintType(ato,
101127
TTrait(traitBound), _, _)
102128
)
103-
or
104-
exists(TypePath blanketPath, TypeParam blanketTypeParam |
105-
Input::hasBlanketCandidate(at, f, blanketPath, blanketTypeParam) and
106-
exists(at.getTypeAt(blanketPath)) and
107-
not hasFirstNonTrivialTraitBound(blanketTypeParam, _)
108-
)
129+
// or
130+
// exists(TypePath blanketPath, TypeParam blanketTypeParam |
131+
// isBlanketLike(impl, _, blanketTypeParam) and
132+
// hasBlanketCandidate(at, impl, blanketPath, blanketTypeParam) and
133+
// not hasFirstNonTrivialTraitBound(blanketTypeParam, _)
134+
// )
109135
}
110136
}
Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,2 @@
11
multipleCallTargets
2-
| main.rs:349:14:349:33 | ... .cmp(...) |
3-
| main.rs:361:9:361:28 | ... .cmp(...) |
42
| main.rs:389:14:389:30 | ... .lt(...) |

0 commit comments

Comments
 (0)