From 7c1bc460f7eccbeef62504d4799b6bccc909e46c Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Sat, 4 Apr 2020 19:02:26 +0200 Subject: [PATCH] test: add Send/Sync tests for all async fns (#2377) Also updates Empty and Pending to be unconditionally Send and Sync. --- tokio/src/stream/empty.rs | 2 + tokio/src/stream/pending.rs | 2 + tokio/tests/async_send_sync.rs | 219 +++++++++++++++++++++++++++++++++ 3 files changed, 223 insertions(+) create mode 100644 tokio/tests/async_send_sync.rs diff --git a/tokio/src/stream/empty.rs b/tokio/src/stream/empty.rs index a320d44b1..6118673e5 100644 --- a/tokio/src/stream/empty.rs +++ b/tokio/src/stream/empty.rs @@ -10,6 +10,8 @@ use core::task::{Context, Poll}; pub struct Empty(PhantomData); impl Unpin for Empty {} +unsafe impl Send for Empty {} +unsafe impl Sync for Empty {} /// Creates a stream that yields nothing. /// diff --git a/tokio/src/stream/pending.rs b/tokio/src/stream/pending.rs index abc38c44f..2e06a1c26 100644 --- a/tokio/src/stream/pending.rs +++ b/tokio/src/stream/pending.rs @@ -10,6 +10,8 @@ use core::task::{Context, Poll}; pub struct Pending(PhantomData); impl Unpin for Pending {} +unsafe impl Send for Pending {} +unsafe impl Sync for Pending {} /// Creates a stream that is never ready /// diff --git a/tokio/tests/async_send_sync.rs b/tokio/tests/async_send_sync.rs new file mode 100644 index 000000000..f50b41a08 --- /dev/null +++ b/tokio/tests/async_send_sync.rs @@ -0,0 +1,219 @@ +#![warn(rust_2018_idioms)] +#![cfg(feature = "full")] + +use std::cell::Cell; +use std::io::Cursor; +use std::net::SocketAddr; +use std::rc::Rc; +use tokio::net::TcpStream; +use tokio::time::{Duration, Instant}; + +#[allow(dead_code)] +type BoxFutureSync = std::pin::Pin + Send + Sync>>; +#[allow(dead_code)] +type BoxFutureSend = std::pin::Pin + Send>>; +#[allow(dead_code)] +type BoxFuture = std::pin::Pin>>; + +#[allow(dead_code)] +fn require_send(_t: &T) {} +#[allow(dead_code)] +fn require_sync(_t: &T) {} + +#[allow(dead_code)] +struct Invalid; + +trait AmbiguousIfSend { + fn some_item(&self) {} +} +impl AmbiguousIfSend<()> for T {} +impl AmbiguousIfSend for T {} + +trait AmbiguousIfSync { + fn some_item(&self) {} +} +impl AmbiguousIfSync<()> for T {} +impl AmbiguousIfSync for T {} + +macro_rules! into_todo { + ($typ:ty) => {{ + let x: $typ = todo!(); + x + }}; +} +macro_rules! async_assert_fn { + ($($f:ident $(< $($generic:ty),* > )? )::+($($arg:ty),*): Send & Sync) => { + #[allow(unreachable_code)] + #[allow(unused_variables)] + const _: fn() = || { + let f = $($f $(::<$($generic),*>)? )::+( $( into_todo!($arg) ),* ); + require_send(&f); + require_sync(&f); + }; + }; + ($($f:ident $(< $($generic:ty),* > )? )::+($($arg:ty),*): Send & !Sync) => { + #[allow(unreachable_code)] + #[allow(unused_variables)] + const _: fn() = || { + let f = $($f $(::<$($generic),*>)? )::+( $( into_todo!($arg) ),* ); + require_send(&f); + AmbiguousIfSync::some_item(&f); + }; + }; + ($($f:ident $(< $($generic:ty),* > )? )::+($($arg:ty),*): !Send & Sync) => { + #[allow(unreachable_code)] + #[allow(unused_variables)] + const _: fn() = || { + let f = $($f $(::<$($generic),*>)? )::+( $( into_todo!($arg) ),* ); + AmbiguousIfSend::some_item(&f); + require_sync(&f); + }; + }; + ($($f:ident $(< $($generic:ty),* > )? )::+($($arg:ty),*): !Send & !Sync) => { + #[allow(unreachable_code)] + #[allow(unused_variables)] + const _: fn() = || { + let f = $($f $(::<$($generic),*>)? )::+( $( into_todo!($arg) ),* ); + AmbiguousIfSend::some_item(&f); + AmbiguousIfSync::some_item(&f); + }; + }; +} + +async_assert_fn!(tokio::io::copy(&mut TcpStream, &mut TcpStream): Send & Sync); +async_assert_fn!(tokio::io::empty(): Send & Sync); +async_assert_fn!(tokio::io::repeat(u8): Send & Sync); +async_assert_fn!(tokio::io::sink(): Send & Sync); +async_assert_fn!(tokio::io::split(TcpStream): Send & Sync); +async_assert_fn!(tokio::io::stderr(): Send & Sync); +async_assert_fn!(tokio::io::stdin(): Send & Sync); +async_assert_fn!(tokio::io::stdout(): Send & Sync); +async_assert_fn!(tokio::io::Split>>::next_segment(_): Send & Sync); + +async_assert_fn!(tokio::fs::canonicalize(&str): Send & Sync); +async_assert_fn!(tokio::fs::copy(&str, &str): Send & Sync); +async_assert_fn!(tokio::fs::create_dir(&str): Send & Sync); +async_assert_fn!(tokio::fs::create_dir_all(&str): Send & Sync); +async_assert_fn!(tokio::fs::hard_link(&str, &str): Send & Sync); +async_assert_fn!(tokio::fs::metadata(&str): Send & Sync); +async_assert_fn!(tokio::fs::read(&str): Send & Sync); +async_assert_fn!(tokio::fs::read_dir(&str): Send & Sync); +async_assert_fn!(tokio::fs::read_link(&str): Send & Sync); +async_assert_fn!(tokio::fs::read_to_string(&str): Send & Sync); +async_assert_fn!(tokio::fs::remove_dir(&str): Send & Sync); +async_assert_fn!(tokio::fs::remove_dir_all(&str): Send & Sync); +async_assert_fn!(tokio::fs::remove_file(&str): Send & Sync); +async_assert_fn!(tokio::fs::rename(&str, &str): Send & Sync); +async_assert_fn!(tokio::fs::set_permissions(&str, std::fs::Permissions): Send & Sync); +async_assert_fn!(tokio::fs::symlink_metadata(&str): Send & Sync); +async_assert_fn!(tokio::fs::write(&str, Vec): Send & Sync); +async_assert_fn!(tokio::fs::ReadDir::next_entry(_): Send & Sync); +async_assert_fn!(tokio::fs::OpenOptions::open(_, &str): Send & Sync); +async_assert_fn!(tokio::fs::DirEntry::metadata(_): Send & Sync); +async_assert_fn!(tokio::fs::DirEntry::file_type(_): Send & Sync); + +async_assert_fn!(tokio::fs::File::open(&str): Send & Sync); +async_assert_fn!(tokio::fs::File::create(&str): Send & Sync); +async_assert_fn!(tokio::fs::File::seek(_, std::io::SeekFrom): Send & Sync); +async_assert_fn!(tokio::fs::File::sync_all(_): Send & Sync); +async_assert_fn!(tokio::fs::File::sync_data(_): Send & Sync); +async_assert_fn!(tokio::fs::File::set_len(_, u64): Send & Sync); +async_assert_fn!(tokio::fs::File::metadata(_): Send & Sync); +async_assert_fn!(tokio::fs::File::try_clone(_): Send & Sync); +async_assert_fn!(tokio::fs::File::into_std(_): Send & Sync); +async_assert_fn!(tokio::fs::File::set_permissions(_, std::fs::Permissions): Send & Sync); + +async_assert_fn!(tokio::net::lookup_host(SocketAddr): Send & Sync); +async_assert_fn!(tokio::net::TcpListener::bind(SocketAddr): Send & Sync); +async_assert_fn!(tokio::net::TcpListener::accept(_): Send & Sync); +async_assert_fn!(tokio::net::TcpStream::connect(SocketAddr): Send & Sync); +async_assert_fn!(tokio::net::TcpStream::peek(_, &mut [u8]): Send & Sync); +async_assert_fn!(tokio::net::tcp::ReadHalf::peek(_, &mut [u8]): Send & Sync); +async_assert_fn!(tokio::net::UdpSocket::bind(SocketAddr): Send & Sync); +async_assert_fn!(tokio::net::UdpSocket::connect(_, SocketAddr): Send & Sync); +async_assert_fn!(tokio::net::UdpSocket::send(_, &[u8]): Send & Sync); +async_assert_fn!(tokio::net::UdpSocket::recv(_, &mut [u8]): Send & Sync); +async_assert_fn!(tokio::net::UdpSocket::send_to(_, &[u8], SocketAddr): Send & Sync); +async_assert_fn!(tokio::net::UdpSocket::recv_from(_, &mut [u8]): Send & Sync); +async_assert_fn!(tokio::net::udp::RecvHalf::recv(_, &mut [u8]): Send & Sync); +async_assert_fn!(tokio::net::udp::RecvHalf::recv_from(_, &mut [u8]): Send & Sync); +async_assert_fn!(tokio::net::udp::SendHalf::send(_, &[u8]): Send & Sync); +async_assert_fn!(tokio::net::udp::SendHalf::send_to(_, &[u8], &SocketAddr): Send & Sync); + +#[cfg(unix)] +mod unix_datagram { + use super::*; + async_assert_fn!(tokio::net::UnixListener::bind(&str): Send & Sync); + async_assert_fn!(tokio::net::UnixListener::accept(_): Send & Sync); + async_assert_fn!(tokio::net::UnixDatagram::send(_, &[u8]): Send & Sync); + async_assert_fn!(tokio::net::UnixDatagram::recv(_, &mut [u8]): Send & Sync); + async_assert_fn!(tokio::net::UnixDatagram::send_to(_, &[u8], &str): Send & Sync); + async_assert_fn!(tokio::net::UnixDatagram::recv_from(_, &mut [u8]): Send & Sync); + async_assert_fn!(tokio::net::UnixStream::connect(&str): Send & Sync); +} + +async_assert_fn!(tokio::process::Child::wait_with_output(_): Send & Sync); +async_assert_fn!(tokio::signal::ctrl_c(): Send & Sync); +#[cfg(unix)] +async_assert_fn!(tokio::signal::unix::Signal::recv(_): Send & Sync); + +async_assert_fn!(tokio::stream::empty>(): Send & Sync); +async_assert_fn!(tokio::stream::pending>(): Send & Sync); +async_assert_fn!(tokio::stream::iter(std::vec::IntoIter): Send & Sync); + +async_assert_fn!(tokio::sync::Barrier::wait(_): Send & Sync); +async_assert_fn!(tokio::sync::Mutex::lock(_): Send & Sync); +async_assert_fn!(tokio::sync::Mutex>::lock(_): Send & Sync); +async_assert_fn!(tokio::sync::Mutex>::lock(_): !Send & !Sync); +async_assert_fn!(tokio::sync::Notify::notified(_): Send & !Sync); +async_assert_fn!(tokio::sync::RwLock::read(_): Send & Sync); +async_assert_fn!(tokio::sync::RwLock::write(_): Send & Sync); +async_assert_fn!(tokio::sync::RwLock>::read(_): !Send & !Sync); +async_assert_fn!(tokio::sync::RwLock>::write(_): !Send & !Sync); +async_assert_fn!(tokio::sync::RwLock>::read(_): !Send & !Sync); +async_assert_fn!(tokio::sync::RwLock>::write(_): !Send & !Sync); +async_assert_fn!(tokio::sync::Semaphore::acquire(_): Send & Sync); + +async_assert_fn!(tokio::sync::broadcast::Receiver::recv(_): Send & Sync); +async_assert_fn!(tokio::sync::broadcast::Receiver>::recv(_): Send & Sync); +async_assert_fn!(tokio::sync::broadcast::Receiver>::recv(_): !Send & !Sync); + +async_assert_fn!(tokio::sync::mpsc::Receiver::recv(_): Send & Sync); +async_assert_fn!(tokio::sync::mpsc::Receiver>::recv(_): Send & Sync); +async_assert_fn!(tokio::sync::mpsc::Receiver>::recv(_): !Send & !Sync); +async_assert_fn!(tokio::sync::mpsc::Sender::send(_, u8): Send & Sync); +async_assert_fn!(tokio::sync::mpsc::Sender>::send(_, Cell): Send & !Sync); +async_assert_fn!(tokio::sync::mpsc::Sender>::send(_, Rc): !Send & !Sync); + +async_assert_fn!(tokio::sync::mpsc::UnboundedReceiver::recv(_): Send & Sync); +async_assert_fn!(tokio::sync::mpsc::UnboundedReceiver>::recv(_): Send & Sync); +async_assert_fn!(tokio::sync::mpsc::UnboundedReceiver>::recv(_): !Send & !Sync); + +async_assert_fn!(tokio::sync::watch::Receiver::recv(_): Send & Sync); +async_assert_fn!(tokio::sync::watch::Receiver>::recv(_): !Send & !Sync); +async_assert_fn!(tokio::sync::watch::Receiver>::recv(_): !Send & !Sync); +async_assert_fn!(tokio::sync::watch::Sender::closed(_): Send & Sync); +async_assert_fn!(tokio::sync::watch::Sender>::closed(_): !Send & !Sync); +async_assert_fn!(tokio::sync::watch::Sender>::closed(_): !Send & !Sync); + +async_assert_fn!(tokio::task::LocalKey::scope(_, u32, BoxFutureSync<()>): Send & Sync); +async_assert_fn!(tokio::task::LocalKey::scope(_, u32, BoxFutureSend<()>): Send & !Sync); +async_assert_fn!(tokio::task::LocalKey::scope(_, u32, BoxFuture<()>): !Send & !Sync); +async_assert_fn!(tokio::task::LocalKey>::scope(_, Cell, BoxFutureSync<()>): Send & !Sync); +async_assert_fn!(tokio::task::LocalKey>::scope(_, Cell, BoxFutureSend<()>): Send & !Sync); +async_assert_fn!(tokio::task::LocalKey>::scope(_, Cell, BoxFuture<()>): !Send & !Sync); +async_assert_fn!(tokio::task::LocalKey>::scope(_, Rc, BoxFutureSync<()>): !Send & !Sync); +async_assert_fn!(tokio::task::LocalKey>::scope(_, Rc, BoxFutureSend<()>): !Send & !Sync); +async_assert_fn!(tokio::task::LocalKey>::scope(_, Rc, BoxFuture<()>): !Send & !Sync); +async_assert_fn!(tokio::task::LocalSet::run_until(_, BoxFutureSync<()>): !Send & !Sync); + +async_assert_fn!(tokio::time::advance(Duration): Send & Sync); +async_assert_fn!(tokio::time::delay_for(Duration): Send & Sync); +async_assert_fn!(tokio::time::delay_until(Instant): Send & Sync); +async_assert_fn!(tokio::time::timeout(Duration, BoxFutureSync<()>): Send & Sync); +async_assert_fn!(tokio::time::timeout(Duration, BoxFutureSend<()>): Send & !Sync); +async_assert_fn!(tokio::time::timeout(Duration, BoxFuture<()>): !Send & !Sync); +async_assert_fn!(tokio::time::timeout_at(Instant, BoxFutureSync<()>): Send & Sync); +async_assert_fn!(tokio::time::timeout_at(Instant, BoxFutureSend<()>): Send & !Sync); +async_assert_fn!(tokio::time::timeout_at(Instant, BoxFuture<()>): !Send & !Sync); +async_assert_fn!(tokio::time::Interval::tick(_): Send & Sync);