-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Rust: Also use specialized types when inferring types for calls #21027
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?
Rust: Also use specialized types when inferring types for calls #21027
Conversation
3776f1f to
846ae48
Compare
846ae48 to
14344e7
Compare
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 enhances type inference for trait method calls by using specialized types when a trait method with a default implementation is invoked. Previously, type parameters like Self remained unresolved in parameter types, leading to ambiguous type inference. Now, these type parameters are specialized to their concrete types (e.g., Self becomes i32 when called on an i32 value), improving type inference accuracy.
Key changes:
- Introduced
FunctionDeclarationclass to handle both free functions and associated functions with optional trait/impl context - Refactored method and non-method call matching to use specialized declaration types that track the impl/trait context
- Simplified
InvokedClosureExprby leveraging existingDynamicCallExprlogic
Reviewed changes
Copilot reviewed 3 out of 4 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| rust/ql/test/library-tests/type-inference/main.rs | Removed obsolete comment about missing type inference for MyOption<S>, now correctly inferred |
| rust/ql/test/library-tests/type-inference/CONSISTENCY/PathResolutionConsistency.expected | Updated line numbers to reflect comment removal from main.rs |
| rust/ql/lib/codeql/rust/internal/TypeInference.qll | Core implementation: added FunctionDeclaration abstraction, refactored matching modules to track impl/trait context for type specialization |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
I think I need to understand the motivation behind this a bit better. The example doesn't type check 😉 and it's not entirely clear that the current behavior is wrong. The type of let x = 0;
let y: usize = 1;
let z = x.max(y);I think it would be great to update the PR with some tests that show the difference that this PR makes. I guess the good cases might involve implicit coercions in the argument? |
14344e7 to
86a4d42
Compare
Sorry, I should have mentioned: It is to avoid inference explosion on #20973.
Sorry about that; I have (force) pushed a test, so we can see the effect of this PR.
My reasoning here is that since we use the type of the receiver to lookup method call targets, then it should be the receivers alone that determine the value of the |
Trait methods with default implementations have their types specialized when performing method resolution, that is, when matching the type of a receiver against the type of the
selfparameter. This PR does the same when inferring types of calls, for example inthe target of
x.max(y)is https://doc.rust-lang.org/std/cmp/trait.Ord.html#method.max, and before this PR the type of theotherparameter would remainSelf, which meant thatzwould have both typesi32andusize. After this PR, the type ofotheris specialized toi32, which meanszwill only have typei32.DCA is uneventful.