Closed
Description
Consider the following code:
pub enum NodeColor {
Black = 0,
Red = 1,
}
impl NodeColor {
fn from_usize_fast(i: usize) -> Self {
match i {
0 => NodeColor::Black,
1 => NodeColor::Red,
_ => panic!(),
}
}
fn from_usize(i: usize) -> Option<Self> {
match i {
0 => Some(NodeColor::Black),
1 => Some(NodeColor::Red),
_ => None,
}
}
}
pub fn to_color_fast(c: usize) -> NodeColor {
NodeColor::from_usize_fast(c & 1)
}
pub fn to_color(c: usize) -> NodeColor {
NodeColor::from_usize(c & 1).unwrap()
}
The & 1
ensures the panicking conditions can never happen. This is the corresponding code generated on godbolt with 1.24 beta and 1.25 nightly:
example::to_color_fast:
push rbp
mov rbp, rsp
and edi, 1
mov eax, edi
pop rbp
ret
example::to_color:
mov rcx, rdi
and rcx, 1
and rdi, 1
je .LBB1_1
mov al, 2
sub al, cl
cmp al, 2
jne .LBB1_5
jmp .LBB1_4
.LBB1_1:
xor eax, eax
cmp al, 2
je .LBB1_4
.LBB1_5:
and al, 1
ret
.LBB1_4:
push rbp
mov rbp, rsp
lea rdi, [rip + .Lref.2]
call core::panicking::panic@PLT
ud2
str.0:
.ascii "called `Option::unwrap()` on a `None` value"
str.1:
.ascii "/checkout/src/libcore/option.rs"
.Lref.2:
.quad str.0
.quad 43
.quad str.1
.quad 31
.long 335
.long 21
Note how to_color
goes through hoops. But the most notable thing is that this is actually a regression from 1.24, because versions up to an including 1.23 were actually generating the same code for both functions.