@@ -1862,8 +1862,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1862
1862
///
1863
1863
/// (1.) Are we borrowing data owned by the parent closure? We can determine if
1864
1864
/// 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`.
1867
1868
///
1868
1869
/// ```rust
1869
1870
/// let x = &1i32; // Let's call this lifetime `'1`.
@@ -1902,10 +1903,22 @@ fn should_reborrow_from_env_of_parent_coroutine_closure<'tcx>(
1902
1903
) -> bool {
1903
1904
// (1.)
1904
1905
( !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
+ } ) )
1909
1922
// (2.)
1910
1923
|| matches ! ( child_capture. info. capture_kind, UpvarCapture :: ByRef ( ty:: BorrowKind :: Mutable ) )
1911
1924
}
0 commit comments