Skip to content

Rust: Add type inference for overloaded index expressions #19833

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

paldepind
Copy link
Contributor

This PR implements support for overloaded index expressions. The implementation is very similar to the existing overloaded operators.

Like the desugaring of * the desugaring of ..[..] includes a * after the overloaded call. This PR fixes a bug around those that I thought I fixed in #19820 but I made a mistake: In inferCallExprBaseType the first and last disjunct could be true at the same time since apos.isReturn() and a instanceof DerefExpr and not apos.isBorrowed(_) are not exclusive. So both disjunct where true in the return position of *. Fixing that removes a whole bunch of spurious reference types 😅

I had hoped we could remove the current special casing for arrays and slices, but that's not possible. The Index instances for those are more complex than what we can understand. See for instance the one for slices:

impl<T, I> ops::Index<I> for [T]
where
    I: SliceIndex<[T]>,
{
    type Output = I::Output;

    #[inline(always)]
    fn index(&self, index: I) -> &I::Output {
        index.index(self)
    }
}

It seems that the type of I is somehow deduced from the I: SliceIndex<[T]> bound and that is not something we can currently handle. So while this works great for Vec and other types, we still need the special casing.

Also, I left the data flow library as-is. Following this PR we could implement index expressions as calls there as well, and that should allow us to add models for index expressions on custom types.

@github-actions github-actions bot added the Rust Pull requests that update Rust code label Jun 20, 2025
@paldepind paldepind marked this pull request as ready for review June 20, 2025 14:35
@Copilot Copilot AI review requested due to automatic review settings June 20, 2025 14:35
@paldepind paldepind requested a review from a team as a code owner June 20, 2025 14:35
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Adds support for overloaded index expressions in the Rust type inference engine, fixes a bug in inferCallExprBaseType that was producing spurious reference types, and updates the library-tests to reflect the new behavior.

  • Introduces IndexCall in CallImpl.qll and extends inferCallExprBaseType to handle IndexExpr
  • Updates inferIndexExprType and test expectations to capture index-based desugaring
  • Skips index expressions in data flow (pending full implementation) and adjusts debug helper for new test ranges

Reviewed Changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
rust/ql/test/library-tests/type-inference/main.rs Expanded test comments and updated index expression assertions
rust/ql/test/library-tests/type-inference/type-inference.expected Removed spurious & entries and added index cases
rust/ql/lib/codeql/rust/internal/TypeInference.qll Refactored inferCallExprBaseType to strip & for IndexExpr and DerefExpr; updated inferIndexExprType
rust/ql/lib/codeql/rust/elements/internal/CallImpl.qll Added IndexCall class to represent IndexExpr calls
rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll Excluded index expressions from data flow calls (TODO)
Comments suppressed due to low confidence (3)

rust/ql/test/library-tests/type-inference/main.rs:1864

  • [nitpick] This test comment is quite verbose; consider moving the detailed explanation into a test annotation or external doc to keep the test code concise.
        // NOTE: `slice` gets the spurious type `[]` because the desugaring of

rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll:964

  • Since data flow currently skips index expressions, add tests and implement support for index-expression calls in the data flow stage to ensure they're properly tracked.
      // TODO: Handle index expressions as calls in data flow.

rust/ql/lib/codeql/rust/elements/internal/CallImpl.qll:169

  • [nitpick] The implicitBorrowAt predicate forces certain = true for self; verify that this covers all borrowing scenarios or document any limitations to avoid unexpected behavior.
    override predicate implicitBorrowAt(ArgumentPosition pos, boolean certain) {

@@ -772,45 +772,48 @@ private Type inferCallExprBaseType(AstNode n, TypePath path) {
n = a.getNodeAt(apos) and
result = CallExprBaseMatching::inferAccessType(a, apos, path0)
|
(
if
Copy link
Preview

Copilot AI Jun 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The nested if/then/else block handling both DerefExpr and IndexExpr is complex; consider extracting this into a helper predicate or simplifying the condition to improve readability.

Copilot uses AI. Check for mistakes.

Comment on lines +1605 to +1606
filepath.matches("%/main.rs") and
startline = [1854 .. 1880]
Copy link
Preview

Copilot AI Jun 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hardcoding file paths and line ranges in the debug predicate is brittle; consider using markers or parameterized patterns so tests remain resilient to refactoring.

Suggested change
filepath.matches("%/main.rs") and
startline = [1854 .. 1880]
filepath.matches("%/*.rs") and
result.getLocation().hasMarker("DEBUG_LOCATABLE")

Copilot uses AI. Check for mistakes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Rust Pull requests that update Rust code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant