Skip to content

Commit 40eff65

Browse files
committed
Rust: Replace special handling of index expressions
1 parent 33cc887 commit 40eff65

File tree

4 files changed

+110
-40
lines changed

4 files changed

+110
-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
@@ -3663,43 +3663,6 @@ private Type inferArrayExprType(ArrayExpr ae) { exists(ae) and result instanceof
36633663
pragma[nomagic]
36643664
private Type inferRangeExprType(RangeExpr re) { result = TDataType(getRangeType(re)) }
36653665

3666-
/**
3667-
* According to [the Rust reference][1]: _"array and slice-typed expressions
3668-
* can be indexed with a `usize` index ... For other types an index expression
3669-
* `a[b]` is equivalent to *std::ops::Index::index(&a, b)"_.
3670-
*
3671-
* The logic below handles array and slice indexing, but for other types it is
3672-
* currently limited to `Vec`.
3673-
*
3674-
* [1]: https://doc.rust-lang.org/reference/expressions/array-expr.html#r-expr.array.index
3675-
*/
3676-
pragma[nomagic]
3677-
private Type inferIndexExprType(IndexExpr ie, TypePath path) {
3678-
// TODO: Method resolution to the `std::ops::Index` trait can handle the
3679-
// `Index` instances for slices and arrays.
3680-
exists(TypePath exprPath, Builtins::BuiltinType t |
3681-
TDataType(t) = inferType(ie.getIndex()) and
3682-
(
3683-
// also allow `i32`, since that is currently the type that we infer for
3684-
// integer literals like `0`
3685-
t instanceof Builtins::I32
3686-
or
3687-
t instanceof Builtins::Usize
3688-
) and
3689-
result = inferType(ie.getBase(), exprPath)
3690-
|
3691-
// todo: remove?
3692-
exprPath.isCons(TTypeParamTypeParameter(any(Vec v).getElementTypeParam()), path)
3693-
or
3694-
exprPath.isCons(getArrayTypeParameter(), path)
3695-
or
3696-
exists(TypePath path0 |
3697-
exprPath.isCons(getRefTypeParameter(_), path0) and
3698-
path0.isCons(getSliceTypeParameter(), path)
3699-
)
3700-
)
3701-
}
3702-
37033666
pragma[nomagic]
37043667
private Type getInferredDerefType(DerefExpr de, TypePath path) { result = inferType(de, path) }
37053668

@@ -3902,7 +3865,8 @@ private module Cached {
39023865
i instanceof ImplItemNode and dispatch = false
39033866
|
39043867
result = call.(AssocFunctionResolution::AssocFunctionCall).resolveCallTarget(i, _, _, _) and
3905-
not call instanceof CallExprImpl::DynamicCallExpr
3868+
not call instanceof CallExprImpl::DynamicCallExpr and
3869+
not i instanceof Builtins::BuiltinImpl
39063870
)
39073871
}
39083872

@@ -4004,8 +3968,6 @@ private module Cached {
40043968
or
40053969
result = inferAwaitExprType(n, path)
40063970
or
4007-
result = inferIndexExprType(n, path)
4008-
or
40093971
result = inferDereferencedExprPtrType(n, path)
40103972
or
40113973
result = inferForLoopExprType(n, path)

rust/tools/builtins/impls.rs

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
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+
/// which the type inference library cannot currently handle (we fail
34+
/// 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> Index<usize> for [T; N] {
48+
type Output = T;
49+
50+
fn index(&self, index: usize) -> &Self::Output {
51+
panic!()
52+
}
53+
}
54+
55+
impl<T> Index<i32> for [T] {
56+
type Output = T;
57+
58+
fn index(&self, index: i32) -> &Self::Output {
59+
panic!()
60+
}
61+
}
62+
63+
impl<T> Index<usize> for [T] {
64+
type Output = T;
65+
66+
fn index(&self, index: usize) -> &Self::Output {
67+
panic!()
68+
}
69+
}
70+
71+
impl<T, A: Allocator> Index<i32> for Vec<T, A> {
72+
type Output = T;
73+
74+
fn index(&self, index: i32) -> &Self::Output {
75+
panic!()
76+
}
77+
}
78+
79+
impl<T, A: Allocator> Index<usize> for Vec<T, A> {
80+
type Output = T;
81+
82+
fn index(&self, index: usize) -> &Self::Output {
83+
panic!()
84+
}
85+
}
86+
}

0 commit comments

Comments
 (0)