Skip to content

Commit 0365a0c

Browse files
committed
wip11
1 parent 2041b4a commit 0365a0c

4 files changed

Lines changed: 155 additions & 127 deletions

File tree

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

Lines changed: 74 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -415,15 +415,30 @@ private module Input3 implements InputSig3 {
415415
}
416416

417417
bindingset[derefChainBorrow]
418-
Type inferCallTypeIn(Call call, string derefChainBorrow, FunctionPosition pos, TypePath path) {
418+
Type inferCallTypeBottomUp(Call call, string derefChainBorrow, FunctionPosition pos, TypePath path) {
419419
result = call.(FunctionCallMatchingInput::Access).getInferredType(derefChainBorrow, pos, path)
420420
}
421421

422-
Type inferCallTypeOut(AstNode n, TypePosition pos, TypePath path) {
423-
result = inferFunctionCallTypeNonSelf(n, pos, path)
422+
Type inferCallReturnType(AstNode n, TypePath path) {
423+
exists(Call call, TypePath path0 |
424+
result = inferCallReturnType(call, _, n, path0) and
425+
if
426+
// index expression `x[i]` desugars to `*x.index(i)`, so we must account for
427+
// the implicit deref
428+
call instanceof IndexExpr
429+
then path0.isCons(getRefTypeParameter(_), path)
430+
else path = path0
431+
)
432+
}
433+
434+
Type inferCallArgumentTypeTopDown(AstNode n, TypePath path) {
435+
exists(FunctionCallMatchingInput::Access call, FunctionPosition pos |
436+
result = inferCallArgumentTypeTopDown(call, pos, n, _, _, path) and
437+
not call.(AssocFunctionResolution::AssocFunctionCall).hasReceiverAtPos(pos)
438+
)
424439
or
425440
exists(FunctionCallMatchingInput::Access a |
426-
result = inferFunctionCallTypeSelf(a, n, DerefChain::nil(), path) and
441+
result = inferFunctionCallSelfArgumentTypeTopDown(a, n, DerefChain::nil(), path) and
427442
if a.(AssocFunctionResolution::AssocFunctionCall).hasReceiver()
428443
then not path.isEmpty()
429444
else any()
@@ -459,7 +474,7 @@ private module Input3 implements InputSig3 {
459474
)
460475
}
461476

462-
Type inferTypeCertainInput(AstNode n, TypePath path) {
477+
Type inferTypeCertainSpecific(AstNode n, TypePath path) {
463478
result = inferFunctionBodyType(n, path)
464479
or
465480
result = inferLiteralType(n, path, true)
@@ -580,36 +595,31 @@ private module Input3 implements InputSig3 {
580595
prefix1.isEmpty()
581596
}
582597

583-
/**
584-
* Holds if `child` is a child of `parent`, and the Rust compiler applies [least
585-
* upper bound (LUB) coercion][1] to infer the type of `parent` from the type of
586-
* `child`.
587-
*
588-
* In this case, we want type information to only flow from `child` to `parent`,
589-
* to avoid (a) either having to model LUB coercions, or (b) risk combinatorial
590-
* explosion in inferred types.
591-
*
592-
* [1]: https://doc.rust-lang.org/reference/type-coercions.html#r-coerce.least-upper-bound
593-
*/
594-
predicate inferLubStep(AstNode child, TypePath path1, AstNode parent, TypePath prefix) {
598+
predicate inferLubStep(AstNode n1, TypePath path1, AstNode n2, TypePath path2) {
595599
path1.isEmpty() and
596600
(
597-
parent = any(ArrayListExpr ale | child = ale.getAnExpr()) and
598-
prefix = TypePath::singleton(getArrayTypeParameter())
601+
n2 = any(ArrayListExpr ale | n1 = ale.getAnExpr()) and
602+
path2 = TypePath::singleton(getArrayTypeParameter())
599603
or
600-
bodyReturns(parent, child) and
601-
prefix.isEmpty()
604+
bodyReturns(n2, n1) and
605+
path2.isEmpty()
602606
or
603607
exists(Struct s |
604-
child = [parent.(RangeExpr).getStart(), parent.(RangeExpr).getEnd()] and
605-
prefix =
608+
n1 = [n2.(RangeExpr).getStart(), n2.(RangeExpr).getEnd()] and
609+
path2 =
606610
TypePath::singleton(TTypeParamTypeParameter(s.getGenericParamList().getATypeParam())) and
607-
s = getRangeType(parent)
611+
s = getRangeType(n2)
608612
)
609613
)
610614
}
611615

612-
Type inferTypeInput(AstNode n, TypePath path) {
616+
Type inferTypeTopDown(AstNode n, TypePath path) {
617+
result = inferTypeFromAnnotationTopDown(n, path)
618+
or
619+
result = inferClosureExprBodyTypeTopDown(n, path)
620+
}
621+
622+
Type inferTypeSpecific(AstNode n, TypePath path) {
613623
result = inferAssignmentOperationType(n, path)
614624
or
615625
result = inferConstructionType(n, path)
@@ -634,7 +644,7 @@ private module Input3 implements InputSig3 {
634644
or
635645
result = inferDeconstructionPatType(n, path)
636646
or
637-
result = inferUnknownTypeFromAnnotation(n, path)
647+
result = inferUnknownType(n, path)
638648
}
639649
}
640650

@@ -928,9 +938,6 @@ private Type inferTypeFromAnnotationTopDown(AstNode n, TypePath path) {
928938
)
929939
}
930940

931-
private predicate inferUnknownTypeFromAnnotation =
932-
TopDownTyping<inferTypeFromAnnotationTopDown/2>::inferType/2;
933-
934941
pragma[nomagic]
935942
private TupleType inferTupleRootType(AstNode n) {
936943
// `typeEquality` handles the non-root cases
@@ -2802,36 +2809,13 @@ private module FunctionCallMatchingInput implements MatchingWithEnvironmentInput
28022809
}
28032810

28042811
pragma[nomagic]
2805-
private Type inferFunctionCallType0(
2812+
private Type inferCallArgumentTypeTopDown(
28062813
FunctionCallMatchingInput::Access call, FunctionPosition pos, AstNode n, DerefChain derefChain,
28072814
BorrowKind borrow, TypePath path
28082815
) {
2809-
exists(TypePath path0 |
2810-
exists(string derefChainBorrow |
2811-
FunctionCallMatchingInput::decodeDerefChainBorrow(derefChainBorrow, derefChain, borrow)
2812-
|
2813-
n = call.getNodeAt(pos) and
2814-
call.hasUnknownTypeAt(derefChainBorrow, pos, path0) and
2815-
result = TUnknownType()
2816-
or
2817-
result = inferCallTypeOut(call, derefChainBorrow, pos, n, path0)
2818-
)
2819-
|
2820-
if
2821-
// index expression `x[i]` desugars to `*x.index(i)`, so we must account for
2822-
// the implicit deref
2823-
pos.isReturn() and
2824-
call instanceof IndexExpr
2825-
then path0.isCons(getRefTypeParameter(_), path)
2826-
else path = path0
2827-
)
2828-
}
2829-
2830-
pragma[nomagic]
2831-
private Type inferFunctionCallTypeNonSelf(AstNode n, FunctionPosition pos, TypePath path) {
2832-
exists(FunctionCallMatchingInput::Access call |
2833-
result = inferFunctionCallType0(call, pos, n, _, _, path) and
2834-
not call.(AssocFunctionResolution::AssocFunctionCall).hasReceiverAtPos(pos)
2816+
exists(string derefChainBorrow |
2817+
FunctionCallMatchingInput::decodeDerefChainBorrow(derefChainBorrow, derefChain, borrow) and
2818+
result = inferCallArgumentTypeTopDown(call, derefChainBorrow, pos, n, path)
28352819
)
28362820
}
28372821

@@ -2843,12 +2827,12 @@ private Type inferFunctionCallTypeNonSelf(AstNode n, FunctionPosition pos, TypeP
28432827
* empty, at which point the inferred type can be applied back to `n`.
28442828
*/
28452829
pragma[nomagic]
2846-
private Type inferFunctionCallTypeSelf(
2830+
private Type inferFunctionCallSelfArgumentTypeTopDown(
28472831
FunctionCallMatchingInput::Access call, AstNode n, DerefChain derefChain, TypePath path
28482832
) {
28492833
exists(FunctionPosition pos, BorrowKind borrow, TypePath path0 |
28502834
call.(AssocFunctionResolution::AssocFunctionCall).hasReceiverAtPos(pos) and
2851-
result = inferFunctionCallType0(call, pos, n, derefChain, borrow, path0)
2835+
result = inferCallArgumentTypeTopDown(call, pos, n, derefChain, borrow, path0)
28522836
|
28532837
borrow.isNoBorrow() and
28542838
path = path0
@@ -2865,7 +2849,7 @@ private Type inferFunctionCallTypeSelf(
28652849
DerefChain derefChain0, Type t0, TypePath path0, DerefImplItemNode impl, Type selfParamType,
28662850
TypePath selfPath
28672851
|
2868-
t0 = inferFunctionCallTypeSelf(call, n, derefChain0, path0) and
2852+
t0 = inferFunctionCallSelfArgumentTypeTopDown(call, n, derefChain0, path0) and
28692853
derefChain0.isCons(impl, derefChain) and
28702854
selfParamType = impl.resolveSelfTypeAt(selfPath)
28712855
|
@@ -3041,17 +3025,37 @@ private module ConstructionMatching = Matching<ConstructionMatchingInput>;
30413025

30423026
pragma[nomagic]
30433027
private Type inferConstructionTypePreCheck(AstNode n, FunctionPosition pos, TypePath path) {
3044-
exists(ConstructionMatchingInput::Access a | n = a.getNodeAt(pos) |
3028+
exists(ConstructionMatchingInput::Access a |
3029+
n = a.getNodeAt(pos) and
30453030
result = ConstructionMatching::inferAccessType(a, pos, path)
3046-
or
3047-
a.hasUnknownTypeAt(pos, path) and
3048-
result = TUnknownType()
30493031
)
30503032
}
30513033

30523034
private predicate inferConstructionType =
30533035
CheckContextTyping<inferConstructionTypePreCheck/3>::check/2;
30543036

3037+
pragma[nomagic]
3038+
private Type inferUnknownType(AstNode n, TypePath path) {
3039+
result = TUnknownType() and
3040+
(
3041+
exists(FunctionCallMatchingInput::Access call, FunctionPosition pos |
3042+
n = call.getNodeAt(pos) and
3043+
call.hasUnknownTypeAt(_, pos, path)
3044+
)
3045+
or
3046+
exists(ConstructionMatchingInput::Access a, FunctionPosition pos |
3047+
n = a.getNodeAt(pos) and
3048+
a.hasUnknownTypeAt(pos, path)
3049+
)
3050+
or
3051+
exists(Param p |
3052+
not p.hasTypeRepr() and
3053+
n = p.getPat() and
3054+
path.isEmpty()
3055+
)
3056+
)
3057+
}
3058+
30553059
/**
30563060
* A matching configuration for resolving types of operations like `a + b`.
30573061
*/
@@ -3633,29 +3637,14 @@ private Type inferClosureExprBodyTypeTopDown(AstNode n, TypePath path) {
36333637
}
36343638

36353639
pragma[nomagic]
3636-
private Type inferClosureExprType(AstNode n, TypePath path) {
3637-
exists(ClosureExpr ce |
3638-
n = ce and
3639-
(
3640-
path = TypePath::singleton(TDynTraitTypeParameter(_, any(FnTrait t).getTypeParam())) and
3641-
result.(TupleType).getArity() = ce.getNumberOfParams()
3642-
or
3643-
exists(TypePath path0 |
3644-
result = ce.getRetType().getTypeRepr().(TypeMention).getTypeAt(path0) and
3645-
path = closureReturnPath().append(path0)
3646-
)
3647-
)
3648-
or
3649-
exists(Param p |
3650-
p = ce.getAParam() and
3651-
not p.hasTypeRepr() and
3652-
n = p.getPat() and
3653-
result = TUnknownType() and
3654-
path.isEmpty()
3655-
)
3656-
)
3640+
private Type inferClosureExprType(ClosureExpr ce, TypePath path) {
3641+
path = TypePath::singleton(TDynTraitTypeParameter(_, any(FnTrait t).getTypeParam())) and
3642+
result.(TupleType).getArity() = ce.getNumberOfParams()
36573643
or
3658-
result = TopDownTyping<inferClosureExprBodyTypeTopDown/2>::inferType(n, path)
3644+
exists(TypePath suffix |
3645+
result = ce.getRetType().getTypeRepr().(TypeMention).getTypeAt(suffix) and
3646+
path = closureReturnPath().append(suffix)
3647+
)
36593648
}
36603649

36613650
pragma[nomagic]
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
multipleResolvedTargets
2+
| main.rs:218:20:218:25 | ... != ... |

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

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10250,7 +10250,6 @@ inferType
1025010250
| main.rs:1412:17:1412:20 | self | TRef.TSlice | main.rs:1410:14:1410:23 | T |
1025110251
| main.rs:1412:17:1412:27 | self.get(...) | | {EXTERNAL LOCATION} | Option |
1025210252
| main.rs:1412:17:1412:27 | self.get(...) | T | {EXTERNAL LOCATION} | & |
10253-
| main.rs:1412:17:1412:27 | self.get(...) | T.TRef | main.rs:1410:14:1410:23 | T |
1025410253
| main.rs:1412:17:1412:36 | ... .unwrap() | | {EXTERNAL LOCATION} | & |
1025510254
| main.rs:1412:17:1412:36 | ... .unwrap() | TRef | main.rs:1410:14:1410:23 | T |
1025610255
| main.rs:1412:26:1412:26 | 0 | | {EXTERNAL LOCATION} | i32 |
@@ -11591,8 +11590,6 @@ inferType
1159111590
| main.rs:2221:18:2221:21 | true | | {EXTERNAL LOCATION} | bool |
1159211591
| main.rs:2223:9:2223:15 | S(...) | | main.rs:2107:5:2107:19 | S |
1159311592
| main.rs:2223:9:2223:15 | S(...) | T | {EXTERNAL LOCATION} | i64 |
11594-
| main.rs:2223:9:2223:15 | S(...) | T | main.rs:2107:5:2107:19 | S |
11595-
| main.rs:2223:9:2223:15 | S(...) | T.T | {EXTERNAL LOCATION} | i64 |
1159611593
| main.rs:2223:9:2223:31 | ... .my_add(...) | | main.rs:2107:5:2107:19 | S |
1159711594
| main.rs:2223:9:2223:31 | ... .my_add(...) | T | {EXTERNAL LOCATION} | i64 |
1159811595
| main.rs:2223:9:2223:31 | ... .my_add(...) | T | main.rs:2107:5:2107:19 | S |
@@ -11611,8 +11608,6 @@ inferType
1161111608
| main.rs:2224:24:2224:27 | 3i64 | | {EXTERNAL LOCATION} | i64 |
1161211609
| main.rs:2225:9:2225:15 | S(...) | | main.rs:2107:5:2107:19 | S |
1161311610
| main.rs:2225:9:2225:15 | S(...) | T | {EXTERNAL LOCATION} | i64 |
11614-
| main.rs:2225:9:2225:15 | S(...) | T | {EXTERNAL LOCATION} | & |
11615-
| main.rs:2225:9:2225:15 | S(...) | T.TRef | {EXTERNAL LOCATION} | i64 |
1161611611
| main.rs:2225:9:2225:29 | ... .my_add(...) | | main.rs:2107:5:2107:19 | S |
1161711612
| main.rs:2225:9:2225:29 | ... .my_add(...) | T | {EXTERNAL LOCATION} | i64 |
1161811613
| main.rs:2225:11:2225:14 | 1i64 | | {EXTERNAL LOCATION} | i64 |

0 commit comments

Comments
 (0)