Allow moving out of mutable references with `panic=abort`

Because of Pin a thread cannot abort, the stack may have a pinned value on it which cannot be deallocated without being dropped. What you could do is leak the thread, essentially just loop { sleep(forever) } it.

1 Like

In the past we have treated it as a bug when -C flags influence whether or not some code compiles. I think that is still the general position of the lang team, so such an RFC seems unlikely to get very far. I would also personally be opposed to having -C flags affect the borrow checker in this way. This would mean people have to adjust their flags depending on which libraries they use, which is a mess.

An avenue that seems worth exploring more, however, are something like "nounwind blocks". We already have the infrastructure to turn all unwinds out of a function into aborts (that is used for extern "C" fn); it could be useful for unsafe code to make that available more conveniently and inside a function. That said, abort_unwind already does that entirely within the library, so maybe it's not worth a lang feature -- at least not yet; experience may show that using a closure for this is inconvenient / not general enough.

Once such blocks exist, maybe they could also be exploited by the borrow checker, though honestly I think adding replace_with to the standard library is the better option here.

(To be clear I am neither on the lang team nor the libs-api team, just speaking for myself here.)

6 Likes

By nounwind blocks, do you mean something like this?

fn foo(x: &mut T) {
  nounwind {
      *x  = *x; // move out and move in
      bar(x);
  } 
}

fn bar(x: &mut T) {
  nounwind {
      *x  = *x; // move out and move in
  } 
}

nounwind block creating "aborting" environment that will abort on any unwind. And bar must use it too, as it has no knowledge that it is called from within that block. I personally don't like that solution, while can accept it as it solves use cases.

What if, for example, have #![allow(moving_out_of_mutable_references)] and compiler will error if panic=unwind ? This breaks direct depency between panic=unwind and borrow checker - seems to me like a good ux.

Thank you for an observation! I think leaking the thread that way is acceptable, as abort is not a very common situation, a good trade of for users that want to handle thread failures gracefully.

I created another thread for this: Leak thread on panic .

Yes. I view this as largely independent of any borrow checker adjustments, unsafe code sometimes just wants to be sure some code does not unwind.

allow controls lints, they should definitely not impact the borrow checker in any way like this. Also this does not avoid the problem that some crates would fail to build depending on -C flags; I don't think that is desirable. cargo build should generally just work without having to tweak RUSTFLAGS depending on my full set of transitive dependencies.

Please familiarize yourself with the general design philosophy of Rust (I know, easier said than done -- what helps a lot here is to just gain more experience as a Rust user to get a better feeling for how everything works together, with a particular eye towards why things are the way they are; another idea is to read the discussion for successful and unsuccessful past language extensions) and look for comparable language features that this could be modeled after. To ensure that the language as a whole remains consistent and predictable in the long term, we can't just have random lints or -C flags have deep consequences like this.

I won't have the time to further participate in this discussion; I just wanted to give you some hints so that you don't spend a lot of time on proposals that are very unlikely to ever be accepted. :slight_smile:

4 Likes

I fully understand that this is a "hack", but with a lot of benefits and allows for backwards compatible migration for better solution like effects, while being a good motivation for that better solution. (Answering to the thread, I'm not expecting an answer, thank you for contribution)

Every non-local dependency you have has an implicit #![allow(moving_out_of_mutable_references)] due to cargo compiling it with --cap-lints allow. As such there is still effectively a direct dependency between panic=unwind and the borrow checker.

1 Like

Yes, this is a problem, thank you for an observation. Exactly because of this this is not a pre-rfc thread, but more like brain storming :smile:

I would encourage you to spell out the benefits of this over the already existing replace_with. Given the downsides of a "hack", there should be some substantial upsides, and those have not been articulated in this thread so far, I think. You said these abstractions are "really unpleasant to work with", which is a subjective statement I do not agree with. A pre-RFC should come with more solid arguments, explaining why you think they are unpleasant to work with, ideally in some objective/quantifiable way.

4 Likes

Thank you for the great feedback!