Skip to content

Commit cac880d

Browse files
committed
wip11
1 parent 2041b4a commit cac880d

3 files changed

Lines changed: 153 additions & 122 deletions

File tree

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

Lines changed: 74 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -415,15 +415,27 @@ 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+
result = inferFunctionCallNonSelfArgumentTypeTopDown(n, path)
424436
or
425437
exists(FunctionCallMatchingInput::Access a |
426-
result = inferFunctionCallTypeSelf(a, n, DerefChain::nil(), path) and
438+
result = inferFunctionCallSelfArgumentTypeTopDown(a, n, DerefChain::nil(), path) and
427439
if a.(AssocFunctionResolution::AssocFunctionCall).hasReceiver()
428440
then not path.isEmpty()
429441
else any()
@@ -459,7 +471,7 @@ private module Input3 implements InputSig3 {
459471
)
460472
}
461473

462-
Type inferTypeCertainInput(AstNode n, TypePath path) {
474+
Type inferTypeCertainSpecific(AstNode n, TypePath path) {
463475
result = inferFunctionBodyType(n, path)
464476
or
465477
result = inferLiteralType(n, path, true)
@@ -580,36 +592,31 @@ private module Input3 implements InputSig3 {
580592
prefix1.isEmpty()
581593
}
582594

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) {
595+
predicate inferLubStep(AstNode n1, TypePath path1, AstNode n2, TypePath path2) {
595596
path1.isEmpty() and
596597
(
597-
parent = any(ArrayListExpr ale | child = ale.getAnExpr()) and
598-
prefix = TypePath::singleton(getArrayTypeParameter())
598+
n2 = any(ArrayListExpr ale | n1 = ale.getAnExpr()) and
599+
path2 = TypePath::singleton(getArrayTypeParameter())
599600
or
600-
bodyReturns(parent, child) and
601-
prefix.isEmpty()
601+
bodyReturns(n2, n1) and
602+
path2.isEmpty()
602603
or
603604
exists(Struct s |
604-
child = [parent.(RangeExpr).getStart(), parent.(RangeExpr).getEnd()] and
605-
prefix =
605+
n1 = [n2.(RangeExpr).getStart(), n2.(RangeExpr).getEnd()] and
606+
path2 =
606607
TypePath::singleton(TTypeParamTypeParameter(s.getGenericParamList().getATypeParam())) and
607-
s = getRangeType(parent)
608+
s = getRangeType(n2)
608609
)
609610
)
610611
}
611612

612-
Type inferTypeInput(AstNode n, TypePath path) {
613+
Type inferTypeTopDown(AstNode n, TypePath path) {
614+
result = inferTypeFromAnnotationTopDown(n, path)
615+
or
616+
result = inferClosureExprBodyTypeTopDown(n, path)
617+
}
618+
619+
Type inferTypeSpecific(AstNode n, TypePath path) {
613620
result = inferAssignmentOperationType(n, path)
614621
or
615622
result = inferConstructionType(n, path)
@@ -634,7 +641,7 @@ private module Input3 implements InputSig3 {
634641
or
635642
result = inferDeconstructionPatType(n, path)
636643
or
637-
result = inferUnknownTypeFromAnnotation(n, path)
644+
result = inferUnknownType(n, path)
638645
}
639646
}
640647

@@ -928,9 +935,6 @@ private Type inferTypeFromAnnotationTopDown(AstNode n, TypePath path) {
928935
)
929936
}
930937

931-
private predicate inferUnknownTypeFromAnnotation =
932-
TopDownTyping<inferTypeFromAnnotationTopDown/2>::inferType/2;
933-
934938
pragma[nomagic]
935939
private TupleType inferTupleRootType(AstNode n) {
936940
// `typeEquality` handles the non-root cases
@@ -2802,35 +2806,20 @@ private module FunctionCallMatchingInput implements MatchingWithEnvironmentInput
28022806
}
28032807

28042808
pragma[nomagic]
2805-
private Type inferFunctionCallType0(
2809+
private Type inferCallArgumentTypeTopDown(
28062810
FunctionCallMatchingInput::Access call, FunctionPosition pos, AstNode n, DerefChain derefChain,
28072811
BorrowKind borrow, TypePath path
28082812
) {
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
2813+
exists(string derefChainBorrow |
2814+
FunctionCallMatchingInput::decodeDerefChainBorrow(derefChainBorrow, derefChain, borrow) and
2815+
result = inferCallArgumentTypeTopDown(call, derefChainBorrow, pos, n, path)
28272816
)
28282817
}
28292818

28302819
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
2820+
private Type inferFunctionCallNonSelfArgumentTypeTopDown(AstNode n, TypePath path) {
2821+
exists(FunctionCallMatchingInput::Access call, FunctionPosition pos |
2822+
result = inferCallArgumentTypeTopDown(call, pos, n, _, _, path) and
28342823
not call.(AssocFunctionResolution::AssocFunctionCall).hasReceiverAtPos(pos)
28352824
)
28362825
}
@@ -2843,12 +2832,12 @@ private Type inferFunctionCallTypeNonSelf(AstNode n, FunctionPosition pos, TypeP
28432832
* empty, at which point the inferred type can be applied back to `n`.
28442833
*/
28452834
pragma[nomagic]
2846-
private Type inferFunctionCallTypeSelf(
2835+
private Type inferFunctionCallSelfArgumentTypeTopDown(
28472836
FunctionCallMatchingInput::Access call, AstNode n, DerefChain derefChain, TypePath path
28482837
) {
28492838
exists(FunctionPosition pos, BorrowKind borrow, TypePath path0 |
28502839
call.(AssocFunctionResolution::AssocFunctionCall).hasReceiverAtPos(pos) and
2851-
result = inferFunctionCallType0(call, pos, n, derefChain, borrow, path0)
2840+
result = inferCallArgumentTypeTopDown(call, pos, n, derefChain, borrow, path0)
28522841
|
28532842
borrow.isNoBorrow() and
28542843
path = path0
@@ -2865,7 +2854,7 @@ private Type inferFunctionCallTypeSelf(
28652854
DerefChain derefChain0, Type t0, TypePath path0, DerefImplItemNode impl, Type selfParamType,
28662855
TypePath selfPath
28672856
|
2868-
t0 = inferFunctionCallTypeSelf(call, n, derefChain0, path0) and
2857+
t0 = inferFunctionCallSelfArgumentTypeTopDown(call, n, derefChain0, path0) and
28692858
derefChain0.isCons(impl, derefChain) and
28702859
selfParamType = impl.resolveSelfTypeAt(selfPath)
28712860
|
@@ -3041,17 +3030,37 @@ private module ConstructionMatching = Matching<ConstructionMatchingInput>;
30413030

30423031
pragma[nomagic]
30433032
private Type inferConstructionTypePreCheck(AstNode n, FunctionPosition pos, TypePath path) {
3044-
exists(ConstructionMatchingInput::Access a | n = a.getNodeAt(pos) |
3033+
exists(ConstructionMatchingInput::Access a |
3034+
n = a.getNodeAt(pos) and
30453035
result = ConstructionMatching::inferAccessType(a, pos, path)
3046-
or
3047-
a.hasUnknownTypeAt(pos, path) and
3048-
result = TUnknownType()
30493036
)
30503037
}
30513038

30523039
private predicate inferConstructionType =
30533040
CheckContextTyping<inferConstructionTypePreCheck/3>::check/2;
30543041

3042+
pragma[nomagic]
3043+
private Type inferUnknownType(AstNode n, TypePath path) {
3044+
result = TUnknownType() and
3045+
(
3046+
exists(FunctionCallMatchingInput::Access call, FunctionPosition pos |
3047+
n = call.getNodeAt(pos) and
3048+
call.hasUnknownTypeAt(_, pos, path)
3049+
)
3050+
or
3051+
exists(ConstructionMatchingInput::Access a, FunctionPosition pos |
3052+
n = a.getNodeAt(pos) and
3053+
a.hasUnknownTypeAt(pos, path)
3054+
)
3055+
or
3056+
exists(Param p |
3057+
not p.hasTypeRepr() and
3058+
n = p.getPat() and
3059+
path.isEmpty()
3060+
)
3061+
)
3062+
}
3063+
30553064
/**
30563065
* A matching configuration for resolving types of operations like `a + b`.
30573066
*/
@@ -3633,29 +3642,14 @@ private Type inferClosureExprBodyTypeTopDown(AstNode n, TypePath path) {
36333642
}
36343643

36353644
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-
)
3645+
private Type inferClosureExprType(ClosureExpr ce, TypePath path) {
3646+
path = TypePath::singleton(TDynTraitTypeParameter(_, any(FnTrait t).getTypeParam())) and
3647+
result.(TupleType).getArity() = ce.getNumberOfParams()
36573648
or
3658-
result = TopDownTyping<inferClosureExprBodyTypeTopDown/2>::inferType(n, path)
3649+
exists(TypePath suffix |
3650+
result = ce.getRetType().getTypeRepr().(TypeMention).getTypeAt(suffix) and
3651+
path = closureReturnPath().append(suffix)
3652+
)
36593653
}
36603654

36613655
pragma[nomagic]

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)