Stream: general

Topic: WriteOnceCell


marmeladema (Apr 14 2020 at 22:15, on Zulip):

Hello! I'd like your opinion about the soundness / safety of this WriteOnceCell: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=6e220ff9a97663dc35f593d0cc8d4bd5

marmeladema (Apr 14 2020 at 22:24, on Zulip):

Maybe using MaybeUninit is overkill? I just realized that Option<T> might be enough?

DPC (Apr 14 2020 at 23:27, on Zulip):

@marmeladema you can also ask #wg-secure-code :slight_smile:

centril (Apr 15 2020 at 00:10, on Zulip):

@WG-unsafe-code-guidelines is probably better for that

marmeladema (Apr 15 2020 at 08:00, on Zulip):

Thank you! I will ask there then!

RalfJ (Apr 15 2020 at 09:50, on Zulip):

@marmeladema yeah on first sight this seems good.
To get some more assurance, you could write a few tests and run them in Miri :D

marmeladema (Apr 15 2020 at 09:59, on Zulip):

I definitely want to take a closer look at Miri, i've heard and read about it but never actually used it myself!

Elichai Turkel (Apr 15 2020 at 11:09, on Zulip):

That gave me an idea. Maybe we can somehow write a safe abstraction over Once to let you safely write into a mutable static because it knows it can only happen once

Elichai Turkel (Apr 15 2020 at 13:55, on Zulip):

What do people think about something along these lines? https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=9d4672b0cb186749c4a3ea977db0cce7
I think it should be possible to decrease the size to 24 bytes and then it would truly be zero cost, but I'm not sure how to do it without heap allocation (being generic over F: Fn() -> T is problematic because statics can't auto infer types)

Hanna Kruppe (Apr 15 2020 at 14:30, on Zulip):

Is this the same functionality as lazy_static, modulo syntactic sugar?

Jake Goulding (Apr 15 2020 at 14:35, on Zulip):

I'm unclear on the differences tween this and OnceCell.

Elichai Turkel (Apr 15 2020 at 15:41, on Zulip):

Jake Goulding said:

I'm unclear on the differences tween this and OnceCell.

Looks interesting, but I don't want to call get_or_init every time I want to access it.
I find myself doing things like this quite a lot: https://play.rust-lang.org/?gist=51a178a221188189e6f711e062c83604

Jake Goulding (Apr 15 2020 at 19:11, on Zulip):

@Elichai Turkel I don't think I'm following. Isn't that literally

use once_cell::sync::OnceCell;

struct Context;

impl Context {
    pub fn new() -> Self{
        // Do something computationally intensive.
        Context
    }
}

fn get_context() -> &'static Context {
    static INSTANCE: OnceCell<Context> = OnceCell::new();
    INSTANCE.get_or_init(Context::new)
}
Jake Goulding (Apr 15 2020 at 19:13, on Zulip):

Or

use once_cell::sync::Lazy;

struct Context;

impl Context {
    pub fn new() -> Self{
        // Do something computationally intensive.
        Context
    }
}

static CONTEXT: Lazy<Context> = Lazy::new(Context::new);
Elichai Turkel (Apr 15 2020 at 19:27, on Zulip):

hehe, you're right. if you plug it into my design then it does look good and free of unsafe :)
Oh and Lazy does exactly that ha.
How does it compile without explictly specifying the exact type? that did not work for me

Elichai Turkel (Apr 15 2020 at 19:41, on Zulip):

oh because of the equal sign in F = fn() -> T

Last update: Jun 05 2020 at 23:10UTC