about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorSimonas Kazlauskas <git@kazlauskas.me>2016-01-28 23:59:00 +0200
committerSimonas Kazlauskas <git@kazlauskas.me>2016-02-04 15:56:01 +0200
commit432460a6fc92e8baecbc4fa175345e78232fe2ed (patch)
treed59c70df2e2c0c9234f8134be320a5932be8d792 /src
parent7b9d6d3bc8730aa565dbb5e285027443696aef0c (diff)
downloadrust-432460a6fc92e8baecbc4fa175345e78232fe2ed.tar.gz
rust-432460a6fc92e8baecbc4fa175345e78232fe2ed.zip
Synthesize calls to box_free language item
This gets rid of Drop(Free, _) MIR construct by synthesizing a call to language item which
takes care of dropping instead.
Diffstat (limited to 'src')
-rw-r--r--src/doc/book/lang-items.md6
-rw-r--r--src/liballoc/heap.rs13
-rw-r--r--src/librustc/middle/dead.rs2
-rw-r--r--src/librustc/middle/lang_items.rs8
-rw-r--r--src/librustc/middle/reachable.rs2
-rw-r--r--src/librustc/mir/repr.rs12
-rw-r--r--src/librustc/mir/visit.rs2
-rw-r--r--src/librustc_metadata/encoder.rs2
-rw-r--r--src/librustc_mir/build/cfg.rs11
-rw-r--r--src/librustc_mir/build/expr/as_rvalue.rs25
-rw-r--r--src/librustc_mir/build/expr/as_temp.rs2
-rw-r--r--src/librustc_mir/build/expr/into.rs2
-rw-r--r--src/librustc_mir/build/matches/mod.rs2
-rw-r--r--src/librustc_mir/build/scope.rs82
-rw-r--r--src/librustc_mir/build/stmt.rs2
-rw-r--r--src/librustc_mir/hair/cx/expr.rs5
-rw-r--r--src/librustc_mir/hair/mod.rs1
-rw-r--r--src/librustc_mir/transform/erase_regions.rs2
-rw-r--r--src/librustc_trans/trans/mir/constant.rs4
-rw-r--r--src/librustc_trans/trans/mir/statement.rs11
20 files changed, 127 insertions, 69 deletions
diff --git a/src/doc/book/lang-items.md b/src/doc/book/lang-items.md
index e492bd3e782..b948567ac5b 100644
--- a/src/doc/book/lang-items.md
+++ b/src/doc/book/lang-items.md
@@ -39,11 +39,17 @@ unsafe fn allocate(size: usize, _align: usize) -> *mut u8 {
 
     p
 }
+
 #[lang = "exchange_free"]
 unsafe fn deallocate(ptr: *mut u8, _size: usize, _align: usize) {
     libc::free(ptr as *mut libc::c_void)
 }
 
+#[lang = "box_free"]
+unsafe fn box_free<T>(ptr: *mut T) {
+    deallocate(ptr as *mut u8, ::core::mem::size_of::<T>(), ::core::mem::align_of::<T>());
+}
+
 #[start]
 fn main(argc: isize, argv: *const *const u8) -> isize {
     let x = box 1;
diff --git a/src/liballoc/heap.rs b/src/liballoc/heap.rs
index 7e7e3c619cb..08b403a60f3 100644
--- a/src/liballoc/heap.rs
+++ b/src/liballoc/heap.rs
@@ -16,6 +16,8 @@
             issue = "27700")]
 
 use core::{isize, usize};
