Skip to content

Commit fcff9e7

Browse files
committed
Fix lifetime of reborrow by Ding Xiang Fei
1 parent 5bbeb16 commit fcff9e7

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
@@ -271,10 +271,12 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'tcx> {
271271
self.local_map.entry(borrowed_place.local).or_default().insert(idx);
272272
} else if let &mir::Rvalue::Reborrow(mutability, borrowed_place) = rvalue {
273273
let borrowed_place_ty = borrowed_place.ty(self.body, self.tcx).ty;
274-
let &ty::Adt(reborrowed_adt, reborrowed_args) = borrowed_place_ty.kind() else {
274+
let &ty::Adt(reborrowed_adt, _reborrowed_args) = borrowed_place_ty.kind() else {
275275
unreachable!()
276276
};
277-
let &ty::Adt(target_adt, _) = assigned_place.ty(self.body, self.tcx).ty.kind() else {
277+
let &ty::Adt(target_adt, assigned_args) =
278+
assigned_place.ty(self.body, self.tcx).ty.kind()
279+
else {
278280
unreachable!()
279281
};
280282
let borrow = if mutability == Mutability::Mut {
@@ -285,7 +287,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'tcx> {
285287
)
286288
}
287289
let Some(ty::GenericArgKind::Lifetime(region)) =
288-
reborrowed_args.get(0).map(|r| r.kind())
290+
assigned_args.get(0).map(|r| r.kind())
289291
else {
290292
bug!(
291293
"hir-typeck passed but {} does not have a lifetime argument",
@@ -310,7 +312,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'tcx> {
310312
)
311313
}
312314
let Some(ty::GenericArgKind::Lifetime(region)) =
313-
reborrowed_args.get(0).map(|r| r.kind())
315+
assigned_args.get(0).map(|r| r.kind())
314316
else {
315317
bug!(
316318
"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
@@ -2537,6 +2537,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
25372537

25382538
let dest_ty = dest.ty(self.body, tcx).ty;
25392539
let borrowed_ty = borrowed_place.ty(self.body, tcx).ty;
2540+
let ty::Adt(_, args) = dest_ty.kind() else { bug!() };
2541+
let [arg, ..] = ***args else { bug!() };
2542+
let ty::GenericArgKind::Lifetime(reborrow_region) = arg.kind() else { bug!() };
2543+
self.constraints.liveness_constraints.add_location(reborrow_region.as_var(), location);
25402544

25412545
if mutability.is_not() {
25422546
// FIXME: for shared reborrow we need to relate the types manually,
@@ -2554,14 +2558,20 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
25542558
};
25552559
let dest_ty = dest_field.ty(tcx, dest_args);
25562560
let borrowed_ty = borrowed_field.ty(tcx, borrowed_args);
2557-
self.relate_types(
2558-
borrowed_ty,
2559-
ty::Variance::Covariant,
2560-
dest_ty,
2561-
location.to_locations(),
2562-
category,
2563-
)
2564-
.unwrap();
2561+
if borrowed_ty.ref_mutability() == Some(Mutability::Mut)
2562+
&& dest_ty.ref_mutability() == Some(Mutability::Not)
2563+
{
2564+
// self.add_reborrow_constraint(location, borrow_region, borrowed_place);
2565+
} else {
2566+
self.relate_types(
2567+
borrowed_ty,
2568+
ty::Variance::Covariant,
2569+
dest_ty,
2570+
location.to_locations(),
2571+
category,
2572+
)
2573+
.unwrap();
2574+
}
25652575
}
25662576
} else {
25672577
// 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)