Skip to content

Commit

Permalink
Unit/regression tests for issues #29092, #30018, #30530, #30822.
Browse files Browse the repository at this point in the history
Note that the test for #30822 is folded into the test for #30530 (but
the file name mentions only 30530).
  • Loading branch information
pnkfelix committed Jan 13, 2016
1 parent f251ff4 commit df1283c
Show file tree
Hide file tree
Showing 4 changed files with 213 additions and 0 deletions.
35 changes: 35 additions & 0 deletions 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 <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);
}
111 changes: 111 additions & 0 deletions 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 <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();
}
32 changes: 32 additions & 0 deletions 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 <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();
}
35 changes: 35 additions & 0 deletions 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 <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,
}
}
}

0 comments on commit df1283c

Please sign in to comment.