4 ms·
mem::forget isn’t the only way you can safely leak a value, you can do it with reference cycles too, right? And there is no way for the compiler to detect that?
by OskarS 2mo ago
mem::forget isn’t the only way you can safely leak a value, you can do it with reference cycles too, right? And there is no way for the compiler to detect that?
Isn’t that why mem::forget is safe, because you can always implement it yourself safely? How do you get around that?
- skitter 2mo agoBy doing the same as with `Sized`: Automatically including the `Forget` bound on generic parameters and letting methods that don't need to be able to forget them opt out. That way existing code continues to compile and existing unsafe code doesn't become unsound.
- stymaar 2mo ago> mem::forget isn’t the only way you can safely leak a value, you can do it with reference cycles too, right? And there is no way for the compiler to detect that? But there's an easy solution for that: you make the reference-counted smart pointers require their pointee type to be Forget. It will be like how Arc<T> doesn't implement Send unless <T: Sync>.
- klauserc 2mo agoAn alternative way to "forget" a value is to hand it off to another thread that then loops infinitely. Could of course be plugged by saying `!Forget : !Send`, but wouldn't that preclude legitimate useful scenarios for `!Forget`?
- aw1621107 2mo ago> An alternative way to "forget" a value is to hand it off to another thread that then loops infinitely. Might be able to address that by only allowing such a handoff to a thread spawned via some scoped abstraction to ensure that progress can only be made if/when the spawned thread terminates?
- Dagonfly 2mo agoPassing ownership to another thread is not the same as forgetting/leaking. The point of !Forget is ensuring that once the owner goes out of scope the destructor must be guaranteed to run. An infinite loop is not a problem, cause the new thread will never leave its scope. Ref-cycles are a problem, cause you can create a ref-cycle. Then the program flow leaves the scope which will run the drop on all RC's but not the drop on the inner type.
- afdbcreid 2mo agoThe more accurate definition of `!Forget`, similar to `Pin<&mut !Unpin>`, is not "can be leaked" but "if the underlying storage is reused, the destructor is guaranteed to run". This enables all important (decidable - preventing leaking is undecidable, even in GC languages) use-cases, and sending the value to a thread does not break this contract.
- Falell 2mo agoThis was my first question too, I don't see anything addressing e.g. the cyclical arc example from the original 'spawn' conversation. It seems like you have to auto-propagate !Forget, and then make 'anything that be used to logically implement forget', probably most importantly things like Rc take a Forget bound and do it at an edition boundary? But the link mentions none of that...