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