Skip to content

Commit b70da1e

Browse files
committed
wip
1 parent b64b04b commit b70da1e

2 files changed

Lines changed: 114 additions & 84 deletions

File tree

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

Lines changed: 101 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -298,14 +298,17 @@ private class FunctionDeclaration extends Function {
298298
}
299299

300300
pragma[nomagic]
301-
Type getParameterType(ImplOrTraitItemNodeOption i, FunctionPosition pos, TypePath path) {
301+
Type getParameterType(ImplOrTraitItemNodeOption i, FunctionPosition posAdj, TypePath path) {
302302
i = parent and
303303
(
304-
not pos.isReturn() and
305-
result = getAssocFunctionTypeAt(this, i.asSome(), pos, path)
304+
exists(FunctionPosition pos |
305+
not pos.isReturn() and
306+
result = getAssocFunctionTypeAt(this, i.asSome(), pos, path) and
307+
posAdj = pos.getFunctionCallAdjusted(this)
308+
)
306309
or
307310
i.isNone() and
308-
result = this.getParam(pos.asPosition()).getTypeRepr().(TypeMention).getTypeAt(path)
311+
result = this.getParam(posAdj.asPosition()).getTypeRepr().(TypeMention).getTypeAt(path)
309312
)
310313
}
311314

@@ -1555,32 +1558,6 @@ private module AssocFunctionResolution {
15551558
AssocFunctionTraitIsVisible::traitIsVisible(afc, impl.resolveTraitTy())
15561559
}
15571560

1558-
private Type getNonTypeParameterTypeQualifier(AssocFunctionCall afc) {
1559-
result = getCallExprTypeQualifier(afc, TypePath::nil(), _) and
1560-
not result instanceof TypeParameter
1561-
}
1562-
1563-
pragma[nomagic]
1564-
private predicate callInfo(
1565-
AssocFunctionCall afc, string name, int arity, TypeOption typeQualifier,
1566-
TypeOption traitQualifier, boolean hasReceiver
1567-
) {
1568-
afc.hasNameAndArity(name, arity) and
1569-
(if afc.hasReceiver() then hasReceiver = true else hasReceiver = false) and
1570-
(
1571-
typeQualifier.asSome() = getNonTypeParameterTypeQualifier(afc)
1572-
or
1573-
not exists(getNonTypeParameterTypeQualifier(afc)) and
1574-
typeQualifier.isNone()
1575-
) and
1576-
(
1577-
traitQualifier.asSome() = TTrait(afc.getATrait())
1578-
or
1579-
not afc.hasATrait() and
1580-
traitQualifier.isNone()
1581-
)
1582-
}
1583-
15841561
bindingset[implType, trait, isMethod]
15851562
private predicate callMatching(
15861563
TypeOption implType, TypeOption trait, boolean isMethod, TypeOption typeQualifier,
@@ -1641,7 +1618,7 @@ private module AssocFunctionResolution {
16411618
string name, int arity, TypeOption typeQualifier, TypeOption traitQualifier,
16421619
boolean hasReceiver
16431620
|
1644-
callInfo(afc, name, arity, typeQualifier, traitQualifier, hasReceiver) and
1621+
afc.hasSyntacticInfo(name, arity, typeQualifier, traitQualifier, hasReceiver) and
16451622
if not afc.hasATrait() and i.(Impl).hasTrait()
16461623
then callVisibleImplTraitCandidate(afc, i)
16471624
else any()
@@ -1686,14 +1663,19 @@ private module AssocFunctionResolution {
16861663
AssocFunctionType self, TypePath blanketPath, TypeParam blanketTypeParam
16871664
) {
16881665
exists(string name, int arity, TypeOption traitQualifier, boolean hasReceiver |
1689-
callInfo(afc, name, arity, _, traitQualifier, hasReceiver) and
1666+
afc.hasSyntacticInfo(name, arity, _, traitQualifier, hasReceiver) and
16901667
assocFunctionSelfInfoBlanketLikeCand(f, name, arity, selfPosAdj, impl, self, blanketPath,
16911668
blanketTypeParam, traitQualifier, hasReceiver)
16921669
|
16931670
if not afc.hasATrait() then callVisibleImplTraitCandidate(afc, impl) else any()
16941671
)
16951672
}
16961673

1674+
private Type getNonTypeParameterTypeQualifier(AssocFunctionCall afc) {
1675+
result = getCallExprTypeQualifier(afc, TypePath::nil(), _) and
1676+
not result instanceof TypeParameter
1677+
}
1678+
16971679
/**
16981680
* A (potential) call to an associated function.
16991681
*
@@ -1746,6 +1728,31 @@ private module AssocFunctionResolution {
17461728

17471729
predicate hasATrait() { exists(this.getATrait()) }
17481730

1731+
/**
1732+
* Holds if this call has the given purely syntactic information, that is,
1733+
* information that does not rely on type inference.
1734+
*/
1735+
pragma[nomagic]
1736+
predicate hasSyntacticInfo(
1737+
string name, int arity, TypeOption typeQualifier, TypeOption traitQualifier,
1738+
boolean hasReceiver
1739+
) {
1740+
this.hasNameAndArity(name, arity) and
1741+
(if this.hasReceiver() then hasReceiver = true else hasReceiver = false) and
1742+
(
1743+
typeQualifier.asSome() = getNonTypeParameterTypeQualifier(this)
1744+
or
1745+
not exists(getNonTypeParameterTypeQualifier(this)) and
1746+
typeQualifier.isNone()
1747+
) and
1748+
(
1749+
traitQualifier.asSome() = TTrait(this.getATrait())
1750+
or
1751+
not this.hasATrait() and
1752+
traitQualifier.isNone()
1753+
)
1754+
}
1755+
17491756
Type getTypeAt(FunctionPosition posAdj, TypePath path) {
17501757
result = inferType(this.getNodeAt(posAdj), path)
17511758
}
@@ -2420,7 +2427,7 @@ private module AssocFunctionResolution {
24202427
or
24212428
selfPosAdj_.asPosition() = 0 and hasReceiver = true
24222429
|
2423-
callInfo(afc_, name, arity, typeQualifier, traitQualifier, _) and
2430+
afc_.hasSyntacticInfo(name, arity, typeQualifier, traitQualifier, _) and
24242431
this.hasSignature(_, selfPosAdj_, strippedTypePath, strippedType, name, arity) and
24252432
forall(Impl i |
24262433
i.isInherent() and
@@ -2718,7 +2725,7 @@ private module AssocFunctionResolution {
27182725

27192726
/**
27202727
* A matching configuration for resolving types of function call expressions
2721-
* like `foo.bar(baz)`.
2728+
* like `foo.bar(baz)` and `Foo::bar(baz)`.
27222729
*/
27232730
private module FunctionCallMatchingInput implements MatchingWithEnvironmentInputSig {
27242731
import FunctionPositionMatchingInput
@@ -2741,10 +2748,10 @@ private module FunctionCallMatchingInput implements MatchingWithEnvironmentInput
27412748
result = f.getTypeParameter(i, ppos)
27422749
}
27432750

2744-
Type getDeclaredType(DeclarationPosition dpos, TypePath path) {
2745-
result = f.getParameterType(i, dpos, path)
2751+
Type getDeclaredType(FunctionPosition posAdj, TypePath path) {
2752+
result = f.getParameterType(i, posAdj, path)
27462753
or
2747-
dpos.isReturn() and
2754+
posAdj.isReturn() and
27482755
result = f.getReturnType(i, path)
27492756
}
27502757

@@ -2816,25 +2823,25 @@ private module FunctionCallMatchingInput implements MatchingWithEnvironmentInput
28162823
}
28172824

28182825
pragma[nomagic]
2819-
private Type getInferredSelfType(FunctionPosition pos, string derefChainBorrow, TypePath path) {
2826+
private Type getInferredSelfType(FunctionPosition posAdj, string derefChainBorrow, TypePath path) {
28202827
exists(DerefChain derefChain, BorrowKind borrow |
2821-
result = super.getSelfTypeAt(pos.getFunctionCallAdjusted(), derefChain, borrow, path) and
2828+
result = super.getSelfTypeAt(posAdj, derefChain, borrow, path) and
28222829
derefChainBorrow = encodeDerefChainBorrow(derefChain, borrow) and
2823-
pos.isSelf()
2830+
super.hasReceiverPos(posAdj)
28242831
)
28252832
}
28262833

28272834
pragma[nomagic]
2828-
private Type getInferredNonSelfType(FunctionPosition pos, TypePath path) {
2829-
result = super.getTypeAt(pos.getFunctionCallAdjusted(), path) and
2830-
not pos.isSelf()
2835+
private Type getInferredNonSelfType(FunctionPosition posAdj, TypePath path) {
2836+
result = super.getTypeAt(posAdj, path) and
2837+
not super.hasReceiverPos(posAdj)
28312838
}
28322839

28332840
bindingset[derefChainBorrow]
2834-
override Type getInferredType(string derefChainBorrow, FunctionPosition pos, TypePath path) {
2835-
result = this.getInferredSelfType(pos, derefChainBorrow, path)
2841+
override Type getInferredType(string derefChainBorrow, FunctionPosition posAdj, TypePath path) {
2842+
result = this.getInferredSelfType(posAdj, derefChainBorrow, path)
28362843
or
2837-
result = this.getInferredNonSelfType(pos, path)
2844+
result = this.getInferredNonSelfType(posAdj, path)
28382845
}
28392846

28402847
Method getTarget(ImplOrTraitItemNode i, string derefChainBorrow) {
@@ -2882,24 +2889,22 @@ private module FunctionCallMatching = MatchingWithEnvironment<FunctionCallMatchi
28822889

28832890
pragma[nomagic]
28842891
private Type inferFunctionCallType0(
2885-
FunctionCallMatchingInput::Access a, FunctionCallMatchingInput::AccessPosition apos, AstNode n,
2886-
DerefChain derefChain, BorrowKind borrow, TypePath path
2892+
FunctionCallMatchingInput::Access a, FunctionPosition posAdj, AstNode n, DerefChain derefChain,
2893+
BorrowKind borrow, TypePath path
28872894
) {
28882895
exists(TypePath path0 |
2889-
exists(FunctionPosition posAdj |
2890-
n = a.getNodeAt(posAdj) and
2891-
posAdj = apos.getFunctionCallAdjusted()
2892-
|
2896+
n = a.getNodeAt(posAdj) and
2897+
(
28932898
exists(string derefChainBorrow |
28942899
FunctionCallMatchingInput::decodeDerefChainBorrow(derefChainBorrow, derefChain, borrow)
28952900
|
2896-
result = FunctionCallMatching::inferAccessType(a, derefChainBorrow, apos, path0)
2901+
result = FunctionCallMatching::inferAccessType(a, derefChainBorrow, posAdj, path0)
28972902
or
2898-
a.hasUnknownTypeAt(derefChainBorrow, apos, path0) and
2903+
a.hasUnknownTypeAt(derefChainBorrow, posAdj, path0) and
28992904
result = TUnknownType()
29002905
)
29012906
or
2902-
a.hasUnknownTypeAt(apos, path0) and
2907+
a.hasUnknownTypeAt(posAdj, path0) and
29032908
result = TUnknownType() and
29042909
derefChain.isEmpty() and
29052910
borrow.isNoBorrow()
@@ -2908,7 +2913,7 @@ private Type inferFunctionCallType0(
29082913
if
29092914
// index expression `x[i]` desugars to `*x.index(i)`, so we must account for
29102915
// the implicit deref
2911-
apos.isReturn() and
2916+
posAdj.isReturn() and
29122917
a instanceof IndexExpr
29132918
then path0.isCons(getRefTypeParameter(_), path)
29142919
else path = path0
@@ -2917,8 +2922,10 @@ private Type inferFunctionCallType0(
29172922

29182923
pragma[nomagic]
29192924
private Type inferFunctionCallTypeNonSelf(AstNode n, FunctionPosition pos, TypePath path) {
2920-
result = inferFunctionCallType0(_, pos, n, _, _, path) and
2921-
not pos.isSelf()
2925+
exists(FunctionCallMatchingInput::Access a |
2926+
result = inferFunctionCallType0(a, pos, n, _, _, path) and
2927+
not a.(AssocFunctionResolution::AssocFunctionCall).hasReceiverPos(pos)
2928+
)
29222929
}
29232930

29242931
/**
@@ -2929,11 +2936,13 @@ private Type inferFunctionCallTypeNonSelf(AstNode n, FunctionPosition pos, TypeP
29292936
* empty, at which point the inferred type can be applied back to `n`.
29302937
*/
29312938
pragma[nomagic]
2932-
private Type inferMethodCallTypeSelf(MethodCall mc, AstNode n, DerefChain derefChain, TypePath path) {
2933-
exists(FunctionCallMatchingInput::AccessPosition apos, BorrowKind borrow, TypePath path0 |
2934-
result = inferFunctionCallType0(mc, apos, n, derefChain, borrow, path0) and
2935-
apos.isSelf()
2939+
private Type inferFunctionCallTypeSelf(
2940+
MethodCall mc, AstNode n, DerefChain derefChain, TypePath path
2941+
) {
2942+
exists(FunctionPosition posAdj, BorrowKind borrow, TypePath path0 |
2943+
result = inferFunctionCallType0(mc, posAdj, n, derefChain, borrow, path0) //and
29362944
|
2945+
posAdj.asPosition() = 0 and
29372946
borrow.isNoBorrow() and
29382947
path = path0
29392948
or
@@ -2949,7 +2958,7 @@ private Type inferMethodCallTypeSelf(MethodCall mc, AstNode n, DerefChain derefC
29492958
DerefChain derefChain0, Type t0, TypePath path0, DerefImplItemNode impl, Type selfParamType,
29502959
TypePath selfPath
29512960
|
2952-
t0 = inferMethodCallTypeSelf(mc, n, derefChain0, path0) and
2961+
t0 = inferFunctionCallTypeSelf(mc, n, derefChain0, path0) and
29532962
derefChain0.isCons(impl, derefChain) and
29542963
selfParamType = impl.resolveSelfTypeAt(selfPath)
29552964
|
@@ -2966,21 +2975,29 @@ private Type inferMethodCallTypeSelf(MethodCall mc, AstNode n, DerefChain derefC
29662975
)
29672976
}
29682977

2969-
private Type inferMethodCallTypePreCheck(AstNode n, FunctionPosition pos, TypePath path) {
2978+
private Type inferFunctionCallTypePreCheck(AstNode n, FunctionPosition pos, TypePath path) {
29702979
result = inferFunctionCallTypeNonSelf(n, pos, path)
29712980
or
2972-
exists(MethodCall mc |
2973-
result = inferMethodCallTypeSelf(mc, n, DerefChain::nil(), path) and
2974-
if mc instanceof CallExpr then pos.asPosition() = 0 else pos.isSelf()
2981+
exists(FunctionCallMatchingInput::Access a |
2982+
result = inferFunctionCallTypeSelf(a, n, DerefChain::nil(), path) and
2983+
if a.(AssocFunctionResolution::AssocFunctionCall).hasReceiver()
2984+
then pos.isSelf()
2985+
else pos.asPosition() = 0
29752986
)
2987+
// result = inferFunctionCallTypeNonSelf(n, pos, path)
2988+
// or
2989+
// exists(MethodCall mc |
2990+
// result = inferMethodCallTypeSelf(mc, n, DerefChain::nil(), path) and
2991+
// if mc instanceof CallExpr then pos.asPosition() = 0 else pos.isSelf()
2992+
// )
29762993
}
29772994

29782995
/**
29792996
* Gets the type of `n` at `path`, where `n` is either a method call or an
29802997
* argument/receiver of a method call.
29812998
*/
2982-
private predicate inferMethodCallType =
2983-
ContextTyping::CheckContextTyping<inferMethodCallTypePreCheck/3>::check/2;
2999+
private predicate inferFunctionCallType =
3000+
ContextTyping::CheckContextTyping<inferFunctionCallTypePreCheck/3>::check/2;
29843001

29853002
abstract private class TupleLikeConstructor extends Addressable {
29863003
final TypeParameter getTypeParameter(TypeParameterPosition ppos) {
@@ -3218,14 +3235,14 @@ private module OperationMatchingInput implements MatchingInputSig {
32183235
}
32193236

32203237
pragma[nomagic]
3221-
private predicate borrowsAt(DeclarationPosition pos) {
3238+
private predicate borrowsAt(FunctionPosition posAdj) {
32223239
exists(TraitItemNode t, string path, string method |
32233240
this.getSelfOrImpl() = t.getAssocItem(method) and
32243241
path = t.getCanonicalPath(_) and
32253242
exists(int borrows | OperationImpl::isOverloaded(_, _, path, method, borrows) |
3226-
pos.isSelf() and borrows >= 1
3243+
posAdj.asPosition() = 0 and borrows >= 1
32273244
or
3228-
pos.asPosition() = 0 and
3245+
posAdj.asPosition() = 1 and
32293246
borrows >= 2
32303247
)
32313248
)
@@ -3234,13 +3251,13 @@ private module OperationMatchingInput implements MatchingInputSig {
32343251
pragma[nomagic]
32353252
private predicate derefsReturn() { this.getSelfOrImpl() = any(DerefTrait t).getDerefFunction() }
32363253

3237-
Type getDeclaredType(DeclarationPosition dpos, TypePath path) {
3254+
Type getDeclaredType(FunctionPosition posAdj, TypePath path) {
32383255
exists(TypePath path0 |
3239-
result = super.getDeclaredType(dpos, path0) and
3256+
result = super.getDeclaredType(posAdj, path0) and
32403257
if
3241-
this.borrowsAt(dpos)
3258+
this.borrowsAt(posAdj)
32423259
or
3243-
dpos.isReturn() and this.derefsReturn()
3260+
posAdj.isReturn() and this.derefsReturn()
32443261
then path0.isCons(getRefTypeParameter(_), path)
32453262
else path0 = path
32463263
)
@@ -3251,8 +3268,8 @@ private module OperationMatchingInput implements MatchingInputSig {
32513268
Type getTypeArgument(TypeArgumentPosition apos, TypePath path) { none() }
32523269

32533270
pragma[nomagic]
3254-
Type getInferredType(FunctionPosition pos, TypePath path) {
3255-
result = inferType(this.getNodeAt(pos.getFunctionCallAdjusted()), path)
3271+
Type getInferredType(FunctionPosition posAdj, TypePath path) {
3272+
result = inferType(this.getNodeAt(posAdj), path)
32563273
}
32573274

32583275
Declaration getTarget() {
@@ -3270,7 +3287,7 @@ private Type inferOperationType0(AstNode n, FunctionPosition pos, TypePath path)
32703287
exists(OperationMatchingInput::Access a, FunctionPosition posAdj |
32713288
n = a.getNodeAt(posAdj) and
32723289
posAdj = pos.getFunctionCallAdjusted() and
3273-
result = OperationMatching::inferAccessType(a, pos, path)
3290+
result = OperationMatching::inferAccessType(a, posAdj, path)
32743291
)
32753292
}
32763293

@@ -4091,7 +4108,7 @@ private module Cached {
40914108
or
40924109
result = inferStructExprType(n, path)
40934110
or
4094-
result = inferMethodCallType(n, path)
4111+
result = inferFunctionCallType(n, path)
40954112
or
40964113
result = inferNonMethodCallType(n, path)
40974114
or
@@ -4134,8 +4151,8 @@ private module Debug {
41344151
Locatable getRelevantLocatable() {
41354152
exists(string filepath, int startline, int startcolumn, int endline, int endcolumn |
41364153
result.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) and
4137-
filepath.matches("%/overloading.rs") and
4138-
startline = 399
4154+
filepath.matches("%/main.rs") and
4155+
startline = 2050
41394156
)
41404157
}
41414158

@@ -4161,9 +4178,9 @@ private module Debug {
41614178
t = self.getTypeAt(path)
41624179
}
41634180

4164-
predicate debugInferMethodCallType(AstNode n, TypePath path, Type t) {
4181+
predicate debugInferFunctionCallType(AstNode n, TypePath path, Type t) {
41654182
n = getRelevantLocatable() and
4166-
t = inferMethodCallType(n, path)
4183+
t = inferFunctionCallType(n, path)
41674184
}
41684185

41694186
predicate debugInferNonMethodCallType(AstNode n, TypePath path, Type t) {

0 commit comments

Comments
 (0)