Skip to content

Commit ee34e33

Browse files
authored
Merge pull request #21698 from hvitved/rust/type-inference-index-expr
Rust: Replace special handling of index expressions in type inference
2 parents f95ee12 + 467933b commit ee34e33

File tree

4 files changed

+158
-40
lines changed

4 files changed

+158
-40
lines changed

rust/ql/lib/codeql/rust/frameworks/stdlib/Builtins.qll

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@ private class BuiltinsTypesFile extends File {
1919
}
2020
}
2121

22+
private class BuiltinsImplsFile extends File {
23+
BuiltinsImplsFile() {
24+
this.getBaseName() = "impls.rs" and
25+
this.getParentContainer() instanceof BuiltinsFolder
26+
}
27+
}
28+
2229
/**
2330
* A builtin type, such as `bool` and `i32`.
2431
*
@@ -221,3 +228,8 @@ class TupleType extends BuiltinType {
221228
)
222229
}
223230
}
231+
232+
/** A builtin implementation. */
233+
class BuiltinImpl extends Impl {
234+
BuiltinImpl() { this.getFile() instanceof BuiltinsImplsFile }
235+
}

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
*/
77

88
private import rust
9+
private import codeql.rust.frameworks.stdlib.Builtins as Builtins
10+
private import codeql.rust.frameworks.stdlib.Stdlib
911
private import codeql.rust.internal.PathResolution
1012
private import Type
1113
private import TypeAbstraction
@@ -94,6 +96,14 @@ private module MkSiblingImpls<resolveTypeMentionAtSig/2 resolveTypeMentionAt> {
9496
not t1 instanceof TypeParameter or
9597
not t2 instanceof TypeParameter
9698
)
99+
or
100+
// todo: handle blanket/non-blanket siblings in `implSiblings`
101+
trait =
102+
any(IndexTrait it |
103+
implSiblingCandidate(impl, it, _, _) and
104+
impl instanceof Builtins::BuiltinImpl and
105+
path = TypePath::singleton(TAssociatedTypeTypeParameter(trait, it.getOutputType()))
106+
)
97107
}
98108
}
99109

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

Lines changed: 2 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -3609,43 +3609,6 @@ private Type inferArrayExprType(ArrayExpr ae) { exists(ae) and result instanceof
36093609
pragma[nomagic]
36103610
private Type inferRangeExprType(RangeExpr re) { result = TDataType(getRangeType(re)) }
36113611

3612-
/**
3613-
* According to [the Rust reference][1]: _"array and slice-typed expressions
3614-
* can be indexed with a `usize` index ... For other types an index expression
3615-
* `a[b]` is equivalent to *std::ops::Index::index(&a, b)"_.
3616-
*
3617-
* The logic below handles array and slice indexing, but for other types it is
3618-
* currently limited to `Vec`.
3619-
*
3620-
* [1]: https://doc.rust-lang.org/reference/expressions/array-expr.html#r-expr.array.index
3621-
*/
3622-
pragma[nomagic]
3623-
private Type inferIndexExprType(IndexExpr ie, TypePath path) {
3624-
// TODO: Method resolution to the `std::ops::Index` trait can handle the
3625-
// `Index` instances for slices and arrays.
3626-
exists(TypePath exprPath, Builtins::BuiltinType t |
3627-
TDataType(t) = inferType(ie.getIndex()) and
3628-
(
3629-
// also allow `i32`, since that is currently the type that we infer for
3630-
// integer literals like `0`
3631-
t instanceof Builtins::I32
3632-
or
3633-
t instanceof Builtins::Usize
3634-
) and
3635-
result = inferType(ie.getBase(), exprPath)
3636-
|
3637-
// todo: remove?
3638-
exprPath.isCons(TTypeParamTypeParameter(any(Vec v).getElementTypeParam()), path)
3639-
or
3640-
exprPath.isCons(getArrayTypeParameter(), path)
3641-
or
3642-
exists(TypePath path0 |
3643-
exprPath.isCons(getRefTypeParameter(_), path0) and
3644-
path0.isCons(getSliceTypeParameter(), path)
3645-
)
3646-
)
3647-
}
3648-
36493612
pragma[nomagic]
36503613
private Type getInferredDerefType(DerefExpr de, TypePath path) { result = inferType(de, path) }
36513614

@@ -3848,7 +3811,8 @@ private module Cached {
38483811
i instanceof ImplItemNode and dispatch = false
38493812
|
38503813
result = call.(AssocFunctionResolution::AssocFunctionCall).resolveCallTarget(i, _, _, _) and
3851-
not call instanceof CallExprImpl::DynamicCallExpr
3814+
not call instanceof CallExprImpl::DynamicCallExpr and
3815+
not i instanceof Builtins::BuiltinImpl
38523816
)
38533817
}
38543818

