Description
Needed toolchains and targets to run the examples (nightly instead of 1.49.0 also works, 1.49.0 is the first release with the regression):
rustup toolchain add 1.48.0
rustup toolchain add 1.49.0
rustup target add thumbv7em-none-eabi --toolchain=1.48.0
rustup target add thumbv7em-none-eabi --toolchain=1.49.0
Code
[package]
name = "foo"
version = "0.1.0"
edition = "2018"
[profile.release]
opt-level = 'z'
codegen-units = 1
panic = 'abort'
lto = true
#![no_std]
#![no_main]
#[no_mangle]
pub extern "C" fn _start() -> ! {
let e: Result<(), ()> = Err(());
e.unwrap();
loop {}
}
#[panic_handler]
fn panic(_info: &core::panic::PanicInfo) -> ! {
loop {}
}
Compiled with:
cargo +1.49.0 build --release --target thumbv7em-none-eabi
I expected the all functions related to panics to be optimized away and the binary size to be relatively small:
Output with toolchain 1.48.0, everything is as expected:
$ nm target/thumbv7em-none-eabi/release/foo
000200e4 T _start
$ du -b target/thumbv7em-none-eabi/release/foo
932 target/thumbv7em-none-eabi/release/foo
The same output when compiled with 1.49.0:
$ nm target/thumbv7em-none-eabi/release/foo
00020154 T _start
00020124 t _ZN45_$LT$$LP$$RP$$u20$as$u20$core..fmt..Debug$GT$3fmt17h83e1a6586aaeb498E
00020160 t _ZN4core3fmt9Formatter3pad17h81a3156a1ec5b453E
00020134 t _ZN4core3ptr13drop_in_place17h3eafc7c4aae35b40E
000204c4 t _ZN4core6option18expect_none_failed17h37d4a90aeed60e0cE
00020138 t _ZN4core6result19Result$LT$T$C$E$GT$6unwrap17hb9125050bd4dfd28E
0002015e t _ZN4core9panicking9panic_fmt17h49c6aff3292697f2E
$ du -b target/thumbv7em-none-eabi/release/foo
11240 target/thumbv7em-none-eabi/release/foo
The binary size blew up by ~10kb. For my embedded program, this increase is too large and for my target and I cannot run the program anymore.
When I inline the code from unwrap()
and call panic!()
manually, the binary size reduces against drastically, though the symbols list still has a panic_fmt
entry that is not optimized away since 1.49.0 (previous toolchains produce a minimal binary with no panic-related code in the binary, as expected):
#![no_std]
#![no_main]
#[no_mangle]
pub extern "C" fn _start() -> ! {
let e: Result<(), ()> = Err(());
match e {
Ok(()) => {}
Err(err) => panic!("error: {:?}", err),
}
loop {}
}
#[panic_handler]
fn panic(_info: &core::panic::PanicInfo) -> ! {
loop {}
}
$ nm target/thumbv7em-none-eabi/release/foo
000200e4 T _start
000200ee t _ZN4core9panicking9panic_fmt17h49c6aff3292697f2E
$ du -b target/thumbv7em-none-eabi/release/foo
1892 target/thumbv7em-none-eabi/release/foo
Version it worked on
Toolchains below 1.49.0
Version with regression
Toolchains since 1.49.0, including today's nightly.