-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Rust: Distinguish &mut T from &T in type inference
#20973
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: Distinguish &mut T from &T in type inference
#20973
Conversation
f8e7c13 to
a74c4e5
Compare
b13cf2b to
c62c00a
Compare
078f152 to
d1eb4ff
Compare
19551e3 to
5682de7
Compare
5682de7 to
99b0d0c
Compare
| string derefChain, boolean borrow, TypePath path | ||
| ) { | ||
| result = substituteLookupTraits(this.getACandidateReceiverTypeAt(derefChain, borrow, path)) | ||
| Type getANonPseudoCandidateReceiverTypeAt(string derefChain, BorrowKind borrow, TypePath path) { |
Check warning
Code scanning / CodeQL
Missing QLDoc for parameter Warning
e30b9f7 to
85c8f0d
Compare
85c8f0d to
63e381c
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 improves Rust type inference by distinguishing between mutable references (&mut T) and shared references (&T), which were previously treated as a single RefType. The change significantly reduces path resolution inconsistencies by eliminating ambiguity when methods are implemented for both borrow types.
Key Changes:
- Split
RefTypeintoRefSharedTypeandRefMutTypein the type system - Updated method resolution to prioritize shared borrows over mutable borrows when constructing candidate receiver types
- Enhanced type inference to track borrow mutability through patterns, reference expressions, and method calls
Reviewed changes
Copilot reviewed 34 out of 34 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| rust/ql/lib/codeql/rust/internal/Type.qll | Refactored RefType into an abstract base class with RefSharedType and RefMutType subclasses |
| rust/ql/lib/codeql/rust/frameworks/stdlib/Builtins.qll | Updated builtin type definitions to distinguish shared and mutable reference types |
| rust/ql/lib/codeql/rust/internal/TypeInference.qll | Enhanced method resolution with BorrowKind enum to track shared/mutable borrows, prioritizing shared borrows in candidate generation |
| rust/ql/lib/codeql/rust/internal/TypeMention.qll | Updated type mention resolution to correctly handle mutable vs shared references |
| rust/ql/lib/codeql/rust/internal/PathResolution.qll | Updated builtin type resolution to distinguish reference types based on mutability |
| rust/ql/lib/codeql/rust/elements/internal/OperationImpl.qll | Added TODO comment for handling DerefMut trait |
| rust/ql/test/**/*.expected | Updated test expectations reflecting reduced path resolution inconsistencies |
| rust/ql/test/**/main.rs, dereference.rs, pattern_matching.rs | Updated test annotations to reflect correct TRefMut types |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // todo: handle `core::ops::deref::DerefMut` | ||
| op = "*" and path = "core::ops::deref::Deref" and method = "deref" and borrows = 1 |
Copilot
AI
Dec 17, 2025
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.
The TODO comment indicates that core::ops::deref::DerefMut is not yet handled. Since this PR introduces distinction between mutable and shared borrows, the dereference operator for mutable references should also be handled to properly support the DerefMut trait, which is used when dereferencing &mut T types. Without this, type inference for operations on mutable references may be incomplete.
| // todo: handle `core::ops::deref::DerefMut` | |
| op = "*" and path = "core::ops::deref::Deref" and method = "deref" and borrows = 1 | |
| op = "*" and path = "core::ops::deref::Deref" and method = "deref" and borrows = 1 | |
| or | |
| op = "*" and path = "core::ops::deref::DerefMut" and method = "deref_mut" and borrows = 1 |
Does what the PR title says, and additionally makes sure to prioritize shared borrows over mutable borrows when constructing candidate receiver types.
DCA is excellent; as expected, we see a large decrease in resolution inconsistencies, because we no longer have resolution overlap for methods with implementations for both shared and mutable borrows.