#![feature(generators, generator_trait)]
#![feature(bindings_after_at)]
+
#![allow(unused_assignments)]
#![allow(unused_variables)]
struct Allocator {
data: RefCell<Vec<bool>>,
- name: &'static str,
failing_op: usize,
cur_ops: Cell<usize>,
}
fn drop(&mut self) {
let data = self.data.borrow();
if data.iter().any(|d| *d) {
- panic!("missing free in {:?}: {:?}", self.name, data);
+ panic!("missing free: {:?}", data);
}
}
}
impl Allocator {
- fn new(failing_op: usize, name: &'static str) -> Self {
+ fn new(failing_op: usize) -> Self {
Allocator {
failing_op: failing_op,
cur_ops: Cell::new(0),
- data: RefCell::new(vec![]),
- name,
+ data: RefCell::new(vec![])
}
}
fn alloc(&self) -> Ptr<'_> {
data.push(true);
Ptr(addr, self)
}
+ // FIXME(#47949) Any use of this indicates a bug in rustc: we should never
+ // be leaking values in the cases here.
+ //
+ // Creates a `Ptr<'_>` and checks that the allocated value is leaked if the
+ // `failing_op` is in the list of exception.
+ fn alloc_leaked(&self, exceptions: Vec<usize>) -> Ptr<'_> {
+ let ptr = self.alloc();
+
+ if exceptions.iter().any(|operation| *operation == self.failing_op) {
+ let mut data = self.data.borrow_mut();
+ data[ptr.0] = false;
+ }
+ ptr
+ }
}
struct Ptr<'a>(usize, &'a Allocator);
impl<'a> Drop for Ptr<'a> {
fn drop(&mut self) {
match self.1.data.borrow_mut()[self.0] {
- false => panic!("double free in {:?} at index {:?}", self.1.name, self.0),
- ref mut d => *d = false,
+ false => {
+ panic!("double free at index {:?}", self.0)
+ }
+ ref mut d => *d = false
}
- self.1.cur_ops.set(self.1.cur_ops.get() + 1);
+ self.1.cur_ops.set(self.1.cur_ops.get()+1);
if self.1.cur_ops.get() == self.1.failing_op {
panic::panic_any(InjectedFailure);
assert!(run_count < 4);
let mut gen = || {
- (a.alloc(), yield a.alloc(), a.alloc(), yield a.alloc());
+ (a.alloc(),
+ yield a.alloc(),
+ a.alloc(),
+ yield a.alloc()
+ );
};
for _ in 0..run_count {
Pin::new(&mut gen).resume(());
}
fn slice_pattern_first(a: &Allocator) {
- let [_x, ..] = [a.alloc(), a.alloc(), a.alloc()];
+ let[_x, ..] = [a.alloc(), a.alloc(), a.alloc()];
}
fn slice_pattern_middle(a: &Allocator) {
- let [_, _x, _] = [a.alloc(), a.alloc(), a.alloc()];
+ let[_, _x, _] = [a.alloc(), a.alloc(), a.alloc()];
}
fn slice_pattern_two(a: &Allocator) {
- let [_x, _, _y, _] = [a.alloc(), a.alloc(), a.alloc(), a.alloc()];
+ let[_x, _, _y, _] = [a.alloc(), a.alloc(), a.alloc(), a.alloc()];
}
fn slice_pattern_last(a: &Allocator) {
- let [.., _y] = [a.alloc(), a.alloc(), a.alloc(), a.alloc()];
+ let[.., _y] = [a.alloc(), a.alloc(), a.alloc(), a.alloc()];
}
fn slice_pattern_one_of(a: &Allocator, i: usize) {
let array = [a.alloc(), a.alloc(), a.alloc(), a.alloc()];
let _x = match i {
- 0 => {
- let [a, ..] = array;
- a
- }
- 1 => {
- let [_, a, ..] = array;
- a
- }
- 2 => {
- let [_, _, a, _] = array;
- a
- }
- 3 => {
- let [_, _, _, a] = array;
- a
- }
+ 0 => { let [a, ..] = array; a }
+ 1 => { let [_, a, ..] = array; a }
+ 2 => { let [_, _, a, _] = array; a }
+ 3 => { let [_, _, _, a] = array; a }
_ => panic!("unmatched"),
};
}
fn subslice_pattern_from_end(a: &Allocator, arg: bool) {
let a = [a.alloc(), a.alloc(), a.alloc()];
if arg {
- let [.., _x, _] = a;
+ let[.., _x, _] = a;
} else {
- let [_, _y @ ..] = a;
+ let[_, _y @ ..] = a;
}
}
}
if arg {
- let [.., _x, _] = a;
+ let[.., _x, _] = a;
} else {
- let [_, _y @ ..] = a;
+ let[_, _y @ ..] = a;
}
}
fn slice_pattern_reassign(a: &Allocator) {
let mut ar = [a.alloc(), a.alloc()];
- let [_, _x] = ar;
+ let[_, _x] = ar;
ar = [a.alloc(), a.alloc()];
- let [.., _y] = ar;
+ let[.., _y] = ar;
}
fn subslice_pattern_reassign(a: &Allocator) {
let mut ar = [a.alloc(), a.alloc(), a.alloc()];
- let [_, _, _x] = ar;
+ let[_, _, _x] = ar;
ar = [a.alloc(), a.alloc(), a.alloc()];
- let [_, _y @ ..] = ar;
+ let[_, _y @ ..] = ar;
}
fn index_field_mixed_ends(a: &Allocator) {
let ar = [(a.alloc(), a.alloc()), (a.alloc(), a.alloc())];
- let [(_x, _), ..] = ar;
- let [(_, _y), _] = ar;
- let [_, (_, _w)] = ar;
- let [.., (_z, _)] = ar;
+ let[(_x, _), ..] = ar;
+ let[(_, _y), _] = ar;
+ let[_, (_, _w)] = ar;
+ let[.., (_z, _)] = ar;
}
fn subslice_mixed_min_lengths(a: &Allocator, c: i32) {
let ar = [(a.alloc(), a.alloc()), (a.alloc(), a.alloc())];
match c {
- 0 => {
- let [_x, ..] = ar;
- }
- 1 => {
- let [_x, _, ..] = ar;
- }
- 2 => {
- let [_x, _] = ar;
- }
- 3 => {
- let [(_x, _), _, ..] = ar;
- }
- 4 => {
- let [.., (_x, _)] = ar;
- }
- 5 => {
- let [.., (_x, _), _] = ar;
- }
- 6 => {
- let [_y @ ..] = ar;
- }
- _ => {
- let [_y @ .., _] = ar;
- }
+ 0 => { let[_x, ..] = ar; }
+ 1 => { let[_x, _, ..] = ar; }
+ 2 => { let[_x, _] = ar; }
+ 3 => { let[(_x, _), _, ..] = ar; }
+ 4 => { let[.., (_x, _)] = ar; }
+ 5 => { let[.., (_x, _), _] = ar; }
+ 6 => { let [_y @ ..] = ar; }
+ _ => { let [_y @ .., _] = ar; }
}
}
}
fn panic_after_return(a: &Allocator) -> Ptr<'_> {
+ // Panic in the drop of `p` or `q` can leak
+ let exceptions = vec![8, 9];
a.alloc();
let p = a.alloc();
{
a.alloc();
let p = a.alloc();
- a.alloc()
+ // FIXME (#47949) We leak values when we panic in a destructor after
+ // evaluating an expression with `rustc_mir::build::Builder::into`.
+ a.alloc_leaked(exceptions)
}
}
fn panic_after_return_expr(a: &Allocator) -> Ptr<'_> {
+ // Panic in the drop of `p` or `q` can leak
+ let exceptions = vec![8, 9];
a.alloc();
let p = a.alloc();
{
a.alloc();
let q = a.alloc();
- return a.alloc();
+ // FIXME (#47949)
+ return a.alloc_leaked(exceptions);
}
}
fn panic_after_init(a: &Allocator) {
+ // Panic in the drop of `r` can leak
+ let exceptions = vec![8];
a.alloc();
let p = a.alloc();
let q = {
a.alloc();
let r = a.alloc();
- a.alloc()
+ // FIXME (#47949)
+ a.alloc_leaked(exceptions)
};
}
fn panic_after_init_temp(a: &Allocator) {
+ // Panic in the drop of `r` can leak
+ let exceptions = vec![8];
a.alloc();
let p = a.alloc();
{
a.alloc();
let r = a.alloc();
- a.alloc()
+ // FIXME (#47949)
+ a.alloc_leaked(exceptions)
};
}
fn panic_after_init_by_loop(a: &Allocator) {
+ // Panic in the drop of `r` can leak
+ let exceptions = vec![8];
a.alloc();
let p = a.alloc();
let q = loop {
a.alloc();
let r = a.alloc();
- break a.alloc();
- };
-}
-
-fn panic_after_init_by_match(a: &Allocator, b: bool) {
- a.alloc();
- let p = a.alloc();
- let _ = loop {
- let q = match b {
- true => {
- a.alloc();
- let r = a.alloc();
- a.alloc()
- }
- false => {
- a.alloc();
- let r = a.alloc();
- break a.alloc();
- }
- };
- return;
- };
-}
-
-fn panic_after_init_by_match_with_guard(a: &Allocator, b: bool) {
- a.alloc();
- let p = a.alloc();
- let q = match a.alloc() {
- _ if b => {
- a.alloc();
- let r = a.alloc();
- a.alloc()
- }
- _ => {
- a.alloc();
- let r = a.alloc();
- a.alloc()
- }
- };
-}
-
-fn panic_after_init_by_match_with_bindings_and_guard(a: &Allocator, b: bool) {
- a.alloc();
- let p = a.alloc();
- let q = match a.alloc() {
- _x if b => {
- a.alloc();
- let r = a.alloc();
- a.alloc()
- }
- _x => {
- a.alloc();
- let r = a.alloc();
- a.alloc()
- }
- };
-}
-
-fn panic_after_init_by_match_with_ref_bindings_and_guard(a: &Allocator, b: bool) {
- a.alloc();
- let p = a.alloc();
- let q = match a.alloc() {
- ref _x if b => {
- a.alloc();
- let r = a.alloc();
- a.alloc()
- }
- ref _x => {
- a.alloc();
- let r = a.alloc();
- a.alloc()
- }
- };
-}
-
-fn panic_after_init_by_break_if(a: &Allocator, b: bool) {
- a.alloc();
- let p = a.alloc();
- let q = loop {
- let r = a.alloc();
- break if b {
- let s = a.alloc();
- a.alloc()
- } else {
- a.alloc()
- };
+ // FIXME (#47949)
+ break a.alloc_leaked(exceptions);
};
}
-fn run_test<F>(mut f: F, name: &'static str)
-where
- F: FnMut(&Allocator),
+fn run_test<F>(mut f: F)
+ where F: FnMut(&Allocator)
{
- let first_alloc = Allocator::new(usize::MAX, name);
+ let first_alloc = Allocator::new(usize::MAX);
f(&first_alloc);
- for failing_op in 1..first_alloc.cur_ops.get() + 1 {
- let alloc = Allocator::new(failing_op, name);
+ for failing_op in 1..first_alloc.cur_ops.get()+1 {
+ let alloc = Allocator::new(failing_op);
let alloc = &alloc;
let f = panic::AssertUnwindSafe(&mut f);
let result = panic::catch_unwind(move || {
f.0(alloc);
});
match result {
- Ok(..) => panic!(
- "test executed {} ops but now {}",
- first_alloc.cur_ops.get(),
- alloc.cur_ops.get()
- ),
+ Ok(..) => panic!("test executed {} ops but now {}",
+ first_alloc.cur_ops.get(), alloc.cur_ops.get()),
Err(e) => {
if e.downcast_ref::<InjectedFailure>().is_none() {
panic::resume_unwind(e);
}
}
-fn run_test_nopanic<F>(mut f: F, name: &'static str)
-where
- F: FnMut(&Allocator),
+fn run_test_nopanic<F>(mut f: F)
+ where F: FnMut(&Allocator)
{
- let first_alloc = Allocator::new(usize::MAX, name);
+ let first_alloc = Allocator::new(usize::MAX);
f(&first_alloc);
}
-macro_rules! run_test {
- ($e:expr) => {
- run_test($e, stringify!($e));
- };
-}
-
fn main() {
- run_test!(|a| dynamic_init(a, false));
- run_test!(|a| dynamic_init(a, true));
- run_test!(|a| dynamic_drop(a, false));
- run_test!(|a| dynamic_drop(a, true));
-
- run_test!(|a| assignment2(a, false, false));
- run_test!(|a| assignment2(a, false, true));
- run_test!(|a| assignment2(a, true, false));
- run_test!(|a| assignment2(a, true, true));
-
- run_test!(|a| assignment1(a, false));
- run_test!(|a| assignment1(a, true));
-
- run_test!(|a| array_simple(a));
- run_test!(|a| vec_simple(a));
- run_test!(|a| vec_unreachable(a));
-
- run_test!(|a| struct_dynamic_drop(a, false, false, false));
- run_test!(|a| struct_dynamic_drop(a, false, false, true));
- run_test!(|a| struct_dynamic_drop(a, false, true, false));
- run_test!(|a| struct_dynamic_drop(a, false, true, true));
- run_test!(|a| struct_dynamic_drop(a, true, false, false));
- run_test!(|a| struct_dynamic_drop(a, true, false, true));
- run_test!(|a| struct_dynamic_drop(a, true, true, false));
- run_test!(|a| struct_dynamic_drop(a, true, true, true));
-
- run_test!(|a| field_assignment(a, false));
- run_test!(|a| field_assignment(a, true));
-
- run_test!(|a| generator(a, 0));
- run_test!(|a| generator(a, 1));
- run_test!(|a| generator(a, 2));
- run_test!(|a| generator(a, 3));
-
- run_test!(|a| mixed_drop_and_nondrop(a));
-
- run_test!(|a| slice_pattern_first(a));
- run_test!(|a| slice_pattern_middle(a));
- run_test!(|a| slice_pattern_two(a));
- run_test!(|a| slice_pattern_last(a));
- run_test!(|a| slice_pattern_one_of(a, 0));
- run_test!(|a| slice_pattern_one_of(a, 1));
- run_test!(|a| slice_pattern_one_of(a, 2));
- run_test!(|a| slice_pattern_one_of(a, 3));
-
- run_test!(|a| subslice_pattern_from_end(a, true));
- run_test!(|a| subslice_pattern_from_end(a, false));
- run_test!(|a| subslice_pattern_from_end_with_drop(a, true, true));
- run_test!(|a| subslice_pattern_from_end_with_drop(a, true, false));
- run_test!(|a| subslice_pattern_from_end_with_drop(a, false, true));
- run_test!(|a| subslice_pattern_from_end_with_drop(a, false, false));
- run_test!(|a| slice_pattern_reassign(a));
- run_test!(|a| subslice_pattern_reassign(a));
-
- run_test!(|a| index_field_mixed_ends(a));
- run_test!(|a| subslice_mixed_min_lengths(a, 0));
- run_test!(|a| subslice_mixed_min_lengths(a, 1));
- run_test!(|a| subslice_mixed_min_lengths(a, 2));
- run_test!(|a| subslice_mixed_min_lengths(a, 3));
- run_test!(|a| subslice_mixed_min_lengths(a, 4));
- run_test!(|a| subslice_mixed_min_lengths(a, 5));
- run_test!(|a| subslice_mixed_min_lengths(a, 6));
- run_test!(|a| subslice_mixed_min_lengths(a, 7));
-
- run_test!(|a| move_ref_pattern(a));
-
- run_test!(|a| {
+ run_test(|a| dynamic_init(a, false));
+ run_test(|a| dynamic_init(a, true));
+ run_test(|a| dynamic_drop(a, false));
+ run_test(|a| dynamic_drop(a, true));
+
+ run_test(|a| assignment2(a, false, false));
+ run_test(|a| assignment2(a, false, true));
+ run_test(|a| assignment2(a, true, false));
+ run_test(|a| assignment2(a, true, true));
+
+ run_test(|a| assignment1(a, false));
+ run_test(|a| assignment1(a, true));
+
+ run_test(|a| array_simple(a));
+ run_test(|a| vec_simple(a));
+ run_test(|a| vec_unreachable(a));
+
+ run_test(|a| struct_dynamic_drop(a, false, false, false));
+ run_test(|a| struct_dynamic_drop(a, false, false, true));
+ run_test(|a| struct_dynamic_drop(a, false, true, false));
+ run_test(|a| struct_dynamic_drop(a, false, true, true));
+ run_test(|a| struct_dynamic_drop(a, true, false, false));
+ run_test(|a| struct_dynamic_drop(a, true, false, true));
+ run_test(|a| struct_dynamic_drop(a, true, true, false));
+ run_test(|a| struct_dynamic_drop(a, true, true, true));
+
+ run_test(|a| field_assignment(a, false));
+ run_test(|a| field_assignment(a, true));
+
+ run_test(|a| generator(a, 0));
+ run_test(|a| generator(a, 1));
+ run_test(|a| generator(a, 2));
+ run_test(|a| generator(a, 3));
+
+ run_test(|a| mixed_drop_and_nondrop(a));
+
+ run_test(|a| slice_pattern_first(a));
+ run_test(|a| slice_pattern_middle(a));
+ run_test(|a| slice_pattern_two(a));
+ run_test(|a| slice_pattern_last(a));
+ run_test(|a| slice_pattern_one_of(a, 0));
+ run_test(|a| slice_pattern_one_of(a, 1));
+ run_test(|a| slice_pattern_one_of(a, 2));
+ run_test(|a| slice_pattern_one_of(a, 3));
+
+ run_test(|a| subslice_pattern_from_end(a, true));
+ run_test(|a| subslice_pattern_from_end(a, false));
+ run_test(|a| subslice_pattern_from_end_with_drop(a, true, true));
+ run_test(|a| subslice_pattern_from_end_with_drop(a, true, false));
+ run_test(|a| subslice_pattern_from_end_with_drop(a, false, true));
+ run_test(|a| subslice_pattern_from_end_with_drop(a, false, false));
+ run_test(|a| slice_pattern_reassign(a));
+ run_test(|a| subslice_pattern_reassign(a));
+
+ run_test(|a| index_field_mixed_ends(a));
+ run_test(|a| subslice_mixed_min_lengths(a, 0));
+ run_test(|a| subslice_mixed_min_lengths(a, 1));
+ run_test(|a| subslice_mixed_min_lengths(a, 2));
+ run_test(|a| subslice_mixed_min_lengths(a, 3));
+ run_test(|a| subslice_mixed_min_lengths(a, 4));
+ run_test(|a| subslice_mixed_min_lengths(a, 5));
+ run_test(|a| subslice_mixed_min_lengths(a, 6));
+ run_test(|a| subslice_mixed_min_lengths(a, 7));
+
+ run_test(|a| move_ref_pattern(a));
+
+ run_test(|a| {
panic_after_return(a);
});
- run_test!(|a| {
+ run_test(|a| {
panic_after_return_expr(a);
});
- run_test!(|a| panic_after_init(a));
- run_test!(|a| panic_after_init_temp(a));
- run_test!(|a| panic_after_init_by_loop(a));
- run_test!(|a| panic_after_init_by_match(a, false));
- run_test!(|a| panic_after_init_by_match(a, true));
- run_test!(|a| panic_after_init_by_match_with_guard(a, false));
- run_test!(|a| panic_after_init_by_match_with_guard(a, true));
- run_test!(|a| panic_after_init_by_match_with_bindings_and_guard(a, false));
- run_test!(|a| panic_after_init_by_match_with_bindings_and_guard(a, true));
- run_test!(|a| panic_after_init_by_match_with_ref_bindings_and_guard(a, false));
- run_test!(|a| panic_after_init_by_match_with_ref_bindings_and_guard(a, true));
- run_test!(|a| panic_after_init_by_break_if(a, false));
- run_test!(|a| panic_after_init_by_break_if(a, true));
-
- run_test!(|a| bindings_after_at_dynamic_init_move(a, true));
- run_test!(|a| bindings_after_at_dynamic_init_move(a, false));
- run_test!(|a| bindings_after_at_dynamic_init_ref(a, true));
- run_test!(|a| bindings_after_at_dynamic_init_ref(a, false));
- run_test!(|a| bindings_after_at_dynamic_drop_move(a, true));
- run_test!(|a| bindings_after_at_dynamic_drop_move(a, false));
- run_test!(|a| bindings_after_at_dynamic_drop_ref(a, true));
- run_test!(|a| bindings_after_at_dynamic_drop_ref(a, false));
-
- run_test_nopanic(|a| union1(a), "|a| union1(a)");
+ run_test(|a| panic_after_init(a));
+ run_test(|a| panic_after_init_temp(a));
+ run_test(|a| panic_after_init_by_loop(a));
+
+ run_test(|a| bindings_after_at_dynamic_init_move(a, true));
+ run_test(|a| bindings_after_at_dynamic_init_move(a, false));
+ run_test(|a| bindings_after_at_dynamic_init_ref(a, true));
+ run_test(|a| bindings_after_at_dynamic_init_ref(a, false));
+ run_test(|a| bindings_after_at_dynamic_drop_move(a, true));
+ run_test(|a| bindings_after_at_dynamic_drop_move(a, false));
+ run_test(|a| bindings_after_at_dynamic_drop_ref(a, true));
+ run_test(|a| bindings_after_at_dynamic_drop_ref(a, false));
+
+ run_test_nopanic(|a| union1(a));
}