Skip to content

Array bounds check not elided when indexing with ZST enum #82871

Closed
@moxian

Description

@moxian

I tried this code:

#[repr(C)]
pub enum E {
    A, 
}

pub fn index(x: &[u32; 3], ind: E) -> u32{
    x[ind as usize]
}

I expected to see this happen: no bounds check

Instead, this happened (with -C opt-level=3)

example::index:
        push    rax
        mov     rax, rdi
        mov     edi, esi
        cmp     esi, 2
        ja      .LBB0_2
        mov     eax, dword ptr [rax + 4*rdi]
        pop     rcx
        ret
.LBB0_2:
        lea     rdx, [rip + .L__unnamed_1]
        mov     esi, 3
        call    qword ptr [rip + core::panicking::panic_bounds_check@GOTPCREL]
        ud2

However adding more variants to the enum makes the bound check go away:

#[repr(C)]
pub enum E {
    A,
    B,
}

pub fn index(x: &[u32; 3], ind: E) -> u32{
    x[ind as usize]
}

generates:

example::index:
        mov     eax, esi
        mov     eax, dword ptr [rdi + 4*rax]
        ret

Here's a godbolt link to play around further: https://rust.godbolt.org/z/dK9e1z
The MIR of the two cases is identical, but the llvm IR in ZST case is lacking @llvm.assume, which I assume (heh!) leads to the bounds check being preserved. (However i don't actually understand LLVM, I'm just reading the diff...)

Meta

rustc 1.50.0

This sounds very closely related to #13926, but I'm not actually sure if it is. Please reroute as appropriate.

Metadata

Metadata

Assignees

Labels

C-bugCategory: This is a bug.E-easyCall for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue.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