Description
I made a mistake in some code, which essentially made everything statically panic. Which is fine. The problem is that in exactly one instance of the same kind of code, rustc actually failed to remove the non-panicking branch. Note this /might/ be a duplicate of #48253. At least, similarly to #48253, it appears to be a regression in 1.24.0, according to godbolt.
A copy/pastable-to-godbolt and reduced version of the mistaken code is:
#[allow(non_camel_case_types)]
pub enum c_void {
// Two dummy variants so the #[repr] attribute can be used.
#[doc(hidden)]
__variant1,
#[doc(hidden)]
__variant2,
}
pub extern "C" fn malloc(size: usize) -> *mut c_void {
FUNCS.malloc.unwrap()(size)
}
pub extern "C" fn calloc(nmemb: usize, size: usize) -> *mut c_void {
FUNCS.calloc.unwrap()(nmemb, size)
}
pub extern "C" fn realloc(ptr: *mut c_void, size: usize) -> *mut c_void {
FUNCS.realloc.unwrap()(ptr, size)
}
pub struct MallocTable {
malloc: Option<extern "C" fn(usize) -> *mut c_void>,
calloc: Option<extern "C" fn(usize, usize) -> *mut c_void>,
realloc: Option<extern "C" fn(*mut c_void, usize) -> *mut c_void>,
}
pub static FUNCS: MallocTable =
MallocTable{malloc: None,
calloc: None,
realloc: None};
This generates the following assembly (skipping the data fields):
example::malloc:
push rbp
mov rbp, rsp
mov rax, qword ptr [rip + example::FUNCS@GOTPCREL]
mov rax, qword ptr [rax]
test rax, rax
je .LBB0_1
call rax
pop rbp
ret
.LBB0_1:
lea rdi, [rip + .Lref.2]
call core::panicking::panic@PLT
ud2
ud2
ud2
example::calloc:
push rbp
mov rbp, rsp
lea rdi, [rip + .Lref.2]
call core::panicking::panic@PLT
ud2
ud2
ud2
example::realloc:
push rbp
mov rbp, rsp
lea rdi, [rip + .Lref.2]
call core::panicking::panic@PLT
ud2
ud2
ud2
Note how calloc
and realloc
are properly just directly panicking because FUNCS is immutable and initialized with empty function pointers, leading to unwrap always panicking, but the same doesn't happen for malloc
. Interestingly, removing realloc
makes malloc
optimized the same way as the others.
The code generated by 1.23.0 was:
example::malloc:
push rbp
mov rbp, rsp
lea rdi, [rip + ref.2]
call core::panicking::panic@PLT
ud2
example::calloc:
push rbp
mov rbp, rsp
lea rdi, [rip + ref.2]
call core::panicking::panic@PLT
ud2
example::realloc:
push rbp
mov rbp, rsp
lea rdi, [rip + ref.2]
call core::panicking::panic@PLT
ud2