Stop using the unpack! macro in MIR building#127416
Stop using the unpack! macro in MIR building#127416Zalathar wants to merge 3 commits intorust-lang:masterfrom
unpack! macro in MIR building#127416Conversation
|
One of the things I strongly dislike about |
|
Some changes occurred in match lowering cc @Nadrieril |
fmease
left a comment
There was a problem hiding this comment.
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.
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.
| // 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.
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.
| let (mut block, rv) = f(self).unpack_to_pair(); | |
| let BlockAnd(mut block, rv) = f(self); |
ditto
| 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.
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.
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.
The name wasn't clear to me. How about unpack_unit?
There was a problem hiding this comment.
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_buildcrate.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 theBlockAndtype.In the majority of cases, we replace this code:
With this code:
Zulip thread