I want to implement this trait for a struct from another crate, but I what to signal there is no data to borrow. For that I use a zero size type, but it's seems not possible to create a reference from nowhere.
impl BorrowData<()> for StructFromAnotherCrate {
fn borrow_data(&mut self) -> &mut () {
// What here ?
}
}
Is it possible with static type to represent the "there is not data" ?
Is it actually unsafe to have a referece to nowhere on a ZST since it's not possible to read from or write into ?
To answer your immediate question, this would work:
fn borrow_data(&mut self) -> &mut () {
&mut ()
}
Through promotion, we create a constant value () and take its address, yielding a &'static mut (). From there, the lifetime can be shortened to the lifetime of &mut self.
However, the design of the BorrowData trait seems odd, especially the use of BorrowData<()> for "there is no data to borrow". How do you anticipate the trait being used?
EDIT: I forgot that promotion only works for immutable references. This is not safely possible for mutable references.
error[E0515]: cannot return reference to temporary value
2 | &mut ()
| ^^^^^--
| | |
| | temporary value created here
| returns a reference to data owned by the current function
I have some method that borrow the struct and takes a callback that received the borrowed data.
For &mut T (as opposed to &T), constant promotion is special cased for arrays of length 0:
fn works<T>() -> &'static mut [T] {
&mut []
}
But not for anything else as far as I know, although it could be for ZSTs.
You could do this:
static mut UNIT: () = ();
fn works() -> &'static mut () {
// SAFETY: `()` is zero-sized and thus cannot alias any memory
unsafe { &mut UNIT }
}
At least until static mut gets deprecated in a few years maybe , in which case you could static-promote an empty array and use unsafe to cast it to a &mut ZST instead.
Edit: But nah, if you have alloc there's a non-unsafe way, see the quoted portion below.