Here's an example of the difference, running the same code with a pointer -- which is allowed to be null -- and a reference -- which is not allowed to be null: https://rust.godbolt.org/z/zxPMT1eeG
pub fn demo1(mut n: u32, x: &u32) -> u32 {
let mut sum = 0;
while n > 0 {
n -= 1;
sum += *x;
}
sum
}
pub unsafe fn demo2(mut n: u32, x: *const u32) -> u32 {
let mut sum = 0;
while n > 0 {
n -= 1;
sum += *x;
}
sum
}
With the reference, that compiles to just n * *x, because references are never null
example::demo1:
mov eax, edi
imul eax, dword ptr [rsi]
ret
But because pointers are allowed to be null, that one compiles to if n != 0 { n * *x } else { 0 } because it has to make sure it doesn't read through a null pointer:
example::demo2:
test edi, edi
je .LBB1_1
mov eax, edi
imul eax, dword ptr [rsi]
ret
.LBB1_1:
xor eax, eax
ret
That's why no, you're not allowed to make references be null even in unsafe code. If you want something to be nullable, use pointers or options-of-references.
Also, if you're wondering why the goldbolt link uses an old version of rustc, it's because there's a been a regression in LLVM. Looks like it's fixed in LLVM trunk, though, as I can repro the same thing in clang 13: https://cpp.godbolt.org/z/8bKb5WzTv