+#[cfg(not(test))]
+use core::intrinsics::{size_of, min_align_of};
 
 #[allow(improper_ctypes)]
 extern "C" {
@@ -147,6 +149,17 @@ unsafe fn exchange_free(ptr: *mut u8, old_size: usize, align: usize) {
     deallocate(ptr, old_size, align);
 }
 
+#[cfg(not(test))]
+#[lang = "box_free"]
+#[inline]
+unsafe fn box_free<T>(ptr: *mut T) {
+    let size = size_of::<T>();
+    // We do not allocate for Box<T> when T is ZST, so deallocation is also not necessary.
+    if size != 0 {
+        deallocate(ptr as *mut u8, size, min_align_of::<T>());
+    }
+}
+
 #[cfg(test)]
 mod tests {
     extern crate test;
diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs
index 1fa4093853b..7ed931265f2 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -435,7 +435,7 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> {
         let is_named = node.name().is_some();
         let field_type = self.tcx.node_id_to_type(node.id);
         let is_marker_field = match field_type.ty_to_def_id() {
-            Some(def_id) => self.tcx.lang_items.items().any(|(_, item)| *item == Some(def_id)),
+            Some(def_id) => self.tcx.lang_items.items().iter().any(|item| *item == Some(def_id)),
             _ => false
         };
         is_named
diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs
index 6e57d5dd1ba..b445f549ba2 100644
--- a/src/librustc/middle/lang_items.rs
+++ b/src/librustc/middle/lang_items.rs
@@ -36,9 +36,6 @@ use syntax::parse::token::InternedString;
 use rustc_front::intravisit::Visitor;
 use rustc_front::hir;
 
-use std::iter::Enumerate;
-use std::slice;
-
 // The actual lang items defined come at the end of this file in one handy table.
 // So you probably just want to nip down to the end.
 macro_rules! lets_do_this {
@@ -69,8 +66,8 @@ impl LanguageItems {
         }
     }
 
-    pub fn items<'a>(&'a self) -> Enumerate<slice::Iter<'a, Option<DefId>>> {
-        self.items.iter().enumerate()
+    pub fn items(&self) -> &[Option<DefId>] {
+        &*self.items
     }
 
     pub fn item_name(index: usize) -> &'static str {
@@ -334,6 +331,7 @@ lets_do_this! {
 
     ExchangeMallocFnLangItem,        "exchange_malloc",         exchange_malloc_fn;
     ExchangeFreeFnLangItem,          "exchange_free",           exchange_free_fn;
+    BoxFreeFnLangItem,               "box_free",                box_free_fn;
     StrDupUniqFnLangItem,            "strdup_uniq",             strdup_uniq_fn;
 
     StartFnLangItem,                 "start",                   start_fn;
diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs
index 6373bfbc55e..6dd447e3b68 100644
--- a/src/librustc/middle/reachable.rs
+++ b/src/librustc/middle/reachable.rs
@@ -362,7 +362,7 @@ pub fn find_reachable(tcx: &ty::ctxt,
     for (id, _) in &access_levels.map {
         reachable_context.worklist.push(*id);
     }
-    for (_, item) in tcx.lang_items.items() {
+    for item in tcx.lang_items.items().iter() {
         if let Some(did) = *item {
             if let Some(node_id) = tcx.map.as_local_node_id(did) {
                 reachable_context.worklist.push(node_id);
diff --git a/src/librustc/mir/repr.rs b/src/librustc/mir/repr.rs
index 988bf2c76a8..b9a94ad0068 100644
--- a/src/librustc/mir/repr.rs
+++ b/src/librustc/mir/repr.rs
@@ -490,14 +490,7 @@ pub struct Statement<'tcx> {
 #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
 pub enum StatementKind<'tcx> {
     Assign(Lvalue<'tcx>, Rvalue<'tcx>),
-    Drop(DropKind, Lvalue<'tcx>),
-}
-
-#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
-pub enum DropKind {
-    /// free a partially constructed box, should go away eventually
-    Free,
-    Deep
+    Drop(Lvalue<'tcx>),
 }
 
 impl<'tcx> Debug for Statement<'tcx> {
@@ -505,8 +498,7 @@ impl<'tcx> Debug for Statement<'tcx> {
         use self::StatementKind::*;
         match self.kind {
             Assign(ref lv, ref rv) => write!(fmt, "{:?} = {:?}", lv, rv),
-            Drop(DropKind::Free, ref lv) => write!(fmt, "free {:?}", lv),
-            Drop(DropKind::Deep, ref lv) => write!(fmt, "drop {:?}", lv),
+            Drop(ref lv) => write!(fmt, "drop {:?}", lv),
         }
     }
 }
diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs
index a38ef078c6f..494eac44b1a 100644
--- a/src/librustc/mir/visit.rs
+++ b/src/librustc/mir/visit.rs
@@ -124,7 +124,7 @@ macro_rules! make_mir_visitor {
                                           ref $($mutability)* rvalue) => {
                         self.visit_assign(block, lvalue, rvalue);
                     }
-                    StatementKind::Drop(_, ref $($mutability)* lvalue) => {
+                    StatementKind::Drop(ref $($mutability)* lvalue) => {
                         self.visit_lvalue(lvalue, LvalueContext::Drop);
                     }
                 }
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index 1e50868f664..8df72016078 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -1649,7 +1649,7 @@ fn encode_crate_deps(rbml_w: &mut Encoder, cstore: &cstore::CStore) {
 fn encode_lang_items(ecx: &EncodeContext, rbml_w: &mut Encoder) {
     rbml_w.start_tag(tag_lang_items);
 
-    for (i, &opt_def_id) in ecx.tcx.lang_items.items() {
+    for (i, &opt_def_id) in ecx.tcx.lang_items.items().iter().enumerate() {
         if let Some(def_id) = opt_def_id {
             if def_id.is_local() {
                 rbml_w.start_tag(tag_lang_items_item);
diff --git a/src/librustc_mir/build/cfg.rs b/src/librustc_mir/build/cfg.rs
index 523ac85cdc5..5be2b8394ee 100644
--- a/src/librustc_mir/build/cfg.rs
+++ b/src/librustc_mir/build/cfg.rs
@@ -32,16 +32,21 @@ impl<'tcx> CFG<'tcx> {
         BasicBlock::new(node_index)
     }
 
+    pub fn start_new_cleanup_block(&mut self) -> BasicBlock {
+        let bb = self.start_new_block();
+        self.block_data_mut(bb).is_cleanup = true;
+        bb
+    }
+
     pub fn push(&mut self, block: BasicBlock, statement: Statement<'tcx>) {
         debug!("push({:?}, {:?})", block, statement);
         self.block_data_mut(block).statements.push(statement);
     }
 
-    pub fn push_drop(&mut self, block: BasicBlock, span: Span,
-                     kind: DropKind, lvalue: &Lvalue<'tcx>) {
+    pub fn push_drop(&mut self, block: BasicBlock, span: Span, lvalue: &Lvalue<'tcx>) {
         self.push(block, Statement {
             span: span,
-            kind: StatementKind::Drop(kind, lvalue.clone())
+            kind: StatementKind::Drop(lvalue.clone())
         });
     }
 
diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs
index e556d707a2d..dea2d750b98 100644
--- a/src/librustc_mir/build/expr/as_rvalue.rs
+++ b/src/librustc_mir/build/expr/as_rvalue.rs
@@ -59,25 +59,18 @@ impl<'a,'tcx> Builder<'a,'tcx> {
                 let arg = unpack!(block = this.as_operand(block, arg));
                 block.and(Rvalue::UnaryOp(op, arg))
             }
-            ExprKind::Box { value } => {
+            ExprKind::Box { value, value_extents } => {
                 let value = this.hir.mirror(value);
                 let result = this.temp(expr.ty);
-
                 // to start, malloc some memory of suitable type (thus far, uninitialized):
-                let rvalue = Rvalue::Box(value.ty);
-                this.cfg.push_assign(block, expr_span, &result, rvalue);
-
-                // schedule a shallow free of that memory, lest we unwind:
-                let extent = this.extent_of_innermost_scope();
-                this.schedule_drop(expr_span, extent, DropKind::Free, &result, value.ty);
-
-                // initialize the box contents:
-                let contents = result.clone().deref();
-                unpack!(block = this.into(&contents, block, value));
-
-                // now that the result is fully initialized, cancel the drop
-                // by "using" the result (which is linear):
-                block.and(Rvalue::Use(Operand::Consume(result)))
+                this.cfg.push_assign(block, expr_span, &result, Rvalue::Box(value.ty));
+                this.in_scope(value_extents, block, |this| {
+                    // schedule a shallow free of that memory, lest we unwind:
+                    this.schedule_box_free(expr_span, value_extents, &result, value.ty);
+                    // initialize the box contents:
+                    unpack!(block = this.into(&result.clone().deref(), block, value));
+                    block.and(Rvalue::Use(Operand::Consume(result)))
+                })
             }
             ExprKind::Cast { source } => {
                 let source = unpack!(block = this.as_operand(block, source));
diff --git a/src/librustc_mir/build/expr/as_temp.rs b/src/librustc_mir/build/expr/as_temp.rs
index 53f8090ad0f..27c374e1ac2 100644
--- a/src/librustc_mir/build/expr/as_temp.rs
+++ b/src/librustc_mir/build/expr/as_temp.rs
@@ -41,7 +41,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
                 this.hir.span_bug(expr.span, "no temp_lifetime for expr");
             }
         };
-        this.schedule_drop(expr.span, temp_lifetime, DropKind::Deep, &temp, expr_ty);
+        this.schedule_drop(expr.span, temp_lifetime, &temp, expr_ty);
 
         // Careful here not to cause an infinite cycle. If we always
         // called `into`, then for lvalues like `x.f`, it would
diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs
index 4261efe8215..7ecd8a26507 100644
--- a/src/librustc_mir/build/expr/into.rs
+++ b/src/librustc_mir/build/expr/into.rs
@@ -188,7 +188,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
                 // operators like x[j] = x[i].
                 let rhs = unpack!(block = this.as_operand(block, rhs));
                 let lhs = unpack!(block = this.as_lvalue(block, lhs));
-                this.cfg.push_drop(block, expr_span, DropKind::Deep, &lhs);
+                this.cfg.push_drop(block, expr_span, &lhs);
                 this.cfg.push_assign(block, expr_span, &lhs, Rvalue::Use(rhs));
                 block.unit()
             }
diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs
index c2c87fcbd20..e6430b7d634 100644
--- a/src/librustc_mir/build/matches/mod.rs
+++ b/src/librustc_mir/build/matches/mod.rs
@@ -601,7 +601,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
             ty: var_ty.clone(),
         });
         let index = index as u32;
-        self.schedule_drop(span, var_extent, DropKind::Deep, &Lvalue::Var(index), var_ty);
+        self.schedule_drop(span, var_extent, &Lvalue::Var(index), var_ty);
         self.var_indices.insert(var_id, index);
 
         debug!("declare_binding: index={:?}", index);
diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs
index dae525c84d0..35153bc8a90 100644
--- a/src/librustc_mir/build/scope.rs
+++ b/src/librustc_mir/build/scope.rs
@@ -89,7 +89,7 @@ should go to.
 use build::{BlockAnd, BlockAndExtension, Builder};
 use rustc::middle::region::CodeExtent;
 use rustc::middle::lang_items;
-use rustc::middle::subst::Substs;
+use rustc::middle::subst::{Substs, VecPerParamSpace};
 use rustc::middle::ty::{self, Ty};
 use rustc::mir::repr::*;
 use syntax::codemap::{Span, DUMMY_SP};
@@ -97,7 +97,8 @@ use syntax::parse::token::intern_and_get_ident;
 
 pub struct Scope<'tcx> {
     extent: CodeExtent,
-    drops: Vec<(DropKind, Span, Lvalue<'tcx>)>,
+    drops: Vec<(Span, Lvalue<'tcx>)>,
+    frees: Vec<(Span, Lvalue<'tcx>, Ty<'tcx>)>,
     cached_block: Option<BasicBlock>,
 }
 
@@ -164,6 +165,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
         self.scopes.push(Scope {
             extent: extent.clone(),
             drops: vec![],
+            frees: vec![],
             cached_block: None,
         });
     }
@@ -180,8 +182,8 @@ impl<'a,'tcx> Builder<'a,'tcx> {
         // add in any drops needed on the fallthrough path (any other
         // exiting paths, such as those that arise from `break`, will
         // have drops already)
-        for (kind, span, lvalue) in scope.drops {
-            self.cfg.push_drop(block, span, kind, &lvalue);
+        for (span, lvalue) in scope.drops {
+            self.cfg.push_drop(block, span, &lvalue);
         }
     }
 
@@ -225,8 +227,8 @@ impl<'a,'tcx> Builder<'a,'tcx> {
         });
 
         for scope in scopes.iter_mut().rev().take(scope_count) {
-            for &(kind, drop_span, ref lvalue) in &scope.drops {
-                cfg.push_drop(block, drop_span, kind, lvalue);
+            for &(drop_span, ref lvalue) in &scope.drops {
+                cfg.push_drop(block, drop_span, lvalue);
             }
         }
         cfg.terminate(block, Terminator::Goto { target: target });
@@ -242,23 +244,55 @@ impl<'a,'tcx> Builder<'a,'tcx> {
             return None;
         }
 
+        let tcx = self.hir.tcx();
+        let unit_tmp = self.get_unit_temp();
         let mut terminator = Terminator::Resume;
         // Given an array of scopes, we generate these from the outermost scope to the innermost
         // one. Thus for array [S0, S1, S2] with corresponding cleanup blocks [B0, B1, B2], we will
         // generate B0 <- B1 <- B2 in left-to-right order. The outermost scope (B0) will always
         // terminate with a Resume terminator.
-        for scope in self.scopes.iter_mut().filter(|s| !s.drops.is_empty()) {
+        for scope in self.scopes.iter_mut().filter(|s| !s.drops.is_empty() || !s.frees.is_empty()) {
             if let Some(b) = scope.cached_block {
                 terminator = Terminator::Goto { target: b };
                 continue;
             } else {
-                let new_block = self.cfg.start_new_block();
-                self.cfg.block_data_mut(new_block).is_cleanup = true;
+                let mut new_block = self.cfg.start_new_cleanup_block();
                 self.cfg.terminate(new_block, terminator);
                 terminator = Terminator::Goto { target: new_block };
-                for &(kind, span, ref lvalue) in scope.drops.iter().rev() {
-                    self.cfg.push_drop(new_block, span, kind, lvalue);
+
+                for &(span, ref lvalue) in scope.drops.iter().rev() {
+                    self.cfg.push_drop(new_block, span, lvalue);
+                }
+
+                for &(_, ref lvalue, ref item_ty) in scope.frees.iter().rev() {
+                    let item = lang_items::SpannedLangItems::box_free_fn(&tcx.lang_items)
+                        .expect("box_free language item required");
+                    let substs = tcx.mk_substs(Substs::new(
+                        VecPerParamSpace::new(vec![], vec![], vec![item_ty]),
+                        VecPerParamSpace::new(vec![], vec![], vec![])
+                    ));
+                    let func = Constant {
+                        span: item.1,
+                        ty: tcx.lookup_item_type(item.0).ty.subst(substs),
+                        literal: Literal::Item {
+                            def_id: item.0,
+                            kind: ItemKind::Function,
+                            substs: substs
+                        }
+                    };
+                    let old_block = new_block;
+                    new_block = self.cfg.start_new_cleanup_block();
+                    self.cfg.terminate(new_block, Terminator::Call {
+                        func: Operand::Constant(func),
+                        args: vec![Operand::Consume(lvalue.clone())],
+                        kind: CallKind::Converging {
+                            target: old_block,
+                            destination: unit_tmp.clone()
+                        }
+                    });
+                    terminator = Terminator::Goto { target: new_block };
                 }
+
                 scope.cached_block = Some(new_block);
             }
         }
@@ -272,7 +306,6 @@ impl<'a,'tcx> Builder<'a,'tcx> {
     pub fn schedule_drop(&mut self,
                          span: Span,
                          extent: CodeExtent,
-                         kind: DropKind,
                          lvalue: &Lvalue<'tcx>,
                          lvalue_ty: Ty<'tcx>) {
         if self.hir.needs_drop(lvalue_ty) {
@@ -282,7 +315,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
                 // incorrect (i.e. they still are pointing at old cached_block).
                 scope.cached_block = None;
                 if scope.extent == extent {
-                    scope.drops.push((kind, span, lvalue.clone()));
+                    scope.drops.push((span, lvalue.clone()));
                     return;
                 }
             }
@@ -291,6 +324,27 @@ impl<'a,'tcx> Builder<'a,'tcx> {
         }
     }
 
+    /// Schedule dropping of a not yet fully initialised box. This cleanup will (and should) only
+    /// be translated into unwind branch. The extent should be for the `EXPR` inside `box EXPR`.
+    pub fn schedule_box_free(&mut self,
+                             span: Span,
+                             extent: CodeExtent,
+                             lvalue: &Lvalue<'tcx>,
+                             item_ty: Ty<'tcx>) {
+        for scope in self.scopes.iter_mut().rev() {
+            // We must invalidate all the cached_blocks leading up to the scope we’re looking
+            // for, because otherwise some/most of the blocks in the chain might become
+            // incorrect (i.e. they still are pointing at old cached_block).
+            scope.cached_block = None;
+            if scope.extent == extent {
+                scope.frees.push((span, lvalue.clone(), item_ty));
+                return;
+            }
+        }
+        self.hir.span_bug(span,
+                          &format!("extent {:?} not in scope to drop {:?}", extent, lvalue));
+    }
+
     pub fn extent_of_innermost_scope(&self) -> CodeExtent {
         self.scopes.last().map(|scope| scope.extent).unwrap()
     }
@@ -299,6 +353,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
         self.scopes.first().map(|scope| scope.extent).unwrap()
     }
 
+
     pub fn panic_bounds_check(&mut self,
                              block: BasicBlock,
                              index: Operand<'tcx>,
@@ -405,4 +460,5 @@ impl<'a,'tcx> Builder<'a,'tcx> {
             literal: self.hir.usize_literal(span_lines.line)
         })
     }
+
 }
diff --git a/src/librustc_mir/build/stmt.rs b/src/librustc_mir/build/stmt.rs
index c70b22893ae..3a50acec94f 100644
--- a/src/librustc_mir/build/stmt.rs
+++ b/src/librustc_mir/build/stmt.rs
@@ -72,7 +72,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
                         let expr = this.hir.mirror(expr);
                         let temp = this.temp(expr.ty.clone());
                         unpack!(block = this.into(&temp, block, expr));
-                        this.cfg.push_drop(block, span, DropKind::Deep, &temp);
+                        this.cfg.push_drop(block, span, &temp);
                         block.unit()
                     }));
                 }
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs
index d8a1930fd5c..f9a9c99f63d 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir/hair/cx/expr.rs
@@ -375,7 +375,10 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
             hir::ExprType(ref source, _) =>
                 return source.make_mirror(cx),
             hir::ExprBox(ref value) =>
-                ExprKind::Box { value: value.to_ref() },
+                ExprKind::Box {
+                    value: value.to_ref(),
+                    value_extents: cx.tcx.region_maps.node_extent(value.id)
+                },
             hir::ExprVec(ref fields) =>
                 ExprKind::Vec { fields: fields.to_ref() },
             hir::ExprTup(ref fields) =>
diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs
index b356e3886d1..0891c2845b0 100644
--- a/src/librustc_mir/hair/mod.rs
+++ b/src/librustc_mir/hair/mod.rs
@@ -123,6 +123,7 @@ pub enum ExprKind<'tcx> {
     },
     Box {
         value: ExprRef<'tcx>,
+        value_extents: CodeExtent,
     },
     Call {
         ty: ty::Ty<'tcx>,
diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs
index 66604786d46..3cd1bd76c54 100644
--- a/src/librustc_mir/transform/erase_regions.rs
+++ b/src/librustc_mir/transform/erase_regions.rs
@@ -69,7 +69,7 @@ impl<'a, 'tcx> EraseRegions<'a, 'tcx> {
                 self.erase_regions_lvalue(lvalue);
                 self.erase_regions_rvalue(rvalue);
             }
-            StatementKind::Drop(_, ref mut lvalue) => {
+            StatementKind::Drop(ref mut lvalue) => {
                 self.erase_regions_lvalue(lvalue);
             }
         }
diff --git a/src/librustc_trans/trans/mir/constant.rs b/src/librustc_trans/trans/mir/constant.rs
index 84cc87e9b13..3b763599f77 100644
--- a/src/librustc_trans/trans/mir/constant.rs
+++ b/src/librustc_trans/trans/mir/constant.rs
@@ -82,13 +82,13 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                           constant: &mir::Constant<'tcx>)
                           -> OperandRef<'tcx>
     {
-        let ty = bcx.monomorphize(&constant.ty);
         match constant.literal {
             mir::Literal::Item { def_id, kind, substs } => {
                 let substs = bcx.tcx().mk_substs(bcx.monomorphize(&substs));
-                self.trans_item_ref(bcx, ty, kind, substs, def_id)
+                self.trans_item_ref(bcx, constant.ty, kind, substs, def_id)
             }
             mir::Literal::Value { ref value } => {
+                let ty = bcx.monomorphize(&constant.ty);
                 self.trans_constval(bcx, value, ty)
             }
         }
diff --git a/src/librustc_trans/trans/mir/statement.rs b/src/librustc_trans/trans/mir/statement.rs
index dae0d3b55c0..cd186de7ca0 100644
--- a/src/librustc_trans/trans/mir/statement.rs
+++ b/src/librustc_trans/trans/mir/statement.rs
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use rustc::middle::ty::LvaluePreference;
 use rustc::mir::repr as mir;
 use trans::common::Block;
 use trans::debuginfo::DebugLoc;
@@ -52,19 +51,11 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                 }
             }
 
-            mir::StatementKind::Drop(mir::DropKind::Deep, ref lvalue) => {
+            mir::StatementKind::Drop(ref lvalue) => {
                 let tr_lvalue = self.trans_lvalue(bcx, lvalue);
                 let ty = tr_lvalue.ty.to_ty(bcx.tcx());
                 glue::drop_ty(bcx, tr_lvalue.llval, ty, DebugLoc::None)
             }
-
-            mir::StatementKind::Drop(mir::DropKind::Free, ref lvalue) => {
-                let tr_lvalue = self.trans_lvalue(bcx, lvalue);
-                let ty = tr_lvalue.ty.to_ty(bcx.tcx());
-                let content_ty = ty.builtin_deref(true, LvaluePreference::NoPreference);
-                let content_ty = content_ty.unwrap().ty;
-                glue::trans_exchange_free_ty(bcx, tr_lvalue.llval, content_ty, DebugLoc::None)
-            }
         }
     }
 }