-
Notifications
You must be signed in to change notification settings - Fork 109
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proof of Concept: making Lazy<T, F>
covariant in F
#230
Proof of Concept: making Lazy<T, F>
covariant in F
#230
Conversation
5e99873
to
a1f3226
Compare
TBH, I am off two minds here, as the following concerns conflict:
I guess, on balance, yeah, we should do that. But before, I am curious, can we optimize this a bit? In particular, the current impl, pub struct Lazy<T, F = fn() -> T> {
cell: OnceCell<T>,
init: Cell<Option<F>>,
} isn't really what it should be, as we have two flags here one in So I think ideally we want something like struct Lazy<T, F> {
state: enum { Init, Uninit, Poison },
data: union {
f: F,
t: T,
poison: (),
}
} can we make that work pedantically correct wrt variance? |
I guess, as another consideration here, give that |
Yes, by slightly amending it 🙂: use ManuallyDrop as MD; // <- necessary red tape
struct Lazy<T, F> {
state: SomeMutWrapper<enum { Init, Uninit, Poison }>, // Uninit=can read `f`, Init=can read 't', Poison=cannot read either
data: union {
f: MD<F>,
t: MD<UnsafeCell<T>>, // 👈 `UnsafeCell` only here
}
}
This has the right variance w.r.t. both
|
Lazy<T, F>
covariant in F
Lazy<T, F>
covariant in F
I'm thus closing this draft PR, but may be submitting a PR implementing this for |
233: Make `unsync::Lazy<T, F>` covariant in `F` r=matklad a=danielhenrymantilla "Continuation" from #230, which partially handles #167. - Incidentally, this also makes `unsync::Lazy` smaller in size in most cases, since `T` and `F` are now sharing the same `union` storage. The `sync` can basically use the same logic (my PR paves the way for such a follow-up PR), only the whole thing would need to be moved to each of the possible `imp`lementations of `sync::OnceCell`, and special care to synchronization semantics will be in order, which I prefer to let somebody else do. Co-authored-by: Daniel Henry-Mantilla <[email protected]>
Proof of Concept of my idea from #167 (comment)
CovariantCellOption<F>
is soundly covariant since theF
value is never overwritten.If this PoC were to be merged, it would fix #167.
Although it does so at the cost of loss of discriminant elision of
Option<F>
, which means it makesLazy
s bigger. This could be deemed too high a cost for a somewhat niche feature.LazyCovariantCtor<T, F>
type which would thereby let users pick their preferred flavor.