-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Stop using the unpack!
macro in MIR building
#127416
Conversation
One of the things I strongly dislike about |
Some changes occurred in match lowering cc @Nadrieril |
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.
Thanks, that's a lot nicer!
r=me with feedback addressed in one way or another
/// | ||
/// This is similar to writing `let _ = ...`, except that it is also | ||
/// (a) postfix, and (b) searchable. | ||
fn unpack_discard(self) {} |
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.
It's not really unpacking anything. I'm not super convinced by this method, I'd just use let _ = …
as the docs mention but er, it's fine.
@@ -102,8 +102,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { | |||
); | |||
|
|||
// Unpack `BlockAnd<BasicBlock>` into `(then_blk, else_blk)`. | |||
let (then_blk, mut else_blk); | |||
else_blk = unpack!(then_blk = then_and_else_blocks); | |||
let (then_blk, mut else_blk) = then_and_else_blocks.unpack_to_pair(); |
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.
Why not just
let (then_blk, mut else_blk) = then_and_else_blocks.unpack_to_pair(); | |
let BlockAnd(then_blk, mut else_blk) = then_and_else_blocks; |
this would allow us to get rid of unpack_to_pair
which essentially converts a tuple struct to a tuple.
let mut block; | ||
let rv = unpack!(block = f(self)); | ||
|
||
let (mut block, rv) = f(self).unpack_to_pair(); |
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.
let (mut block, rv) = f(self).unpack_to_pair(); | |
let BlockAnd(mut block, rv) = f(self); |
ditto
@@ -128,7 +128,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { | |||
block.and(Operand::Constant(Box::new(constant))) | |||
} | |||
Category::Constant | Category::Place | Category::Rvalue(..) => { | |||
let operand = unpack!(block = this.as_temp(block, scope, expr_id, Mutability::Mut)); | |||
let operand = | |||
this.as_temp(block, scope, expr_id, Mutability::Mut).unpack(&mut block); |
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.
I have mixed feelings about this, the flow of block
is easier to follow with the macro imo. Have we considered:
this.as_temp(block, scope, expr_id, Mutability::Mut).unpack(&mut block); | |
this.as_temp(&mut block, scope, expr_id, Mutability::Mut); |
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.
I quite like using &mut block
as an in+out parameter, and have used it in some of my previous coverage work.
The main reason I didn't try to use it here was to keep this PR as modest as possible. But it's certainly something I'd like to explore.
impl BlockAnd<()> { | ||
/// Unpacks `BlockAnd<()>` into a [`BasicBlock`]. | ||
#[must_use] | ||
fn unpack_block(self) -> BasicBlock { |
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 name wasn't clear to me. How about unpack_unit
?
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.
I might just try unpack_block_and_unit
instead.
After considering feedback, I think my current plan is to split this up into 3 stages:
|
This kind of unpacking can be expressed as an ordinary method on `BlockAnd<()>`.
MIR building: Stop using `unpack!` for `BlockAnd<()>` This is a subset of rust-lang#127416, containing only the parts related to `BlockAnd<()>`. The first patch removes the non-assigning form of the `unpack!` macro, because it is frustratingly inconsistent with the main form. We can replace it with an ordinary method that discards the `()` and returns the block. The second patch then finds all of the remaining code that was using `unpack!` with `BlockAnd<()>`, and updates it to use that new method instead. --- Changes since original review of rust-lang#127416: - Renamed `fn unpack_block` → `fn into_block` - Removed `fn unpack_discard`, replacing it with `let _: BlockAnd<()> = ...` (2 occurrences) - Tweaked `arm_end_blocks` to unpack earlier and build `Vec<BasicBlock>` instead of `Vec<BlockAnd<()>>`
Rollup merge of rust-lang#127472 - Zalathar:block-and-unit, r=fmease MIR building: Stop using `unpack!` for `BlockAnd<()>` This is a subset of rust-lang#127416, containing only the parts related to `BlockAnd<()>`. The first patch removes the non-assigning form of the `unpack!` macro, because it is frustratingly inconsistent with the main form. We can replace it with an ordinary method that discards the `()` and returns the block. The second patch then finds all of the remaining code that was using `unpack!` with `BlockAnd<()>`, and updates it to use that new method instead. --- Changes since original review of rust-lang#127416: - Renamed `fn unpack_block` → `fn into_block` - Removed `fn unpack_discard`, replacing it with `let _: BlockAnd<()> = ...` (2 occurrences) - Tweaked `arm_end_blocks` to unpack earlier and build `Vec<BasicBlock>` instead of `Vec<BlockAnd<()>>`
☔ The latest upstream changes (presumably #127865) made this pull request unmergeable. Please resolve the merge conflicts. |
Having dealt with the So I think I'm going to close this for now. |
MIR building currently has an
unpack!
macro (documented in the dev guide) that is used to unpack values ofBlockAnd<T>
, by assigning the block to a variable and then returning the value. It is used in around 100 places in therustc_mir_build
crate.The downside is that understanding this code requires understanding a custom macro, which to me seems like a poor tradeoff relative to the modest benefits of using the macro.
To explore this, I've prepared a PR that removes the
unpack!
macro completely, replacing it with a small number of ordinary methods on theBlockAnd
type.In the majority of cases, we replace this code:
With this code:
Zulip thread