facebook / starlark-rust

A Rust implementation of the Starlark language
Apache License 2.0
672 stars 53 forks source link

How to create a `FrozenValue` from `Value<'a>`? #122

Closed johnynek closed 3 weeks ago

johnynek commented 4 weeks ago

I have a use case to build a small number of FrozenValues that I can keep in a HashMap for instance.

There seems no way I can find from user code to do this. Freezer is pub, but I can't create one since the new method that accepts a FrozenHeap is pub(crate).

Is this operation fundamentally unsafe since FrozenValue doesn't have a lifetime? I see that inside Freezer there is unsafe code.

Really I just need to have some way to store some kind of value, that inside a global I can recover back into a Value<'a> in the context of another Evaluator<'a, '_> which should have the same type and compare == to the original value. It's fine if this is limited to only None, bool, int, float, str, record, enum and tuples, lists, dicts of these recursively.

stepancheg commented 4 weeks ago

To create FrozenValue from Value you need to call module.freeze — that creates a freezer, and freezes data.

And the value with references to preserve the values can be put into module extra value, or just in module globals.

Alternatively, you can just allocate the values in frozen heap. They cannot be garbage collected, but that might not be an issue depending on your use case.

since FrozenValue doesn't have a lifetime

I think FrozenValue should have lifetime. It is more convenient to work without lifetime, but it is memory unsafe.

Is this operation fundamentally unsafe since

Which operation?

Generally Freeze (as well as Trace) operation does complicated memory things (object graph traversal and patching pointers), so many interfaces are unsafe. However, most APIs needed by end users are safe.

johnynek commented 3 weeks ago

Thanks. Using FrozenModule and OwnedFrozenValue::owned_value with the FrozenHeap from my Evaluator seems to do the trick.