Comment by stymaar
14 hours 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>.
An 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`?
The 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.
Passing 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.
> 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?