diff --git a/src/test/run-pass/issue-29092.rs b/src/test/run-pass/issue-29092.rs new file mode 100644 index 00000000000..c55cc91cc92 --- /dev/null +++ b/src/test/run-pass/issue-29092.rs @@ -0,0 +1,35 @@ +// Copyright 2012-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. + +// Regression test for Issue #29092. +// +// (Possibly redundant with regression test run-pass/issue-30530.rs) + +use self::Term::*; + +#[derive(Clone)] +pub enum Term { + Dummy, + A(Box), + B(Box), +} + +// a small-step evaluator +pub fn small_eval(v: Term) -> Term { + match v { + A(t) => *t.clone(), + B(t) => *t.clone(), + _ => Dummy, + } +} + +fn main() { + small_eval(Dummy); +} diff --git a/src/test/run-pass/issue-30018-nopanic.rs b/src/test/run-pass/issue-30018-nopanic.rs new file mode 100644 index 00000000000..25eff9def9d --- /dev/null +++ b/src/test/run-pass/issue-30018-nopanic.rs @@ -0,0 +1,111 @@ +// Copyright 2012-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. + +// More thorough regression test for Issues #30018 and #30822. This +// attempts to explore different ways that array element construction +// (for both scratch arrays and non-scratch ones) interacts with +// breaks in the control-flow, in terms of the order of evaluation of +// the destructors (which may change; see RFC Issue 744) and the +// number of times that the destructor evaluates for each value (which +// should never exceed 1; this latter case is what #30822 is about). + +use std::cell::RefCell; + +struct D<'a>(&'a RefCell>, i32); + +impl<'a> Drop for D<'a> { + fn drop(&mut self) { + println!("Dropping D({})", self.1); + (self.0).borrow_mut().push(self.1); + } +} + +fn main() { + println!("Start"); + break_during_elem(); + break_after_whole(); + println!("Finis"); +} + +fn break_during_elem() { + let log = &RefCell::new(Vec::new()); + + // CASE 1: Fixed-size array itself is stored in _r slot. + loop { + let _r = [D(log, 10), + D(log, 11), + { D(log, 12); break; }, + D(log, 13)]; + } + assert_eq!(&log.borrow()[..], &[12, 11, 10]); + log.borrow_mut().clear(); + + // CASE 2: Slice (borrow of array) is stored in _r slot. + // This is the case that is actually being reported in #30018. + loop { + let _r = &[D(log, 20), + D(log, 21), + { D(log, 22); break; }, + D(log, 23)]; + } + assert_eq!(&log.borrow()[..], &[22, 21, 20]); + log.borrow_mut().clear(); + + // CASE 3: (Borrow of) slice-index of array is stored in _r slot. + loop { + let _r = &[D(log, 30), + D(log, 31), + { D(log, 32); break; }, + D(log, 33)][..]; + } + assert_eq!(&log.borrow()[..], &[32, 31, 30]); + log.borrow_mut().clear(); +} + +// The purpose of these functions is to test what happens when we +// panic after an array has been constructed in its entirety. +// +// It is meant to act as proof that we still need to continue +// scheduling the destruction of an array even after we've scheduling +// drop for its elements during construction; the latter is tested by +// `fn break_during_elem()`. +fn break_after_whole() { + let log = &RefCell::new(Vec::new()); + + // CASE 1: Fixed-size array itself is stored in _r slot. + loop { + let _r = [D(log, 10), + D(log, 11), + D(log, 12)]; + break; + } + assert_eq!(&log.borrow()[..], &[10, 11, 12]); + log.borrow_mut().clear(); + + // CASE 2: Slice (borrow of array) is stored in _r slot. + loop { + let _r = &[D(log, 20), + D(log, 21), + D(log, 22)]; + break; + } + assert_eq!(&log.borrow()[..], &[20, 21, 22]); + log.borrow_mut().clear(); + + // CASE 3: (Borrow of) slice-index of array is stored in _r slot. + loop { + let _r = &[D(log, 30), + D(log, 31), + D(log, 32)][..]; + break; + } + assert_eq!(&log.borrow()[..], &[30, 31, 32]); + log.borrow_mut().clear(); +} diff --git a/src/test/run-pass/issue-30018-panic.rs b/src/test/run-pass/issue-30018-panic.rs new file mode 100644 index 00000000000..da4d5f19d4a --- /dev/null +++ b/src/test/run-pass/issue-30018-panic.rs @@ -0,0 +1,32 @@ +// Copyright 2012-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. + +// Regression test for Issue #30018. This is very similar to the +// original reported test, except that the panic is wrapped in a +// spawned thread to isolate the expected error result from the +// SIGTRAP injected by the drop-flag consistency checking. + +struct Foo; + +impl Drop for Foo { + fn drop(&mut self) {} +} + +fn foo() -> Foo { + panic!(); +} + +fn main() { + use std::thread; + let handle = thread::spawn(|| { + let _ = &[foo()]; + }); + let _ = handle.join(); +} diff --git a/src/test/run-pass/issue-30530.rs b/src/test/run-pass/issue-30530.rs new file mode 100644 index 00000000000..d5139c908bd --- /dev/null +++ b/src/test/run-pass/issue-30530.rs @@ -0,0 +1,35 @@ +// Copyright 2012-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. + +// Regression test for Issue #30530: alloca's created for storing +// intermediate scratch values during brace-less match arms need to be +// initialized with their drop-flag set to "dropped" (or else we end +// up running the destructors on garbage data at the end of the +// function). + +pub enum Handler { + Default, + #[allow(dead_code)] + Custom(*mut Box), +} + +fn main() { + take(Handler::Default, Box::new(main)); +} + +#[inline(never)] +pub fn take(h: Handler, f: Box) -> Box { + unsafe { + match h { + Handler::Custom(ptr) => *Box::from_raw(ptr), + Handler::Default => f, + } + } +}