Allow unary operand types to be inferred later - #159744
chenyukang wants to merge 4 commits into
Conversation
|
r? @fee1-dead rustbot has assigned @fee1-dead. Use Why was this reviewer chosen?The reviewer was selected based on:
|
|
hard for me to know if this is the right thing to do, hmm.. r? types |
be7c566 to
d13857f
Compare
| let oprnd_t = match unop { | ||
| hir::UnOp::Deref => self.structurally_resolve_type(expr.span, oprnd_t), | ||
| hir::UnOp::Not | hir::UnOp::Neg => self.resolve_vars_with_obligations(oprnd_t), | ||
| }; |
There was a problem hiding this comment.
This definitely needs a comment. But:
- Can we just use
resolve_vars_with_obligationshere for all three? - If not, I think it makes sense to just move these into the match arms, rather than matching twice.
There was a problem hiding this comment.
If we also use resolve_vars_with_obligations for Deref, this code will treat a later-inferred raw pointer as an overloaded Deref, for example this code was reporting a proper E0282:
fn make<T>() -> T {
loop {}
}
fn main() {
let pointer = make();
//~^ ERROR type annotations needed
let value = unsafe { *pointer };
let _: *const u8 = pointer;
let _: u8 = value;
}error[E0282]: type annotations needed
--> src/main.rs:9:9
|
9 | let pointer = make();
| ^^^^^^^
10 | //~^ ERROR type annotations needed
11 | let value = unsafe { *pointer };
| -------- type must be known at this point
|
help: consider giving `pointer` an explicit type
|
9 | let pointer: /* Type */ = make();
| ++++++++++++
For more information about this error, try `rustc --explain E0282`.if we changed to use resolve_vars_with_obligations, the error changed to:
error[E0277]: the trait bound `*const u8: Deref` is not satisfied
--> tests/ui/inference/unary-deref-late-raw-pointer-inference-issue-106138.rs:11:26
|
11 | let value = unsafe { *pointer };
| ^^^^^^^^ the trait `Deref` is not implemented for `*const u8`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0277`.I'm not sure whether there is other cases, we'd better keep structurally_resolve_type for Deref, and I added this test code as a unit test.
|
This should also close #26830, I think? Also, for what it's worth, this would slightly expand the surface area of #114380 (also reported as #151202). Currently, the following fails to type-check: fn main() {
let input = Default::default();
let output = !{ input };
let _: u8 = output;
println!("{}", std::any::type_name_of_val(&input));
}Under this PR, it would compile successfully and print |
d13857f to
5fd2ec6
Compare
This comment has been minimized.
This comment has been minimized.
5fd2ec6 to
26b55d3
Compare
This comment has been minimized.
This comment has been minimized.
I added a test in this PR for #26830 |
|
@rustbot ready |
|
@rfcbot merge types Minor change here. This |
|
@jackh726 has proposed to merge this. The next step is review by the rest of the tagged team members: Concerns:
Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! See this document for info about what commands tagged team members can give me. |
|
🔔 This is now entering its final comment period, as per the review above. 🔔 |
d85b37c to
8a8c40a
Compare
This comment has been minimized.
This comment has been minimized.
8a8c40a to
9bfeb05
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
9bfeb05 to
108faae
Compare
|
@rfcbot concern lang-decision @rust-lang/lang wants to discuss this further |
This comment has been minimized.
This comment has been minimized.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
|
@rfcbot resolve lang-decision see poll |
|
🔔 This is now entering its final comment period, as per the review above. 🔔 |
|
@rfcbot poll lang We discussed this in the lang-team meeting. Meeting consensus was that we are ok with this and so we decided not to create a rfcbot merge (but I'm using the poll so people can signal their assent). We discussed two questions: what is the motivation for this change and are we ok with not having auto-deref here. The answer to both came down to a consistency argument. We felt that !x is conceptually similar to binary operators like x + y that consume a value and not similar to place-operators like index and field access. This change (iiuc) makes the type checker for ! behave more analogously to + (i.e., it consumes the value it is applied to directly and it creates a pending trait obligation that can be constrained at any point during method type checking). Similarly, + does not autoderef. Therefore, this makes sense. |
|
@nikomatsakis has asked teams: T-lang, for consensus on: |
The note from the meeting that I found particularly persuasive is that place projections are already a distinct category from value operations, and things like Plus we have existing impls like |
108faae to
4b2dec1
Compare
|
This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed. Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers. |
View all comments
Fixes #106138
Fix the inference issue by allowing
NotandNegoperand types to remain unresolved until obligations and constraints can determine them.closes #26830