Skip to content

Commit 89c6a6a

Browse files
committed
wip3
1 parent 43c075e commit 89c6a6a

File tree

8 files changed

+104
-119
lines changed

8 files changed

+104
-119
lines changed

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

Lines changed: 58 additions & 62 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
/**
@@ -1492,15 +1484,18 @@ private module MethodResolution {
14921484
)
14931485
}
14941486

1487+
pragma[nomagic]
1488+
private predicate argIsInstanceOf(ImplOrTraitItemNode i) {
1489+
ArgIsInstantiationOf<MethodCallCand, MethodCallReceiverIsInstantiationOfInput>::argIsInstanceOf(this,
1490+
i, _)
1491+
or
1492+
IsInstantiationOf<MethodCallCallExpr, TypeMentionTypeTree, MethodCallCallExprIsInstantiationOfInput>::isInstantiationOf(mc_,
1493+
i, _)
1494+
}
1495+
14951496
pragma[nomagic]
14961497
private predicate argIsInstanceOf(ImplOrTraitItemNode i, string name, int arity) {
1497-
(
1498-
ArgIsInstantiationOf<MethodCallCand, MethodCallReceiverIsInstantiationOfInput>::argIsInstanceOf(this,
1499-
i, _)
1500-
or
1501-
IsInstantiationOf<MethodCallCallExpr, TypeMentionTypeTree, MethodCallCallExprIsInstantiationOfInput>::isInstantiationOf(mc_,
1502-
i, _)
1503-
) and
1498+
this.argIsInstanceOf(i) and
15041499
mc_.hasNameAndArity(name, arity)
15051500
}
15061501

@@ -1553,11 +1548,11 @@ private module MethodResolution {
15531548
{
15541549
pragma[nomagic]
15551550
predicate hasBlanketCandidate(
1556-
MethodCallCand mcc, Function m, TypePath blanketPath, TypeParam blanketTypeParam
1551+
MethodCallCand mcc, ImplItemNode impl, TypePath blanketPath, TypeParam blanketTypeParam
15571552
) {
15581553
exists(MethodCall mc, string name, int arity |
15591554
mcc.hasSignature(mc, _, _, name, arity) and
1560-
methodCallBlanketCandidate(mc, m, _, _, blanketPath, blanketTypeParam) and
1555+
methodCallBlanketCandidate(mc, _, impl, _, blanketPath, blanketTypeParam) and
15611556
// Only apply blanket implementations when no other implementations are possible;
15621557
// this is to account for codebases that use the (unstable) specialization feature
15631558
// (https://rust-lang.github.io/rfcs/1210-impl-specialization.html)
@@ -1587,7 +1582,7 @@ private module MethodResolution {
15871582
or
15881583
methodCallBlanketCandidate(mc, m, i, selfType, _, _) and
15891584
BlanketImplementation::SatisfiesBlanketConstraint<MethodCallCand, SatisfiesBlanketConstraintInput>::satisfiesBlanketConstraint(mcc,
1590-
m)
1585+
i)
15911586
)
15921587
}
15931588

@@ -1634,7 +1629,7 @@ private module MethodResolution {
16341629
then
16351630
// inherent methods take precedence over trait methods, so only allow
16361631
// trait methods when there are no matching inherent methods
1637-
MkMethodCallCand(ce, "").(MethodCallCand).hasNoInherentTarget()
1632+
MkMethodCallCand(ce, ";").(MethodCallCand).hasNoInherentTarget()
16381633
else any()
16391634
}
16401635

@@ -1914,10 +1909,10 @@ private module AssocFunctionResolution {
19141909

19151910
pragma[nomagic]
19161911
private predicate functionCallBlanketCandidate(
1917-
AssocFunctionCall fc, AssocFunction f, FunctionTypePosition pos, TypePath blanketPath,
1918-
TypeParam blanketTypeParam
1912+
AssocFunctionCall fc, AssocFunction f, ImplItemNode impl, FunctionTypePosition pos,
1913+
TypePath blanketPath, TypeParam blanketTypeParam
19191914
) {
1920-
exists(string name, int arity, ImplItemNode impl, Trait trait, FunctionType t |
1915+
exists(string name, int arity, Trait trait, FunctionType t |
19211916
fc.hasNameAndArity(name, arity) and
19221917
exists(getTypeAt(fc, pos, blanketPath)) and
19231918
functionInfoBlanketRelevantPos(f, name, arity, impl, trait, pos, t, blanketPath,
@@ -1928,7 +1923,7 @@ private module AssocFunctionResolution {
19281923

19291924
private newtype TAssocFunctionCallAndPos =
19301925
MkAssocFunctionCallAndPos(AssocFunctionCall fc, FunctionTypePosition pos) {
1931-
functionCallBlanketCandidate(fc, _, pos, _, _)
1926+
functionCallBlanketCandidate(fc, _, _, pos, _, _)
19321927
}
19331928

19341929
class AssocFunctionCallAndPos extends MkAssocFunctionCallAndPos {
@@ -1949,11 +1944,12 @@ private module AssocFunctionResolution {
19491944
{
19501945
pragma[nomagic]
19511946
predicate hasBlanketCandidate(
1952-
AssocFunctionCallAndPos fcp, Function f, TypePath blanketPath, TypeParam blanketTypeParam
1947+
AssocFunctionCallAndPos fcp, ImplItemNode impl, TypePath blanketPath,
1948+
TypeParam blanketTypeParam
19531949
) {
19541950
exists(AssocFunctionCall fc, FunctionTypePosition pos |
19551951
fcp = MkAssocFunctionCallAndPos(fc, pos) and
1956-
functionCallBlanketCandidate(fc, f, pos, blanketPath, blanketTypeParam)
1952+
functionCallBlanketCandidate(fc, _, impl, pos, blanketPath, blanketTypeParam)
19571953
)
19581954
}
19591955
}
@@ -1969,11 +1965,11 @@ private module AssocFunctionResolution {
19691965
predicate potentialInstantiationOf(
19701966
AssocFunctionCallAndPos fcp, TypeAbstraction abs, FunctionType constraint
19711967
) {
1972-
exists(Function f, FunctionTypePosition pos |
1968+
exists(FunctionTypePosition pos |
19731969
BlanketImplementation::SatisfiesBlanketConstraint<AssocFunctionCallAndPos, SatisfiesBlanketConstraintInput>::satisfiesBlanketConstraint(fcp,
1974-
f) and
1970+
abs) and
19751971
fcp = MkAssocFunctionCallAndPos(_, pos) and
1976-
functionInfoBlanketRelevantPos(f, _, _, abs, _, pos, constraint, _, _)
1972+
functionInfoBlanketRelevantPos(_, _, _, abs, _, pos, constraint, _, _)
19771973
)
19781974
}
19791975

@@ -3079,8 +3075,8 @@ module Debug {
30793075
Locatable getRelevantLocatable() {
30803076
exists(string filepath, int startline, int startcolumn, int endline, int endcolumn |
30813077
result.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) and
3082-
filepath.matches("%/sqlx.rs") and
3083-
startline = 246
3078+
filepath.matches("%/main.rs") and
3079+
startline = 570
30843080
)
30853081
}
30863082

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

rust/ql/test/library-tests/dataflow/sources/CONSISTENCY/PathResolutionConsistency.expected

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ multipleCallTargets
1212
| test.rs:179:30:179:68 | ...::_print(...) |
1313
| test.rs:188:26:188:105 | ...::_print(...) |
1414
| test.rs:229:22:229:72 | ... .read_to_string(...) |
15-
| test.rs:385:32:385:88 | ... .split(...) |
16-
| test.rs:394:25:394:38 | reader.lines() |
1715
| test.rs:639:26:639:43 | file1.chain(...) |
1816
| test.rs:640:9:640:42 | reader.read_to_string(...) |
1917
| test.rs:647:26:647:40 | file1.take(...) |
@@ -87,7 +85,3 @@ multipleCallTargets
8785
| test_futures_io.rs:69:23:69:67 | ... .poll_fill_buf(...) |
8886
| test_futures_io.rs:93:26:93:63 | pinned.poll_read(...) |
8987
| test_futures_io.rs:116:22:116:50 | pinned.poll_fill_buf(...) |
90-
| web_frameworks.rs:242:13:247:9 | ... .map(...) |
91-
| web_frameworks.rs:242:13:247:10 | ... .map(...) |
92-
| web_frameworks.rs:272:34:278:15 | ... .map(...) |
93-
| web_frameworks.rs:272:34:279:9 | ... .map(...) |

0 commit comments

Comments
 (0)