]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/interpret/terminator/drop.rs
d750c1f47a662f5deb968d4289755e4d96f1f2d3
[rust.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             &[valty],
82             span,
83             fn_sig,
84         )
85     }
86 }