Skip to content

Commit 1f968e7

Browse files
committed
Fix lifetime of reborrow by Ding Xiang Fei
1 parent 77a6156 commit 1f968e7

3 files changed

Lines changed: 42 additions & 12 deletions

File tree

compiler/rustc_borrowck/src/borrow_set.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -304,10 +304,12 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'tcx> {
304304
self.local_map.entry(borrowed_place.local).or_default().insert(idx);
305305
} else if let &mir::Rvalue::Reborrow(mutability, borrowed_place) = rvalue {
306306
let borrowed_place_ty = borrowed_place.ty(self.body, self.tcx).ty;
307-
let &ty::Adt(reborrowed_adt, reborrowed_args) = borrowed_place_ty.kind() else {
307+
let &ty::Adt(reborrowed_adt, _reborrowed_args) = borrowed_place_ty.kind() else {
308308
unreachable!()
309309
};
310-
let &ty::Adt(target_adt, _) = assigned_place.ty(self.body, self.tcx).ty.kind() else {
310+
let &ty::Adt(target_adt, assigned_args) =
311+
assigned_place.ty(self.body, self.tcx).ty.kind()
312+
else {
311313
unreachable!()
312314
};
313315
let borrow = if mutability == Mutability::Mut {
@@ -318,7 +320,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'tcx> {
318320
)
319321
}
320322
let Some(ty::GenericArgKind::Lifetime(region)) =
321-
reborrowed_args.get(0).map(|r| r.kind())
323+
assigned_args.get(0).map(|r| r.kind())
322324
else {
323325
bug!(
324326
"hir-typeck passed but {} does not have a lifetime argument",
@@ -343,7 +345,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'tcx> {
343345
)
344346
}
345347
let Some(ty::GenericArgKind::Lifetime(region)) =
346-
reborrowed_args.get(0).map(|r| r.kind())
348+
assigned_args.get(0).map(|r| r.kind())
347349
else {
348350
bug!(
349351
"hir-typeck passed but {} does not have a lifetime argument",

compiler/rustc_borrowck/src/type_check/mod.rs

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2503,6 +2503,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
25032503

25042504
let dest_ty = dest.ty(self.body, tcx).ty;
25052505
let borrowed_ty = borrowed_place.ty(self.body, tcx).ty;
2506+
let ty::Adt(_, args) = dest_ty.kind() else { bug!() };
2507+
let [arg, ..] = ***args else { bug!() };
2508+
let ty::GenericArgKind::Lifetime(reborrow_region) = arg.kind() else { bug!() };
2509+
self.constraints.liveness_constraints.add_location(reborrow_region.as_var(), location);
25062510

25072511
if mutability.is_not() {
25082512
// FIXME: for shared reborrow we need to relate the types manually,
@@ -2520,14 +2524,20 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
25202524
};
25212525
let dest_ty = dest_field.ty(tcx, dest_args);
25222526
let borrowed_ty = borrowed_field.ty(tcx, borrowed_args);
2523-
self.relate_types(
2524-
borrowed_ty,
2525-
ty::Variance::Covariant,
2526-
dest_ty,
2527-
location.to_locations(),
2528-
category,
2529-
)
2530-
.unwrap();
2527+
if borrowed_ty.ref_mutability() == Some(Mutability::Mut)
2528+
&& dest_ty.ref_mutability() == Some(Mutability::Not)
2529+
{
2530+
// self.add_reborrow_constraint(location, borrow_region, borrowed_place);
2531+
} else {
2532+
self.relate_types(
2533+
borrowed_ty,
2534+
ty::Variance::Covariant,
2535+
dest_ty,
2536+
location.to_locations(),
2537+
category,
2538+
)
2539+
.unwrap();
2540+
}
25312541
}
25322542
} else {
25332543
// Exclusive reborrow

compiler/rustc_hir_analysis/src/coherence/builtin.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,10 @@ fn assert_field_type_is_reborrow<'tcx>(
534534
ty: Ty<'tcx>,
535535
span: Span,
536536
) -> Result<(), Vec<FulfillmentError<'tcx>>> {
537+
if ty.ref_mutability() == Some(ty::Mutability::Mut) {
538+
// Mutable references are Reborrow but not really.
539+
return Ok(());
540+
}
537541
let ocx = ObligationCtxt::new_with_diagnostics(infcx);
538542
let cause = traits::ObligationCause::misc(span, impl_did);
539543
let obligation =
@@ -667,6 +671,20 @@ pub(crate) fn coerce_shared_info<'tcx>(
667671
//
668672
// 1 data field each; they must be the same type and Copy, or relate to one another using
669673
// CoerceShared.
674+
if source.ref_mutability() == Some(ty::Mutability::Mut)
675+
&& target.ref_mutability() == Some(ty::Mutability::Not)
676+
&& infcx
677+
.eq_structurally_relating_aliases(
678+
param_env,
679+
source.peel_refs(),
680+
target.peel_refs(),
681+
source_field_span,
682+
)
683+
.is_ok()
684+
{
685+
// &mut T implements CoerceShared to &T, except not really.
686+
return Ok(CoerceSharedInfo {});
687+
}
670688
if infcx
671689
.eq_structurally_relating_aliases(param_env, source, target, source_field_span)
672690
.is_err()

0 commit comments

Comments
 (0)