On Fri, Jul 26, 2024 at 9:26 AM Manos Pitsidianakis <manos.pitsidiana...@linaro.org> wrote: > > On Thu, 25 Jul 2024 18:15, Paolo Bonzini <pbonz...@redhat.com> wrote: > >On Thu, Jul 25, 2024 at 4:48 PM Manos Pitsidianakis > ><manos.pitsidiana...@linaro.org> wrote: > >> > pl011_receive (called by qemu_chr_fe_accept_input) creates a mutable > >> > reference that *overlaps* the lifetime of the outer reference created > >> > by pl011_read. This is undefined behavior. You're effectively writing: > >> > >> There is no overlap there, sorry. Once qemu_chr_fe_accept_input > >> returns, any references it created do not exist anymore. > > > >read |-------------| > >receive |-----| > > > >That's the overlap. Maybe you're thinking that the outer &mut "goes to > >sleep" and is reborn when qemu_chr_fe_accept_input() returns, but > >there's no such thing in the language. > > There's no overlap, because the read scope is not live while receive is > active. References are linear types, when you give `&mut sth` as an > argument to a function call, you can model it in your mind as "giving > the mutual reference to the function call" and "receiving it back" when > it returns.
There is no such thing as "being active", the only exception being when you create an &mut from *the same* &mut. To clarify further: in principle, if you have code like this in pl011_read(): self.a = 42; qemu_chr_accept_input(self.chardev); return self.a The compiler can optimize the second "self.a" to 42. The optimization is incorrect if pl011_receive() overwrites "self.a". But that's not a problem with the optimization, it's a problem with what pl011_receive() does. In other words, the *mere existence* of a &mut in an outer scope makes it invalid to create *another* &mut pointing to the same memory in an inner scope. As I said, I don't see the point in discussing this more, and I'm not going to unless you provide a clear pointer to documentation that states the opposite. Paolo > There'd be an overlap if qemu_chr_fe_accept_input got two mutual > references of the same memory location, such as calling foo(&mut self, > &mut self) with foo being `fn foo(a: &mut T, b: &mut T)`.