Unit/regression tests for issues #29092, #30018, #30530, #30822.

Note that the test for #30822 is folded into the test for #30530 (but
the file name mentions only 30530).
This commit is contained in:
Felix S. Klock II 2016-01-11 18:32:28 +01:00
parent f251ff4081
commit df1283cd1a
4 changed files with 213 additions and 0 deletions

View File

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<Term>),
B(Box<Term>),
}
// 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);
}

View File

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<Vec<i32>>, 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();
}

View File

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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();
}

View File

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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()>),
}
fn main() {
take(Handler::Default, Box::new(main));
}
#[inline(never)]
pub fn take(h: Handler, f: Box<Fn()>) -> Box<Fn()> {
unsafe {
match h {
Handler::Custom(ptr) => *Box::from_raw(ptr),
Handler::Default => f,
}
}
}