Closed
Description
This code:
use std::ptr::NonNull;
// type Value = NonNull<i64>;
type Value = *const i64;
pub fn pop2(stack: &mut Vec<Value>) -> (Value, Value) {
assert!(stack.len() >= 2);
let b = stack.pop().unwrap();
let a = stack.pop().unwrap();
(a, b)
}
optimizes differently based on if Value
is *const i64
or NonNull<i64>
(or apparently any other type with niche optimizations, like &i64
or NonZeroI64
).
Specifically, *const i64
has the unwrap panic checks optimized out,
push rax
mov rax, qword ptr [rdi + 16]
cmp rax, 1
jbe .LBB0_1 ; assert
mov rcx, qword ptr [rdi + 8]
mov rdx, qword ptr [rcx + 8*rax - 8]
lea rsi, [rax - 2]
mov qword ptr [rdi + 16], rsi
mov rax, qword ptr [rcx + 8*rax - 16]
pop rcx
ret
while NonNull<i64>
keeps them.
example::pop2:
cmp rax, 2
jb .LBB0_7 ; assert
...
test rdx, rdx
je .LBB0_2 ; unwrap 1
...
test rax, rax
je .LBB0_5 ; unwrap 2
Meta
rustc --version --verbose
:
rustc 1.69.0-nightly (c8e6a9e8b 2023-01-23)
binary: rustc
commit-hash: c8e6a9e8b6251bbc8276cb78cabe1998deecbed7
commit-date: 2023-01-23
host: x86_64-unknown-linux-gnu
release: 1.69.0-nightly
LLVM version: 15.0.7