Code change:
<ins> // check that we don't forget to drop the Box if we early return before // initializing it // ignore-tidy-linelength // ignore-wasm32-bare compiled with panic=abort by default #![feature(box_syntax)] fn test() -> Option<Box<u32>> { Some(box (None?)) } fn main() { test(); } // END RUST SOURCE // START rustc.test.ElaborateDrops.before.mir // fn test() -> std::option::Option<std::boxed::Box<u32>> { //     ... //     bb0: { //         StorageLive(_1); //         StorageLive(_2); //         _2 = Box(u32); //         StorageLive(_3); //         StorageLive(_4); //         _4 = std::option::Option::<u32>::None; //         _3 = const <std::option::Option<u32> as std::ops::Try>::into_result(move _4) -> [return: bb2, unwind: bb3]; //     } //     bb1 (cleanup): { //         resume; //     } //     bb2: { //         StorageDead(_4); //         _5 = discriminant(_3); //         switchInt(move _5) -> [0isize: bb10, 1isize: bb5, otherwise: bb4]; //     } //     bb3 (cleanup): { //         drop(_2) -> bb1; //     } //     bb4: { //         unreachable; //     } //     bb5: { //         StorageLive(_6); //         _6 = ((_3 as Err).0: std::option::NoneError); //         StorageLive(_8); //         StorageLive(_9); //         _9 = _6; //         _8 = const <std::option::NoneError as std::convert::From<std::option::NoneError>>::from(move _9) -> [return: bb7, unwind: bb3]; //     } //     bb6: { //         return; //     } //     bb7: { //         StorageDead(_9); //         _0 = const <std::option::Option<std::boxed::Box<u32>> as std::ops::Try>::from_error(move _8) -> [return: bb8, unwind: bb3]; //     } //     bb8: { //         StorageDead(_8); //         StorageDead(_6); //         drop(_2) -> bb9; //     } //     bb9: { //         StorageDead(_2); //         StorageDead(_1); //         StorageDead(_3); //         goto -> bb6; //     } //     bb10: { //         StorageLive(_10); //         _10 = ((_3 as Ok).0: u32); //         (*_2) = _10; //         StorageDead(_10); //         _1 = move _2; //         drop(_2) -> [return: bb12, unwind: bb11]; //     } //     bb11 (cleanup): { //         drop(_1) -> bb1; //     } //     bb12: { //         StorageDead(_2); //         _0 = std::option::Option::<std::boxed::Box<u32>>::Some(move _1,); //         drop(_1) -> bb13; //     } //     bb13: { //         StorageDead(_1); //         StorageDead(_3); //         goto -> bb6; //     } // } // END rustc.test.ElaborateDrops.before.mir </ins>

Related discussion:
text: mentioned a leak coming from but not , I think I tracked this down to the use of in when given a comma-separated list. I've made that demonstrates it with , if it gets much simpler than this then the leak doesn't occur when built with --release. I'm testing on rustc 1.37.0-nightly ( 2019-06-30) nightly-x8664-pc-windows-msvc, targeting x8664-pc-windows-msvc.
Valgrind Memcheck also reports heap in use at exit on a Linux VM with the test linked above.
Thanks a lot for creating a reduced test case and creating this issue here. I stumbled over the original issue when carg-fuzz reported a memory leak in this code This PR appears to fix the issue This was also with rustc 1.37.0-nightly on Linux. I can check if I can repro with the fuzz test case on other platforms.
Looks like the early return doesn't interact well with box syntax's preallocation. MIR generation issue? cc
should be here: Now that can only schedule drops for locals, we should get the type from to avoid this sort of problem in the future.
Confirmed with my fuzzing test case that the problem is fixed in the latest rust nightly. Thanks for fixing it so quickly.