3 ms·
I'm going to point out one potential footgun with your library: circularly-linked Drops. If you have values A and B, both instances of T that implement Drop an
by kmeisthax 3y ago
I'm going to point out one potential footgun with your library: circularly-linked Drops.
If you have values A and B, both instances of T that implement Drop and hold a Gc<T> to one another, then either A sees a dropped B or B sees a dropped A, and you get UB. Technically this isn't a problem because you already marked it as an unsafe trait, but your documentation should also mention this problem.
You have a safe derive macro for Collectable, however, so it needs to reject Drop. This is possible with some weird macro magic[0].
For those wondering, while Python doesn't have UB, it used to enforce the same rules until PEP 442[1]. Circularly linked garbage that implemented __del__ would instead get stored in sys.gc.garbage and you'd have to go in there and break references on __del__ types. However, native code objects will actually still trigger this behavior[2] presumably to avoid UB.
I have no clue if Java finalizers need to worry about this.
[0] In Ruffle we use gc_arena as our garbage collector. It enforces no_drop in it's Collect derive macro. See: https://github.com/kyren/gc-arena/blob/master/src/gc-arena-derive/src/lib.rs https://github.com/kyren/gc-arena/blob/master/src/gc-arena-d...
Actually, I lied: no_drop is one of two safe constraints you can use Collect with. The alternative is require_static, which only works because gc_arena treats the entire GC heap as a data structure that is owned and has a lifetime that all Gc pointers borrow. This doesn't work for dumpster, though, so ignore it.
[1] https://peps.python.org/pep-0442/ https://peps.python.org/pep-0442/
[2] https://docs.python.org/3/library/gc.html#gc.garbage https://docs.python.org/3/library/gc.html#gc.garbage
- appplication 3y agoThis comment would be significantly improved by fully spelling out what UB is at least once.
- kmeisthax 3y agoUndefined behavior means the compiler will rewrite your program in ways that do not follow from the meaning of the source code. This means things like conditions and guards just disappearing, code being reordered in ways that don't make sense, and so on. All of the safety guarantees of Rust go out the window once UB is triggered, because everything goes out the window. Which is why Rust is designed so that safe code can't trigger UB. But unsafe code still has to worry about it.
- jenadine 3y ago> the compiler will rewrite your program in ways that do not follow from the meaning of the source code. It's not that, it's just that the source code has no meaning for a particular code path, so the compiler can do anything so that other code paths or conditions can be faster/more optimized. Just nitpicking.
- claytonwramsey 3y agoThese issues are currently handled by my library. It’s not mentioned in the blog post because it would be a little distracting. Dereferencing a “dead” GC during Drop currently yields a panic, while all GCs must be ‘static.