Skip to content

Commit 214079f

Browse files
committed
Rust: Simple type inference for index expressions
1 parent 8fe2699 commit 214079f

File tree

3 files changed

+92
-5
lines changed

3 files changed

+92
-5
lines changed

rust/ql/lib/codeql/rust/internal/Type.qll

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,13 @@ newtype TType =
1515
TTrait(Trait t) or
1616
TArrayType() or // todo: add size?
1717
TRefType() or // todo: add mut?
18+
TSliceType() or
1819
TTypeParamTypeParameter(TypeParam t) or
1920
TAssociatedTypeTypeParameter(TypeAlias t) { any(TraitItemNode trait).getAnAssocItem() = t } or
21+
TArrayTypeParameter() or
2022
TRefTypeParameter() or
21-
TSelfTypeParameter(Trait t)
23+
TSelfTypeParameter(Trait t) or
24+
TSliceTypeParameter()
2225

2326
/**
2427
* A type without type arguments.
@@ -145,7 +148,8 @@ class ArrayType extends Type, TArrayType {
145148
override TupleField getTupleField(int i) { none() }
146149

147150
override TypeParameter getTypeParameter(int i) {
148-
none() // todo
151+
result = TArrayTypeParameter() and
152+
i = 0
149153
}
150154

151155
override string toString() { result = "[]" }
@@ -176,6 +180,29 @@ class RefType extends Type, TRefType {
176180
override Location getLocation() { result instanceof EmptyLocation }
177181
}
178182

183+
/**
184+
* A slice type.
185+
*
186+
* Slice types like `[i64]` are modeled as normal generic types
187+
* with a single type argument.
188+
*/
189+
class SliceType extends Type, TSliceType {
190+
SliceType() { this = TSliceType() }
191+
192+
override StructField getStructField(string name) { none() }
193+
194+
override TupleField getTupleField(int i) { none() }
195+
196+
override TypeParameter getTypeParameter(int i) {
197+
result = TSliceTypeParameter() and
198+
i = 0
199+
}
200+
201+
override string toString() { result = "[]" }
202+
203+
override Location getLocation() { result instanceof EmptyLocation }
204+
}
205+
179206
/** A type parameter. */
180207
abstract class TypeParameter extends Type {
181208
override StructField getStructField(string name) { none() }
@@ -255,13 +282,27 @@ class AssociatedTypeTypeParameter extends TypeParameter, TAssociatedTypeTypePara
255282
override Location getLocation() { result = typeAlias.getLocation() }
256283
}
257284

285+
/** An implicit array type parameter. */
286+
class ArrayTypeParameter extends TypeParameter, TArrayTypeParameter {
287+
override string toString() { result = "[T;...]" }
288+
289+
override Location getLocation() { result instanceof EmptyLocation }
290+
}
291+
258292
/** An implicit reference type parameter. */
259293
class RefTypeParameter extends TypeParameter, TRefTypeParameter {
260294
override string toString() { result = "&T" }
261295

262296
override Location getLocation() { result instanceof EmptyLocation }
263297
}
264298

299+
/** An implicit slice type parameter. */
300+
class SliceTypeParameter extends TypeParameter, TSliceTypeParameter {
301+
override string toString() { result = "[T]" }
302+
303+
override Location getLocation() { result instanceof EmptyLocation }
304+
}
305+
265306
/**
266307
* The implicit `Self` type parameter of a trait, that refers to the
267308
* implementing type of the trait.

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

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,18 @@ private module Input1 implements InputSig1<Location> {
8080
int getTypeParameterId(TypeParameter tp) {
8181
tp =
8282
rank[result](TypeParameter tp0, int kind, int id |
83-
tp0 instanceof RefTypeParameter and
83+
tp0 instanceof ArrayTypeParameter and
8484
kind = 0 and
8585
id = 0
8686
or
87+
tp0 instanceof RefTypeParameter and
88+
kind = 0 and
89+
id = 1
90+
or
91+
tp0 instanceof SliceTypeParameter and
92+
kind = 0 and
93+
id = 2
94+
or
8795
kind = 1 and
8896
exists(AstNode node | id = idOfTypeParameterAstNode(node) |
8997
node = tp0.(TypeParamTypeParameter).getTypeParam() or
@@ -569,7 +577,7 @@ private module CallExprBaseMatchingInput implements MatchingInputSig {
569577
exists(Param p, int i, boolean inMethod |
570578
paramPos(this.getParamList(), p, i, inMethod) and
571579
dpos = TPositionalDeclarationPosition(i, inMethod) and
572-
result = inferAnnotatedType(p.getPat(), path)
580+
result = p.getTypeRepr().(TypeMention).resolveTypeAt(path)
573581
)
574582
or
575583
exists(SelfParam self |
@@ -1010,6 +1018,36 @@ private StructType inferLiteralType(LiteralExpr le) {
10101018
)
10111019
}
10121020

1021+
private class Vec extends Struct {
1022+
Vec() { this.getCanonicalPath() = "alloc::vec::Vec" }
1023+
1024+
TypeParamTypeParameter getElementTypeParameter() {
1025+
result.getTypeParam() = this.getGenericParamList().getTypeParam(0)
1026+
}
1027+
}
1028+
1029+
pragma[nomagic]
1030+
private Type inferIndexExprType(IndexExpr ie, TypePath path) {
1031+
// TODO: Should be implemented as method resolution, using the special
1032+
// `std::ops::Index` trait.
1033+
exists(TypePath exprPath, Builtins::BuiltinType t, TypeParameter tp |
1034+
TStruct(t) = inferType(ie.getIndex()) and
1035+
(
1036+
t instanceof Builtins::I32
1037+
or
1038+
t instanceof Builtins::Usize
1039+
) and
1040+
result = inferType(ie.getBase(), exprPath) and
1041+
exprPath.isCons(tp, path)
1042+
|
1043+
tp = any(Vec v).getElementTypeParameter()
1044+
or
1045+
tp instanceof ArrayTypeParameter
1046+
or
1047+
tp instanceof SliceTypeParameter
1048+
)
1049+
}
1050+
10131051
private module MethodCall {
10141052
/** An expression that calls a method. */
10151053
abstract private class MethodCallImpl extends Expr {
@@ -1347,6 +1385,8 @@ private module Cached {
13471385
or
13481386
result = inferLiteralType(n) and
13491387
path.isEmpty()
1388+
or
1389+
result = inferIndexExprType(n, path)
13501390
}
13511391
}
13521392

@@ -1363,7 +1403,7 @@ private module Debug {
13631403
exists(string filepath, int startline, int startcolumn, int endline, int endcolumn |
13641404
result.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) and
13651405
filepath.matches("%/main.rs") and
1366-
startline = 948
1406+
startline = 1718
13671407
)
13681408
}
13691409

rust/ql/lib/codeql/rust/internal/TypeMention.qll

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ class RefTypeReprMention extends TypeMention instanceof RefTypeRepr {
4343
override Type resolveType() { result = TRefType() }
4444
}
4545

46+
class SliceTypeReprMention extends TypeMention instanceof SliceTypeRepr {
47+
override TypeMention getTypeArgument(int i) { result = super.getTypeRepr() and i = 0 }
48+
49+
override Type resolveType() { result = TSliceType() }
50+
}
51+
4652
class PathTypeReprMention extends TypeMention instanceof PathTypeRepr {
4753
Path path;
4854
ItemNode resolved;

0 commit comments

Comments
 (0)