From 40eff6525de8cd74af954a06bd16ed7a8287daa7 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Fri, 10 Apr 2026 16:57:58 +0200 Subject: [PATCH 1/2] Rust: Replace special handling of index expressions --- .../rust/frameworks/stdlib/Builtins.qll | 12 +++ .../typeinference/FunctionOverloading.qll | 10 +++ .../internal/typeinference/TypeInference.qll | 42 +-------- rust/tools/builtins/impls.rs | 86 +++++++++++++++++++ 4 files changed, 110 insertions(+), 40 deletions(-) create mode 100644 rust/tools/builtins/impls.rs diff --git a/rust/ql/lib/codeql/rust/frameworks/stdlib/Builtins.qll b/rust/ql/lib/codeql/rust/frameworks/stdlib/Builtins.qll index 6b09ababd741..1a545da0db5c 100644 --- a/rust/ql/lib/codeql/rust/frameworks/stdlib/Builtins.qll +++ b/rust/ql/lib/codeql/rust/frameworks/stdlib/Builtins.qll @@ -19,6 +19,13 @@ private class BuiltinsTypesFile extends File { } } +private class BuiltinsImplsFile extends File { + BuiltinsImplsFile() { + this.getBaseName() = "impls.rs" and + this.getParentContainer() instanceof BuiltinsFolder + } +} + /** * A builtin type, such as `bool` and `i32`. * @@ -221,3 +228,8 @@ class TupleType extends BuiltinType { ) } } + +/** A builtin implementation. */ +class BuiltinImpl extends Impl { + BuiltinImpl() { this.getFile() instanceof BuiltinsImplsFile } +} diff --git a/rust/ql/lib/codeql/rust/internal/typeinference/FunctionOverloading.qll b/rust/ql/lib/codeql/rust/internal/typeinference/FunctionOverloading.qll index d217fc3760a9..ec0152c7ecae 100644 --- a/rust/ql/lib/codeql/rust/internal/typeinference/FunctionOverloading.qll +++ b/rust/ql/lib/codeql/rust/internal/typeinference/FunctionOverloading.qll @@ -6,6 +6,8 @@ */ private import rust +private import codeql.rust.frameworks.stdlib.Builtins as Builtins +private import codeql.rust.frameworks.stdlib.Stdlib private import codeql.rust.internal.PathResolution private import Type private import TypeAbstraction @@ -94,6 +96,14 @@ private module MkSiblingImpls { not t1 instanceof TypeParameter or not t2 instanceof TypeParameter ) + or + // todo: handle blanket/non-blanket siblings in `implSiblings` + trait = + any(IndexTrait it | + implSiblingCandidate(impl, it, _, _) and + impl instanceof Builtins::BuiltinImpl and + path = TypePath::singleton(TAssociatedTypeTypeParameter(trait, it.getOutputType())) + ) } } diff --git a/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll b/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll index c6a268be126f..a2f3d6efd789 100644 --- a/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll +++ b/rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll @@ -3663,43 +3663,6 @@ private Type inferArrayExprType(ArrayExpr ae) { exists(ae) and result instanceof pragma[nomagic] private Type inferRangeExprType(RangeExpr re) { result = TDataType(getRangeType(re)) } -/** - * 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: Method resolution to the `std::ops::Index` trait can handle the - // `Index` instances for slices and arrays. - exists(TypePath exprPath, Builtins::BuiltinType t | - TDataType(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) - | - // todo: remove? - exprPath.isCons(TTypeParamTypeParameter(any(Vec v).getElementTypeParam()), path) - or - exprPath.isCons(getArrayTypeParameter(), path) - or - exists(TypePath path0 | - exprPath.isCons(getRefTypeParameter(_), path0) and - path0.isCons(getSliceTypeParameter(), path) - ) - ) -} - pragma[nomagic] private Type getInferredDerefType(DerefExpr de, TypePath path) { result = inferType(de, path) } @@ -3902,7 +3865,8 @@ private module Cached { i instanceof ImplItemNode and dispatch = false | result = call.(AssocFunctionResolution::AssocFunctionCall).resolveCallTarget(i, _, _, _) and - not call instanceof CallExprImpl::DynamicCallExpr + not call instanceof CallExprImpl::DynamicCallExpr and + not i instanceof Builtins::BuiltinImpl ) } @@ -4004,8 +3968,6 @@ private module Cached { or result = inferAwaitExprType(n, path) or - result = inferIndexExprType(n, path) - or result = inferDereferencedExprPtrType(n, path) or result = inferForLoopExprType(n, path) diff --git a/rust/tools/builtins/impls.rs b/rust/tools/builtins/impls.rs new file mode 100644 index 000000000000..3bc028a51a61 --- /dev/null +++ b/rust/tools/builtins/impls.rs @@ -0,0 +1,86 @@ +/// Contains type-specialized versions of +/// +/// ``` +/// impl Index for [T; N] +/// where +/// [T]: Index, +/// { +/// type Output = <[T] as Index>::Output; +/// ... +/// } +/// ``` +/// +/// and +/// +/// ``` +/// impl ops::Index for [T] +/// where +/// I: SliceIndex<[T]>, +/// { +/// type Output = I::Output; +/// ... +/// } +/// ``` +/// +/// and +/// ``` +/// impl, A: Allocator> Index for Vec { +/// type Output = I::Output; +/// ... +/// } +/// ``` +/// +/// which the type inference library cannot currently handle (we fail +/// to resolve the `Output` types). +mod index_impls { + use std::alloc::Allocator; + use std::ops::Index; + + impl Index for [T; N] { + type Output = T; + + fn index(&self, index: i32) -> &Self::Output { + panic!() + } + } + + impl Index for [T; N] { + type Output = T; + + fn index(&self, index: usize) -> &Self::Output { + panic!() + } + } + + impl Index for [T] { + type Output = T; + + fn index(&self, index: i32) -> &Self::Output { + panic!() + } + } + + impl Index for [T] { + type Output = T; + + fn index(&self, index: usize) -> &Self::Output { + panic!() + } + } + + impl Index for Vec { + type Output = T; + + fn index(&self, index: i32) -> &Self::Output { + panic!() + } + } + + impl Index for Vec { + type Output = T; + + fn index(&self, index: usize) -> &Self::Output { + panic!() + } + } +} From 467933bbb1118913d2518749fbd5c6fe7e8460ca Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Tue, 14 Apr 2026 15:45:14 +0200 Subject: [PATCH 2/2] Rust: Also add specialized `IndexMut` implementations --- rust/tools/builtins/impls.rs | 52 ++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/rust/tools/builtins/impls.rs b/rust/tools/builtins/impls.rs index 3bc028a51a61..facffd700058 100644 --- a/rust/tools/builtins/impls.rs +++ b/rust/tools/builtins/impls.rs @@ -30,8 +30,8 @@ /// } /// ``` /// -/// which the type inference library cannot currently handle (we fail -/// to resolve the `Output` types). +/// (as well as their `IndexMut` counterparts), which the type inference library +/// cannot currently handle (we fail to resolve the `Output` types). mod index_impls { use std::alloc::Allocator; use std::ops::Index; @@ -44,6 +44,14 @@ mod index_impls { } } + impl IndexMut for [T; N] { + type Output = T; + + fn index_mut(&mut self, index: i32) -> &mut Self::Output { + panic!() + } + } + impl Index for [T; N] { type Output = T; @@ -52,6 +60,14 @@ mod index_impls { } } + impl IndexMut for [T; N] { + type Output = T; + + fn index_mut(&mut self, index: usize) -> &mut Self::Output { + panic!() + } + } + impl Index for [T] { type Output = T; @@ -60,6 +76,14 @@ mod index_impls { } } + impl IndexMut for [T] { + type Output = T; + + fn index_mut(&mut self, index: i32) -> &mut Self::Output { + panic!() + } + } + impl Index for [T] { type Output = T; @@ -68,6 +92,14 @@ mod index_impls { } } + impl IndexMut for [T] { + type Output = T; + + fn index_mut(&mut self, index: usize) -> &mut Self::Output { + panic!() + } + } + impl Index for Vec { type Output = T; @@ -76,6 +108,14 @@ mod index_impls { } } + impl IndexMut for Vec { + type Output = T; + + fn index_mut(&mut self, index: i32) -> &mut Self::Output { + panic!() + } + } + impl Index for Vec { type Output = T; @@ -83,4 +123,12 @@ mod index_impls { panic!() } } + + impl IndexMut for Vec { + type Output = T; + + fn index_mut(&mut self, index: usize) -> &mut Self::Output { + panic!() + } + } }