-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Rust: Fix context-based type inference explosion #21217
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
base: main
Are you sure you want to change the base?
Conversation
38929dd to
50ce393
Compare
| hasTypeConstraint(tt, constraint) and | ||
| t = getTypeAt(tt, path) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This conjunction has non-linear recursion, hence the magic'ed version of hasTypeConstraint.
There was a problem hiding this 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 type inference explosion issue in Rust queries by correcting two bugs in the type inference implementation:
- Path resolution bug: Changed
getASuccessor(_)togetAnAssocItem()to correctly resolve trait functions only from the trait itself, not from sub-traits - Context-based return type checking: Enhanced the logic to only use return type for disambiguation when all argument positions are trivially satisfied
Changes:
- Fixed trait function resolution to prevent matching sub-trait implementations
- Added logic to check return type matches calling context for polymorphic functions
- Refactored Input modules into a unified structure
- Added regression test for the
Default::default()andFrom::from()pattern
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| shared/typeinference/codeql/typeinference/internal/TypeInference.qll | Added helper predicate with pragma[nomagic] to optimize type constraint checking |
| rust/ql/lib/codeql/rust/internal/typeinference/TypeInference.qll | Fixed getASuccessor → getAnAssocItem bug, merged Input modules, fixed parameter ordering in context typing |
| rust/ql/lib/codeql/rust/internal/typeinference/FunctionOverloading.qll | Split predicate and added return type disambiguation logic |
| rust/ql/test/library-tests/type-inference/main.rs | Added regression test for from_default module |
| rust/ql/test/library-tests/type-inference/type-inference.expected | Updated expected test output |
| rust/ql/test/query-tests/security/CWE-312/CONSISTENCY/PathResolutionConsistency.expected | Removed spurious multiple resolution error |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
geoffw0
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks helpful.
Is there a reason this is still draft?
I would like to rework this a bit more; while it does fix the example posted in the description, there are still cases resulting in timeouts that I would like to cover as well. |
50ce393 to
3244471
Compare
c1b3551 to
9079fde
Compare
26cb1d9 to
ef9ba0c
Compare
ef9ba0c to
4b6311f
Compare
4b6311f to
b05fe36
Compare
Before
```
Evaluated relational algebra for predicate _PathResolution::ImplItemNode.getTraitPath/0#dispred#3b7d1cb6_PathResolution::ImplOrTraitItemNode.ge__#shared@0d3de6d9 with tuple counts:
395360270 ~2% {5} r1 = JOIN Type::TAssociatedTypeTypeParameter#6da9e52a WITH `PathResolution::ImplItemNode.getTraitPath/0#dispred#3b7d1cb6` CARTESIAN PRODUCT OUTPUT Rhs.0, Lhs.0, Lhs.1, Lhs.2, Rhs.1
1274237644 ~0% {6} | JOIN WITH `PathResolution::ItemNode.getASuccessor/1#8f430f71` ON FIRST 1 OUTPUT Lhs.1, Lhs.2, Lhs.3, Lhs.4, Rhs.1, Rhs.2
1274237644 ~0% {6} | JOIN WITH PathResolution::TraitItemNode#8d4ce62d ON FIRST 1 OUTPUT Lhs.0, Lhs.4, Lhs.1, Lhs.2, Lhs.3, Lhs.5
6984871 ~0% {5} | JOIN WITH `PathResolution::ImplOrTraitItemNode.getAssocItem/1#f77bb9ed` ON FIRST 3 OUTPUT Lhs.2, Lhs.0, Lhs.3, Lhs.4, Lhs.5
6984871 ~0% {4} | JOIN WITH TypeAlias::Generated::TypeAlias#1ca97780 ON FIRST 1 OUTPUT Lhs.4, Lhs.1, Lhs.2, Lhs.3
6076675 ~0% {4} | JOIN WITH `TypeAlias::Generated::TypeAlias.getTypeRepr/0#dispred#5fd7e521` ON FIRST 1 OUTPUT Rhs.1, Lhs.1, Lhs.2, Lhs.3
return r1
```
After
```
Evaluated relational algebra for predicate _PathResolution::ImplItemNode.getTraitPath/0#dispred#3b7d1cb6_PathResolution::ImplOrTraitItemNode.ge__#shared@760e0499 with tuple counts:
443292 ~2% {3} r1 = SCAN `PathResolution::ImplOrTraitItemNode.getAssocItem/1#f77bb9ed` OUTPUT In.0, In.2, In.1
1258 ~1% {3} | JOIN WITH Type::TAssociatedTypeTypeParameter#6da9e52a ON FIRST 2 OUTPUT Lhs.2, Lhs.0, Rhs.2
13656944 ~3% {4} | JOIN WITH `PathResolution::ItemNode.getASuccessor/1#8f430f71_102#join_rhs` ON FIRST 1 OUTPUT Rhs.1, Lhs.1, Lhs.2, Rhs.2
6984871 ~0% {4} | JOIN WITH `PathResolution::ImplItemNode.getTraitPath/0#dispred#3b7d1cb6` ON FIRST 1 OUTPUT Lhs.3, Lhs.1, Lhs.2, Rhs.1
6076675 ~0% {4} | JOIN WITH `TypeAlias::Generated::TypeAlias.getTypeRepr/0#dispred#5fd7e521` ON FIRST 1 OUTPUT Rhs.1, Lhs.1, Lhs.2, Lhs.3
return r1
```
The following simple program would make our type inference implementation explode:
Firstly, because of a
getSuccessorvsgetAssocItembug,From::fromwould allow for any sub trait ofFrom, for example theInttrait, which meant thatxcould be inferred to have typebool. Secondly, since manyfromimplementations are polymorphic in their argument, we should really be checking that the return type matches the type of the calling context.This PR makes those two adjustments, and adds the regression test.
DCA looks good; we loose some call edges, but nothing too serious.