#![warn(rust_2018_idioms)]
#![allow(clippy::type_complexity, clippy::diverging_sub_expression)]
use std::cell::Cell;
use std::net::SocketAddr;
use std::rc::Rc;
use std::time::{Duration, Instant};
#[derive(Clone)]
struct YY {}
#[derive(Clone)]
struct YN {
_value: Cell<u8>,
}
#[derive(Clone)]
struct NN {
_value: Rc<u8>,
}
type BoxFutureSync<T> = std::pin::Pin<Box<dyn std::future::Future<Output = T> + Send + Sync>>;
type BoxFutureSend<T> = std::pin::Pin<Box<dyn std::future::Future<Output = T> + Send>>;
type BoxFuture<T> = std::pin::Pin<Box<dyn std::future::Future<Output = T>>>;
fn require_send<T: Send>(_t: &T) {}
fn require_sync<T: Sync>(_t: &T) {}
fn require_unpin<T: Unpin>(_t: &T) {}
struct Invalid;
trait AmbiguousIfSend<A> {
fn some_item(&self) {}
}
impl<T: ?Sized> AmbiguousIfSend<()> for T {}
impl<T: ?Sized + Send> AmbiguousIfSend<Invalid> for T {}
trait AmbiguousIfSync<A> {
fn some_item(&self) {}
}
impl<T: ?Sized> AmbiguousIfSync<()> for T {}
impl<T: ?Sized + Sync> AmbiguousIfSync<Invalid> for T {}
trait AmbiguousIfUnpin<A> {
fn some_item(&self) {}
}
impl<T: ?Sized> AmbiguousIfUnpin<()> for T {}
impl<T: ?Sized + Unpin> AmbiguousIfUnpin<Invalid> for T {}
macro_rules! into_todo {
($typ:ty) => {{
let x: $typ = todo!();
x
}};
}
macro_rules! async_assert_fn_send {
(Send & $(!)?Sync & $(!)?Unpin, $value:expr) => {
require_send(&$value);
};
(!Send & $(!)?Sync & $(!)?Unpin, $value:expr) => {
AmbiguousIfSend::some_item(&$value);
};
}
macro_rules! async_assert_fn_sync {
($(!)?Send & Sync & $(!)?Unpin, $value:expr) => {
require_sync(&$value);
};
($(!)?Send & !Sync & $(!)?Unpin, $value:expr) => {
AmbiguousIfSync::some_item(&$value);
};
}
macro_rules! async_assert_fn_unpin {
($(!)?Send & $(!)?Sync & Unpin, $value:expr) => {
require_unpin(&$value);
};
($(!)?Send & $(!)?Sync & !Unpin, $value:expr) => {
AmbiguousIfUnpin::some_item(&$value);
};
}
macro_rules! async_assert_fn {
($($f:ident $(< $($generic:ty),* > )? )::+($($arg:ty),*): $($tok:tt)*) => {
#[allow(unreachable_code)]
#[allow(unused_variables)]
const _: fn() = || {
let f = $($f $(::<$($generic),*>)? )::+( $( into_todo!($arg) ),* );
async_assert_fn_send!($($tok)*, f);
async_assert_fn_sync!($($tok)*, f);
async_assert_fn_unpin!($($tok)*, f);
};
};
}
macro_rules! assert_value {
($type:ty: $($tok:tt)*) => {
#[allow(unreachable_code)]
#[allow(unused_variables)]
const _: fn() = || {
let f: $type = todo!();
async_assert_fn_send!($($tok)*, f);
async_assert_fn_sync!($($tok)*, f);
async_assert_fn_unpin!($($tok)*, f);
};
};
}
macro_rules! cfg_not_wasi {
($($item:item)*) => {
$(
#[cfg(not(target_os = "wasi"))]
$item
)*
}
}
const _: fn() = || {
let _pinned = std::marker::PhantomPinned;
let f = tokio::macros::support::poll_fn(move |_| {
let _ = &_pinned;
std::task::Poll::Pending::<()>
});
require_send(&f);
require_sync(&f);
AmbiguousIfUnpin::some_item(&f);
};
cfg_not_wasi! {
mod fs {
use super::*;
assert_value!(nio::fs::DirBuilder: Send & Sync & Unpin);
assert_value!(nio::fs::DirEntry: Send & Sync & Unpin);
assert_value!(nio::fs::ReadDir: Send & Sync & Unpin);
async_assert_fn!(nio::fs::canonicalize(&str): Send & Sync & !Unpin);
async_assert_fn!(nio::fs::copy(&str, &str): Send & Sync & !Unpin);
async_assert_fn!(nio::fs::create_dir(&str): Send & Sync & !Unpin);
async_assert_fn!(nio::fs::create_dir_all(&str): Send & Sync & !Unpin);
async_assert_fn!(nio::fs::hard_link(&str, &str): Send & Sync & !Unpin);
async_assert_fn!(nio::fs::metadata(&str): Send & Sync & !Unpin);
async_assert_fn!(nio::fs::read(&str): Send & Sync & !Unpin);
async_assert_fn!(nio::fs::read_dir(&str): Send & Sync & !Unpin);
async_assert_fn!(nio::fs::read_link(&str): Send & Sync & !Unpin);
async_assert_fn!(nio::fs::read_to_string(&str): Send & Sync & !Unpin);
async_assert_fn!(nio::fs::remove_dir(&str): Send & Sync & !Unpin);
async_assert_fn!(nio::fs::remove_dir_all(&str): Send & Sync & !Unpin);
async_assert_fn!(nio::fs::remove_file(&str): Send & Sync & !Unpin);
async_assert_fn!(nio::fs::rename(&str, &str): Send & Sync & !Unpin);
async_assert_fn!(nio::fs::set_permissions(&str, std::fs::Permissions): Send & Sync & !Unpin);
async_assert_fn!(nio::fs::symlink_metadata(&str): Send & Sync & !Unpin);
async_assert_fn!(nio::fs::write(&str, Vec<u8>): Send & Sync & !Unpin);
async_assert_fn!(nio::fs::ReadDir::next_entry(_): Send & Sync & !Unpin);
async_assert_fn!(nio::fs::DirBuilder::create(_, &str): Send & Sync & !Unpin);
async_assert_fn!(nio::fs::DirEntry::metadata(_): Send & Sync & !Unpin);
async_assert_fn!(nio::fs::DirEntry::file_type(_): Send & Sync & !Unpin);
}
}
cfg_not_wasi! {
async_assert_fn!(nio::net::TcpListener::bind(SocketAddr): !Send & !Sync & Unpin);
async_assert_fn!(nio::net::TcpStream::connect(SocketAddr): !Send & !Sync & !Unpin);
}
assert_value!(nio::net::TcpListener: !Send & !Sync & Unpin);
assert_value!(nio::net::TcpStream: !Send & !Sync & Unpin);
assert_value!(nio::net::TcpReader: !Send & !Sync & Unpin);
assert_value!(nio::net::TcpWriter: !Send & !Sync & Unpin);
async_assert_fn!(nio::net::TcpListener::accept(_): !Send & !Sync & Unpin);
async_assert_fn!(nio::net::TcpStream::peek(_, &mut [u8]): !Send & !Sync & Unpin);
cfg_not_wasi! {
mod udp_socket {
use super::*;
assert_value!(nio::net::UdpSocket: !Send & !Sync & Unpin);
async_assert_fn!(nio::net::UdpSocket::bind(SocketAddr): !Send & !Sync & Unpin);
async_assert_fn!(nio::net::UdpSocket::connect(_, SocketAddr): Send & Sync & Unpin);
async_assert_fn!(nio::net::UdpSocket::peek_from(_, &mut [u8]): !Send & !Sync & Unpin);
async_assert_fn!(nio::net::UdpSocket::recv(_, &mut [u8]): !Send & !Sync & Unpin);
async_assert_fn!(nio::net::UdpSocket::recv_from(_, &mut [u8]): !Send & !Sync & Unpin);
async_assert_fn!(nio::net::UdpSocket::send(_, &[u8]): !Send & !Sync & Unpin);
async_assert_fn!(nio::net::UdpSocket::send_to(_, &[u8], SocketAddr): !Send & !Sync & Unpin);
}
}
async_assert_fn!(nio::net::TcpReader::peek(_, &mut [u8]): !Send & !Sync & Unpin);
assert_value!(nio::JoinHandle<NN>: !Send & !Sync & Unpin);
assert_value!(nio::JoinHandle<YN>: Send & Sync & Unpin);
assert_value!(nio::JoinHandle<YY>: Send & Sync & Unpin);
assert_value!(nio::RuntimeBuilder: Send & Sync & Unpin);
assert_value!(nio::RuntimeContext: Send & Sync & Unpin);
assert_value!(nio::Runtime: Send & Sync & Unpin);
assert_value!(nio::Interval: !Send & !Sync & Unpin);
assert_value!(nio::Sleep: !Send & !Sync & Unpin);
assert_value!(nio::Timeout<BoxFutureSync<()>>: !Send & !Sync & Unpin);
assert_value!(nio::Timeout<BoxFutureSend<()>>: !Send & !Sync & Unpin);
assert_value!(nio::Timeout<BoxFuture<()>>: !Send & !Sync & Unpin);
async_assert_fn!(nio::sleep(Duration): !Send & !Sync & Unpin);
async_assert_fn!(nio::Sleep::at(Instant): !Send & !Sync & Unpin);
async_assert_fn!(nio::timeout(Duration, BoxFutureSync<()>): !Send & !Sync & Unpin);
async_assert_fn!(nio::timeout(Duration, BoxFutureSend<()>): !Send & !Sync & Unpin);
async_assert_fn!(nio::timeout(Duration, BoxFuture<()>): !Send & !Sync & Unpin);
async_assert_fn!(nio::Timeout::at(Instant, BoxFutureSync<()>): !Send & !Sync & Unpin);
async_assert_fn!(nio::Timeout::at(Instant, BoxFutureSend<()>): !Send & !Sync & Unpin);
async_assert_fn!(nio::Timeout::at(Instant, BoxFuture<()>): !Send & !Sync & Unpin);
async_assert_fn!(nio::Interval::tick(_): !Send & !Sync & Unpin);
assert_value!(nio::LocalContext: !Send & !Sync & Unpin);