Change:
I've returned to one of my projects after a few months of pause. Before I was using rust nigthly ~1.7x (around November 2023). It also worked through whole 2022 and 2021 IIRC. I've moved to new computer and installed rust nightly 1.80 (latest). After upgrading I noticed that my whole codebase is full of errors around capturing something from environment. . However if I change to it builds and works like previosly. Minimal example below. The error for first method is: i booted my very old PC to check, this is definately not the last version this worked fine: I definately does not work with:
Minimal: This should be possible now to support due to changes in . I'll put up a fix soon.

Discussion:
pub fn coroutine_witness_ty(self) -> Ty<'tcx> { self.split().coroutine_witness_ty } <ins> pub fn has_self_borrows(&self) -> bool { match self.coroutine_captures_by_ref_ty().kind() { ty::FnPtr(sig) => sig .skip_binder() .visit_with(&mut HasRegionsBoundAt { binder: ty::INNERMOST }) .is_break(), ty::Error(_) => true, _ => bug!(), } } } /// Unlike `has_escaping_bound_vars` or `outermost_exclusive_binder`, this will /// detect only regions bound *at* the debruijn index. struct HasRegionsBoundAt { binder: ty::DebruijnIndex, } // FIXME: Could be optimized to not walk into components with no escaping bound vars. impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for HasRegionsBoundAt { type Result = ControlFlow<()>; fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>( &mut self, t: &ty::Binder<'tcx, T>, ) -> Self::Result { self.binder.shift_in(1); t.super_visit_with(self)?; self.binder.shift_out(1); ControlFlow::Continue(()) } fn visit_region(&mut self, r: ty::Region<'tcx>) -> Self::Result { if let ty::ReBound(binder, _) = *r && self.binder == binder { ControlFlow::Break(()) } else { ControlFlow::Continue(()) } } </ins> } #[derive(Copy, Clone, PartialEq, Eq, Debug, TypeFoldable, TypeVisitable)]

return Err(NoSolution); } <del> // If `Fn`/`FnMut`, we only implement this goal if we // have no captures. let no_borrows = match args.tupled_upvars_ty().kind() { ty::Tuple(tys) => tys.is_empty(), ty::Error(_) => false, _ => bug!("tuple_fields called on non-tuple"), }; if closure_kind != ty::ClosureKind::FnOnce && !no_borrows { </del> <ins> // A coroutine-closure implements `FnOnce` *always*, since it may // always be called once. It additionally implements `Fn`/`FnMut` // only if it has no upvars referencing the closure-env lifetime, // and if the closure kind permits it. if closure_kind != ty::ClosureKind::FnOnce && args.has_self_borrows() { </ins> return Err(NoSolution); }

// Ambiguity if upvars haven't been constrained yet && !args.tupled_upvars_ty().is_ty_var() { <del> let no_borrows = match args.tupled_upvars_ty().kind() { ty::Tuple(tys) => tys.is_empty(), ty::Error(_) => false, _ => bug!("tuple_fields called on non-tuple"), }; </del> // A coroutine-closure implements `FnOnce` *always*, since it may // always be called once. It additionally implements `Fn`/`FnMut` <del> // only if it has no upvars (therefore no borrows from the closure // that would need to be represented with a lifetime) and if the // closure kind permits it. // FIXME(async_closures): Actually, it could also implement `Fn`/`FnMut` // if it takes all of its upvars by copy, and none by ref. This would // require us to record a bit more information during upvar analysis. if no_borrows && closure_kind.extends(kind) { </del> <ins> // only if it has no upvars referencing the closure-env lifetime, // and if the closure kind permits it. if closure_kind.extends(kind) && !args.has_self_borrows() { </ins> candidates.vec.push(ClosureCandidate { is_const }); } else if kind == ty::ClosureKind::FnOnce { candidates.vec.push(ClosureCandidate { is_const });

<ins> //@ check-pass //@ edition: 2021 // Demonstrates that an async closure may implement `FnMut` (not just `async FnMut`!) // if it has no self-borrows. In this case, `&Ty` is not borrowed from the closure env, // since it's fine to reborrow it with its original lifetime. See the doc comment on // `should_reborrow_from_env_of_parent_coroutine_closure` for more detail for when we // must borrow from the closure env. #![feature(async_closure)] fn main() {} fn needs_fn_mut<T>(x: impl FnMut() -> T) {} fn hello(x: &Ty) { needs_fn_mut(async || { x.hello(); }); } struct Ty; impl Ty { fn hello(&self) {} } </ins>