Skip to content

Conversation

@hvitved
Copy link
Contributor

@hvitved hvitved commented Dec 16, 2025

When inferring call targets involving traits bounds such as

fn foo<T : Bar + Baz>(x : T) {
  x.m();
}

we substitute in the trait bounds in the receiver type (using substituteLookupTraits), meaning we treat x as having both types Bar and Baz. That is, we attempt to lookup m in both Bar and Baz. However, when computing candidate receiver types we should only progress to &Bar and &Baz when m cannot be found in both Bar and Baz, which previously was implemented as either Bar or Baz.

This PR fixes the issue above, and as usual we use ranked recursion to implement efficient forex.

DCA is fine.

@github-actions github-actions bot added the Rust Pull requests that update Rust code label Dec 16, 2025
string derefChain, boolean borrow, TypePath path
) {
result = substituteLookupTraits(this.getACandidateReceiverTypeAt(derefChain, borrow, path))
Type getANonPseudoCandidateReceiverTypeAt(string derefChain, boolean borrow, TypePath path) {

Check warning

Code scanning / CodeQL

Missing QLDoc for parameter Warning

The QLDoc has no documentation for borrow, or derefChain, or path, but the QLDoc mentions unknown
@hvitved hvitved added the no-change-note-required This PR does not need a change note label Dec 16, 2025
@hvitved hvitved marked this pull request as ready for review December 16, 2025 11:03
@hvitved hvitved requested a review from a team as a code owner December 16, 2025 11:03
@hvitved hvitved requested review from Copilot and paldepind December 16, 2025 11:03
Copy link
Contributor

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

This PR fixes a bug in the Rust type inference for trait bounds where method lookup incorrectly required finding a method in either trait bound instead of requiring it to be absent from both trait bounds before progressing to the next candidate receiver type (e.g., from Bar and Baz to &Bar and &Baz). The fix uses ranked recursion to efficiently implement the "for all exists" (forex) pattern needed for this check.

Key changes:

  • Introduced getNthLookupType and getLastLookupTypeIndex helper predicates to enumerate trait bounds in a deterministic order
  • Refactored the hasNoCompatibleTarget* predicates to use recursive predicates that check all trait bounds using ranked recursion
  • Added test case demonstrating the fix with overlapping trait bounds

Reviewed changes

Copilot reviewed 5 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
rust/ql/lib/codeql/rust/internal/typeinference/FunctionType.qll Added helper predicates getNthLookupType and getLastLookupTypeIndex to enumerate lookup traits in a deterministic order for efficient forex implementation
rust/ql/lib/codeql/rust/internal/TypeInference.qll Refactored method resolution predicates to use recursive helpers that check all trait bounds rather than just one, implementing the correct "all traits" semantics
rust/ql/test/library-tests/type-inference/main.rs Added test case bound_overlap demonstrating trait bounds with overlapping method names correctly resolved based on receiver type
rust/ql/test/library-tests/type-inference/blanket_impl.rs Updated test expectation from MISSING to correctly identifying S1::m1 as the resolution target
rust/ql/test/library-tests/type-inference/CONSISTENCY/PathResolutionConsistency.expected Updated line numbers to reflect additions to main.rs test file

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

}

/**
* Gets the `n`th `substituteLookupTraits` type for `t`, per some abitrary order.
Copy link

Copilot AI Dec 16, 2025

Choose a reason for hiding this comment

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

Spelling error: "abitrary" should be "arbitrary".

Suggested change
* Gets the `n`th `substituteLookupTraits` type for `t`, per some abitrary order.
* Gets the `n`th `substituteLookupTraits` type for `t`, per some arbitrary order.

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

no-change-note-required This PR does not need a change note Rust Pull requests that update Rust code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant