@@ -1581,6 +1581,17 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
15811581 self . add_reborrow_constraint ( location, * region, borrowed_place) ;
15821582 }
15831583
1584+ Rvalue :: Reborrow ( target, mutability, borrowed_place) => {
1585+ // Reborrow needs to produce a relation between the source and destination fields,
1586+ // which means that we have had to already handle this in visit_assign.
1587+ self . add_generic_reborrow_constraint (
1588+ * mutability,
1589+ location,
1590+ borrowed_place,
1591+ * target,
1592+ ) ;
1593+ }
1594+
15841595 Rvalue :: BinaryOp (
15851596 BinOp :: Eq | BinOp :: Ne | BinOp :: Lt | BinOp :: Le | BinOp :: Gt | BinOp :: Ge ,
15861597 box ( left, right) ,
@@ -2217,6 +2228,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
22172228 | Rvalue :: ThreadLocalRef ( _)
22182229 | Rvalue :: Repeat ( ..)
22192230 | Rvalue :: Ref ( ..)
2231+ | Rvalue :: Reborrow ( ..)
22202232 | Rvalue :: RawPtr ( ..)
22212233 | Rvalue :: Cast ( ..)
22222234 | Rvalue :: BinaryOp ( ..)
@@ -2421,6 +2433,122 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
24212433 }
24222434 }
24232435
2436+ fn add_generic_reborrow_constraint (
2437+ & mut self ,
2438+ mutability : Mutability ,
2439+ location : Location ,
2440+ borrowed_place : & Place < ' tcx > ,
2441+ dest_ty : Ty < ' tcx > ,
2442+ ) {
2443+ // These constraints are only meaningful during borrowck:
2444+ let Self { borrow_set, location_table, polonius_facts, constraints, infcx, body, .. } =
2445+ self ;
2446+
2447+ // If we are reborrowing the referent of another reference, we
2448+ // need to add outlives relationships. In a case like `&mut
2449+ // *p`, where the `p` has type `&'b mut Foo`, for example, we
2450+ // need to ensure that `'b: 'a`.
2451+
2452+ debug ! (
2453+ "add_generic_reborrow_constraint({:?}, {:?}, {:?}, {:?})" ,
2454+ mutability, location, borrowed_place, dest_ty
2455+ ) ;
2456+
2457+ let tcx = infcx. tcx ;
2458+ let def = body. source . def_id ( ) . expect_local ( ) ;
2459+ let upvars = tcx. closure_captures ( def) ;
2460+ let field =
2461+ path_utils:: is_upvar_field_projection ( tcx, upvars, borrowed_place. as_ref ( ) , body) ;
2462+ let category = if let Some ( field) = field {
2463+ ConstraintCategory :: ClosureUpvar ( field)
2464+ } else {
2465+ ConstraintCategory :: Boring
2466+ } ;
2467+
2468+ let borrowed_ty = borrowed_place. ty ( self . body , tcx) . ty ;
2469+
2470+ let ty:: Adt ( dest_adt, dest_args) = dest_ty. kind ( ) else { bug ! ( ) } ;
2471+ let [ dest_arg, ..] = * * * dest_args else { bug ! ( ) } ;
2472+ let ty:: GenericArgKind :: Lifetime ( dest_region) = dest_arg. kind ( ) else { bug ! ( ) } ;
2473+ constraints. liveness_constraints . add_location ( dest_region. as_var ( ) , location) ;
2474+
2475+ // In Polonius mode, we also push a `loan_issued_at` fact
2476+ // linking the loan to the region.
2477+ if let Some ( polonius_facts) = polonius_facts {
2478+ let _prof_timer = infcx. tcx . prof . generic_activity ( "polonius_fact_generation" ) ;
2479+ if let Some ( borrow_index) = borrow_set. get_index_of ( & location) {
2480+ let region_vid = dest_region. as_var ( ) ;
2481+ polonius_facts. loan_issued_at . push ( (
2482+ region_vid. into ( ) ,
2483+ borrow_index,
2484+ location_table. mid_index ( location) ,
2485+ ) ) ;
2486+ }
2487+ }
2488+
2489+ if mutability. is_not ( ) {
2490+ // FIXME(@aapoalas): for CoerceShared we need to relate the types manually, field by
2491+ // field. We cannot just attempt to relate `T` and `<T as CoerceShared>::Target` by
2492+ // calling relate_types as they are (generally) two unrelated user-defined ADTs, such as
2493+ // `CustomMut<'a>` and `CustomRef<'a>`, or `CustomMut<'a, T>` and `CustomRef<'a, T>`.
2494+ // Field-by-field relate_types is expected to work based on the wf-checks that the
2495+ // CoerceShared trait performs.
2496+ let ty:: Adt ( borrowed_adt, borrowed_args) = borrowed_ty. kind ( ) else { unreachable ! ( ) } ;
2497+ let borrowed_fields = borrowed_adt. all_fields ( ) . collect :: < Vec < _ > > ( ) ;
2498+ for dest_field in dest_adt. all_fields ( ) {
2499+ let Some ( borrowed_field) =
2500+ borrowed_fields. iter ( ) . find ( |f| f. name == dest_field. name )
2501+ else {
2502+ continue ;
2503+ } ;
2504+ let dest_ty = dest_field. ty ( tcx, dest_args) ;
2505+ let borrowed_ty = borrowed_field. ty ( tcx, borrowed_args) ;
2506+ if let (
2507+ ty:: Ref ( borrow_region, _, Mutability :: Mut ) ,
2508+ ty:: Ref ( ref_region, _, Mutability :: Not ) ,
2509+ ) = ( borrowed_ty. kind ( ) , dest_ty. kind ( ) )
2510+ {
2511+ self . relate_types (
2512+ borrowed_ty. peel_refs ( ) ,
2513+ ty:: Variance :: Covariant ,
2514+ dest_ty. peel_refs ( ) ,
2515+ location. to_locations ( ) ,
2516+ category,
2517+ )
2518+ . unwrap ( ) ;
2519+ self . constraints . outlives_constraints . push ( OutlivesConstraint {
2520+ sup : ref_region. as_var ( ) ,
2521+ sub : borrow_region. as_var ( ) ,
2522+ locations : location. to_locations ( ) ,
2523+ span : location. to_locations ( ) . span ( self . body ) ,
2524+ category,
2525+ variance_info : ty:: VarianceDiagInfo :: default ( ) ,
2526+ from_closure : false ,
2527+ } ) ;
2528+ } else {
2529+ self . relate_types (
2530+ borrowed_ty,
2531+ ty:: Variance :: Covariant ,
2532+ dest_ty,
2533+ location. to_locations ( ) ,
2534+ category,
2535+ )
2536+ . unwrap ( ) ;
2537+ }
2538+ }
2539+ } else {
2540+ // Exclusive reborrow
2541+ self . relate_types (
2542+ borrowed_ty,
2543+ ty:: Variance :: Covariant ,
2544+ dest_ty,
2545+ location. to_locations ( ) ,
2546+ category,
2547+ )
2548+ . unwrap ( ) ;
2549+ }
2550+ }
2551+
24242552 fn prove_aggregate_predicates (
24252553 & mut self ,
24262554 aggregate_kind : & AggregateKind < ' tcx > ,
0 commit comments