Apologies if the title is confusing.
What I'm trying to do is something like:
pub struct BitField(pub usize);
impl std::ops::Index<usize> for BitField {
type Output = bool;
fn index(&self, index: usize) -> &Self::Output {
if self.0 & (1 << index) > 0
}
}
I understand why this doesn't compile: the output requires a reference and I would have to create some reference that can actually live past the end of the function body.
So I turned it into this:
pub struct BitField(pub usize);
impl std::ops::Index<usize> for BitField {
type Output = bool;
fn index(&self, index: usize) -> &Self::Output {
if self.0 & (1 << index) > 0 {
&true
} else {
&false
}
}
}
Building it in play.rust-lang.org with release optimizations turned on gives the following assembly:
<playground::BitField as core::ops::index::Index<usize>>::index:
movq (%rdi), %rax
btq %rsi, %rax
leaq .L__unnamed_1(%rip), %rcx
leaq .L__unnamed_2(%rip), %rax
cmovaeq %rcx, %rax
retq
.L__unnamed_2:
.byte 1
.L__unnamed_1:
.zero 1
If I'm understanding this correctly, the compiler isn't generating the 0 or 1 that represents the boolean directly but instead reading it from some other memory location. Is this correct?
If I am correct, what I am then confused about is why is the indirection necessary in this case.
Since the return is &bool, which is immutable and can't self-reference, it should be valid for the compiler to eliminate the indirection entirely and simply generate the value in place rather than copy it from somewhere else
In short, I was expecting the assembly to be something that is close to a direct translation of this, without the indirection:
self.0 & (1 << index) > 0
Is there any reason why the compiler isn't allowed to do this or is it merely insufficient optimization?