Improve upvar analysis for deref of child capture by compiler-errors · Pull Request #138517 · rust-lang/rust (original) (raw)

Two fixes to the heuristic I implemented in #123660. As I noted in the code:

Luckily, if this function is not correct, then the program is not unsound, since we still borrowck and validate the choices made from this function -- the only side-effect is that the user may receive unnecessary borrowck errors.

This indeed fixes unnecessary borrowck errors.

r? oli-obk


The heuristic is only valid if we deref a &T, not a &mut T or Box<T>, so make sure to check the type. This fixes:

struct Foo { precise: i32 }

fn mut_ref_inside_mut(f: &mut Foo) { let x: impl AsyncFn() = async move || { let y = &f.precise; }; }

Since the capture from f to &f.precise needs to be treated as a lending borrow from the parent coroutine-closure to the child coroutine.


The heuristic is also valid if any deref projection in the child capture's projections is a &T, but we were only looking at the last one. This ensures that this function is considered not to be lending:

struct Foo { precise: i32 }

fn ref_inside_mut(f: &mut &Foo) { let x: impl Fn() -> _ = async move || { let y = &f.precise; }; }

(Specifically, checking that impl Fn() -> _ is satisfied is exercising that the coroutine is not considered to be lending.)