I stumbled upon strange behavior that I can't make sense of yet. I have the following function:
pub fn complete(self) {
let last_value: Option<BasicValueEnum<'ctx>> = self.last_value.into_inner();
// self.builder.build_return(last_value.as_ref()); // <- does not work
match last_value {
Some(value) => {
self.builder.build_return(Some(&value)); // <- works
},
None => { self.builder.build_return(None); },
}
self.function.verify(true);
}
where self.builder.build_return has the following signature:
pub fn build_return(&self, value: Option<&dyn BasicValue<'ctx>>) -> InstructionValue<'ctx>
Now, the builder comes from a library so I don't know much about the specifics, but just looking at the signatures this behavior looks quite strange to me. Shouldn't Option.as_ref() return a Option<&T>, which in my case should be the same as what my match expression does?
I have the strong feeling that I'm missing some concept instead of that I've encountered some bug.
If it helps, the builder comes from the inkwell library.
With the working code, the compiler sees that &value has to be of type &dyn BasicValue<'ctx> and can coerce it.
But with Option::as_ref with signature fn(&self) -> Option<&T> there is no coercion possible because it always converts &Option<T> into Option<&T>, therefore the types are different,
one is Option<&BasicValueEnum<'ctx>> the other is Option<&dyn BasicValue<'ctx>>.
To make it work with as_ref you can manually cast the concrete reference into a reference to a trait object:
self.builder.build_return(last_value.as_ref().map(|x| x as _));
Where _ can be derived by the compiler to be &dyn BasicValue<'ctx>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With