Description
Scopes threads as currently implemented are potentially unsound due to passing a reference to a function where the memory the reference points to is potentially deallocated while the function still runs.
Specifically, this main function here takes as implicit argument its closure environment, which contains f
. That environment might just be a reference to some memory that is allocated in the caller stack frame. However the main
function can keep running after their_packet
got dropped (implicitly at the end of main
). Then the scope might end and the memory might be deallocated all while main
is still running. If the environment is just a reference, it ends up being a newtype and we will (AFAIK) add the dereferenceable
attribute, meaning deallocation while the function runs is actually LLVM UB.
Miri found the error in this doc test, where the a.push(4)
invalidates the &a
reference that was passed to the forked-off threads. (a
doesn't actually get deallocated, it just has a unique reference created to it, but deallocation is also a possibility).
To fix this properly, I think we need a language extension: we want a way to store references in a type without having alias guarantees for that reference. In terms of Stacked Borrows this means Stacked Borrows will stop recursing at that type during retags. In terms of the LLVM IR we generate it means we must not add noalias
or dereferenceable
attributes for references inside that type. We don't have such a type currently but I think it makes sense to make ManuallyDrop
that type (or even if we add a new type for this, ManuallyDrop
should use it). Also see this Zulip discussion.