Skip to content

rustc fails to remove dead panic! code when unwrapping an Option #48253

Closed
@glandium

Description

@glandium

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-codegenArea: Code generationC-enhancementCategory: An issue proposing an enhancement or a PR with one.I-slowIssue: Problems and improvements with respect to performance of generated code.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions