diff options
| author | Vadim Petrochenkov <vadim.petrochenkov@gmail.com> | 2019-07-27 01:33:01 +0300 |
|---|---|---|
| committer | Vadim Petrochenkov <vadim.petrochenkov@gmail.com> | 2019-07-27 18:56:16 +0300 |
| commit | 9be35f82c1abf2ecbab489bca9eca138ea648312 (patch) | |
| tree | 69888506e34af447d9748c0d542de3ba1dd76210 /src/test/ui/threads-sendsync | |
| parent | ca9faa52f5ada0054b1fa27d97aedf448afb059b (diff) | |
| download | rust-9be35f82c1abf2ecbab489bca9eca138ea648312.tar.gz rust-9be35f82c1abf2ecbab489bca9eca138ea648312.zip | |
tests: Move run-pass tests without naming conflicts to ui
Diffstat (limited to 'src/test/ui/threads-sendsync')
46 files changed, 1476 insertions, 0 deletions
diff --git a/src/test/ui/threads-sendsync/auxiliary/thread-local-extern-static.rs b/src/test/ui/threads-sendsync/auxiliary/thread-local-extern-static.rs new file mode 100644 index 00000000000..b237b1c480e --- /dev/null +++ b/src/test/ui/threads-sendsync/auxiliary/thread-local-extern-static.rs @@ -0,0 +1,10 @@ +#![feature(cfg_target_thread_local, const_fn, thread_local)] +#![crate_type = "lib"] + +#[cfg(target_thread_local)] +use std::cell::Cell; + +#[no_mangle] +#[cfg(target_thread_local)] +#[thread_local] +pub static FOO: Cell<u32> = Cell::new(3); diff --git a/src/test/ui/threads-sendsync/comm.rs b/src/test/ui/threads-sendsync/comm.rs new file mode 100644 index 00000000000..aa86e174d44 --- /dev/null +++ b/src/test/ui/threads-sendsync/comm.rs @@ -0,0 +1,22 @@ +// run-pass +#![allow(unused_must_use)] +// ignore-emscripten no threads support + +use std::thread; +use std::sync::mpsc::{channel, Sender}; + +pub fn main() { + let (tx, rx) = channel(); + let t = thread::spawn(move|| { child(&tx) }); + let y = rx.recv().unwrap(); + println!("received"); + println!("{}", y); + assert_eq!(y, 10); + t.join(); +} + +fn child(c: &Sender<isize>) { + println!("sending"); + c.send(10).unwrap(); + println!("value sent"); +} diff --git a/src/test/ui/threads-sendsync/send-is-not-static-par-for.rs b/src/test/ui/threads-sendsync/send-is-not-static-par-for.rs new file mode 100644 index 00000000000..dbe46555101 --- /dev/null +++ b/src/test/ui/threads-sendsync/send-is-not-static-par-for.rs @@ -0,0 +1,34 @@ +// run-pass +#![allow(unused_imports)] +use std::thread; +use std::sync::Mutex; + +fn par_for<I, F>(iter: I, f: F) + where I: Iterator, + I::Item: Send, + F: Fn(I::Item) + Sync +{ + for item in iter { + f(item) + } +} + +fn sum(x: &[i32]) { + let sum_lengths = Mutex::new(0); + par_for(x.windows(4), |x| { + *sum_lengths.lock().unwrap() += x.len() + }); + + assert_eq!(*sum_lengths.lock().unwrap(), (x.len() - 3) * 4); +} + +fn main() { + let mut elements = [0; 20]; + + // iterators over references into this stack frame + par_for(elements.iter_mut().enumerate(), |(i, x)| { + *x = i as i32 + }); + + sum(&elements) +} diff --git a/src/test/ui/threads-sendsync/send-resource.rs b/src/test/ui/threads-sendsync/send-resource.rs new file mode 100644 index 00000000000..023a84d6b6e --- /dev/null +++ b/src/test/ui/threads-sendsync/send-resource.rs @@ -0,0 +1,39 @@ +// run-pass +#![allow(unused_must_use)] +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +// pretty-expanded FIXME #23616 +// ignore-emscripten no threads support + +use std::thread; +use std::sync::mpsc::channel; + +struct test { + f: isize, +} + +impl Drop for test { + fn drop(&mut self) {} +} + +fn test(f: isize) -> test { + test { + f: f + } +} + +pub fn main() { + let (tx, rx) = channel(); + + let t = thread::spawn(move|| { + let (tx2, rx2) = channel(); + tx.send(tx2).unwrap(); + + let _r = rx2.recv().unwrap(); + }); + + rx.recv().unwrap().send(test(42)).unwrap(); + + t.join(); +} diff --git a/src/test/ui/threads-sendsync/send-type-inference.rs b/src/test/ui/threads-sendsync/send-type-inference.rs new file mode 100644 index 00000000000..0d9af7512b4 --- /dev/null +++ b/src/test/ui/threads-sendsync/send-type-inference.rs @@ -0,0 +1,19 @@ +// run-pass +#![allow(unused_must_use)] +#![allow(dead_code)] +#![allow(unused_mut)] +// pretty-expanded FIXME #23616 + +use std::sync::mpsc::{channel, Sender}; + +// tests that ctrl's type gets inferred properly +struct Command<K, V> { + key: K, + val: V +} + +fn cache_server<K:Send+'static,V:Send+'static>(mut tx: Sender<Sender<Command<K, V>>>) { + let (tx1, _rx) = channel(); + tx.send(tx1); +} +pub fn main() { } diff --git a/src/test/ui/threads-sendsync/send_str_hashmap.rs b/src/test/ui/threads-sendsync/send_str_hashmap.rs new file mode 100644 index 00000000000..7d4cca8ad74 --- /dev/null +++ b/src/test/ui/threads-sendsync/send_str_hashmap.rs @@ -0,0 +1,53 @@ +// run-pass +use std::collections::HashMap; +use std::borrow::Cow; + +use std::borrow::Cow::Borrowed as B; +use std::borrow::Cow::Owned as O; + +type SendStr = Cow<'static, str>; + +fn main() { + let mut map: HashMap<SendStr, usize> = HashMap::new(); + assert!(map.insert(B("foo"), 42).is_none()); + assert!(map.insert(O("foo".to_string()), 42).is_some()); + assert!(map.insert(B("foo"), 42).is_some()); + assert!(map.insert(O("foo".to_string()), 42).is_some()); + + assert!(map.insert(B("foo"), 43).is_some()); + assert!(map.insert(O("foo".to_string()), 44).is_some()); + assert!(map.insert(B("foo"), 45).is_some()); + assert!(map.insert(O("foo".to_string()), 46).is_some()); + + let v = 46; + + assert_eq!(map.get(&O("foo".to_string())), Some(&v)); + assert_eq!(map.get(&B("foo")), Some(&v)); + + let (a, b, c, d) = (50, 51, 52, 53); + + assert!(map.insert(B("abc"), a).is_none()); + assert!(map.insert(O("bcd".to_string()), b).is_none()); + assert!(map.insert(B("cde"), c).is_none()); + assert!(map.insert(O("def".to_string()), d).is_none()); + + assert!(map.insert(B("abc"), a).is_some()); + assert!(map.insert(O("bcd".to_string()), b).is_some()); + assert!(map.insert(B("cde"), c).is_some()); + assert!(map.insert(O("def".to_string()), d).is_some()); + + assert!(map.insert(O("abc".to_string()), a).is_some()); + assert!(map.insert(B("bcd"), b).is_some()); + assert!(map.insert(O("cde".to_string()), c).is_some()); + assert!(map.insert(B("def"), d).is_some()); + + assert_eq!(map.get("abc"), Some(&a)); + assert_eq!(map.get("bcd"), Some(&b)); + assert_eq!(map.get("cde"), Some(&c)); + assert_eq!(map.get("def"), Some(&d)); + + assert_eq!(map.get(&B("abc")), Some(&a)); + assert_eq!(map.get(&B("bcd")), Some(&b)); + assert_eq!(map.get(&B("cde")), Some(&c)); + assert_eq!(map.get(&B("def")), Some(&d)); +} diff --git a/src/test/ui/threads-sendsync/send_str_treemap.rs b/src/test/ui/threads-sendsync/send_str_treemap.rs new file mode 100644 index 00000000000..4d463174590 --- /dev/null +++ b/src/test/ui/threads-sendsync/send_str_treemap.rs @@ -0,0 +1,58 @@ +// run-pass +use std::collections::BTreeMap; +use std::borrow::Cow; + +use std::borrow::Cow::{Owned as O, Borrowed as B}; + +type SendStr = Cow<'static, str>; + +fn main() { + let mut map: BTreeMap<SendStr, usize> = BTreeMap::new(); + assert!(map.insert(B("foo"), 42).is_none()); + assert!(map.insert(O("foo".to_string()), 42).is_some()); + assert!(map.insert(B("foo"), 42).is_some()); + assert!(map.insert(O("foo".to_string()), 42).is_some()); + + assert!(map.insert(B("foo"), 43).is_some()); + assert!(map.insert(O("foo".to_string()), 44).is_some()); + assert!(map.insert(B("foo"), 45).is_some()); + assert!(map.insert(O("foo".to_string()), 46).is_some()); + + let v = 46; + + assert_eq!(map.get(&O("foo".to_string())), Some(&v)); + assert_eq!(map.get(&B("foo")), Some(&v)); + + let (a, b, c, d) = (50, 51, 52, 53); + + assert!(map.insert(B("abc"), a).is_none()); + assert!(map.insert(O("bcd".to_string()), b).is_none()); + assert!(map.insert(B("cde"), c).is_none()); + assert!(map.insert(O("def".to_string()), d).is_none()); + + assert!(map.insert(B("abc"), a).is_some()); + assert!(map.insert(O("bcd".to_string()), b).is_some()); + assert!(map.insert(B("cde"), c).is_some()); + assert!(map.insert(O("def".to_string()), d).is_some()); + + assert!(map.insert(O("abc".to_string()), a).is_some()); + assert!(map.insert(B("bcd"), b).is_some()); + assert!(map.insert(O("cde".to_string()), c).is_some()); + assert!(map.insert(B("def"), d).is_some()); + + assert_eq!(map.get(&B("abc")), Some(&a)); + assert_eq!(map.get(&B("bcd")), Some(&b)); + assert_eq!(map.get(&B("cde")), Some(&c)); + assert_eq!(map.get(&B("def")), Some(&d)); + + assert_eq!(map.get(&O("abc".to_string())), Some(&a)); + assert_eq!(map.get(&O("bcd".to_string())), Some(&b)); + assert_eq!(map.get(&O("cde".to_string())), Some(&c)); + assert_eq!(map.get(&O("def".to_string())), Some(&d)); + + assert!(map.remove(&B("foo")).is_some()); + assert_eq!(map.into_iter().map(|(k, v)| format!("{}{}", k, v)) + .collect::<Vec<String>>() + .concat(), + "abc50bcd51cde52def53".to_string()); +} diff --git a/src/test/ui/threads-sendsync/sendable-class.rs b/src/test/ui/threads-sendsync/sendable-class.rs new file mode 100644 index 00000000000..7facf245bde --- /dev/null +++ b/src/test/ui/threads-sendsync/sendable-class.rs @@ -0,0 +1,28 @@ +// run-pass +#![allow(unused_must_use)] +#![allow(dead_code)] +#![allow(unused_variables)] +#![allow(non_camel_case_types)] + +// Test that a class with only sendable fields can be sent + +// pretty-expanded FIXME #23616 + +use std::sync::mpsc::channel; + +struct foo { + i: isize, + j: char, +} + +fn foo(i:isize, j: char) -> foo { + foo { + i: i, + j: j + } +} + +pub fn main() { + let (tx, rx) = channel(); + tx.send(foo(42, 'c')); +} diff --git a/src/test/ui/threads-sendsync/sendfn-is-a-block.rs b/src/test/ui/threads-sendsync/sendfn-is-a-block.rs new file mode 100644 index 00000000000..62807d8941a --- /dev/null +++ b/src/test/ui/threads-sendsync/sendfn-is-a-block.rs @@ -0,0 +1,11 @@ +// run-pass + + +fn test<F>(f: F) -> usize where F: FnOnce(usize) -> usize { + return f(22); +} + +pub fn main() { + let y = test(|x| 4 * x); + assert_eq!(y, 88); +} diff --git a/src/test/ui/threads-sendsync/sendfn-spawn-with-fn-arg.rs b/src/test/ui/threads-sendsync/sendfn-spawn-with-fn-arg.rs new file mode 100644 index 00000000000..8c40b2a5f11 --- /dev/null +++ b/src/test/ui/threads-sendsync/sendfn-spawn-with-fn-arg.rs @@ -0,0 +1,23 @@ +// run-pass +// ignore-emscripten no threads support + +#![feature(box_syntax)] + +use std::thread; + +pub fn main() { test05(); } + +fn test05_start<F:FnOnce(isize)>(f: F) { + f(22); +} + +fn test05() { + let three: Box<_> = box 3; + let fn_to_send = move|n:isize| { + println!("{}", *three + n); // will copy x into the closure + assert_eq!(*three, 3); + }; + thread::spawn(move|| { + test05_start(fn_to_send); + }).join().ok().unwrap(); +} diff --git a/src/test/ui/threads-sendsync/spawn-fn.rs b/src/test/ui/threads-sendsync/spawn-fn.rs new file mode 100644 index 00000000000..1243bb2579f --- /dev/null +++ b/src/test/ui/threads-sendsync/spawn-fn.rs @@ -0,0 +1,25 @@ +// run-pass +#![allow(unused_must_use)] +// ignore-emscripten no threads support + +use std::thread; + +fn x(s: String, n: isize) { + println!("{}", s); + println!("{}", n); +} + +pub fn main() { + let t1 = thread::spawn(|| x("hello from first spawned fn".to_string(), 65) ); + let t2 = thread::spawn(|| x("hello from second spawned fn".to_string(), 66) ); + let t3 = thread::spawn(|| x("hello from third spawned fn".to_string(), 67) ); + let mut i = 30; + while i > 0 { + i = i - 1; + println!("parent sleeping"); + thread::yield_now(); + } + t1.join(); + t2.join(); + t3.join(); +} diff --git a/src/test/ui/threads-sendsync/spawn-types.rs b/src/test/ui/threads-sendsync/spawn-types.rs new file mode 100644 index 00000000000..1bead6e1bb1 --- /dev/null +++ b/src/test/ui/threads-sendsync/spawn-types.rs @@ -0,0 +1,25 @@ +// run-pass +#![allow(non_camel_case_types)] + +// ignore-emscripten no threads support + +/* + Make sure we can spawn tasks that take different types of + parameters. This is based on a test case for #520 provided by Rob + Arnold. + */ + +use std::thread; +use std::sync::mpsc::{channel, Sender}; + +type ctx = Sender<isize>; + +fn iotask(_tx: &ctx, ip: String) { + assert_eq!(ip, "localhost".to_string()); +} + +pub fn main() { + let (tx, _rx) = channel::<isize>(); + let t = thread::spawn(move|| iotask(&tx, "localhost".to_string()) ); + t.join().ok().unwrap(); +} diff --git a/src/test/ui/threads-sendsync/spawn.rs b/src/test/ui/threads-sendsync/spawn.rs new file mode 100644 index 00000000000..b1dcc9417fb --- /dev/null +++ b/src/test/ui/threads-sendsync/spawn.rs @@ -0,0 +1,10 @@ +// run-pass +// ignore-emscripten no threads support + +use std::thread; + +pub fn main() { + thread::spawn(move|| child(10)).join().ok().unwrap(); +} + +fn child(i: isize) { println!("{}", i); assert_eq!(i, 10); } diff --git a/src/test/ui/threads-sendsync/spawn2.rs b/src/test/ui/threads-sendsync/spawn2.rs new file mode 100644 index 00000000000..83e066aef96 --- /dev/null +++ b/src/test/ui/threads-sendsync/spawn2.rs @@ -0,0 +1,31 @@ +// run-pass +// ignore-emscripten no threads support + +use std::thread; + +pub fn main() { + let t = thread::spawn(move|| child((10, 20, 30, 40, 50, 60, 70, 80, 90)) ); + t.join().ok().unwrap(); // forget Err value, since it doesn't implement Debug +} + +fn child(args: (isize, isize, isize, isize, isize, isize, isize, isize, isize)) { + let (i1, i2, i3, i4, i5, i6, i7, i8, i9) = args; + println!("{}", i1); + println!("{}", i2); + println!("{}", i3); + println!("{}", i4); + println!("{}", i5); + println!("{}", i6); + println!("{}", i7); + println!("{}", i8); + println!("{}", i9); + assert_eq!(i1, 10); + assert_eq!(i2, 20); + assert_eq!(i3, 30); + assert_eq!(i4, 40); + assert_eq!(i5, 50); + assert_eq!(i6, 60); + assert_eq!(i7, 70); + assert_eq!(i8, 80); + assert_eq!(i9, 90); +} diff --git a/src/test/ui/threads-sendsync/spawning-with-debug.rs b/src/test/ui/threads-sendsync/spawning-with-debug.rs new file mode 100644 index 00000000000..388d62aa710 --- /dev/null +++ b/src/test/ui/threads-sendsync/spawning-with-debug.rs @@ -0,0 +1,15 @@ +// run-pass +#![allow(unused_must_use)] +#![allow(unused_mut)] +// ignore-windows +// exec-env:RUSTC_LOG=debug +// ignore-emscripten no threads support + +// regression test for issue #10405, make sure we don't call println! too soon. + +use std::thread::Builder; + +pub fn main() { + let mut t = Builder::new(); + t.spawn(move|| ()); +} diff --git a/src/test/ui/threads-sendsync/std-sync-right-kind-impls.rs b/src/test/ui/threads-sendsync/std-sync-right-kind-impls.rs new file mode 100644 index 00000000000..bc64c816243 --- /dev/null +++ b/src/test/ui/threads-sendsync/std-sync-right-kind-impls.rs @@ -0,0 +1,16 @@ +// run-pass +// pretty-expanded FIXME #23616 + +use std::sync; + +fn assert_both<T: Sync + Send>() {} + +fn main() { + assert_both::<sync::Mutex<()>>(); + assert_both::<sync::Condvar>(); + assert_both::<sync::RwLock<()>>(); + assert_both::<sync::Barrier>(); + assert_both::<sync::Arc<()>>(); + assert_both::<sync::Weak<()>>(); + assert_both::<sync::Once>(); +} diff --git a/src/test/ui/threads-sendsync/sync-send-atomics.rs b/src/test/ui/threads-sendsync/sync-send-atomics.rs new file mode 100644 index 00000000000..0466f4f0e9d --- /dev/null +++ b/src/test/ui/threads-sendsync/sync-send-atomics.rs @@ -0,0 +1,14 @@ +// run-pass + +// pretty-expanded FIXME #23616 + +use std::sync::atomic::*; + +trait SendSync: Send + Sync {} + +impl SendSync for AtomicBool {} +impl SendSync for AtomicIsize {} +impl SendSync for AtomicUsize {} +impl<T> SendSync for AtomicPtr<T> {} + +fn main() {} diff --git a/src/test/ui/threads-sendsync/sync-send-in-std.rs b/src/test/ui/threads-sendsync/sync-send-in-std.rs new file mode 100644 index 00000000000..15e10dc250f --- /dev/null +++ b/src/test/ui/threads-sendsync/sync-send-in-std.rs @@ -0,0 +1,25 @@ +// run-pass + +// ignore-cloudabi networking not available +// ignore-wasm32-bare networking not available +// ignore-sgx ToSocketAddrs cannot be used for DNS Resolution + +use std::net::ToSocketAddrs; + +fn is_sync<T>(_: T) where T: Sync {} +fn is_send<T>(_: T) where T: Send {} + +macro_rules! all_sync_send { + ($ctor:expr, $($iter:ident),+) => ({ + $( + let mut x = $ctor; + is_sync(x.$iter()); + let mut y = $ctor; + is_send(y.$iter()); + )+ + }) +} + +fn main() { + all_sync_send!("localhost:80".to_socket_addrs().unwrap(), next); +} diff --git a/src/test/ui/threads-sendsync/sync-send-iterators-in-libcollections.rs b/src/test/ui/threads-sendsync/sync-send-iterators-in-libcollections.rs new file mode 100644 index 00000000000..fd53bb607f7 --- /dev/null +++ b/src/test/ui/threads-sendsync/sync-send-iterators-in-libcollections.rs @@ -0,0 +1,71 @@ +// run-pass + +#![allow(warnings)] +#![feature(drain, collections_bound, btree_range)] + +use std::collections::BinaryHeap; +use std::collections::{BTreeMap, BTreeSet}; +use std::collections::LinkedList; +use std::collections::VecDeque; +use std::collections::HashMap; +use std::collections::HashSet; + +use std::mem; +use std::ops::Bound::Included; + +fn is_sync<T>(_: T) where T: Sync {} +fn is_send<T>(_: T) where T: Send {} + +macro_rules! all_sync_send { + ($ctor:expr, $($iter:ident),+) => ({ + $( + let mut x = $ctor; + is_sync(x.$iter()); + let mut y = $ctor; + is_send(y.$iter()); + )+ + }) +} + +macro_rules! is_sync_send { + ($ctor:expr, $iter:ident($($param:expr),+)) => ({ + let mut x = $ctor; + is_sync(x.$iter($( $param ),+)); + let mut y = $ctor; + is_send(y.$iter($( $param ),+)); + }) +} + +fn main() { + // The iterator "generator" list should exhaust what corresponding + // implementations have where `Sync` and `Send` semantics apply. + all_sync_send!(BinaryHeap::<usize>::new(), iter, drain, into_iter); + + all_sync_send!(BTreeMap::<usize, usize>::new(), iter, iter_mut, into_iter, keys, values); + is_sync_send!(BTreeMap::<usize, usize>::new(), range((Included(&0), Included(&9)))); + is_sync_send!(BTreeMap::<usize, usize>::new(), range_mut((Included(&0), Included(&9)))); + + all_sync_send!(BTreeSet::<usize>::new(), iter, into_iter); + is_sync_send!(BTreeSet::<usize>::new(), range((Included(&0), Included(&9)))); + is_sync_send!(BTreeSet::<usize>::new(), difference(&BTreeSet::<usize>::new())); + is_sync_send!(BTreeSet::<usize>::new(), symmetric_difference(&BTreeSet::<usize>::new())); + is_sync_send!(BTreeSet::<usize>::new(), intersection(&BTreeSet::<usize>::new())); + is_sync_send!(BTreeSet::<usize>::new(), union(&BTreeSet::<usize>::new())); + + all_sync_send!(HashMap::<usize, usize>::new(), iter, iter_mut, drain, into_iter, keys, values); + is_sync_send!(HashMap::<usize, usize>::new(), entry(0)); + all_sync_send!(HashSet::<usize>::new(), iter, drain, into_iter); + is_sync_send!(HashSet::<usize>::new(), difference(&HashSet::<usize>::new())); + is_sync_send!(HashSet::<usize>::new(), symmetric_difference(&HashSet::<usize>::new())); + is_sync_send!(HashSet::<usize>::new(), intersection(&HashSet::<usize>::new())); + is_sync_send!(HashSet::<usize>::new(), union(&HashSet::<usize>::new())); + + all_sync_send!(LinkedList::<usize>::new(), iter, iter_mut, into_iter); + + all_sync_send!(VecDeque::<usize>::new(), iter, iter_mut, into_iter); + is_sync_send!(VecDeque::<usize>::new(), drain(..)); + + all_sync_send!(Vec::<usize>::new(), into_iter); + is_sync_send!(Vec::<usize>::new(), drain(..)); + is_sync_send!(String::new(), drain(..)); +} diff --git a/src/test/ui/threads-sendsync/sync-send-iterators-in-libcore.rs b/src/test/ui/threads-sendsync/sync-send-iterators-in-libcore.rs new file mode 100644 index 00000000000..44beb9dc1e5 --- /dev/null +++ b/src/test/ui/threads-sendsync/sync-send-iterators-in-libcore.rs @@ -0,0 +1,104 @@ +// run-pass +// pretty-expanded FIXME #23616 + +#![allow(warnings)] + +use std::iter::{empty, once, repeat}; + +fn is_sync<T>(_: T) where T: Sync {} +fn is_send<T>(_: T) where T: Send {} + +macro_rules! all_sync_send { + ($ctor:expr, $iter:ident) => ({ + let mut x = $ctor; + is_sync(x.$iter()); + let mut y = $ctor; + is_send(y.$iter()); + }); + ($ctor:expr, $iter:ident($($param:expr),+)) => ({ + let mut x = $ctor; + is_sync(x.$iter($( $param ),+)); + let mut y = $ctor; + is_send(y.$iter($( $param ),+)); + }); + ($ctor:expr, $iter:ident, $($rest:tt)*) => ({ + all_sync_send!($ctor, $iter); + all_sync_send!($ctor, $($rest)*); + }); + ($ctor:expr, $iter:ident($($param:expr),+), $($rest:tt)*) => ({ + all_sync_send!($ctor, $iter($( $param ),+)); + all_sync_send!($ctor, $($rest)*); + }); +} + +macro_rules! all_sync_send_mutable_ref { + ($ctor:expr, $($iter:ident),+) => ({ + $( + let mut x = $ctor; + is_sync((&mut x).$iter()); + let mut y = $ctor; + is_send((&mut y).$iter()); + )+ + }) +} + +macro_rules! is_sync_send { + ($ctor:expr) => ({ + let x = $ctor; + is_sync(x); + let y = $ctor; + is_send(y); + }) +} + +fn main() { + // for char.rs + all_sync_send!("Я", escape_debug, escape_default, escape_unicode); + + // for iter.rs + all_sync_send_mutable_ref!([1], iter); + + // Bytes implements DoubleEndedIterator + all_sync_send!("a".bytes(), rev); + + let a = [1]; + let b = [2]; + all_sync_send!(a.iter(), + cloned, + cycle, + chain([2].iter()), + zip([2].iter()), + map(|_| 1), + filter(|_| true), + filter_map(|_| Some(1)), + enumerate, + peekable, + skip_while(|_| true), + take_while(|_| true), + skip(1), + take(1), + scan(1, |_, _| Some(1)), + flat_map(|_| b.iter()), + fuse, + inspect(|_| ())); + + is_sync_send!((1..).step_by(2)); + is_sync_send!((1..2).step_by(2)); + is_sync_send!((1..2)); + is_sync_send!((1..)); + is_sync_send!(repeat(1)); + is_sync_send!(empty::<usize>()); + is_sync_send!(once(1)); + + // for option.rs + // FIXME + + // for result.rs + // FIXME + + // for slice.rs + // FIXME + + // for str/mod.rs + // FIXME +} diff --git a/src/test/ui/threads-sendsync/task-comm-0.rs b/src/test/ui/threads-sendsync/task-comm-0.rs new file mode 100644 index 00000000000..2b9a50e4d41 --- /dev/null +++ b/src/test/ui/threads-sendsync/task-comm-0.rs @@ -0,0 +1,30 @@ +// run-pass +#![allow(unused_must_use)] +// ignore-emscripten no threads support + +use std::thread; +use std::sync::mpsc::{channel, Sender}; + +pub fn main() { test05(); } + +fn test05_start(tx : &Sender<isize>) { + tx.send(10).unwrap(); + println!("sent 10"); + tx.send(20).unwrap(); + println!("sent 20"); + tx.send(30).unwrap(); + println!("sent 30"); +} + +fn test05() { + let (tx, rx) = channel(); + let t = thread::spawn(move|| { test05_start(&tx) }); + let mut value: isize = rx.recv().unwrap(); + println!("{}", value); + value = rx.recv().unwrap(); + println!("{}", value); + value = rx.recv().unwrap(); + println!("{}", value); + assert_eq!(value, 30); + t.join(); +} diff --git a/src/test/ui/threads-sendsync/task-comm-1.rs b/src/test/ui/threads-sendsync/task-comm-1.rs new file mode 100644 index 00000000000..68ca62909bf --- /dev/null +++ b/src/test/ui/threads-sendsync/task-comm-1.rs @@ -0,0 +1,14 @@ +// run-pass +#![allow(unused_must_use)] +// ignore-emscripten no threads support + +use std::thread; + +pub fn main() { test00(); } + +fn start() { println!("Started / Finished task."); } + +fn test00() { + thread::spawn(move|| start() ).join(); + println!("Completing."); +} diff --git a/src/test/ui/threads-sendsync/task-comm-10.rs b/src/test/ui/threads-sendsync/task-comm-10.rs new file mode 100644 index 00000000000..4cac0dc90cf --- /dev/null +++ b/src/test/ui/threads-sendsync/task-comm-10.rs @@ -0,0 +1,33 @@ +// run-pass +#![allow(unused_must_use)] +#![allow(unused_mut)] +// ignore-emscripten no threads support + +use std::thread; +use std::sync::mpsc::{channel, Sender}; + +fn start(tx: &Sender<Sender<String>>) { + let (tx2, rx) = channel(); + tx.send(tx2).unwrap(); + + let mut a; + let mut b; + a = rx.recv().unwrap(); + assert_eq!(a, "A".to_string()); + println!("{}", a); + b = rx.recv().unwrap(); + assert_eq!(b, "B".to_string()); + println!("{}", b); +} + +pub fn main() { + let (tx, rx) = channel(); + let child = thread::spawn(move|| { start(&tx) }); + + let mut c = rx.recv().unwrap(); + c.send("A".to_string()).unwrap(); + c.send("B".to_string()).unwrap(); + thread::yield_now(); + + child.join(); +} diff --git a/src/test/ui/threads-sendsync/task-comm-11.rs b/src/test/ui/threads-sendsync/task-comm-11.rs new file mode 100644 index 00000000000..8541e143fb9 --- /dev/null +++ b/src/test/ui/threads-sendsync/task-comm-11.rs @@ -0,0 +1,21 @@ +// run-pass +#![allow(unused_must_use)] +// pretty-expanded FIXME #23616 +// ignore-emscripten no threads support + +use std::sync::mpsc::{channel, Sender}; +use std::thread; + +fn start(tx: &Sender<Sender<isize>>) { + let (tx2, _rx) = channel(); + tx.send(tx2).unwrap(); +} + +pub fn main() { + let (tx, rx) = channel(); + let child = thread::spawn(move|| { + start(&tx) + }); + let _tx = rx.recv().unwrap(); + child.join(); +} diff --git a/src/test/ui/threads-sendsync/task-comm-12.rs b/src/test/ui/threads-sendsync/task-comm-12.rs new file mode 100644 index 00000000000..613a5cee58b --- /dev/null +++ b/src/test/ui/threads-sendsync/task-comm-12.rs @@ -0,0 +1,29 @@ +// run-pass +#![allow(unused_must_use)] +#![allow(unused_mut)] +// ignore-emscripten no threads support + +use std::thread; + +pub fn main() { test00(); } + +fn start(_task_number: isize) { println!("Started / Finished task."); } + +fn test00() { + let i: isize = 0; + let mut result = thread::spawn(move|| { + start(i) + }); + + // Sleep long enough for the thread to finish. + let mut i = 0_usize; + while i < 10000 { + thread::yield_now(); + i += 1; + } + + // Try joining threads that have already finished. + result.join(); + + println!("Joined task."); +} diff --git a/src/test/ui/threads-sendsync/task-comm-13.rs b/src/test/ui/threads-sendsync/task-comm-13.rs new file mode 100644 index 00000000000..327eaaf8fa1 --- /dev/null +++ b/src/test/ui/threads-sendsync/task-comm-13.rs @@ -0,0 +1,18 @@ +// run-pass +#![allow(unused_variables)] +// ignore-emscripten no threads support + +use std::sync::mpsc::{channel, Sender}; +use std::thread; + +fn start(tx: &Sender<isize>, start: isize, number_of_messages: isize) { + let mut i: isize = 0; + while i< number_of_messages { tx.send(start + i).unwrap(); i += 1; } +} + +pub fn main() { + println!("Check that we don't deadlock."); + let (tx, rx) = channel(); + let _ = thread::spawn(move|| { start(&tx, 0, 10) }).join(); + println!("Joined task"); +} diff --git a/src/test/ui/threads-sendsync/task-comm-14.rs b/src/test/ui/threads-sendsync/task-comm-14.rs new file mode 100644 index 00000000000..88d6b090268 --- /dev/null +++ b/src/test/ui/threads-sendsync/task-comm-14.rs @@ -0,0 +1,36 @@ +// run-pass +#![allow(unused_parens)] +// ignore-emscripten no threads support + +use std::sync::mpsc::{channel, Sender}; +use std::thread; + +pub fn main() { + let (tx, rx) = channel(); + + // Spawn 10 threads each sending us back one isize. + let mut i = 10; + while (i > 0) { + println!("{}", i); + let tx = tx.clone(); + thread::spawn({let i = i; move|| { child(i, &tx) }}); + i = i - 1; + } + + // Spawned threads are likely killed before they get a chance to send + // anything back, so we deadlock here. + + i = 10; + while (i > 0) { + println!("{}", i); + rx.recv().unwrap(); + i = i - 1; + } + + println!("main thread exiting"); +} + +fn child(x: isize, tx: &Sender<isize>) { + println!("{}", x); + tx.send(x).unwrap(); +} diff --git a/src/test/ui/threads-sendsync/task-comm-15.rs b/src/test/ui/threads-sendsync/task-comm-15.rs new file mode 100644 index 00000000000..adb14abdce9 --- /dev/null +++ b/src/test/ui/threads-sendsync/task-comm-15.rs @@ -0,0 +1,28 @@ +// run-pass +#![allow(unused_must_use)] +// ignore-emscripten no threads support +// pretty-expanded FIXME #23616 + +use std::sync::mpsc::{channel, Sender}; +use std::thread; + +fn start(tx: &Sender<isize>, i0: isize) { + let mut i = i0; + while i > 0 { + tx.send(0).unwrap(); + i = i - 1; + } +} + +pub fn main() { + // Spawn a thread that sends us back messages. The parent thread + // is likely to terminate before the child completes, so from + // the child's point of view the receiver may die. We should + // drop messages on the floor in this case, and not crash! + let (tx, rx) = channel(); + let t = thread::spawn(move|| { + start(&tx, 10) + }); + rx.recv(); + t.join(); +} diff --git a/src/test/ui/threads-sendsync/task-comm-16.rs b/src/test/ui/threads-sendsync/task-comm-16.rs new file mode 100644 index 00000000000..d808fd9aceb --- /dev/null +++ b/src/test/ui/threads-sendsync/task-comm-16.rs @@ -0,0 +1,111 @@ +// run-pass +#![allow(unused_mut)] +#![allow(unused_parens)] +#![allow(non_camel_case_types)] + +use std::sync::mpsc::channel; +use std::cmp; + +// Tests of ports and channels on various types +fn test_rec() { + struct R {val0: isize, val1: u8, val2: char} + + let (tx, rx) = channel(); + let r0: R = R {val0: 0, val1: 1, val2: '2'}; + tx.send(r0).unwrap(); + let mut r1: R; + r1 = rx.recv().unwrap(); + assert_eq!(r1.val0, 0); + assert_eq!(r1.val1, 1); + assert_eq!(r1.val2, '2'); +} + +fn test_vec() { + let (tx, rx) = channel(); + let v0: Vec<isize> = vec![0, 1, 2]; + tx.send(v0).unwrap(); + let v1 = rx.recv().unwrap(); + assert_eq!(v1[0], 0); + assert_eq!(v1[1], 1); + assert_eq!(v1[2], 2); +} + +fn test_str() { + let (tx, rx) = channel(); + let s0 = "test".to_string(); + tx.send(s0).unwrap(); + let s1 = rx.recv().unwrap(); + assert_eq!(s1.as_bytes()[0], 't' as u8); + assert_eq!(s1.as_bytes()[1], 'e' as u8); + assert_eq!(s1.as_bytes()[2], 's' as u8); + assert_eq!(s1.as_bytes()[3], 't' as u8); +} + +#[derive(Debug)] +enum t { + tag1, + tag2(isize), + tag3(isize, u8, char) +} + +impl cmp::PartialEq for t { + fn eq(&self, other: &t) -> bool { + match *self { + t::tag1 => { + match (*other) { + t::tag1 => true, + _ => false + } + } + t::tag2(e0a) => { + match (*other) { + t::tag2(e0b) => e0a == e0b, + _ => false + } + } + t::tag3(e0a, e1a, e2a) => { + match (*other) { + t::tag3(e0b, e1b, e2b) => + e0a == e0b && e1a == e1b && e2a == e2b, + _ => false + } + } + } + } + fn ne(&self, other: &t) -> bool { !(*self).eq(other) } +} + +fn test_tag() { + let (tx, rx) = channel(); + tx.send(t::tag1).unwrap(); + tx.send(t::tag2(10)).unwrap(); + tx.send(t::tag3(10, 11, 'A')).unwrap(); + let mut t1: t; + t1 = rx.recv().unwrap(); + assert_eq!(t1, t::tag1); + t1 = rx.recv().unwrap(); + assert_eq!(t1, t::tag2(10)); + t1 = rx.recv().unwrap(); + assert_eq!(t1, t::tag3(10, 11, 'A')); +} + +fn test_chan() { + let (tx1, rx1) = channel(); + let (tx2, rx2) = channel(); + tx1.send(tx2).unwrap(); + let tx2 = rx1.recv().unwrap(); + // Does the transmitted channel still work? + + tx2.send(10).unwrap(); + let mut i: isize; + i = rx2.recv().unwrap(); + assert_eq!(i, 10); +} + +pub fn main() { + test_rec(); + test_vec(); + test_str(); + test_tag(); + test_chan(); +} diff --git a/src/test/ui/threads-sendsync/task-comm-17.rs b/src/test/ui/threads-sendsync/task-comm-17.rs new file mode 100644 index 00000000000..72249787093 --- /dev/null +++ b/src/test/ui/threads-sendsync/task-comm-17.rs @@ -0,0 +1,17 @@ +// run-pass +#![allow(unused_must_use)] +// ignore-emscripten no threads support +// pretty-expanded FIXME #23616 + +// Issue #922 + +// This test is specifically about spawning temporary closures. + +use std::thread; + +fn f() { +} + +pub fn main() { + thread::spawn(move|| f() ).join(); +} diff --git a/src/test/ui/threads-sendsync/task-comm-3.rs b/src/test/ui/threads-sendsync/task-comm-3.rs new file mode 100644 index 00000000000..570ae0a82ff --- /dev/null +++ b/src/test/ui/threads-sendsync/task-comm-3.rs @@ -0,0 +1,63 @@ +// run-pass +#![allow(unused_must_use)] +// ignore-emscripten no threads support + +use std::thread; +use std::sync::mpsc::{channel, Sender}; + +pub fn main() { println!("===== WITHOUT THREADS ====="); test00(); } + +fn test00_start(ch: &Sender<isize>, message: isize, count: isize) { + println!("Starting test00_start"); + let mut i: isize = 0; + while i < count { + println!("Sending Message"); + ch.send(message + 0).unwrap(); + i = i + 1; + } + println!("Ending test00_start"); +} + +fn test00() { + let number_of_tasks: isize = 16; + let number_of_messages: isize = 4; + + println!("Creating tasks"); + + let (tx, rx) = channel(); + + let mut i: isize = 0; + + // Create and spawn threads... + let mut results = Vec::new(); + while i < number_of_tasks { + let tx = tx.clone(); + results.push(thread::spawn({ + let i = i; + move|| { + test00_start(&tx, i, number_of_messages) + } + })); + i = i + 1; + } + + // Read from spawned threads... + let mut sum = 0; + for _r in &results { + i = 0; + while i < number_of_messages { + let value = rx.recv().unwrap(); + sum += value; + i = i + 1; + } + } + + // Join spawned threads... + for r in results { r.join(); } + + println!("Completed: Final number is: "); + println!("{}", sum); + // assert (sum == (((number_of_threads * (number_of_threads - 1)) / 2) * + // number_of_messages)); + assert_eq!(sum, 480); +} diff --git a/src/test/ui/threads-sendsync/task-comm-4.rs b/src/test/ui/threads-sendsync/task-comm-4.rs new file mode 100644 index 00000000000..b259d69d15d --- /dev/null +++ b/src/test/ui/threads-sendsync/task-comm-4.rs @@ -0,0 +1,45 @@ +// run-pass +#![allow(unused_assignments)] + +use std::sync::mpsc::channel; + +pub fn main() { test00(); } + +fn test00() { + let mut r: isize = 0; + let mut sum: isize = 0; + let (tx, rx) = channel(); + tx.send(1).unwrap(); + tx.send(2).unwrap(); + tx.send(3).unwrap(); + tx.send(4).unwrap(); + r = rx.recv().unwrap(); + sum += r; + println!("{}", r); + r = rx.recv().unwrap(); + sum += r; + println!("{}", r); + r = rx.recv().unwrap(); + sum += r; + println!("{}", r); + r = rx.recv().unwrap(); + sum += r; + println!("{}", r); + tx.send(5).unwrap(); + tx.send(6).unwrap(); + tx.send(7).unwrap(); + tx.send(8).unwrap(); + r = rx.recv().unwrap(); + sum += r; + println!("{}", r); + r = rx.recv().unwrap(); + sum += r; + println!("{}", r); + r = rx.recv().unwrap(); + sum += r; + println!("{}", r); + r = rx.recv().unwrap(); + sum += r; + println!("{}", r); + assert_eq!(sum, 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8); +} diff --git a/src/test/ui/threads-sendsync/task-comm-5.rs b/src/test/ui/threads-sendsync/task-comm-5.rs new file mode 100644 index 00000000000..cdedf034ac3 --- /dev/null +++ b/src/test/ui/threads-sendsync/task-comm-5.rs @@ -0,0 +1,17 @@ +// run-pass + +use std::sync::mpsc::channel; + +pub fn main() { test00(); } + +fn test00() { + let _r: isize = 0; + let mut sum: isize = 0; + let (tx, rx) = channel(); + let number_of_messages: isize = 1000; + let mut i: isize = 0; + while i < number_of_messages { tx.send(i + 0).unwrap(); i += 1; } + i = 0; + while i < number_of_messages { sum += rx.recv().unwrap(); i += 1; } + assert_eq!(sum, number_of_messages * (number_of_messages - 1) / 2); +} diff --git a/src/test/ui/threads-sendsync/task-comm-6.rs b/src/test/ui/threads-sendsync/task-comm-6.rs new file mode 100644 index 00000000000..990205ad334 --- /dev/null +++ b/src/test/ui/threads-sendsync/task-comm-6.rs @@ -0,0 +1,42 @@ +// run-pass +#![allow(unused_mut)] +#![allow(unused_assignments)] + +use std::sync::mpsc::channel; + +pub fn main() { test00(); } + +fn test00() { + let mut r: isize = 0; + let mut sum: isize = 0; + let (tx, rx) = channel(); + let mut tx0 = tx.clone(); + let mut tx1 = tx.clone(); + let mut tx2 = tx.clone(); + let mut tx3 = tx.clone(); + let number_of_messages: isize = 1000; + let mut i: isize = 0; + while i < number_of_messages { + tx0.send(i + 0).unwrap(); + tx1.send(i + 0).unwrap(); + tx2.send(i + 0).unwrap(); + tx3.send(i + 0).unwrap(); + i += 1; + } + i = 0; + while i < number_of_messages { + r = rx.recv().unwrap(); + sum += r; + r = rx.recv().unwrap(); + sum += r; + r = rx.recv().unwrap(); + sum += r; + r = rx.recv().unwrap(); + sum += r; + i += 1; + } + assert_eq!(sum, 1998000); + // assert (sum == 4 * ((number_of_messages * + // (number_of_messages - 1)) / 2)); + +} diff --git a/src/test/ui/threads-sendsync/task-comm-7.rs b/src/test/ui/threads-sendsync/task-comm-7.rs new file mode 100644 index 00000000000..0b9673e0033 --- /dev/null +++ b/src/test/ui/threads-sendsync/task-comm-7.rs @@ -0,0 +1,59 @@ +// run-pass +#![allow(unused_must_use)] +#![allow(unused_assignments)] +// ignore-emscripten no threads support + +use std::sync::mpsc::{channel, Sender}; +use std::thread; + +pub fn main() { test00(); } + +fn test00_start(c: &Sender<isize>, start: isize, + number_of_messages: isize) { + let mut i: isize = 0; + while i < number_of_messages { c.send(start + i).unwrap(); i += 1; } +} + +fn test00() { + let mut r: isize = 0; + let mut sum: isize = 0; + let (tx, rx) = channel(); + let number_of_messages: isize = 10; + + let tx2 = tx.clone(); + let t1 = thread::spawn(move|| { + test00_start(&tx2, number_of_messages * 0, number_of_messages); + }); + let tx2 = tx.clone(); + let t2 = thread::spawn(move|| { + test00_start(&tx2, number_of_messages * 1, number_of_messages); + }); + let tx2 = tx.clone(); + let t3 = thread::spawn(move|| { + test00_start(&tx2, number_of_messages * 2, number_of_messages); + }); + let tx2 = tx.clone(); + let t4 = thread::spawn(move|| { + test00_start(&tx2, number_of_messages * 3, number_of_messages); + }); + + let mut i: isize = 0; + while i < number_of_messages { + r = rx.recv().unwrap(); + sum += r; + r = rx.recv().unwrap(); + sum += r; + r = rx.recv().unwrap(); + sum += r; + r = rx.recv().unwrap(); + sum += r; + i += 1; + } + + assert_eq!(sum, number_of_messages * 4 * (number_of_messages * 4 - 1) / 2); + + t1.join(); + t2.join(); + t3.join(); + t4.join(); +} diff --git a/src/test/ui/threads-sendsync/task-comm-9.rs b/src/test/ui/threads-sendsync/task-comm-9.rs new file mode 100644 index 00000000000..5ed33012100 --- /dev/null +++ b/src/test/ui/threads-sendsync/task-comm-9.rs @@ -0,0 +1,35 @@ +// run-pass +#![allow(unused_must_use)] +// ignore-emscripten no threads support + +use std::thread; +use std::sync::mpsc::{channel, Sender}; + +pub fn main() { test00(); } + +fn test00_start(c: &Sender<isize>, number_of_messages: isize) { + let mut i: isize = 0; + while i < number_of_messages { c.send(i + 0).unwrap(); i += 1; } +} + +fn test00() { + let r: isize = 0; + let mut sum: isize = 0; + let (tx, rx) = channel(); + let number_of_messages: isize = 10; + + let result = thread::spawn(move|| { + test00_start(&tx, number_of_messages); + }); + + let mut i: isize = 0; + while i < number_of_messages { + sum += rx.recv().unwrap(); + println!("{}", r); + i += 1; + } + + result.join(); + + assert_eq!(sum, number_of_messages * (number_of_messages - 1) / 2); +} diff --git a/src/test/ui/threads-sendsync/task-comm-chan-nil.rs b/src/test/ui/threads-sendsync/task-comm-chan-nil.rs new file mode 100644 index 00000000000..a93ddff43dc --- /dev/null +++ b/src/test/ui/threads-sendsync/task-comm-chan-nil.rs @@ -0,0 +1,13 @@ +// run-pass + +use std::sync::mpsc::channel; + +// rustboot can't transmit nils across channels because they don't have +// any size, but rustc currently can because they do have size. Whether +// or not this is desirable I don't know, but here's a regression test. +pub fn main() { + let (tx, rx) = channel(); + tx.send(()).unwrap(); + let n: () = rx.recv().unwrap(); + assert_eq!(n, ()); +} diff --git a/src/test/ui/threads-sendsync/task-life-0.rs b/src/test/ui/threads-sendsync/task-life-0.rs new file mode 100644 index 00000000000..785cff9a0f3 --- /dev/null +++ b/src/test/ui/threads-sendsync/task-life-0.rs @@ -0,0 +1,14 @@ +// run-pass +#![allow(unused_must_use)] +// ignore-emscripten no threads support +// pretty-expanded FIXME #23616 + +use std::thread; + +pub fn main() { + thread::spawn(move|| child("Hello".to_string()) ).join(); +} + +fn child(_s: String) { + +} diff --git a/src/test/ui/threads-sendsync/task-spawn-move-and-copy.rs b/src/test/ui/threads-sendsync/task-spawn-move-and-copy.rs new file mode 100644 index 00000000000..458f5653885 --- /dev/null +++ b/src/test/ui/threads-sendsync/task-spawn-move-and-copy.rs @@ -0,0 +1,25 @@ +// run-pass +#![allow(unused_must_use)] +// ignore-emscripten no threads support + +#![feature(box_syntax)] + +use std::thread; +use std::sync::mpsc::channel; + +pub fn main() { + let (tx, rx) = channel::<usize>(); + + let x: Box<isize> = box 1; + let x_in_parent = &(*x) as *const isize as usize; + + let t = thread::spawn(move || { + let x_in_child = &(*x) as *const isize as usize; + tx.send(x_in_child).unwrap(); + }); + + let x_in_child = rx.recv().unwrap(); + assert_eq!(x_in_parent, x_in_child); + + t.join(); +} diff --git a/src/test/ui/threads-sendsync/task-stderr.rs b/src/test/ui/threads-sendsync/task-stderr.rs new file mode 100644 index 00000000000..d474084bf20 --- /dev/null +++ b/src/test/ui/threads-sendsync/task-stderr.rs @@ -0,0 +1,32 @@ +// run-pass +// ignore-emscripten no threads support + +#![feature(box_syntax, set_stdio)] + +use std::io::prelude::*; +use std::io; +use std::str; +use std::sync::{Arc, Mutex}; +use std::thread; + +struct Sink(Arc<Mutex<Vec<u8>>>); +impl Write for Sink { + fn write(&mut self, data: &[u8]) -> io::Result<usize> { + Write::write(&mut *self.0.lock().unwrap(), data) + } + fn flush(&mut self) -> io::Result<()> { Ok(()) } +} + +fn main() { + let data = Arc::new(Mutex::new(Vec::new())); + let sink = Sink(data.clone()); + let res = thread::Builder::new().spawn(move|| -> () { + io::set_panic(Some(Box::new(sink))); + panic!("Hello, world!") + }).unwrap().join(); + assert!(res.is_err()); + + let output = data.lock().unwrap(); + let output = str::from_utf8(&output).unwrap(); + assert!(output.contains("Hello, world!")); +} diff --git a/src/test/ui/threads-sendsync/thread-local-extern-static.rs b/src/test/ui/threads-sendsync/thread-local-extern-static.rs new file mode 100644 index 00000000000..e10f5174b12 --- /dev/null +++ b/src/test/ui/threads-sendsync/thread-local-extern-static.rs @@ -0,0 +1,27 @@ +// run-pass +// ignore-windows +// aux-build:thread-local-extern-static.rs + +#![feature(cfg_target_thread_local, thread_local)] + +#[cfg(target_thread_local)] +extern crate thread_local_extern_static; + +#[cfg(target_thread_local)] +use std::cell::Cell; + +#[cfg(target_thread_local)] +extern { + #[thread_local] + static FOO: Cell<u32>; +} + +#[cfg(target_thread_local)] +fn main() { + unsafe { + assert_eq!(FOO.get(), 3); + } +} + +#[cfg(not(target_thread_local))] +fn main() {} diff --git a/src/test/ui/threads-sendsync/thread-local-syntax.rs b/src/test/ui/threads-sendsync/thread-local-syntax.rs new file mode 100644 index 00000000000..2f4805e4731 --- /dev/null +++ b/src/test/ui/threads-sendsync/thread-local-syntax.rs @@ -0,0 +1,22 @@ +// run-pass +#![deny(missing_docs)] +//! this tests the syntax of `thread_local!` + +mod foo { + mod bar { + thread_local! { + // no docs + #[allow(unused)] + static FOO: i32 = 42; + /// docs + pub static BAR: String = String::from("bar"); + + // look at these restrictions!! + pub(crate) static BAZ: usize = 0; + pub(in foo) static QUUX: usize = 0; + } + thread_local!(static SPLOK: u32 = 0); + } +} + +fn main() {} diff --git a/src/test/ui/threads-sendsync/threads.rs b/src/test/ui/threads-sendsync/threads.rs new file mode 100644 index 00000000000..e3da83aa12b --- /dev/null +++ b/src/test/ui/threads-sendsync/threads.rs @@ -0,0 +1,16 @@ +// run-pass +#![allow(unused_must_use)] +// ignore-emscripten no threads support + +use std::thread; + +pub fn main() { + let mut i = 10; + while i > 0 { + thread::spawn({let i = i; move|| child(i)}).join(); + i = i - 1; + } + println!("main thread exiting"); +} + +fn child(x: isize) { println!("{}", x); } diff --git a/src/test/ui/threads-sendsync/tls-dtors-are-run-in-a-static-binary.rs b/src/test/ui/threads-sendsync/tls-dtors-are-run-in-a-static-binary.rs new file mode 100644 index 00000000000..8baef433410 --- /dev/null +++ b/src/test/ui/threads-sendsync/tls-dtors-are-run-in-a-static-binary.rs @@ -0,0 +1,22 @@ +// run-pass +// no-prefer-dynamic +// ignore-emscripten no threads support + +static mut HIT: bool = false; + +struct Foo; + +impl Drop for Foo { + fn drop(&mut self) { + unsafe { HIT = true; } + } +} + +thread_local!(static FOO: Foo = Foo); + +fn main() { + std::thread::spawn(|| { + FOO.with(|_| {}); + }).join().unwrap(); + assert!(unsafe { HIT }); +} diff --git a/src/test/ui/threads-sendsync/tls-init-on-init.rs b/src/test/ui/threads-sendsync/tls-init-on-init.rs new file mode 100644 index 00000000000..193c1815105 --- /dev/null +++ b/src/test/ui/threads-sendsync/tls-init-on-init.rs @@ -0,0 +1,44 @@ +// run-pass +#![allow(stable_features)] + +// ignore-emscripten no threads support + +#![feature(thread_local_try_with)] + +use std::thread; +use std::sync::atomic::{AtomicUsize, Ordering}; + +struct Foo { cnt: usize } + +thread_local!(static FOO: Foo = Foo::init()); + +static CNT: AtomicUsize = AtomicUsize::new(0); + +impl Foo { + fn init() -> Foo { + let cnt = CNT.fetch_add(1, Ordering::SeqCst); + if cnt == 0 { + FOO.with(|_| {}); + } + Foo { cnt: cnt } + } +} + +impl Drop for Foo { + fn drop(&mut self) { + if self.cnt == 1 { + FOO.with(|foo| assert_eq!(foo.cnt, 0)); + } else { + assert_eq!(self.cnt, 0); + if FOO.try_with(|_| ()).is_ok() { + panic!("should not be in valid state"); + } + } + } +} + +fn main() { + thread::spawn(|| { + FOO.with(|_| {}); + }).join().unwrap(); +} diff --git a/src/test/ui/threads-sendsync/tls-try-with.rs b/src/test/ui/threads-sendsync/tls-try-with.rs new file mode 100644 index 00000000000..f36ab4e4f9c --- /dev/null +++ b/src/test/ui/threads-sendsync/tls-try-with.rs @@ -0,0 +1,30 @@ +// run-pass +#![allow(stable_features)] + +// ignore-emscripten no threads support + +#![feature(thread_local_try_with)] + +use std::thread; + +static mut DROP_RUN: bool = false; + +struct Foo; + +thread_local!(static FOO: Foo = Foo {}); + +impl Drop for Foo { + fn drop(&mut self) { + assert!(FOO.try_with(|_| panic!("`try_with` closure run")).is_err()); + unsafe { DROP_RUN = true; } + } +} + +fn main() { + thread::spawn(|| { + assert_eq!(FOO.try_with(|_| { + 132 + }).expect("`try_with` failed"), 132); + }).join().unwrap(); + assert!(unsafe { DROP_RUN }); +} |
