]> git.proxmox.com Git - rustc.git/blob - src/librustc_mir/interpret/terminator/drop.rs
New upstream version 1.28.0~beta.14+dfsg1
[rustc.git] / src / librustc_mir / interpret / terminator / drop.rs
1 use rustc::mir::BasicBlock;
2 use rustc::ty::{self, Ty};
3 use syntax::codemap::Span;
4
5 use rustc::mir::interpret::{EvalResult, Scalar, Value};
6 use interpret::{Machine, ValTy, EvalContext, Place, PlaceExtra};
7
8 impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
9 pub(crate) fn drop_place(
10 &mut self,
11 place: Place,
12 instance: ty::Instance<'tcx>,
13 ty: Ty<'tcx>,
14 span: Span,
15 target: BasicBlock,
16 ) -> EvalResult<'tcx> {
17 trace!("drop_place: {:#?}", place);
18 // We take the address of the object. This may well be unaligned, which is fine for us here.
19 // However, unaligned accesses will probably make the actual drop implementation fail -- a problem shared
20 // by rustc.
21 let val = match self.force_allocation(place)? {
22 Place::Ptr {
23 ptr,
24 align: _,
25 extra: PlaceExtra::Vtable(vtable),
26 } => ptr.to_value_with_vtable(vtable),
27 Place::Ptr {
28 ptr,
29 align: _,
30 extra: PlaceExtra::Length(len),
31 } => ptr.to_value_with_len(len, self.tcx.tcx),
32 Place::Ptr {
33 ptr,
34 align: _,
35 extra: PlaceExtra::None,
36 } => ptr.to_value(),
37 _ => bug!("force_allocation broken"),
38 };
39 self.drop(val, instance, ty, span, target)
40 }
41
42 fn drop(
43 &mut self,
44 arg: Value,
45 instance: ty::Instance<'tcx>,
46 ty: Ty<'tcx>,
47 span: Span,
48 target: BasicBlock,
49 ) -> EvalResult<'tcx> {
50 trace!("drop: {:#?}, {:?}, {:?}", arg, ty.sty, instance.def);
51
52 let instance = match ty.sty {
53 ty::TyDynamic(..) => {
54 let vtable = match arg {
55 Value::ScalarPair(_, Scalar::Ptr(vtable)) => vtable,
56 _ => bug!("expected fat ptr, got {:?}", arg),
57 };
58 match self.read_drop_type_from_vtable(vtable)? {
59 Some(func) => func,
60 // no drop fn -> bail out
61 None => {
62 self.goto_block(target);
63 return Ok(())
64 },
65 }
66 }
67 _ => instance,
68 };
69
70 // the drop function expects a reference to the value
71 let valty = ValTy {
72 value: arg,
73 ty: self.tcx.mk_mut_ptr(ty),
74 };
75
76 let fn_sig = self.tcx.fn_sig(instance.def_id()).skip_binder().clone();
77
78 self.eval_fn_call(
79 instance,
80 Some((Place::undef(), target)),
81 &vec![valty],
82 span,
83 fn_sig,
84 )
85 }
86 }