Rust: Replace special handling of index expressions in type inference#21698
Rust: Replace special handling of index expressions in type inference#21698hvitved wants to merge 2 commits intogithub:mainfrom
Conversation
be02d9a to
40eff65
Compare
There was a problem hiding this comment.
Pull request overview
This PR aims to remove bespoke type-inference handling for Rust index expressions (foo[bar]) by instead supplying type-specialized builtin Index impls whose Output types are directly resolvable, allowing the existing method-resolution-based inference to determine element types.
Changes:
- Add builtin, type-specialized
std::ops::Indeximpls for arrays, slices, andVecforusizeandi32indices. - Remove the dedicated
inferIndexExprTypespecial-casing from the type inference library and rely on overload/method resolution instead. - Introduce/adjust QL classifications and sibling-impl logic to recognize builtin impls for resolution purposes.
Show a summary per file
| File | Description |
|---|---|
| rust/tools/builtins/impls.rs | Adds specialized builtin Index impl stubs to make Output resolvable for common indexing targets. |
| rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll | Removes the previous index-expression type inference special-case and updates call target handling around builtin impls. |
| rust/ql/lib/codeql/rust/internal/typeinference/FunctionOverloading.qll | Adjusts overload/sibling-impl logic with builtin-aware handling related to Index’s Output. |
| rust/ql/lib/codeql/rust/frameworks/stdlib/Builtins.qll | Adds identification of builtin impls via the new impls.rs builtins file. |
Copilot's findings
Comments suppressed due to low confidence (2)
rust/tools/builtins/impls.rs:69
- These builtins add
Index<...>for slices ([T]), but mutable indexing (slice[i] = ...) desugars toIndexMut::index_mut. If the generic stdIndexMutimpl’sOutputremains unresolvable, mutable slice indexing will still miss element type inference. AddIndexMut<i32>/IndexMut<usize>impls for[T]withtype Output = T.
impl<T> Index<i32> for [T] {
type Output = T;
fn index(&self, index: i32) -> &Self::Output {
panic!()
}
}
impl<T> Index<usize> for [T] {
type Output = T;
fn index(&self, index: usize) -> &Self::Output {
panic!()
}
}
rust/tools/builtins/impls.rs:85
- For
Vec, onlyIndex<...>is stubbed here. Sincevec[i] = ...usesIndexMut::index_mut, consider addingIndexMut<i32>/IndexMut<usize>impls forVec<T, A>(withtype Output = T) so mutable vector indexing can infer the element type as well.
impl<T, A: Allocator> Index<i32> for Vec<T, A> {
type Output = T;
fn index(&self, index: i32) -> &Self::Output {
panic!()
}
}
impl<T, A: Allocator> Index<usize> for Vec<T, A> {
type Output = T;
fn index(&self, index: usize) -> &Self::Output {
panic!()
}
}
- Files reviewed: 4/4 changed files
- Comments generated: 1
| impl<T, const N: usize> Index<i32> for [T; N] { | ||
| type Output = T; | ||
|
|
||
| fn index(&self, index: i32) -> &Self::Output { | ||
| panic!() | ||
| } | ||
| } | ||
|
|
||
| impl<T, const N: usize> Index<usize> for [T; N] { | ||
| type Output = T; | ||
|
|
||
| fn index(&self, index: usize) -> &Self::Output { | ||
| panic!() | ||
| } | ||
| } |
There was a problem hiding this comment.
Type inference resolves a[b] to Index::index or IndexMut::index_mut based on whether the index expression is used mutably (e.g. a[b] = ...). These builtins only add Index<...> for arrays, so mutable array indexing may still lack a resolvable Output type. Add corresponding IndexMut<i32>/IndexMut<usize> impls for [T; N] with type Output = T.
This issue also appears in the following locations of the same file:
- line 55
- line 71
We have special logic for handling type inference for index expressions
foo[bar]wherebaris an integer andfoois either an array, a slice, or a vector; in this case the type is whatever the element type is.Special casing is needed because, even though we correctly see
foo[bar]as syntactic sugar forfoo.index(bar), we cannot resolve theOutputtypes in theIndeximplementations for slices, arrays, and vectors. However, instead of having special logic in the type inference library, we can achieve the same effect by adding type-specialized implementations where we can resolve theOutputtype, which is somewhat cleaner.DCA is mostly uneventful.