diff --git a/src/test/compile-fail/generator/yield-during-borrow.rs b/src/test/compile-fail/generator/yield-during-borrow.rs new file mode 100644 index 000000000000..46732ce6599a --- /dev/null +++ b/src/test/compile-fail/generator/yield-during-borrow.rs @@ -0,0 +1,144 @@ +// Copyright 2017 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(generators, generator_trait)] + +use std::ops::{State, Generator}; +use std::cell::Cell; + +fn borrow_local_inline() { + // Not OK to yield with a borrow of a temporary. + // + // (This error occurs because the region shows up in the type of + // `b` and gets extended by region inference.) + let mut b = move || { + let a = &3; + yield(); + println!("{}", a); + }; //~ ERROR E0597 + b.resume(); +} + +fn borrow_local_inline_done() { + // No error here -- `a` is not in scope at the point of `yield`. + let mut b = move || { + { + let a = &3; + } + yield(); + }; + b.resume(); +} + +fn borrow_local() { + // Not OK to yield with a borrow of a temporary. + // + // (This error occurs because the region shows up in the type of + // `b` and gets extended by region inference.) + let mut b = move || { + let a = 3; + { + let b = &a; + yield(); + println!("{}", b); + } + }; //~ ERROR E0597 + b.resume(); +} + +fn reborrow_shared_ref(x: &i32) { + // This is OK -- we have a borrow live over the yield, but it's of + // data that outlives the generator. + let mut b = move || { + let a = &*x; + yield(); + println!("{}", a); + }; + b.resume(); +} + +fn reborrow_mutable_ref(x: &mut i32) { + // This is OK -- we have a borrow live over the yield, but it's of + // data that outlives the generator. + let mut b = move || { + let a = &mut *x; + yield(); + println!("{}", a); + }; + b.resume(); +} + +fn reborrow_mutable_ref_2(x: &mut i32) { + // ...but not OK to go on using `x`. + let mut b = || { + let a = &mut *x; + yield(); + println!("{}", a); + }; + println!("{}", x); //~ ERROR E0501 + b.resume(); +} + +fn yield_during_iter_owned_data(x: Vec) { + // The generator owns `x`, so we error out when yielding with a + // reference to it. This winds up becoming a rather confusing + // regionck error -- in particular, we would freeze with the + // reference in scope, and it doesn't live long enough. + let _b = move || { + for p in &x { + yield(); + } + }; //~ ERROR E0597 +} + +fn yield_during_iter_borrowed_slice(x: &[i32]) { + let _b = move || { + for p in x { + yield(); + } + }; +} + +fn yield_during_iter_borrowed_slice_2() { + let mut x = vec![22_i32]; + let _b = || { + for p in &x { + yield(); + } + }; + println!("{:?}", x); +} + +fn yield_during_iter_borrowed_slice_3() { + // OK to take a mutable ref to `x` and yield + // up pointers from it: + let mut x = vec![22_i32]; + let mut b = || { + for p in &mut x { + yield p; + } + }; + b.resume(); +} + +fn yield_during_iter_borrowed_slice_4() { + // ...but not OK to do that while reading + // from `x` too + let mut x = vec![22_i32]; + let mut b = || { + for p in &mut x { + yield p; + } + }; + println!("{}", x[0]); //~ ERROR cannot borrow `x` as immutable + b.resume(); +} + +fn main() { }