@@ -251,8 +251,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
251251 ty:: RawPtr ( _, b_mutbl) => {
252252 return self . coerce_to_raw_ptr ( a, b, b_mutbl) ;
253253 }
254- ty:: Ref ( _ , _, mutbl_b) => {
255- return self . coerce_to_ref ( a, b, mutbl_b) ;
254+ ty:: Ref ( r_b , _, mutbl_b) => {
255+ return self . coerce_to_ref ( a, b, mutbl_b, r_b ) ;
256256 }
257257 ty:: Adt ( pin, _)
258258 if self . tcx . features ( ) . pin_ergonomics ( )
@@ -343,15 +343,16 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
343343 a : Ty < ' tcx > ,
344344 b : Ty < ' tcx > ,
345345 mutbl_b : hir:: Mutability ,
346+ r_b : ty:: Region < ' tcx > ,
346347 ) -> CoerceResult < ' tcx > {
347348 debug ! ( "coerce_to_ref(a={:?}, b={:?})" , a, b) ;
348349 debug_assert ! ( self . shallow_resolve( a) == a) ;
349350 debug_assert ! ( self . shallow_resolve( b) == b) ;
350351
351- let mt_a = match * a. kind ( ) {
352- ty:: Ref ( _ , ty, mutbl) => {
352+ let ( r_a , mt_a) = match * a. kind ( ) {
353+ ty:: Ref ( r_a , ty, mutbl) => {
353354 coerce_mutbls ( mutbl, mutbl_b) ?;
354- ty:: TypeAndMut { ty, mutbl }
355+ ( r_a , ty:: TypeAndMut { ty, mutbl } )
355356 }
356357 _ => return self . unify ( a, b) ,
357358 } ;
@@ -368,6 +369,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
368369 // 3. `[T]`, autoref'd ty: `&M [T]`
369370 // - `&M [T]` does unify with `&M [T]`
370371 let mut first_error = None ;
372+ let mut r_borrow_var = None ;
371373 let mut autoderef = self . autoderef ( self . cause . span , a) ;
372374 let found = autoderef. by_ref ( ) . find_map ( |( deref_ty, autoderefs) | {
373375 if autoderefs == 0 {
@@ -376,9 +378,28 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
376378 return None ;
377379 }
378380
379- let coercion = RegionVariableOrigin :: Coercion ( self . cause . span ) ;
380- let r_borrow = self . next_region_var ( coercion) ;
381- let autorefd_deref_ty = Ty :: new_ref ( self . tcx , r_borrow, deref_ty, mutbl_b) ;
381+ // The logic here really shouldn't exist. We don't care about free
382+ // lifetimes during HIR typeck. Unfortunately later parts of this
383+ // function rely on structural identity of the autoref'd deref'd ty.
384+ //
385+ // This means that what region we use here actually impacts whether
386+ // we emit a reborrow coercion or not which can affect diagnostics
387+ // and capture analysis (which in turn affects borrowck).
388+ let r = if !self . use_lub {
389+ r_b
390+ } else if autoderefs == 1 {
391+ r_a
392+ } else {
393+ if r_borrow_var. is_none ( ) {
394+ // create var lazily, at most once
395+ let coercion = RegionVariableOrigin :: Coercion ( self . cause . span ) ;
396+ let r = self . next_region_var ( coercion) ;
397+ r_borrow_var = Some ( r) ;
398+ }
399+ r_borrow_var. unwrap ( )
400+ } ;
401+
402+ let autorefd_deref_ty = Ty :: new_ref ( self . tcx , r, deref_ty, mutbl_b) ;
382403
383404 // Note that we unify the autoref'd `Target` type with `b` rather than
384405 // the `Target` type with the pointee of `b`. This is necessary
@@ -417,8 +438,12 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
417438 if coerced_a == a && mt_a. mutbl . is_not ( ) && autoderef. step_count ( ) == 1 {
418439 // As a special case, if we would produce `&'a *x`, that's
419440 // a total no-op. We end up with the type `&'a T` just as
420- // we started with. In that case, just skip it
421- // altogether. This is just an optimization.
441+ // we started with. In that case, just skip it altogether.
442+ //
443+ // Unfortunately, this can actually effect capture analysis
444+ // which in turn means this effects borrow checking. This can
445+ // also effect diagnostics.
446+ // FIXME(BoxyUwU): we should always emit reborrow coercions
422447 //
423448 // Note that for `&mut`, we DO want to reborrow --
424449 // otherwise, this would be a move, which might be an
0 commit comments