Skip to content

Commit 2f0c744

Browse files
committed
wip8
1 parent 2f74251 commit 2f0c744

3 files changed

Lines changed: 134 additions & 111 deletions

File tree

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

Lines changed: 81 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ private newtype TTypeArgumentPosition =
2828
TMethodTypeArgumentPosition(int pos) {
2929
exists(any(MethodCallExpr mce).getGenericArgList().getTypeArg(pos))
3030
} or
31-
TTypeParamTypeArgumentPosition(TypeParam tp)
31+
TTypeParamTypeArgumentPosition(TypeParameter tp)
3232

3333
private module Input1 implements InputSig1<Location> {
3434
private import Type as T
@@ -46,46 +46,35 @@ private module Input1 implements InputSig1<Location> {
4646
class TypeArgumentPosition extends TTypeArgumentPosition {
4747
int asMethodTypeArgumentPosition() { this = TMethodTypeArgumentPosition(result) }
4848

49-
TypeParam asTypeParam() { this = TTypeParamTypeArgumentPosition(result) }
49+
TypeParameter asTypeParameter() { this = TTypeParamTypeArgumentPosition(result) }
50+
51+
TypeParam asTypeParam() {
52+
result = this.asTypeParameter().(TypeParamTypeParameter).getTypeParam()
53+
}
5054

5155
string toString() {
5256
result = this.asMethodTypeArgumentPosition().toString()
5357
or
54-
result = this.asTypeParam().toString()
58+
result = this.asTypeParameter().toString()
5559
}
5660
}
5761

58-
private newtype TTypeParameterPosition =
59-
TTypeParamTypeParameterPosition(TypeParam tp) or
60-
TImplicitTypeParameterPosition()
62+
private newtype TTypeParameterPosition = TTypeParamTypeParameterPosition(TypeParameter tp)
6163

6264
class TypeParameterPosition extends TTypeParameterPosition {
63-
TypeParam asTypeParam() { this = TTypeParamTypeParameterPosition(result) }
64-
65-
/**
66-
* Holds if this is the implicit type parameter position used to represent
67-
* parameters that are never passed explicitly as arguments.
68-
*/
69-
predicate isImplicit() { this = TImplicitTypeParameterPosition() }
65+
TypeParameter asTypeParameter() { this = TTypeParamTypeParameterPosition(result) }
7066

71-
string toString() {
72-
result = this.asTypeParam().toString()
73-
or
74-
result = "Implicit" and this.isImplicit()
67+
TypeParam asTypeParam() {
68+
result = this.asTypeParameter().(TypeParamTypeParameter).getTypeParam()
7569
}
76-
}
7770

78-
/** Holds if `typeParam`, `param` and `ppos` all concern the same `TypeParam`. */
79-
additional predicate typeParamMatchPosition(
80-
TypeParam typeParam, TypeParamTypeParameter param, TypeParameterPosition ppos
81-
) {
82-
typeParam = param.getTypeParam() and typeParam = ppos.asTypeParam()
71+
string toString() { result = this.asTypeParameter().toString() }
8372
}
8473

8574
bindingset[apos]
8675
bindingset[ppos]
8776
predicate typeArgumentParameterPositionMatch(TypeArgumentPosition apos, TypeParameterPosition ppos) {
88-
apos.asTypeParam() = ppos.asTypeParam()
77+
apos.asTypeParameter() = ppos.asTypeParameter()
8978
or
9079
apos.asMethodTypeArgumentPosition() = ppos.asTypeParam().getPosition()
9180
}
@@ -420,8 +409,6 @@ private module Input3 implements InputSig3 {
420409

421410
class CallResolutionContext = FunctionCallMatchingInput::AccessEnvironment;
422411

423-
class TypePosition = FunctionPosition;
424-
425412
class Callable extends FunctionCallMatchingInput::Declaration {
426413
TypeMention getAdditionalTypeParameterConstraint(TypeParameter tp) {
427414
result =
@@ -430,20 +417,39 @@ private module Input3 implements InputSig3 {
430417
.getAdditionalTypeBound(this.getFunction(), _)
431418
.getTypeRepr()
432419
}
420+
421+
Type getParameterType(int j, TypePath path) {
422+
exists(FunctionPosition pos | j = pos.asPosition() | result = this.getDeclaredType(pos, path))
423+
}
424+
425+
Type getReturnType(TypePath path) {
426+
exists(FunctionPosition pos | pos.isReturn() | result = this.getDeclaredType(pos, path))
427+
}
433428
}
434429

435430
class Call extends FunctionCallMatchingInput::Access {
436431
Callable getTarget(string derefChainBorrow) { result = super.getTarget(derefChainBorrow) }
432+
433+
AstNode getArgument(int i) {
434+
exists(FunctionPosition pos |
435+
result = this.getNodeAt(pos) and
436+
i = pos.asPosition()
437+
)
438+
}
437439
}
438440

439441
bindingset[derefChainBorrow]
440-
Type inferCallTypeAtPos(Call call, string derefChainBorrow, FunctionPosition pos, TypePath path) {
441-
result = call.(FunctionCallMatchingInput::Access).getInferredType(derefChainBorrow, pos, path)
442+
Type inferCallArgumentType(Call call, string derefChainBorrow, int i, TypePath path) {
443+
exists(FunctionPosition pos |
444+
i = pos.asPosition() and
445+
result = call.(FunctionCallMatchingInput::Access).getInferredType(derefChainBorrow, pos, path)
446+
)
442447
}
443448

444449
Type inferCallReturnType(AstNode n, TypePath path) {
445450
exists(Call call, TypePath path0 |
446-
result = M3::inferCallReturnType(call, _, n, path0) and
451+
result = M3::inferCallReturnType(call, _, path0) and
452+
n = call and
447453
if
448454
// index expression `x[i]` desugars to `*x.index(i)`, so we must account for
449455
// the implicit deref
@@ -455,7 +461,7 @@ private module Input3 implements InputSig3 {
455461

456462
Type inferCallArgumentType(AstNode n, TypePath path) {
457463
exists(FunctionCallMatchingInput::Access call, FunctionPosition pos |
458-
result = inferCallArgumentType(call, pos, n, _, _, path) and
464+
result = inferCallArgumentType(call, pos.asPosition(), n, _, _, path) and
459465
not call.(AssocFunctionResolution::AssocFunctionCall).hasReceiverAtPos(pos)
460466
)
461467
or
@@ -733,20 +739,22 @@ private class FunctionDeclaration extends Function {
733739
}
734740

735741
TypeParameter getTypeParameter(ImplOrTraitItemNodeOption i, TypeParameterPosition ppos) {
736-
typeParamMatchPosition(this.getTypeParam(i), result, ppos)
737-
or
738-
// For every `TypeParam` of this function, any associated types accessed on
739-
// the type parameter are also type parameters.
740-
ppos.isImplicit() and
741-
result.(TypeParamAssociatedTypeTypeParameter).getTypeParam() = this.getTypeParam(i)
742-
or
743-
i = parent and
742+
result = ppos.asTypeParameter() and
744743
(
745-
ppos.isImplicit() and result = TSelfTypeParameter(i.asSome())
744+
ppos.asTypeParam() = this.getTypeParam(i)
746745
or
747-
ppos.isImplicit() and result.(AssociatedTypeTypeParameter).getTrait() = i.asSome()
746+
// For every `TypeParam` of this function, any associated types accessed on
747+
// the type parameter are also type parameters.
748+
result.(TypeParamAssociatedTypeTypeParameter).getTypeParam() = this.getTypeParam(i)
748749
or
749-
ppos.isImplicit() and this = result.(ImplTraitTypeTypeParameter).getFunction()
750+
i = parent and
751+
(
752+
result = TSelfTypeParameter(i.asSome())
753+
or
754+
result.(AssociatedTypeTypeParameter).getTrait() = i.asSome()
755+
or
756+
this = result.(ImplTraitTypeTypeParameter).getFunction()
757+
)
750758
)
751759
}
752760

@@ -810,27 +818,39 @@ private TypePath getPathToImplSelfTypeParam(TypeParam tp) {
810818

811819
pragma[nomagic]
812820
private Type getCallExprTypeArgument(CallExpr ce, TypeArgumentPosition apos, TypePath path) {
813-
exists(Path p, ItemNode resolved, TypeParam tp |
821+
exists(Path p, ItemNode resolved, TypeParameter tp |
814822
p = CallExprImpl::getFunctionPath(ce) and
815823
resolved = resolvePath(p) and
816-
apos.asTypeParam() = tp
824+
apos.asTypeParameter() = tp
817825
|
818-
// For type parameters of the function we must resolve their
819-
// instantiation from the path. For instance, for `fn bar<A>(a: A) -> A`
820-
// and the path `bar<i64>`, we must resolve `A` to `i64`.
821-
exists(int i |
822-
tp = resolved.getTypeParam(pragma[only_bind_into](i)) and
823-
result = getPathTypeArgument(p, pragma[only_bind_into](i)).getTypeAt(path)
826+
exists(TypeParam param | param = tp.(TypeParamTypeParameter).getTypeParam() |
827+
// For type parameters of the function we must resolve their
828+
// instantiation from the path. For instance, for `fn bar<A>(a: A) -> A`
829+
// and the path `bar<i64>`, we must resolve `A` to `i64`.
830+
exists(int i |
831+
param = resolved.getTypeParam(pragma[only_bind_into](i)) and
832+
result = getPathTypeArgument(p, pragma[only_bind_into](i)).getTypeAt(path)
833+
)
834+
or
835+
// For type parameters of the `impl` block we must resolve their
836+
// instantiation from the path. For instance, for `impl<A> for Foo<A>`
837+
// and the path `Foo<i64>::bar` we must resolve `A` to `i64`.
838+
exists(ImplItemNode impl, TypePath pathToTp |
839+
resolved = impl.getASuccessor(_) and
840+
param = impl.getTypeParam(_) and
841+
pathToTp = getPathToImplSelfTypeParam(param) and
842+
result = p.getQualifier().(TypeMention).getTypeAt(pathToTp.appendInverse(path))
843+
)
824844
)
825845
or
826-
// For type parameters of the `impl` block we must resolve their
827-
// instantiation from the path. For instance, for `impl<A> for Foo<A>`
828-
// and the path `Foo<i64>::bar` we must resolve `A` to `i64`.
829-
exists(ImplItemNode impl, TypePath pathToTp |
830-
resolved = impl.getASuccessor(_) and
831-
tp = impl.getTypeParam(_) and
832-
pathToTp = getPathToImplSelfTypeParam(tp) and
833-
result = p.getQualifier().(TypeMention).getTypeAt(pathToTp.appendInverse(path))
846+
// In calls like `T::default()` where `T` is a type parameter with a `Default` constraint,
847+
// we consider `T` to be an explicit type argument for the implicit `Self` type parameter.
848+
exists(TraitItemNode trait, TypeMention qualifier |
849+
resolved = trait.getASuccessor(_) and
850+
tp = TSelfTypeParameter(trait) and
851+
qualifier = p.getQualifier() and
852+
result = qualifier.(TypeMention).getTypeAt(path) and
853+
not qualifier.(TypeMention).getType() instanceof TraitType
834854
)
835855
)
836856
or
@@ -2833,7 +2853,7 @@ private module FunctionCallMatchingInput implements MatchingWithEnvironmentInput
28332853

28342854
pragma[nomagic]
28352855
private Type inferCallArgumentType(
2836-
FunctionCallMatchingInput::Access call, FunctionPosition pos, AstNode n, DerefChain derefChain,
2856+
FunctionCallMatchingInput::Access call, int pos, AstNode n, DerefChain derefChain,
28372857
BorrowKind borrow, TypePath path
28382858
) {
28392859
exists(string derefChainBorrow |
@@ -2855,7 +2875,7 @@ private Type inferFunctionCallSelfArgumentType(
28552875
) {
28562876
exists(FunctionPosition pos, BorrowKind borrow, TypePath path0 |
28572877
call.(AssocFunctionResolution::AssocFunctionCall).hasReceiverAtPos(pos) and
2858-
result = inferCallArgumentType(call, pos, n, derefChain, borrow, path0)
2878+
result = inferCallArgumentType(call, pos.asPosition(), n, derefChain, borrow, path0)
28592879
|
28602880
borrow.isNoBorrow() and
28612881
path = path0
@@ -2891,7 +2911,8 @@ private Type inferFunctionCallSelfArgumentType(
28912911

28922912
abstract private class Constructor extends Addressable {
28932913
final TypeParameter getTypeParameter(TypeParameterPosition ppos) {
2894-
typeParamMatchPosition(this.getTypeItem().getGenericParamList().getATypeParam(), result, ppos)
2914+
result = ppos.asTypeParameter() and
2915+
ppos.asTypeParam() = this.getTypeItem().getGenericParamList().getATypeParam()
28952916
}
28962917

28972918
abstract TypeItem getTypeItem();

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14223,7 +14223,6 @@ inferType
1422314223
| pattern_matching.rs:809:13:809:17 | stack | T | {EXTERNAL LOCATION} | i32 |
1422414224
| pattern_matching.rs:809:31:809:46 | MacroExpr | | {EXTERNAL LOCATION} | Vec |
1422514225
| pattern_matching.rs:809:31:809:46 | MacroExpr | A | {EXTERNAL LOCATION} | Global |
14226-
| pattern_matching.rs:809:31:809:46 | MacroExpr | T | {EXTERNAL LOCATION} | i32 |
1422714226
| pattern_matching.rs:809:36:809:39 | 1i32 | | {EXTERNAL LOCATION} | i32 |
1422814227
| pattern_matching.rs:809:42:809:42 | 2 | | {EXTERNAL LOCATION} | i32 |
1422914228
| pattern_matching.rs:809:45:809:45 | 3 | | {EXTERNAL LOCATION} | i32 |

0 commit comments

Comments
 (0)