Skip to content

Commit 83d9f22

Browse files
committed
Fix const-eval CoerceShared reborrow leaf
1 parent 9713677 commit 83d9f22

1 file changed

Lines changed: 48 additions & 17 deletions

File tree

  • compiler/rustc_const_eval/src/interpret

compiler/rustc_const_eval/src/interpret/step.rs

Lines changed: 48 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use std::iter;
77
use either::Either;
88
use rustc_abi::{FIRST_VARIANT, FieldIdx};
99
use rustc_data_structures::fx::FxHashSet;
10+
use rustc_hir::Mutability;
1011
use rustc_index::IndexSlice;
1112
use rustc_middle::ty::reborrow::{self, CoerceSharedFieldPairError};
1213
use rustc_middle::ty::{self, Instance, Ty};
@@ -207,28 +208,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
207208
}
208209

209210
Ref(_, borrow_kind, place) => {
210-
let src = self.eval_place(place)?;
211-
let place = self.force_allocation(&src)?;
212-
let mut val = ImmTy::from_immediate(place.to_ref(self), dest.layout);
213-
// A fresh reference was created, make sure it gets retagged with the right mode.
214211
let mode = if borrow_kind.is_two_phase_borrow() {
215212
RetagMode::TwoPhase
216213
} else {
217214
RetagMode::Default
218215
};
219-
M::with_retag_mode(self, mode, |ecx| {
220-
// If validation is disabled, we still want to do this retag. This is because
221-
// const-eval disables validation for performance reasons but wants to retag
222-
// shared references. So we add a bit of a hack here to do the retag manually
223-
// if the write would not incur validation.
224-
if !M::enforce_validity(ecx, val.layout) {
225-
if let Some(new_val) = M::retag_ptr_value(ecx, &val, val.layout.ty)? {
226-
val = new_val;
227-
}
228-
}
229-
// Now do the actual write.
230-
ecx.write_immediate(*val, &dest)
231-
})?;
216+
self.write_ref_to_place(place, &dest, mode)?;
232217
}
233218

234219
Reborrow(target_ty, _, place) => {
@@ -286,6 +271,31 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
286271
interp_ok(())
287272
}
288273

274+
fn write_ref_to_place(
275+
&mut self,
276+
source_place: mir::Place<'tcx>,
277+
dest: &PlaceTy<'tcx, M::Provenance>,
278+
mode: RetagMode,
279+
) -> InterpResult<'tcx> {
280+
let src = self.eval_place(source_place)?;
281+
let place = self.force_allocation(&src)?;
282+
let mut val = ImmTy::from_immediate(place.to_ref(self), dest.layout);
283+
// A fresh reference was created, make sure it gets retagged with the right mode.
284+
M::with_retag_mode(self, mode, |ecx| {
285+
// If validation is disabled, we still want to do this retag. This is because
286+
// const-eval disables validation for performance reasons but wants to retag
287+
// shared references. So we add a bit of a hack here to do the retag manually
288+
// if the write would not incur validation.
289+
if !M::enforce_validity(ecx, val.layout) {
290+
if let Some(new_val) = M::retag_ptr_value(ecx, &val, val.layout.ty)? {
291+
val = new_val;
292+
}
293+
}
294+
// Now do the actual write.
295+
ecx.write_immediate(*val, dest)
296+
})
297+
}
298+
289299
fn eval_reborrow_into_place(
290300
&mut self,
291301
target_ty: Ty<'tcx>,
@@ -301,6 +311,27 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
301311
let (ty::Adt(source_def, source_args), ty::Adt(target_def, target_args)) =
302312
(source_ty.kind(), target_ty.kind())
303313
else {
314+
let is_mut_to_shared_ref = if let (
315+
ty::Ref(_, source_pointee, Mutability::Mut),
316+
ty::Ref(_, target_pointee, Mutability::Not),
317+
) = (source_ty.kind(), target_ty.kind())
318+
{
319+
util::relate_types(
320+
tcx,
321+
self.typing_env,
322+
ty::Variance::Covariant,
323+
*source_pointee,
324+
*target_pointee,
325+
)
326+
} else {
327+
false
328+
};
329+
if is_mut_to_shared_ref {
330+
let deref_source = source_place.project_deeper(&[mir::ProjectionElem::Deref], tcx);
331+
self.write_ref_to_place(deref_source, dest, RetagMode::Default)?;
332+
return interp_ok(());
333+
}
334+
304335
let op = self.eval_place_to_op(source_place, Some(dest.layout))?;
305336
self.copy_op(&op, dest)?;
306337
return interp_ok(());

0 commit comments

Comments
 (0)