As usual, one should write whatever's most readable in the vast majority of cases.
That said, && and || are short-circuiting, as you know. That's essential in lots of cases -- x != 0 && foo(z / x) and similar -- and a good default for anything non-trivial on the RHS.
But it's control flow, so for a sufficiently trivial RHS it can make it easier on the optimizer to not write short-circuiting, so it knows that it's allowed to just run it and that's ok, without needing to prove it safe to run. (After all, if it's not short-circuiting it's going to run always.)
It looks like LLVM's gotten smarter so my go-to example is now fully optimized either way (https://rust.godbolt.org/z/TnvKdqPfb, at least in x64).
But if you use a compiler from three years ago, then https://rust.godbolt.org/z/EfdzWjn16
pub struct Demo(u16, u16, u16, u16);
#[no_mangle]
pub fn obvious_eq(x: &Demo, y: &Demo) -> bool {
x.0 == y.0 && x.1 == y.1 && x.2 == y.2 && x.3 == y.3
}
#[no_mangle]
pub fn no_short_circuit_eq(x: &Demo, y: &Demo) -> bool {
(x.0 == y.0) & (x.1 == y.1) & (x.2 == y.2) & (x.3 == y.3)
}
compiled to
obvious_eq:
movzx ecx, word ptr [rdi]
xor eax, eax
cmp cx, word ptr [rsi]
jne .LBB0_5
movzx ecx, word ptr [rsi + 2]
cmp word ptr [rdi + 2], cx
jne .LBB0_5
movzx eax, word ptr [rdi + 4]
cmp ax, word ptr [rsi + 4]
jne .LBB0_3
movzx eax, word ptr [rdi + 6]
cmp ax, word ptr [rsi + 6]
sete al
.LBB0_5:
ret
.LBB0_3:
xor eax, eax
ret
no_short_circuit_eq:
mov rax, qword ptr [rdi]
cmp rax, qword ptr [rsi]
sete al
ret
So someone who was micro-optimizing a bit of code like that might have chosen to change the normal && implementation to & in order to get an optimization like that, if it was done at a time when LLVM's optimizer wasn't yet capable of doing it automatically.