Change:
The doesn't have any effect. (Labeling because this prevents codegen of the like . Which may result in a few extra instructions being emitted to move registers and jump to the return block for cg_clif.) modify labels: +A-mir +A-mir-opt +A-cranelift
We already have a pass that propagates the terminator, it should be possible to make it handle as well. (however can leave sideeffects visible to the caller, so maybe this should be a proper dead code elimination pass instead)
For background, this is a side-effect of (see the MIR diagram in the PR summary) and . The MIR for the above example used to contain a frivolous open drop of . After my changes to drop elaboration, all branches of the open drop become no-op s, which are then removed by the pass. The read of the discriminant as part of the open drop remains, however. To my knowledge, we don't have a dead-code elimination pass for the MIR, which would be the proper way to handle this.

Discussion:
if location.statement_index != block.statements.len() { let stmt = &block.statements[location.statement_index]; <del> if let StatementKind::Assign(box (p, Rvalue::Use(Operand::Constant(c)))) = &stmt.kind { match c.literal.val { // Keep assignments from unevaluated constants around, since the evaluation // may report errors, even if the use of the constant is dead code. ty::ConstKind::Unevaluated(..) => {} _ => { if !p.is_indirect() { trace!("skipping store of const value {:?} to {:?}", c, p); return; </del> <ins> if let StatementKind::Assign(box (dest, rvalue)) = &stmt.kind { if !dest.is_indirect() && dest.local == *local { if let Rvalue::Use(Operand::Constant(c)) = rvalue { match c.literal.val { // Keep assignments from unevaluated constants around, since the // evaluation may report errors, even if the use of the constant // is dead code. ty::ConstKind::Unevaluated(..) => {} _ => { trace!("skipping store of const value {:?} to {:?}", c, dest); return; } </ins> } <ins> } else if let Rvalue::Discriminant(d) = rvalue { trace!("skipping store of discriminant value {:?} to {:?}", d, dest); return; </ins> } } }

<ins> fn map(x: Option<Box<()>>) -> Option<Box<()>> { match x { None => None, Some(x) => Some(x), } } fn main() { map(None); } // EMIT_MIR rustc.map.SimplifyLocals.diff </ins>

<ins> - // MIR for `map` before SimplifyLocals + // MIR for `map` after SimplifyLocals fn map(_1: std::option::Option<std::boxed::Box<()>>) -> std::option::Option<std::boxed::Box<()>> { debug x => _1;                       // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:1:8: 1:9 let mut _0: std::option::Option<std::boxed::Box<()>>; // return place in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:1:31: 1:46 let mut _2: isize;                   // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:9: 3:13 let _3: std::boxed::Box<()>;         // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:4:14: 4:15 -     let mut _4: std::boxed::Box<()>;     // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:4:25: 4:26 -     let mut _5: isize;                   // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:6:1: 6:2 -     let mut _6: isize;                   // in scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:6:1: 6:2 scope 1 { debug x => _3;                   // in scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:4:14: 4:15 } bb0: { _2 = discriminant(_1);           // bb0[0]: scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:9: 3:13 switchInt(move _2) -> [0isize: bb2, otherwise: bb1]; // bb0[1]: scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:9: 3:13 } bb1: { _0 = move _1;                    // bb1[0]: scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:4:20: 4:27 goto -> bb3;                     // bb1[1]: scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:2:5: 5:6 } bb2: { discriminant(_0) = 0;            // bb2[0]: scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:17: 3:21 goto -> bb3;                     // bb2[1]: scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:2:5: 5:6 } bb3: { -         _5 = discriminant(_1);           // bb3[0]: scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:6:1: 6:2 -         return;                          // bb3[1]: scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:6:2: 6:2 +         return;                          // bb3[0]: scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:6:2: 6:2 } } </ins>

// fn try_identity(_1: std::result::Result<u32, i32>) -> std::result::Result<u32, i32> { //     debug x => _1; //     let mut _0: std::result::Result<u32, i32>; <del> //     let mut _2: isize; //     let _3: i32; //     let _4: u32; </del> <ins> //     let _2: i32; //     let _3: u32; </ins> //     scope 1 { <del> //         debug y => _4; </del> <ins> //         debug y => _3; </ins> //     } //     scope 2 { <del> //         debug err => _3; </del> <ins> //         debug err => _2; </ins> //         scope 3 { //             scope 7 { <del> //                 debug t => _3; </del> <ins> //                 debug t => _2; </ins> //             } //             scope 8 { <del> //                 debug v => _3; </del> <ins> //                 debug v => _2; </ins> //             } //         } //     } //     scope 4 { <del> //         debug val => _4; </del> <ins> //         debug val => _3; </ins> //         scope 5 { //         } //     }

//         debug self => _1; //     } //     bb0: { <del> //         _2 = discriminant(_1); </del> //         _0 = move _1; //         return; //     }