@@ -3950,8 +3914,6 @@ private module Cached {
39503914
or
39513915
result = inferAwaitExprType(n, path)
39523916
or
3953-
result = inferIndexExprType(n, path)
3954-
or
39553917
result = inferDereferencedExprPtrType(n, path)
39563918
or
39573919
result = inferForLoopExprType(n, path)

rust/tools/builtins/impls.rs

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
/// Contains type-specialized versions of
2+
///
3+
/// ```
4+
/// impl<T, I, const N: usize> Index<I> for [T; N]
5+
/// where
6+
/// [T]: Index<I>,
7+
/// {
8+
/// type Output = <[T] as Index<I>>::Output;
9+
/// ...
10+
/// }
11+
/// ```
12+
///
13+
/// and
14+
///
15+
/// ```
16+
/// impl<T, I> ops::Index<I> for [T]
17+
/// where
18+
/// I: SliceIndex<[T]>,
19+
/// {
20+
/// type Output = I::Output;
21+
/// ...
22+
/// }
23+
/// ```
24+
///
25+
/// and
26+
/// ```
27+
/// impl<T, I: SliceIndex<[T]>, A: Allocator> Index<I> for Vec<T, A> {
28+
/// type Output = I::Output;
29+
/// ...
30+
/// }
31+
/// ```
32+
///
33+
/// (as well as their `IndexMut` counterparts), which the type inference library
34+
/// cannot currently handle (we fail to resolve the `Output` types).
35+
mod index_impls {
36+
use std::alloc::Allocator;
37+
use std::ops::Index;
38+
39+
impl<T, const N: usize> Index<i32> for [T; N] {
40+
type Output = T;
41+
42+
fn index(&self, index: i32) -> &Self::Output {
43+
panic!()
44+
}
45+
}
46+
47+
impl<T, const N: usize> IndexMut<i32> for [T; N] {
48+
type Output = T;
49+
50+
fn index_mut(&mut self, index: i32) -> &mut Self::Output {
51+
panic!()
52+
}
53+
}
54+
55+
impl<T, const N: usize> Index<usize> for [T; N] {
56+
type Output = T;
57+
58+
fn index(&self, index: usize) -> &Self::Output {
59+
panic!()
60+
}
61+
}
62+
63+
impl<T, const N: usize> IndexMut<usize> for [T; N] {
64+
type Output = T;
65+
66+
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
67+
panic!()
68+
}
69+
}
70+
71+
impl<T> Index<i32> for [T] {
72+
type Output = T;
73+
74+
fn index(&self, index: i32) -> &Self::Output {
75+
panic!()
76+
}
77+
}
78+
79+
impl<T> IndexMut<i32> for [T] {
80+
type Output = T;
81+
82+
fn index_mut(&mut self, index: i32) -> &mut Self::Output {
83+
panic!()
84+
}
85+
}
86+
87+
impl<T> Index<usize> for [T] {
88+
type Output = T;
89+
90+
fn index(&self, index: usize) -> &Self::Output {
91+
panic!()
92+
}
93+
}
94+
95+
impl<T> IndexMut<usize> for [T] {
96+
type Output = T;
97+
98+
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
99+
panic!()
100+
}
101+
}
102+
103+
impl<T, A: Allocator> Index<i32> for Vec<T, A> {
104+
type Output = T;
105+
106+
fn index(&self, index: i32) -> &Self::Output {
107+
panic!()
108+
}
109+
}
110+
111+
impl<T, A: Allocator> IndexMut<i32> for Vec<T, A> {
112+
type Output = T;
113+
114+
fn index_mut(&mut self, index: i32) -> &mut Self::Output {
115+
panic!()
116+
}
117+
}
118+
119+
impl<T, A: Allocator> Index<usize> for Vec<T, A> {
120+
type Output = T;
121+
122+
fn index(&self, index: usize) -> &Self::Output {
123+
panic!()
124+
}
125+
}
126+
127+
impl<T, A: Allocator> IndexMut<usize> for Vec<T, A> {
128+
type Output = T;
129+
130+
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
131+
panic!()
132+
}
133+
}
134+
}

0 commit comments

Comments
 (0)