From ebf6341d1dfe57a7ad6f7f87501b018ffe24bba8 Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Sat, 30 Jan 2016 19:32:50 +0200 Subject: [PATCH] Translation part of drop panic recovery With this commit we now finally execute all the leftover drops once some drop panics for some reason! --- src/librustc_trans/trans/mir/block.rs | 33 ++++++++++++++++++++++--- src/librustc_trans/trans/mir/lvalue.rs | 2 +- src/librustc_trans/trans/mir/mod.rs | 8 +++--- src/test/run-fail/mir_drop_panics.rs | 34 ++++++++++++++++++++++++++ 4 files changed, 68 insertions(+), 9 deletions(-) create mode 100644 src/test/run-fail/mir_drop_panics.rs diff --git a/src/librustc_trans/trans/mir/block.rs b/src/librustc_trans/trans/mir/block.rs index bb43c5ae97e..5be585c4189 100644 --- a/src/librustc_trans/trans/mir/block.rs +++ b/src/librustc_trans/trans/mir/block.rs @@ -95,11 +95,36 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { base::build_return_block(bcx.fcx, bcx, return_ty, DebugLoc::None); } - mir::Terminator::Drop { ref value, target, unwind: _ } => { + mir::Terminator::Drop { ref value, target, unwind } => { let lvalue = self.trans_lvalue(bcx, value); - // FIXME: this does not account for possibility of unwinding (and totally should). - glue::drop_ty(bcx, lvalue.llval, lvalue.ty.to_ty(bcx.tcx()), DebugLoc::None); - build::Br(bcx, self.llblock(target), DebugLoc::None); + let ty = lvalue.ty.to_ty(bcx.tcx()); + // Double check for necessity to drop + if !glue::type_needs_drop(bcx.tcx(), ty) { + build::Br(bcx, self.llblock(target), DebugLoc::None); + return; + } + let drop_fn = glue::get_drop_glue(bcx.ccx(), ty); + let drop_ty = glue::get_drop_glue_type(bcx.ccx(), ty); + let llvalue = if drop_ty != ty { + build::PointerCast(bcx, lvalue.llval, + type_of::type_of(bcx.ccx(), drop_ty).ptr_to()) + } else { + lvalue.llval + }; + if let Some(unwind) = unwind { + let uwbcx = self.bcx(unwind); + let unwind = self.make_landing_pad(uwbcx); + build::Invoke(bcx, + drop_fn, + &[llvalue], + self.llblock(target), + unwind.llbb, + None, + DebugLoc::None); + } else { + build::Call(bcx, drop_fn, &[llvalue], None, DebugLoc::None); + build::Br(bcx, self.llblock(target), DebugLoc::None); + } } mir::Terminator::Call { ref func, ref args, ref destination, ref cleanup } => { diff --git a/src/librustc_trans/trans/mir/lvalue.rs b/src/librustc_trans/trans/mir/lvalue.rs index a6ba069742d..d994f1ea7b0 100644 --- a/src/librustc_trans/trans/mir/lvalue.rs +++ b/src/librustc_trans/trans/mir/lvalue.rs @@ -65,7 +65,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { assert!(lvalue.llextra != ptr::null_mut()); lvalue.llextra } - _ => bcx.sess().bug("unexpected type in get_base_and_len"), + _ => bcx.sess().bug("unexpected type in lvalue_len"), } } diff --git a/src/librustc_trans/trans/mir/mod.rs b/src/librustc_trans/trans/mir/mod.rs index cfe48af35ca..b19ecc45a4e 100644 --- a/src/librustc_trans/trans/mir/mod.rs +++ b/src/librustc_trans/trans/mir/mod.rs @@ -195,8 +195,8 @@ fn arg_value_refs<'bcx, 'tcx>(bcx: Block<'bcx, 'tcx>, mod analyze; mod block; mod constant; -mod lvalue; -mod rvalue; -mod operand; -mod statement; mod did; +mod lvalue; +mod operand; +mod rvalue; +mod statement; diff --git a/src/test/run-fail/mir_drop_panics.rs b/src/test/run-fail/mir_drop_panics.rs new file mode 100644 index 00000000000..9868ff4c241 --- /dev/null +++ b/src/test/run-fail/mir_drop_panics.rs @@ -0,0 +1,34 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +#![feature(rustc_attrs)] +// error-pattern:panic 1 +// error-pattern:drop 2 +use std::io::{self, Write}; + +struct Droppable(u32); +impl Drop for Droppable { + fn drop(&mut self) { + if self.0 == 1 { + panic!("panic 1"); + } else { + write!(io::stderr(), "drop {}", self.0); + } + } +} + +#[rustc_mir] +fn mir() { + let x = Droppable(2); + let y = Droppable(1); +} + +fn main() { + mir(); +}