Skip to content

Rust: Unify call resolution logic#21355

Open
hvitved wants to merge 2 commits intogithub:mainfrom
hvitved:rust/type-inference-unify
Open

Rust: Unify call resolution logic#21355
hvitved wants to merge 2 commits intogithub:mainfrom
hvitved:rust/type-inference-unify

Conversation

@hvitved
Copy link
Contributor

@hvitved hvitved commented Feb 23, 2026

Overview

I was investigating a type inference performance issue on tayu0110/exml, and came up with a small reproduction case (first commit, regressions.rs), which revealed that we are not correctly handling resolution of calls to non-method associated functions when the argument used to resolve the call has multiple trait bounds.

For method calls we are handling multiple trait bounds correctly since #21043, so the obvious solution would be to replicate this logic for non-method calls as well.

However, with #21217 we have:

As for calls to methods, we now also always check the Self type for calls to associated non-methods f.

which allows us to instead unify the resolution logic for calls to methods (module MethodResolution) and calls to non-methods (module NonMethodResolution) in a single implementation encompassing calls to all associated functions (module AssocFunctionResolution). Calls to non-associated functions does not rely on type inference (but instead on path resolution only), which is handled in the class NonAssocCallExpr.

Just like we can unify call resolution logic, we can also unify propagation of type information through resolved calls for calls to methods (module MethodCallMatching) and calls to non-methods (module NonMethodCallMatching) in a single implementation (module FunctionCallMatching), and type inference for tuple-like variant and struct constructions such as Option::Some(42) is then done in a separate module TupleLikeConstructionMatching.

A common theme in the changes on this PR is that we use function-call syntax adjusted positions for both calls and functions, which means that for example x in x.m() and self in fn method(self,...) have position 0 instead of position self. This change is needed since now that we are no longer distinguishing between methods and non-methods in resolution, we cannot know up front whether x in Foo::m(x) should map to a self parameter (when m is a method) or the first positional parameter (when m is not a method).

Impact

  • The performance issue on tayu0110/exml is resolved, which was the original motivation for this work.
  • Changes to expected test output show that we additionally fix missing call targets and remove spurious call targets.
  • We eliminate code duplication in TypeInference.qll, a net reduction in 100 lines, reducing maintenance burden going forward.
  • DCA shows:
    • an increase in Percentage of calls with call target from 83.02 % to 84.28 while at the same time reducing Path resolution inconsistencies, which means that the added call targets are genuinely new resolved calls.
    • 259 new alerts across all projects.
    • Overall almost no performance changes, except a significant regression on rust; this happens because we are now resolving more calls, making the data flow computation for AccessAfterLifetime.ql much more expensive. Turning off trait dispatch makes the query run fast again, which suggests that we should at some point consider doing type-based pruning like for other static languages. This, however, is not the responsibility of the type inference library.

@github-actions github-actions bot added the Rust Pull requests that update Rust code label Feb 23, 2026
@hvitved hvitved force-pushed the rust/type-inference-unify branch from 46c92f3 to ed0c757 Compare February 23, 2026 18:17
@hvitved hvitved force-pushed the rust/type-inference-unify branch from 786d5bd to 9a87116 Compare February 23, 2026 21:01
@hvitved hvitved force-pushed the rust/type-inference-unify branch 4 times, most recently from 0eaade9 to 237b806 Compare February 25, 2026 07:49
@hvitved hvitved force-pushed the rust/type-inference-unify branch from 237b806 to b647e6f Compare February 25, 2026 08:44
@hvitved hvitved force-pushed the rust/type-inference-unify branch 7 times, most recently from 7bd16e0 to 331d5d5 Compare February 27, 2026 13:54
@hvitved hvitved force-pushed the rust/type-inference-unify branch 7 times, most recently from d7ac787 to eeb8264 Compare March 4, 2026 11:17
@hvitved hvitved force-pushed the rust/type-inference-unify branch 3 times, most recently from 9db7fbd to aca2ce0 Compare March 5, 2026 08:45
@hvitved hvitved force-pushed the rust/type-inference-unify branch 8 times, most recently from 27d4522 to 6a6ccd9 Compare March 10, 2026 09:41
@hvitved hvitved added the no-change-note-required This PR does not need a change note label Mar 10, 2026
@hvitved hvitved marked this pull request as ready for review March 10, 2026 10:03
@hvitved hvitved requested review from a team as code owners March 10, 2026 10:03
@hvitved hvitved requested review from Copilot and paldepind March 10, 2026 10: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 refactors Rust call resolution/type inference to use a unified implementation for resolving all associated function calls (methods and non-method associated functions), addressing missed/incorrect call targets in cases involving multiple trait bounds and reducing duplication in the type inference library.

Changes:

  • Unifies method and non-method associated-function resolution into a single associated-function-based resolver and matching pipeline, using function-call-syntax–adjusted positions throughout.
  • Adjusts blanket-implementation handling and supporting utilities used by call resolution/type inference.
  • Updates/extends Rust type-inference, dataflow, and security query tests to reflect improved call-target resolution and taint/value flows.

Reviewed changes

Copilot reviewed 14 out of 15 changed files in this pull request and generated no comments.

Show a summary per file
File Description
shared/util/codeql/util/Option.qll Adds a none_() constructor to complement some(...), used by new resolution logic.
rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll Major refactor: unifies associated-function resolution/matching and splits tuple-like construction matching.
rust/ql/lib/codeql/rust/internal/typeinference/FunctionType.qll Updates function-position “function-call adjusted” logic used by the unified resolution/matching.
rust/ql/lib/codeql/rust/internal/typeinference/BlanketImplementation.qll Tightens blanket-like implementation identification used during resolution.
rust/ql/lib/codeql/rust/elements/internal/InvocationExprImpl.qll Adjusts argument-position domain for invocation expressions.
rust/ql/lib/codeql/rust/elements/internal/ImplImpl.qll Adds isInherent() helper for impl blocks.
rust/ql/test/library-tests/type-inference/regressions.rs Adds a regression covering associated-function resolution with multiple trait bounds.
rust/ql/test/library-tests/type-inference/overloading.rs Adds overloading scenarios for inherent-vs-trait associated-function targeting.
rust/ql/test/library-tests/type-inference/type-inference.expected Updates expected type inference results for new resolution behavior.
rust/ql/test/library-tests/dataflow/taint/main.rs Updates inline flow expectations where call targets now resolve.
rust/ql/test/library-tests/dataflow/taint/inline-taint-flow.expected Updates expected taint-flow graph to reflect newly resolved call edges.
rust/ql/test/library-tests/dataflow/sources/net/CONSISTENCY/PathResolutionConsistency.expected Removes previously-expected multiple-resolved-target consistency entries.
rust/ql/test/query-tests/security/CWE-327/BrokenCryptoAlgorithm/test_cipher.rs Updates expectations for newly detected weak-crypto alerts.
rust/ql/test/query-tests/security/CWE-327/BrokenCryptoAlgorithm/BrokenCryptoAlgorithm.expected Updates expected alert set/locations after improved call resolution.
rust/ql/test/query-tests/security/CWE-327/BrokenCryptoAlgorithm/CONSISTENCY/PathResolutionConsistency.expected Removes now-resolved path-resolution inconsistency expectation.

@hvitved hvitved force-pushed the rust/type-inference-unify branch from 6a6ccd9 to b03dcdd Compare March 10, 2026 19:16
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.

2 participants