Skip to content

Commit 2522d9a

Browse files
committed
wip3
1 parent 43c075e commit 2522d9a

File tree

3 files changed

+97
-77
lines changed

3 files changed

+97
-77
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: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,27 @@
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)
22+
)
23+
}
24+
25+
predicate isBlanket(ImplItemNode i, TypePath path, TypeParam tp) {
26+
tp = i.getBlanketImplementationTypeParam() and
27+
path.isEmpty()
28+
or
29+
isBlanketLike(i, path, tp)
30+
}
31+
1332
/**
1433
* Holds if `tp` is the type parameter of a blanket implementation and
1534
* `traitBound` is the first non-trivial trait bound of `tp`.
@@ -33,24 +52,30 @@ private predicate hasFirstNonTrivialTraitBound(TypeParamItemNode tp, Trait trait
3352

3453
signature module SatisfiesBlanketConstraintInputSig<HasTypeTreeSig ArgumentType> {
3554
/**
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`.
55+
* Holds if a call with argument type `at` may potentially target a function belonging
56+
* to blanket implementation `impl` with type parameter `blanketTypeParam`.
3857
*
39-
* `blanketPath` points to the type `blanketTypeParam` inside the type of
40-
* `f`'s parameter at the matching position.
58+
* `blanketPath` points to the type `blanketTypeParam` inside the type of the parameter
59+
* at the matching position.
4160
*/
4261
predicate hasBlanketCandidate(
43-
ArgumentType at, Function f, TypePath blanketPath, TypeParam blanketTypeParam
62+
ArgumentType at, ImplItemNode impl, TypePath blanketPath, TypeParam blanketTypeParam
4463
);
4564
}
4665

4766
module SatisfiesBlanketConstraint<
4867
HasTypeTreeSig ArgumentType, SatisfiesBlanketConstraintInputSig<ArgumentType> Input>
4968
{
69+
private predicate hasBlanketCandidate(
70+
ArgumentType at, ImplItemNode impl, TypePath blanketPath, TypeParam blanketTypeParam
71+
) {
72+
Input::hasBlanketCandidate(at, impl, blanketPath, blanketTypeParam) and
73+
exists(at.getTypeAt(blanketPath))
74+
}
75+
5076
private newtype TArgumentTypeAndBlanketOffset =
5177
MkArgumentTypeAndBlanketOffset(ArgumentType at, TypePath blanketPath) {
52-
Input::hasBlanketCandidate(at, _, blanketPath, _) and
53-
exists(at.getTypeAt(blanketPath))
78+
hasBlanketCandidate(at, _, blanketPath, _)
5479
}
5580

5681
private class ArgumentTypeAndBlanketOffset extends MkArgumentTypeAndBlanketOffset {
@@ -71,11 +96,11 @@ module SatisfiesBlanketConstraint<
7196
{
7297
pragma[nomagic]
7398
additional predicate relevantConstraint(
74-
ArgumentTypeAndBlanketOffset ato, Function f, Trait traitBound
99+
ArgumentTypeAndBlanketOffset ato, ImplItemNode impl, Trait traitBound
75100
) {
76101
exists(ArgumentType at, TypePath blanketPath, TypeParam blanketTypeParam |
77102
ato = MkArgumentTypeAndBlanketOffset(at, blanketPath) and
78-
Input::hasBlanketCandidate(at, f, blanketPath, blanketTypeParam) and
103+
hasBlanketCandidate(at, impl, blanketPath, blanketTypeParam) and
79104
hasFirstNonTrivialTraitBound(blanketTypeParam, traitBound)
80105
)
81106
}
@@ -90,20 +115,20 @@ module SatisfiesBlanketConstraint<
90115

91116
/**
92117
* Holds if the argument type `at` satisfies the first non-trivial blanket
93-
* constraint of the function `f`, if such a constraint exists.
118+
* constraint of `impl`, if such a constraint exists.
94119
*/
95120
pragma[nomagic]
96-
predicate satisfiesBlanketConstraint(ArgumentType at, Function f) {
121+
predicate satisfiesBlanketConstraint(ArgumentType at, ImplItemNode impl) {
97122
exists(ArgumentTypeAndBlanketOffset ato, Trait traitBound |
98123
ato = MkArgumentTypeAndBlanketOffset(at, _) and
99-
SatisfiesBlanketConstraintInput::relevantConstraint(ato, f, traitBound) and
124+
SatisfiesBlanketConstraintInput::relevantConstraint(ato, impl, traitBound) and
100125
SatisfiesConstraint<ArgumentTypeAndBlanketOffset, SatisfiesBlanketConstraintInput>::satisfiesConstraintType(ato,
101126
TTrait(traitBound), _, _)
102127
)
103128
or
104129
exists(TypePath blanketPath, TypeParam blanketTypeParam |
105-
Input::hasBlanketCandidate(at, f, blanketPath, blanketTypeParam) and
106-
exists(at.getTypeAt(blanketPath)) and
130+
isBlanketLike(impl, _, blanketTypeParam) and
131+
hasBlanketCandidate(at, impl, blanketPath, blanketTypeParam) and
107132
not hasFirstNonTrivialTraitBound(blanketTypeParam, _)
108133
)
109134
}

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7102,4 +7102,3 @@ inferType
71027102
| pattern_matching.rs:827:5:827:7 | f(...) | | {EXTERNAL LOCATION} | Option |
71037103
| pattern_matching.rs:827:5:827:7 | f(...) | T | file://:0:0:0:0 | () |
71047104
testFailures
7105-
| main.rs:2566:20:2566:32 | ... .into() | Fixed missing result: target=into |

0 commit comments

Comments
 (0)