@@ -1862,8 +1862,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
18621862///
18631863/// (1.) Are we borrowing data owned by the parent closure? We can determine if
18641864/// that is the case by checking if the parent capture is by move, EXCEPT if we
1865- /// apply a deref projection, which means we're reborrowing a reference that we
1866- /// captured by move.
1865+ /// apply a deref projection of an immutable reference, reborrows of immutable
1866+ /// references which aren't restricted to the LUB of the lifetimes of the deref
1867+ /// chain. This is why `&'short mut &'long T` can be reborrowed as `&'long T`.
18671868///
18681869/// ```rust
18691870/// let x = &1i32; // Let's call this lifetime `'1`.
@@ -1902,10 +1903,22 @@ fn should_reborrow_from_env_of_parent_coroutine_closure<'tcx>(
19021903) -> bool {
19031904 // (1.)
19041905 ( !parent_capture. is_by_ref ( )
1905- && !matches ! (
1906- child_capture. place. projections. get( parent_capture. place. projections. len( ) ) ,
1907- Some ( Projection { kind: ProjectionKind :: Deref , .. } )
1908- ) )
1906+ // This is just inlined `place.deref_tys()` but truncated to just
1907+ // the child projections. Namely, look for a `&T` deref, since we
1908+ // can always extend `&'short mut &'long T` to `&'long T`.
1909+ && !child_capture
1910+ . place
1911+ . projections
1912+ . iter ( )
1913+ . enumerate ( )
1914+ . skip ( parent_capture. place . projections . len ( ) )
1915+ . any ( |( idx, proj) | {
1916+ matches ! ( proj. kind, ProjectionKind :: Deref )
1917+ && matches ! (
1918+ child_capture. place. ty_before_projection( idx) . kind( ) ,
1919+ ty:: Ref ( .., ty:: Mutability :: Not )
1920+ )
1921+ } ) )
19091922 // (2.)
19101923 || matches ! ( child_capture. info. capture_kind, UpvarCapture :: ByRef ( ty:: BorrowKind :: Mutable ) )
19111924}
0 commit comments