about summary refs log tree commit diff
path: root/src/test/ui/threads-sendsync
diff options
context:
space:
mode:
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>2019-07-27 01:33:01 +0300
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>2019-07-27 18:56:16 +0300
commit9be35f82c1abf2ecbab489bca9eca138ea648312 (patch)
tree69888506e34af447d9748c0d542de3ba1dd76210 /src/test/ui/threads-sendsync
parentca9faa52f5ada0054b1fa27d97aedf448afb059b (diff)
downloadrust-9be35f82c1abf2ecbab489bca9eca138ea648312.tar.gz
rust-9be35f82c1abf2ecbab489bca9eca138ea648312.zip
tests: Move run-pass tests without naming conflicts to ui
Diffstat (limited to 'src/test/ui/threads-sendsync')
-rw-r--r--src/test/ui/threads-sendsync/auxiliary/thread-local-extern-static.rs10
-rw-r--r--src/test/ui/threads-sendsync/comm.rs22
-rw-r--r--src/test/ui/threads-sendsync/send-is-not-static-par-for.rs34
-rw-r--r--src/test/ui/threads-sendsync/send-resource.rs39
-rw-r--r--src/test/ui/threads-sendsync/send-type-inference.rs19
-rw-r--r--src/test/ui/threads-sendsync/send_str_hashmap.rs53
-rw-r--r--src/test/ui/threads-sendsync/send_str_treemap.rs58
-rw-r--r--src/test/ui/threads-sendsync/sendable-class.rs28
-rw-r--r--src/test/ui/threads-sendsync/sendfn-is-a-block.rs11
-rw-r--r--src/test/ui/threads-sendsync/sendfn-spawn-with-fn-arg.rs23
-rw-r--r--src/test/ui/threads-sendsync/spawn-fn.rs25
-rw-r--r--src/test/ui/threads-sendsync/spawn-types.rs25
-rw-r--r--src/test/ui/threads-sendsync/spawn.rs10
-rw-r--r--src/test/ui/threads-sendsync/spawn2.rs31
-rw-r--r--src/test/ui/threads-sendsync/spawning-with-debug.rs15
-rw-r--r--src/test/ui/threads-sendsync/std-sync-right-kind-impls.rs16
-rw-r--r--src/test/ui/threads-sendsync/sync-send-atomics.rs14
-rw-r--r--src/test/ui/threads-sendsync/sync-send-in-std.rs25
-rw-r--r--src/test/ui/threads-sendsync/sync-send-iterators-in-libcollections.rs71
-rw-r--r--src/test/ui/threads-sendsync/sync-send-iterators-in-libcore.rs104
-rw-r--r--src/test/ui/threads-sendsync/task-comm-0.rs30
-rw-r--r--src/test/ui/threads-sendsync/task-comm-1.rs14
-rw-r--r--src/test/ui/threads-sendsync/task-comm-10.rs33
-rw-r--r--src/test/ui/threads-sendsync/task-comm-11.rs21
-rw-r--r--src/test/ui/threads-sendsync/task-comm-12.rs29
-rw-r--r--src/test/ui/threads-sendsync/task-comm-13.rs18
-rw-r--r--src/test/ui/threads-sendsync/task-comm-14.rs36
-rw-r--r--src/test/ui/threads-sendsync/task-comm-15.rs28
-rw-r--r--src/test/ui/threads-sendsync/task-comm-16.rs111
-rw-r--r--src/test/ui/threads-sendsync/task-comm-17.rs17
-rw-r--r--src/test/ui/threads-sendsync/task-comm-3.rs63
-rw-r--r--src/test/ui/threads-sendsync/task-comm-4.rs45
-rw-r--r--src/test/ui/threads-sendsync/task-comm-5.rs17
-rw-r--r--src/test/ui/threads-sendsync/task-comm-6.rs42
-rw-r--r--src/test/ui/threads-sendsync/task-comm-7.rs59
-rw-r--r--src/test/ui/threads-sendsync/task-comm-9.rs35
-rw-r--r--src/test/ui/threads-sendsync/task-comm-chan-nil.rs13
-rw-r--r--src/test/ui/threads-sendsync/task-life-0.rs14
-rw-r--r--src/test/ui/threads-sendsync/task-spawn-move-and-copy.rs25
-rw-r--r--src/test/ui/threads-sendsync/task-stderr.rs32
-rw-r--r--src/test/ui/threads-sendsync/thread-local-extern-static.rs27
-rw-r--r--src/test/ui/threads-sendsync/thread-local-syntax.rs22
-rw-r--r--src/test/ui/threads-sendsync/threads.rs16
-rw-r--r--src/test/ui/threads-sendsync/tls-dtors-are-run-in-a-static-binary.rs22
-rw-r--r--src/test/ui/threads-sendsync/tls-init-on-init.rs44
-rw-r--r--src/test/ui/threads-sendsync/tls-try-with.rs30
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 });
+}