Skip to content

Commit 43b24c6

Browse files
committed
Pass the right type to box_free() in MIR
Currently, MIR just passes the raw Box to box_free(), which happens to work because practically, it's the same thing. But that might not be true in the future, with Box<T, A: Alloc>. The MIR inline pass actually fixes up the argument while inlining box_free, but this is not enabled by default and doesn't necessarily happen (the inline threshold needs to be passed). This change effectively moves what the MIR inline pass does to the elaborate_drops pass, so that box_free() is passed the raw pointer instead of the Box.
1 parent 8830a03 commit 43b24c6

File tree

2 files changed

+34
-70
lines changed

2 files changed

+34
-70
lines changed

src/librustc_mir/transform/inline.rs

Lines changed: 2 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -379,8 +379,6 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
379379
TerminatorKind::Call { args, destination: Some(destination), cleanup, .. } => {
380380
debug!("Inlined {:?} into {:?}", callsite.callee, self.source);
381381

382-
let is_box_free = Some(callsite.callee) == self.tcx.lang_items().box_free_fn();
383-
384382
let mut local_map = IndexVec::with_capacity(callee_mir.local_decls.len());
385383
let mut scope_map = IndexVec::with_capacity(callee_mir.visibility_scopes.len());
386384
let mut promoted_map = IndexVec::with_capacity(callee_mir.promoted.len());
@@ -460,24 +458,8 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
460458

461459
let return_block = destination.1;
462460

463-
let args : Vec<_> = if is_box_free {
464-
assert!(args.len() == 1);
465-
// box_free takes a Box, but is defined with a *mut T, inlining
466-
// needs to generate the cast.
467-
// FIXME: we should probably just generate correct MIR in the first place...
468-
469-
let arg = if let Operand::Move(ref place) = args[0] {
470-
place.clone()
471-
} else {
472-
bug!("Constant arg to \"box_free\"");
473-
};
474-
475-
let ptr_ty = args[0].ty(caller_mir, self.tcx);
476-
vec![self.cast_box_free_arg(arg, ptr_ty, &callsite, caller_mir)]
477-
} else {
478-
// Copy the arguments if needed.
479-
self.make_call_args(args, &callsite, caller_mir)
480-
};
461+
// Copy the arguments if needed.
462+
let args: Vec<_> = self.make_call_args(args, &callsite, caller_mir);
481463

482464
let bb_len = caller_mir.basic_blocks().len();
483465
let mut integrator = Integrator {
@@ -518,49 +500,6 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
518500
}
519501
}
520502

521-
fn cast_box_free_arg(&self, arg: Place<'tcx>, ptr_ty: Ty<'tcx>,
522-
callsite: &CallSite<'tcx>, caller_mir: &mut Mir<'tcx>) -> Local {
523-
let arg = Rvalue::Ref(
524-
self.tcx.types.re_erased,
525-
BorrowKind::Mut { allow_two_phase_borrow: false },
526-
arg.deref());
527-
528-
let ty = arg.ty(caller_mir, self.tcx);
529-
let ref_tmp = LocalDecl::new_temp(ty, callsite.location.span);
530-
let ref_tmp = caller_mir.local_decls.push(ref_tmp);
531-
let ref_tmp = Place::Local(ref_tmp);
532-
533-
let ref_stmt = Statement {
534-
source_info: callsite.location,
535-
kind: StatementKind::Assign(ref_tmp.clone(), arg)
536-
};
537-
538-
caller_mir[callsite.bb]
539-
.statements.push(ref_stmt);
540-
541-
let pointee_ty = match ptr_ty.sty {
542-
ty::TyRawPtr(tm) | ty::TyRef(_, tm) => tm.ty,
543-
_ if ptr_ty.is_box() => ptr_ty.boxed_ty(),
544-
_ => bug!("Invalid type `{:?}` for call to box_free", ptr_ty)
545-
};
546-
let ptr_ty = self.tcx.mk_mut_ptr(pointee_ty);
547-
548-
let raw_ptr = Rvalue::Cast(CastKind::Misc, Operand::Move(ref_tmp), ptr_ty);
549-
550-
let cast_tmp = LocalDecl::new_temp(ptr_ty, callsite.location.span);
551-
let cast_tmp = caller_mir.local_decls.push(cast_tmp);
552-
553-
let cast_stmt = Statement {
554-
source_info: callsite.location,
555-
kind: StatementKind::Assign(Place::Local(cast_tmp), raw_ptr)
556-
};
557-
558-
caller_mir[callsite.bb]
559-
.statements.push(cast_stmt);
560-
561-
cast_tmp
562-
}
563-
564503
fn make_call_args(
565504
&self,
566505
args: Vec<Operand<'tcx>>,

src/librustc_mir/util/elaborate_drops.rs

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -876,14 +876,39 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
876876
let unit_temp = Place::Local(self.new_temp(tcx.mk_nil()));
877877
let free_func = tcx.require_lang_item(lang_items::BoxFreeFnLangItem);
878878
let substs = tcx.mk_substs(iter::once(Kind::from(ty)));
879+
let ref_ty = tcx.mk_ref(tcx.types.re_erased, ty::TypeAndMut {
880+
ty: ty,
881+
mutbl: hir::Mutability::MutMutable
882+
});
883+
let ptr_ty = tcx.mk_mut_ptr(ty);
884+
let ref_tmp = Place::Local(self.new_temp(ref_ty));
885+
let ptr_tmp = Place::Local(self.new_temp(ptr_ty));
879886

880-
let call = TerminatorKind::Call {
881-
func: Operand::function_handle(tcx, free_func, substs, self.source_info.span),
882-
args: vec![Operand::Move(self.place.clone())],
883-
destination: Some((unit_temp, target)),
884-
cleanup: None
885-
}; // FIXME(#43234)
886-
let free_block = self.new_block(unwind, call);
887+
let free_block = BasicBlockData {
888+
statements: vec![
889+
self.assign(&ref_tmp, Rvalue::Ref(
890+
tcx.types.re_erased,
891+
BorrowKind::Mut { allow_two_phase_borrow: false },
892+
self.place.clone().deref()
893+
)),
894+
self.assign(&ptr_tmp, Rvalue::Cast(
895+
CastKind::Misc,
896+
Operand::Move(ref_tmp),
897+
ptr_ty,
898+
)),
899+
],
900+
terminator: Some(Terminator {
901+
kind: TerminatorKind::Call {
902+
func: Operand::function_handle(tcx, free_func, substs, self.source_info.span),
903+
args: vec![Operand::Move(ptr_tmp)],
904+
destination: Some((unit_temp, target)),
905+
cleanup: None
906+
}, // FIXME(#43234)
907+
source_info: self.source_info,
908+
}),
909+
is_cleanup: unwind.is_cleanup()
910+
};
911+
let free_block = self.elaborator.patch().new_block(free_block);
887912

888913
let block_start = Location { block: free_block, statement_index: 0 };
889914
self.elaborator.clear_drop_flag(block_start, self.path, DropFlagMode::Shallow);

0 commit comments

Comments
 (0)