Type inference 2.0 - #21795
Draft
hvitved wants to merge 4 commits into
Draft
Conversation
hvitved
force-pushed
the
rust/type-inference-shared
branch
from
May 5, 2026 13:31
8ca252c to
30be9c4
Compare
hvitved
force-pushed
the
rust/type-inference-shared
branch
2 times, most recently
from
May 6, 2026 18:23
a9b24ec to
15c4c30
Compare
hvitved
force-pushed
the
rust/type-inference-shared
branch
2 times, most recently
from
May 7, 2026 18:15
aefd835 to
12256f3
Compare
hvitved
force-pushed
the
rust/type-inference-shared
branch
2 times, most recently
from
May 13, 2026 11:39
657b890 to
8d0c5a3
Compare
hvitved
force-pushed
the
rust/type-inference-shared
branch
3 times, most recently
from
June 4, 2026 09:07
654fd25 to
1d071ac
Compare
hvitved
force-pushed
the
rust/type-inference-shared
branch
3 times, most recently
from
June 8, 2026 18:25
2694a80 to
8093c96
Compare
hvitved
force-pushed
the
rust/type-inference-shared
branch
from
June 15, 2026 19:17
8093c96 to
96a5210
Compare
hvitved
force-pushed
the
rust/type-inference-shared
branch
2 times, most recently
from
June 17, 2026 09:02
981f66e to
ba8029f
Compare
hvitved
force-pushed
the
rust/type-inference-shared
branch
3 times, most recently
from
June 19, 2026 09:10
c3189e9 to
04100d4
Compare
hvitved
force-pushed
the
rust/type-inference-shared
branch
8 times, most recently
from
July 6, 2026 13:04
d518fe7 to
d96e11b
Compare
hvitved
force-pushed
the
rust/type-inference-shared
branch
7 times, most recently
from
July 7, 2026 08:52
13023aa to
d5fa0a3
Compare
hvitved
force-pushed
the
rust/type-inference-shared
branch
from
July 9, 2026 14:29
d5fa0a3 to
02d48fe
Compare
hvitved
force-pushed
the
rust/type-inference-shared
branch
2 times, most recently
from
August 7, 2026 06:26
eb47861 to
6f3e3ba
Compare
hvitved
force-pushed
the
rust/type-inference-shared
branch
5 times, most recently
from
August 17, 2026 18:50
ff6a4e0 to
a43fd10
Compare
Contributor
There was a problem hiding this comment.
Pull request overview
Refactors Rust type inference around the shared library’s new bottom-up and contextual inference architecture.
Changes:
- Adds shared AST inference, contextual typing, closure handling, and diagnostics.
- Reimplements Rust inference through the shared
Make3interface. - Updates Rust tests and consistency expectations.
Show a summary per file
| File | Description |
|---|---|
shared/util/codeql/util/UnboundList.qll |
Adds list append helper. |
shared/typeinference/codeql/typeinference/internal/TypeInference.qll |
Implements shared inference framework. |
rust/ql/test/library-tests/type-inference/type-inference.ql |
Uses shared type-test support. |
rust/ql/test/library-tests/type-inference/pattern_matching.rs |
Updates inference expectations. |
rust/ql/test/library-tests/type-inference/overloading.rs |
Records contextual inference regression. |
rust/ql/test/library-tests/type-inference/main.rs |
Updates coverage and expectations. |
rust/ql/test/library-tests/type-inference/dereference.rs |
Exercises inferred generic arguments. |
rust/ql/test/library-tests/type-inference/CONSISTENCY/PathResolutionConsistency.expected |
Updates generated consistency output. |
rust/ql/test/library-tests/type-inference/closure.rs |
Updates closure expectations. |
rust/ql/test/library-tests/dataflow/sources/web_frameworks/CONSISTENCY/TypeInferenceConsistency.expected |
Updates generated consistency output. |
rust/ql/test/library-tests/dataflow/models/CONSISTENCY/PathResolutionConsistency.expected |
Updates generated consistency output. |
rust/ql/lib/codeql/rust/internal/typeinference/TypeMention.qll |
Adds contextual and constructor type mentions. |
rust/ql/lib/codeql/rust/internal/typeinference/TypeInferenceConsistency.qll |
Adopts shared consistency checks. |
rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll |
Adapts Rust inference to Make3. |
rust/ql/lib/codeql/rust/internal/typeinference/Type.qll |
Introduces generalized pseudo-types. |
rust/ql/lib/codeql/rust/internal/typeinference/FunctionType.qll |
Generalizes pseudo-type filtering. |
rust/ql/lib/codeql/rust/internal/typeinference/BlanketImplementation.qll |
Generalizes pseudo-type filtering. |
rust/ql/lib/codeql/rust/internal/CachedStages.qll |
Uses the shared inference cache stage. |
Review details
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Suppressed comments (1)
shared/typeinference/codeql/typeinference/internal/TypeInference.qll:3345
- Remove the duplicated article.
* Holds if the the textual representation `repr` should be used for `n` in
- Files reviewed: 17/19 changed files
- Comments generated: 4
- Review effort level: Balanced
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR makes a significant overhaul of our QL based implementation of type inference for Rust (hence the tacky PR title). At a high level, a lot of code is moved from the Rust codebase to the shared type inference library (in preparation for unified/Swift), and there is now a very clear distinction between bottom-up type inference and top-down (contextual) type inference.
Before this PR
Shared logic for mapping AST node to types
We introduce a new
Make3parameterization layer to the shared type inference library, which takes as input a definition of AST nodes, including common concepts such as calls and callables, as well as language-specific typing rules, and constructs theinferTypepredicate for recursively inferring the types of AST nodes.The input signature of
Make3is deliberately similar to that of the shared CFG library, and it may be possible to align them at some point.The shared library takes care of typing of many standard constructs such as calls and field accesses, and also has logic for contextual typing and typing of closures.
Bottom-up vs top-down inference
Perhaps the most important change is that we now distinguish between bottom-up type inference (the default) and top-down type inference. For example, in order to infer the type of a conditional expression,
if cond { e1 } else { e2 }, we propagate type information from either of the branchese1ande2into the conditional expression (for simplicity, we do not attempt to calculate least-upper-bound types or similar). This corresponds to the two bottom-up type inference rules:Now, if we have a conditional expression like
where the type of
Default::default()needs to be inferred from the context, wei64, using thecond-thenrule,Default::default()the specialUnknownType(the shared library has logic for identifying calls where (parts of) the return type needs to be inferred from the context), andelsebranch hasUnknownType, we apply thecond-elserule backwards to infer thatDefault::default()has typei64.Note that
UnknownTypecan propagate bottom-up like any other type, which is needed in cases like for examplewhere the
UknownTypewill propagate upwards using two bottom-up steps, and the contextual inference will then propagate thei64type backwards using two reversed steps.Reversal of bottom-up steps happens inside the
ContextualTyping::inferTypeContextualCand0predicate, and contextual propagation into a nodenat type pathpathis only allowed whennhasUnknownTypeat some prefix ofpath, and furthermore ifpathis non-empty, then it must be compatible with an already inferred type (contextually or not). The latter part means that the Rust-specific typing rule for*eexpressions, whenehas a raw pointer type, can be handled by a single bottom-up rule (the first disjunct ofstepLanguageSpecific) instead of two rules in the old implementation.Simplified and shared certain type inference
The logic for inferring types with certainty has been moved inside the shared library (
Make3::Certain), but we no longer attempt to infer certain type inference for calls. This simplifies the implementation significantly, but without resulting in combinatorial explosions because the revised handling of contextual inference is much less prone to explosions.Improved and shared handling of closure typing
Closures typically need to have their parameter and return types inferred from the context in which they are used.
Improved and shared handling of type arguments and type qualifiers
Other minor changes
NeverTypefor!typed expressions; instead we simply useUnknownTypeto indicate that the actual type must be inferred from the context.asyncreturn types are now also taken into account for closures.Note for the reviewer
As usual, commit-by-commit reviewing is encouraged. The first commit (which compiles and works) moves a bunch of logic around in the Rust implementation, which is then removed in the subsequent commit (which doesn't compile). I found that doing it like this resulted in a cleaner diff on the last commit, and it also makes it more clear which parts of the logic are now handled by shared code.
Impact
Future work