mirror of
https://github.com/github/codeql.git
synced 2026-04-19 14:04:09 +02:00
Rust: Simple type inference for index expressions
This commit is contained in:
@@ -16,10 +16,13 @@ newtype TType =
|
||||
TArrayType() or // todo: add size?
|
||||
TRefType() or // todo: add mut?
|
||||
TImplTraitType(ImplTraitTypeRepr impl) or
|
||||
TSliceType() or
|
||||
TTypeParamTypeParameter(TypeParam t) or
|
||||
TAssociatedTypeTypeParameter(TypeAlias t) { any(TraitItemNode trait).getAnAssocItem() = t } or
|
||||
TArrayTypeParameter() or
|
||||
TRefTypeParameter() or
|
||||
TSelfTypeParameter(Trait t)
|
||||
TSelfTypeParameter(Trait t) or
|
||||
TSliceTypeParameter()
|
||||
|
||||
/**
|
||||
* A type without type arguments.
|
||||
@@ -149,7 +152,8 @@ class ArrayType extends Type, TArrayType {
|
||||
override TupleField getTupleField(int i) { none() }
|
||||
|
||||
override TypeParameter getTypeParameter(int i) {
|
||||
none() // todo
|
||||
result = TArrayTypeParameter() and
|
||||
i = 0
|
||||
}
|
||||
|
||||
override string toString() { result = "[]" }
|
||||
@@ -227,6 +231,29 @@ class ImplTraitReturnType extends ImplTraitType {
|
||||
override Function getFunction() { result = function }
|
||||
}
|
||||
|
||||
/**
|
||||
* A slice type.
|
||||
*
|
||||
* Slice types like `[i64]` are modeled as normal generic types
|
||||
* with a single type argument.
|
||||
*/
|
||||
class SliceType extends Type, TSliceType {
|
||||
SliceType() { this = TSliceType() }
|
||||
|
||||
override StructField getStructField(string name) { none() }
|
||||
|
||||
override TupleField getTupleField(int i) { none() }
|
||||
|
||||
override TypeParameter getTypeParameter(int i) {
|
||||
result = TSliceTypeParameter() and
|
||||
i = 0
|
||||
}
|
||||
|
||||
override string toString() { result = "[]" }
|
||||
|
||||
override Location getLocation() { result instanceof EmptyLocation }
|
||||
}
|
||||
|
||||
/** A type parameter. */
|
||||
abstract class TypeParameter extends Type {
|
||||
override StructField getStructField(string name) { none() }
|
||||
@@ -306,6 +333,13 @@ class AssociatedTypeTypeParameter extends TypeParameter, TAssociatedTypeTypePara
|
||||
override Location getLocation() { result = typeAlias.getLocation() }
|
||||
}
|
||||
|
||||
/** An implicit array type parameter. */
|
||||
class ArrayTypeParameter extends TypeParameter, TArrayTypeParameter {
|
||||
override string toString() { result = "[T;...]" }
|
||||
|
||||
override Location getLocation() { result instanceof EmptyLocation }
|
||||
}
|
||||
|
||||
/** An implicit reference type parameter. */
|
||||
class RefTypeParameter extends TypeParameter, TRefTypeParameter {
|
||||
override string toString() { result = "&T" }
|
||||
@@ -313,6 +347,13 @@ class RefTypeParameter extends TypeParameter, TRefTypeParameter {
|
||||
override Location getLocation() { result instanceof EmptyLocation }
|
||||
}
|
||||
|
||||
/** An implicit slice type parameter. */
|
||||
class SliceTypeParameter extends TypeParameter, TSliceTypeParameter {
|
||||
override string toString() { result = "[T]" }
|
||||
|
||||
override Location getLocation() { result instanceof EmptyLocation }
|
||||
}
|
||||
|
||||
/**
|
||||
* The implicit `Self` type parameter of a trait, that refers to the
|
||||
* implementing type of the trait.
|
||||
|
||||
@@ -80,10 +80,18 @@ private module Input1 implements InputSig1<Location> {
|
||||
int getTypeParameterId(TypeParameter tp) {
|
||||
tp =
|
||||
rank[result](TypeParameter tp0, int kind, int id |
|
||||
tp0 instanceof RefTypeParameter and
|
||||
tp0 instanceof ArrayTypeParameter and
|
||||
kind = 0 and
|
||||
id = 0
|
||||
or
|
||||
tp0 instanceof RefTypeParameter and
|
||||
kind = 0 and
|
||||
id = 1
|
||||
or
|
||||
tp0 instanceof SliceTypeParameter and
|
||||
kind = 0 and
|
||||
id = 2
|
||||
or
|
||||
kind = 1 and
|
||||
exists(AstNode node | id = idOfTypeParameterAstNode(node) |
|
||||
node = tp0.(TypeParamTypeParameter).getTypeParam() or
|
||||
@@ -1128,6 +1136,50 @@ private Type inferAwaitExprType(AstNode n, TypePath path) {
|
||||
)
|
||||
}
|
||||
|
||||
private class Vec extends Struct {
|
||||
Vec() { this.getCanonicalPath() = "alloc::vec::Vec" }
|
||||
|
||||
TypeParamTypeParameter getElementTypeParameter() {
|
||||
result.getTypeParam() = this.getGenericParamList().getTypeParam(0)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* According to [the Rust reference][1]: _"array and slice-typed expressions
|
||||
* can be indexed with a `usize` index ... For other types an index expression
|
||||
* `a[b]` is equivalent to *std::ops::Index::index(&a, b)"_.
|
||||
*
|
||||
* The logic below handles array and slice indexing, but for other types it is
|
||||
* currently limited to `Vec`.
|
||||
*
|
||||
* [1]: https://doc.rust-lang.org/reference/expressions/array-expr.html#r-expr.array.index
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private Type inferIndexExprType(IndexExpr ie, TypePath path) {
|
||||
// TODO: Should be implemented as method resolution, using the special
|
||||
// `std::ops::Index` trait.
|
||||
exists(TypePath exprPath, Builtins::BuiltinType t |
|
||||
TStruct(t) = inferType(ie.getIndex()) and
|
||||
(
|
||||
// also allow `i32`, since that is currently the type that we infer for
|
||||
// integer literals like `0`
|
||||
t instanceof Builtins::I32
|
||||
or
|
||||
t instanceof Builtins::Usize
|
||||
) and
|
||||
result = inferType(ie.getBase(), exprPath)
|
||||
|
|
||||
exprPath.isCons(any(Vec v).getElementTypeParameter(), path)
|
||||
or
|
||||
exprPath.isCons(any(ArrayTypeParameter tp), path)
|
||||
or
|
||||
exists(TypePath path0 |
|
||||
exprPath.isCons(any(RefTypeParameter tp), path0) and
|
||||
path0.isCons(any(SliceTypeParameter tp), path)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private module MethodCall {
|
||||
/** An expression that calls a method. */
|
||||
abstract private class MethodCallImpl extends Expr {
|
||||
@@ -1487,6 +1539,8 @@ private module Cached {
|
||||
path.isEmpty()
|
||||
or
|
||||
result = inferAwaitExprType(n, path)
|
||||
or
|
||||
result = inferIndexExprType(n, path)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,12 @@ class RefTypeReprMention extends TypeMention instanceof RefTypeRepr {
|
||||
override Type resolveType() { result = TRefType() }
|
||||
}
|
||||
|
||||
class SliceTypeReprMention extends TypeMention instanceof SliceTypeRepr {
|
||||
override TypeMention getTypeArgument(int i) { result = super.getTypeRepr() and i = 0 }
|
||||
|
||||
override Type resolveType() { result = TSliceType() }
|
||||
}
|
||||
|
||||
class PathTypeReprMention extends TypeMention instanceof PathTypeRepr {
|
||||
Path path;
|
||||
ItemNode resolved;
|
||||
|
||||
@@ -1790,16 +1790,16 @@ mod indexers {
|
||||
}
|
||||
|
||||
fn analyze_slice(slice: &[S]) {
|
||||
let x = slice[0].foo(); // $ MISSING: method=foo MISSING: type=x:S
|
||||
let x = slice[0].foo(); // $ method=foo type=x:S
|
||||
}
|
||||
|
||||
pub fn f() {
|
||||
let mut vec = MyVec::new(); // $ type=vec:T.S
|
||||
vec.push(S); // $ method=push
|
||||
vec[0].foo(); // $ MISSING: method=foo
|
||||
vec[0].foo(); // $ MISSING: method=foo -- type inference does not support the `Index` trait yet
|
||||
|
||||
let xs: [S; 1] = [S];
|
||||
let x = xs[0].foo(); // $ MISSING: method=foo MISSING: type=x:S
|
||||
let x = xs[0].foo(); // $ method=foo type=x:S
|
||||
|
||||
analyze_slice(&xs);
|
||||
}
|
||||
|
||||
@@ -2561,7 +2561,14 @@ inferType
|
||||
| main.rs:1788:14:1788:29 | ...[index] | | main.rs:1783:10:1783:10 | T |
|
||||
| main.rs:1788:24:1788:28 | index | | {EXTERNAL LOCATION} | usize |
|
||||
| main.rs:1792:22:1792:26 | slice | | file://:0:0:0:0 | & |
|
||||
| main.rs:1792:22:1792:26 | slice | &T | file://:0:0:0:0 | [] |
|
||||
| main.rs:1792:22:1792:26 | slice | &T.[T] | main.rs:1759:5:1760:13 | S |
|
||||
| main.rs:1793:13:1793:13 | x | | main.rs:1759:5:1760:13 | S |
|
||||
| main.rs:1793:17:1793:21 | slice | | file://:0:0:0:0 | & |
|
||||
| main.rs:1793:17:1793:21 | slice | &T | file://:0:0:0:0 | [] |
|
||||
| main.rs:1793:17:1793:21 | slice | &T.[T] | main.rs:1759:5:1760:13 | S |
|
||||
| main.rs:1793:17:1793:24 | slice[0] | | main.rs:1759:5:1760:13 | S |
|
||||
| main.rs:1793:17:1793:30 | ... .foo() | | main.rs:1759:5:1760:13 | S |
|
||||
| main.rs:1793:23:1793:23 | 0 | | {EXTERNAL LOCATION} | i32 |
|
||||
| main.rs:1797:13:1797:19 | mut vec | | main.rs:1768:5:1771:5 | MyVec |
|
||||
| main.rs:1797:13:1797:19 | mut vec | T | main.rs:1759:5:1760:13 | S |
|
||||
@@ -2574,14 +2581,32 @@ inferType
|
||||
| main.rs:1799:9:1799:11 | vec | T | main.rs:1759:5:1760:13 | S |
|
||||
| main.rs:1799:13:1799:13 | 0 | | {EXTERNAL LOCATION} | i32 |
|
||||
| main.rs:1801:13:1801:14 | xs | | file://:0:0:0:0 | [] |
|
||||
| main.rs:1801:13:1801:14 | xs | | file://:0:0:0:0 | [] |
|
||||
| main.rs:1801:13:1801:14 | xs | [T;...] | main.rs:1759:5:1760:13 | S |
|
||||
| main.rs:1801:13:1801:14 | xs | [T] | main.rs:1759:5:1760:13 | S |
|
||||
| main.rs:1801:21:1801:21 | 1 | | {EXTERNAL LOCATION} | i32 |
|
||||
| main.rs:1801:26:1801:28 | [...] | | file://:0:0:0:0 | [] |
|
||||
| main.rs:1801:26:1801:28 | [...] | | file://:0:0:0:0 | [] |
|
||||
| main.rs:1801:26:1801:28 | [...] | [T;...] | main.rs:1759:5:1760:13 | S |
|
||||
| main.rs:1801:26:1801:28 | [...] | [T] | main.rs:1759:5:1760:13 | S |
|
||||
| main.rs:1801:27:1801:27 | S | | main.rs:1759:5:1760:13 | S |
|
||||
| main.rs:1802:13:1802:13 | x | | main.rs:1759:5:1760:13 | S |
|
||||
| main.rs:1802:17:1802:18 | xs | | file://:0:0:0:0 | [] |
|
||||
| main.rs:1802:17:1802:18 | xs | | file://:0:0:0:0 | [] |
|
||||
| main.rs:1802:17:1802:18 | xs | [T;...] | main.rs:1759:5:1760:13 | S |
|
||||
| main.rs:1802:17:1802:18 | xs | [T] | main.rs:1759:5:1760:13 | S |
|
||||
| main.rs:1802:17:1802:21 | xs[0] | | main.rs:1759:5:1760:13 | S |
|
||||
| main.rs:1802:17:1802:27 | ... .foo() | | main.rs:1759:5:1760:13 | S |
|
||||
| main.rs:1802:20:1802:20 | 0 | | {EXTERNAL LOCATION} | i32 |
|
||||
| main.rs:1804:23:1804:25 | &xs | | file://:0:0:0:0 | & |
|
||||
| main.rs:1804:23:1804:25 | &xs | &T | file://:0:0:0:0 | [] |
|
||||
| main.rs:1804:23:1804:25 | &xs | &T | file://:0:0:0:0 | [] |
|
||||
| main.rs:1804:23:1804:25 | &xs | &T.[T;...] | main.rs:1759:5:1760:13 | S |
|
||||
| main.rs:1804:23:1804:25 | &xs | &T.[T] | main.rs:1759:5:1760:13 | S |
|
||||
| main.rs:1804:24:1804:25 | xs | | file://:0:0:0:0 | [] |
|
||||
| main.rs:1804:24:1804:25 | xs | | file://:0:0:0:0 | [] |
|
||||
| main.rs:1804:24:1804:25 | xs | [T;...] | main.rs:1759:5:1760:13 | S |
|
||||
| main.rs:1804:24:1804:25 | xs | [T] | main.rs:1759:5:1760:13 | S |
|
||||
| main.rs:1810:5:1810:20 | ...::f(...) | | main.rs:67:5:67:21 | Foo |
|
||||
| main.rs:1811:5:1811:60 | ...::g(...) | | main.rs:67:5:67:21 | Foo |
|
||||
| main.rs:1811:20:1811:38 | ...::Foo {...} | | main.rs:67:5:67:21 | Foo |
|
||||
|
||||
Reference in New Issue
Block a user