NonZeroU32 :: get이 0을 반환하지 않는다는 것을 옵티 마이저에 알리는 방법은 무엇입니까?

Nov 16 2020

문제가 발생한 코드 샘플은 다음과 같습니다.

pub fn div(x: u32, y: u32) -> u32 {
    x / y
}
pub fn safe_div(x: u32, y: std::num::NonZeroU32) -> u32 {
    x / y.get() // an unchecked division expected
}

Godbolt 의 rustc 1.47.0 -O은 두 기능에 대해 동일한 어셈블리를 생성합니다.

example::div:
        push    rax
        test    esi, esi
        je      .LBB0_2
        mov     eax, edi
        xor     edx, edx
        div     esi
        pop     rcx
        ret
.LBB0_2:
        lea     rdi, [rip + str.0]
        lea     rdx, [rip + .L__unnamed_1]
        mov     esi, 25
        call    qword ptr [rip + core::panicking::panic@GOTPCREL]
        ud2

example::safe_div:
        push    rax
        test    esi, esi
        je      .LBB1_2
        mov     eax, edi
        xor     edx, edx
        div     esi
        pop     rcx
        ret
.LBB1_2:
        lea     rdi, [rip + str.0]
        lea     rdx, [rip + .L__unnamed_2]
        mov     esi, 25
        call    qword ptr [rip + core::panicking::panic@GOTPCREL]
        ud2

그러나 NonZeroU32::get0에 대한 결과 를 확인하는 것은 무의미하다는 것이 정적으로 알려져 있습니다. 어떻게 든 (어쩌면 새로운 창조와 최적화가 믿을 수 struct이에 대한들)을 unsafe덜 방법은?

관련 GitHub 문제 # 49572

답변

1 Ohad Dec 29 2020 at 14:46

귀하의 질문을 본 후 std에 필요한 s를 추가impl 했으므로 이제 야간 릴리스 (및 향후 1.51 안정 릴리스)에서이를 지원합니다!

Godbolt for

pub fn div(x: u32, y: u32) -> u32 {
    x / y
}

pub fn safe_div(x: u32, y: std::num::NonZeroU32) -> u32 {
    x / y
}

pub fn safe_rem(x: u32, y: std::num::NonZeroU32) -> u32 {
    x % y
}

예상되는 어셈블리를 생성합니다.

example::div:
        push    rax
        test    esi, esi
        je      .LBB0_2
        mov     eax, edi
        xor     edx, edx
        div     esi
        pop     rcx
        ret
.LBB0_2:
        lea     rdi, [rip + str.0]
        lea     rdx, [rip + .L__unnamed_1]
        mov     esi, 25
        call    qword ptr [rip + core::panicking::panic@GOTPCREL]
        ud2

example::safe_div:
        mov     eax, edi
        xor     edx, edx
        div     esi
        ret

example::safe_rem:
        mov     eax, edi
        xor     edx, edx
        div     esi
        mov     eax, edx
        ret