matklad/once_cell

Support unsized coercions for `Lazy` type.

EFanZh opened this issue · 2 comments

Currently, the following code does not compile:

use once_cell::sync::Lazy;
use std::sync::Arc;

fn foo() {
    let x: Arc<Lazy<[i32; 3]>> = Arc::new(Lazy::new(|| [2, 3, 4]));
    let y: Arc<Lazy<[i32]>> = x;
}

Is it possible for Lazy to support unsized coercions like types like RefCell? For example, with RefCell, I can do this:

use std::cell::RefCell;
use std::sync::Arc;

fn foo() {
    let x: Arc<RefCell<[i32; 3]>> = Arc::new(RefCell::new([2, 3, 4]));
    let y: Arc<RefCell<[i32]>> = x;
}

What a delightful nerdy issue, thanks!

Yeah, I think that should be possible with some work. I think (haven't checked) that the reason why it doesn't work today is because we ultimately store an Option. Using MaybeUninit and a bool flag might help here!

Now I start to think it might not be possible. The problem is that Lazy has another generic argument F which should be a FnOnce type. So the sized Lazy type could be:

Lazy<[i32; 3], impl FnOnce() -> [i32; 3]>

And the unsized Lazy type would be

Lazy<[i32], impl FnOnce() -> [i32]>

I have not idea how the conversion would work. If it is not possible for Lazy, how about OnceCell?