diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index 3eb9d23a32a25..05ec10f180b95 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -30,6 +30,7 @@ pub mod no_landing_pads; pub mod promote_consts; pub mod qualify_min_const_fn; pub mod remove_noop_landing_pads; +pub mod remove_unit_storage; pub mod rustc_peek; pub mod simplify; pub mod simplify_branches; @@ -299,6 +300,7 @@ fn run_optimization_passes<'tcx>( // From here on out, regions are gone. &erase_regions::EraseRegions, // Optimizations begin. + &remove_unit_storage::RemoveUnitStorage, &unreachable_prop::UnreachablePropagation, &uninhabited_enum_branching::UninhabitedEnumBranching, &simplify::SimplifyCfg::new("after-uninhabited-enum-branching"), diff --git a/src/librustc_mir/transform/remove_unit_storage.rs b/src/librustc_mir/transform/remove_unit_storage.rs new file mode 100644 index 0000000000000..0bc37baf9f04c --- /dev/null +++ b/src/librustc_mir/transform/remove_unit_storage.rs @@ -0,0 +1,29 @@ +//! The `RemoveUnitStorage` pass removes `StorageLive` and `StorageDead` statements +//! which operates on locals of type `()`. + +use crate::transform::{MirPass, MirSource}; +use rustc::mir::*; +use rustc::ty::TyCtxt; + +pub struct RemoveUnitStorage; + +impl<'tcx> MirPass<'tcx> for RemoveUnitStorage { + fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>) { + // This pass removes UB, so only run it when optimizations are enabled. + if tcx.sess.opts.debugging_opts.mir_opt_level == 0 { + return; + } + + let (blocks, locals) = body.basic_blocks_and_local_decls_mut(); + + for block in blocks { + for stmt in &mut block.statements { + if let StatementKind::StorageLive(l) | StatementKind::StorageDead(l) = stmt.kind { + if locals[l].ty == tcx.types.unit { + stmt.make_nop(); + } + } + } + } + } +} diff --git a/src/test/ui/consts/dangling-alloc-id-ice.rs b/src/test/ui/consts/dangling-alloc-id-ice.rs index dbc50f1fbd4b4..7970758e188f4 100644 --- a/src/test/ui/consts/dangling-alloc-id-ice.rs +++ b/src/test/ui/consts/dangling-alloc-id-ice.rs @@ -1,11 +1,14 @@ +// run-pass // https://github.com/rust-lang/rust/issues/55223 union Foo<'a> { + //~^ WARN union is never used y: &'a (), long_live_the_unit: &'static (), } -const FOO: &() = { //~ ERROR any use of this value will cause an error +const FOO: &() = { + //~^ WARN constant item is never used let y = (); unsafe { Foo { y: &y }.long_live_the_unit } }; diff --git a/src/test/ui/consts/dangling-alloc-id-ice.stderr b/src/test/ui/consts/dangling-alloc-id-ice.stderr index 0e213555052c8..06d32b34e1842 100644 --- a/src/test/ui/consts/dangling-alloc-id-ice.stderr +++ b/src/test/ui/consts/dangling-alloc-id-ice.stderr @@ -1,13 +1,18 @@ -error: any use of this value will cause an error - --> $DIR/dangling-alloc-id-ice.rs:8:1 +warning: union is never used: `Foo` + --> $DIR/dangling-alloc-id-ice.rs:4:7 + | +LL | union Foo<'a> { + | ^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: constant item is never used: `FOO` + --> $DIR/dangling-alloc-id-ice.rs:10:1 | LL | / const FOO: &() = { +LL | | LL | | let y = (); LL | | unsafe { Foo { y: &y }.long_live_the_unit } LL | | }; - | |__^ encountered dangling pointer in final constant - | - = note: `#[deny(const_err)]` on by default - -error: aborting due to previous error + | |__^