diff options
Diffstat (limited to 'third_party/rust/async-trait/tests')
31 files changed, 2189 insertions, 0 deletions
diff --git a/third_party/rust/async-trait/tests/compiletest.rs b/third_party/rust/async-trait/tests/compiletest.rs new file mode 100644 index 0000000000..7974a6249e --- /dev/null +++ b/third_party/rust/async-trait/tests/compiletest.rs @@ -0,0 +1,7 @@ +#[rustversion::attr(not(nightly), ignore)] +#[cfg_attr(miri, ignore)] +#[test] +fn ui() { + let t = trybuild::TestCases::new(); + t.compile_fail("tests/ui/*.rs"); +} diff --git a/third_party/rust/async-trait/tests/executor/mod.rs b/third_party/rust/async-trait/tests/executor/mod.rs new file mode 100644 index 0000000000..912fb79844 --- /dev/null +++ b/third_party/rust/async-trait/tests/executor/mod.rs @@ -0,0 +1,36 @@ +use std::future::Future; +use std::pin::Pin; +use std::ptr; +use std::task::{Context, Poll, RawWaker, RawWakerVTable, Waker}; + +// Executor for a future that resolves immediately (test only). +#[allow(clippy::missing_panics_doc)] +pub fn block_on_simple<F: Future>(mut fut: F) -> F::Output { + unsafe fn clone(_null: *const ()) -> RawWaker { + unimplemented!() + } + + unsafe fn wake(_null: *const ()) { + unimplemented!() + } + + unsafe fn wake_by_ref(_null: *const ()) { + unimplemented!() + } + + unsafe fn drop(_null: *const ()) {} + + let data = ptr::null(); + let vtable = &RawWakerVTable::new(clone, wake, wake_by_ref, drop); + let raw_waker = RawWaker::new(data, vtable); + let waker = unsafe { Waker::from_raw(raw_waker) }; + let mut cx = Context::from_waker(&waker); + + // fut does not move until it gets dropped. + let fut = unsafe { Pin::new_unchecked(&mut fut) }; + + match fut.poll(&mut cx) { + Poll::Ready(output) => output, + Poll::Pending => panic!("future did not resolve immediately"), + } +} diff --git a/third_party/rust/async-trait/tests/test.rs b/third_party/rust/async-trait/tests/test.rs new file mode 100644 index 0000000000..458904e162 --- /dev/null +++ b/third_party/rust/async-trait/tests/test.rs @@ -0,0 +1,1586 @@ +#![cfg_attr( + async_trait_nightly_testing, + feature(min_specialization, type_alias_impl_trait) +)] +#![deny(rust_2021_compatibility)] +#![allow( + clippy::let_unit_value, + clippy::missing_panics_doc, + clippy::missing_safety_doc, + clippy::needless_return, + clippy::trivially_copy_pass_by_ref, + clippy::unused_async +)] + +use async_trait::async_trait; + +pub mod executor; + +// Dummy module to check that the expansion refer to rust's core crate +mod core {} + +#[async_trait] +trait Trait { + type Assoc; + + async fn selfvalue(self) + where + Self: Sized, + { + } + + async fn selfref(&self) {} + + async fn selfmut(&mut self) {} + + async fn required() -> Self::Assoc; + + async fn elided_lifetime(_x: &str) {} + + async fn explicit_lifetime<'a>(_x: &'a str) {} + + async fn generic_type_param<T: Send>(x: Box<T>) -> T { + *x + } + + async fn calls(&self) { + self.selfref().await; + Self::elided_lifetime("").await; + <Self>::elided_lifetime("").await; + } + + async fn calls_mut(&mut self) { + self.selfmut().await; + } +} + +struct Struct; + +#[async_trait] +impl Trait for Struct { + type Assoc = (); + + async fn selfvalue(self) {} + + async fn selfref(&self) {} + + async fn selfmut(&mut self) {} + + async fn required() -> Self::Assoc {} + + async fn elided_lifetime(_x: &str) {} + + async fn explicit_lifetime<'a>(_x: &'a str) {} + + async fn generic_type_param<T: Send>(x: Box<T>) -> T { + *x + } + + async fn calls(&self) { + self.selfref().await; + Self::elided_lifetime("").await; + <Self>::elided_lifetime("").await; + } + + async fn calls_mut(&mut self) { + self.selfmut().await; + } +} + +pub async fn test() { + let mut s = Struct; + s.selfref().await; + s.selfmut().await; + s.selfvalue().await; + + Struct::required().await; + Struct::elided_lifetime("").await; + Struct::explicit_lifetime("").await; + Struct::generic_type_param(Box::new("")).await; + + let mut s = Struct; + s.calls().await; + s.calls_mut().await; +} + +pub async fn test_object_safe_without_default() { + #[async_trait] + trait ObjectSafe { + async fn f(&self); + } + + #[async_trait] + impl ObjectSafe for Struct { + async fn f(&self) {} + } + + let object = &Struct as &dyn ObjectSafe; + object.f().await; +} + +pub async fn test_object_safe_with_default() { + #[async_trait] + trait ObjectSafe: Sync { + async fn f(&self) {} + } + + #[async_trait] + impl ObjectSafe for Struct { + async fn f(&self) {} + } + + let object = &Struct as &dyn ObjectSafe; + object.f().await; +} + +pub async fn test_object_no_send() { + #[async_trait(?Send)] + trait ObjectSafe: Sync { + async fn f(&self) {} + } + + #[async_trait(?Send)] + impl ObjectSafe for Struct { + async fn f(&self) {} + } + + let object = &Struct as &dyn ObjectSafe; + object.f().await; +} + +#[async_trait] +pub unsafe trait UnsafeTrait {} + +#[async_trait] +unsafe impl UnsafeTrait for () {} + +#[async_trait] +pub(crate) unsafe trait UnsafeTraitPubCrate {} + +#[async_trait] +unsafe trait UnsafeTraitPrivate {} + +pub async fn test_can_destruct() { + #[async_trait] + trait CanDestruct { + async fn f(&self, foos: (u8, u8, u8, u8)); + } + + #[async_trait] + impl CanDestruct for Struct { + async fn f(&self, (a, ref mut b, ref c, d): (u8, u8, u8, u8)) { + let _a: u8 = a; + let _b: &mut u8 = b; + let _c: &u8 = c; + let _d: u8 = d; + } + } +} + +pub async fn test_self_in_macro() { + #[async_trait] + trait Trait { + async fn a(self); + async fn b(&mut self); + async fn c(&self); + } + + #[async_trait] + impl Trait for String { + async fn a(self) { + println!("{}", self); + } + async fn b(&mut self) { + println!("{}", self); + } + async fn c(&self) { + println!("{}", self); + } + } +} + +pub async fn test_inference() { + #[async_trait] + pub trait Trait { + async fn f() -> Box<dyn Iterator<Item = ()>> { + Box::new(std::iter::empty()) + } + } +} + +pub async fn test_internal_items() { + #[async_trait] + #[allow(dead_code, clippy::items_after_statements)] + pub trait Trait: Sized { + async fn f(self) { + struct Struct; + + impl Struct { + fn f(self) { + let _ = self; + } + } + } + } +} + +pub async fn test_unimplemented() { + #[async_trait] + pub trait Trait { + async fn f() { + unimplemented!() + } + } +} + +// https://github.com/dtolnay/async-trait/issues/1 +pub mod issue1 { + use async_trait::async_trait; + + #[async_trait] + trait Issue1 { + async fn f<U>(&self); + } + + #[async_trait] + impl<T: Sync> Issue1 for Vec<T> { + async fn f<U>(&self) {} + } +} + +// https://github.com/dtolnay/async-trait/issues/2 +pub mod issue2 { + use async_trait::async_trait; + use std::future::Future; + + #[async_trait] + pub trait Issue2: Future { + async fn flatten(self) -> <Self::Output as Future>::Output + where + Self::Output: Future + Send, + Self: Sized, + { + let nested_future = self.await; + nested_future.await + } + } +} + +// https://github.com/dtolnay/async-trait/issues/9 +pub mod issue9 { + use async_trait::async_trait; + + #[async_trait] + pub trait Issue9: Sized + Send { + async fn f(_x: Self) {} + } +} + +// https://github.com/dtolnay/async-trait/issues/11 +pub mod issue11 { + use async_trait::async_trait; + use std::sync::Arc; + + #[async_trait] + trait Issue11 { + async fn example(self: Arc<Self>); + } + + struct Struct; + + #[async_trait] + impl Issue11 for Struct { + async fn example(self: Arc<Self>) {} + } +} + +// https://github.com/dtolnay/async-trait/issues/15 +pub mod issue15 { + use async_trait::async_trait; + use std::marker::PhantomData; + + trait Trait {} + + #[async_trait] + trait Issue15 { + async fn myfn(&self, _: PhantomData<dyn Trait + Send>) {} + } +} + +// https://github.com/dtolnay/async-trait/issues/17 +pub mod issue17 { + use async_trait::async_trait; + + #[async_trait] + trait Issue17 { + async fn f(&self); + } + + struct Struct { + string: String, + } + + #[async_trait] + impl Issue17 for Struct { + async fn f(&self) { + println!("{}", self.string); + } + } +} + +// https://github.com/dtolnay/async-trait/issues/23 +pub mod issue23 { + use async_trait::async_trait; + + #[async_trait] + pub trait Issue23 { + async fn f(self); + + async fn g(mut self) + where + Self: Sized, + { + do_something(&mut self); + } + } + + struct S {} + + #[async_trait] + impl Issue23 for S { + async fn f(mut self) { + do_something(&mut self); + } + } + + fn do_something<T>(_: &mut T) {} +} + +// https://github.com/dtolnay/async-trait/issues/25 +#[cfg(async_trait_nightly_testing)] +pub mod issue25 { + use crate::executor; + use async_trait::async_trait; + use std::fmt::{Display, Write}; + + #[async_trait] + trait AsyncToString { + async fn async_to_string(&self) -> String; + } + + #[async_trait] + impl AsyncToString for String { + async fn async_to_string(&self) -> String { + "special".to_owned() + } + } + + macro_rules! hide_from_stable_parser { + ($($tt:tt)*) => { + $($tt)* + }; + } + + hide_from_stable_parser! { + #[async_trait] + impl<T: ?Sized + Display + Sync> AsyncToString for T { + default async fn async_to_string(&self) -> String { + let mut buf = String::new(); + buf.write_fmt(format_args!("{}", self)).unwrap(); + buf + } + } + } + + #[test] + fn test() { + let fut = true.async_to_string(); + assert_eq!(executor::block_on_simple(fut), "true"); + + let string = String::new(); + let fut = string.async_to_string(); + assert_eq!(executor::block_on_simple(fut), "special"); + } +} + +// https://github.com/dtolnay/async-trait/issues/28 +pub mod issue28 { + use async_trait::async_trait; + + struct Str<'a>(&'a str); + + #[async_trait] + trait Trait1<'a> { + async fn f(x: Str<'a>) -> &'a str; + async fn g(x: Str<'a>) -> &'a str { + x.0 + } + } + + #[async_trait] + impl<'a> Trait1<'a> for str { + async fn f(x: Str<'a>) -> &'a str { + x.0 + } + } + + #[async_trait] + trait Trait2 { + async fn f(); + } + + #[async_trait] + impl<'a> Trait2 for &'a () { + async fn f() {} + } + + #[async_trait] + trait Trait3<'a, 'b> { + async fn f(_: &'a &'b ()); // chain 'a and 'b + async fn g(_: &'b ()); // chain 'b only + async fn h(); // do not chain + } +} + +// https://github.com/dtolnay/async-trait/issues/31 +pub mod issue31 { + use async_trait::async_trait; + + pub struct Struct<'a> { + pub name: &'a str, + } + + #[async_trait] + pub trait Trait<'a> { + async fn hello(thing: Struct<'a>) -> String; + async fn hello_twice(one: Struct<'a>, two: Struct<'a>) -> String { + let str1 = Self::hello(one).await; + let str2 = Self::hello(two).await; + str1 + &str2 + } + } +} + +// https://github.com/dtolnay/async-trait/issues/42 +pub mod issue42 { + use async_trait::async_trait; + + #[async_trait] + pub trait Context: Sized { + async fn from_parts() -> Self; + } + + pub struct TokenContext; + + #[async_trait] + impl Context for TokenContext { + async fn from_parts() -> TokenContext { + TokenContext + } + } +} + +// https://github.com/dtolnay/async-trait/issues/44 +pub mod issue44 { + use async_trait::async_trait; + + #[async_trait] + pub trait StaticWithWhereSelf + where + Box<Self>: Sized, + Self: Sized + Send, + { + async fn get_one() -> u8 { + 1 + } + } + + pub struct Struct; + + #[async_trait] + impl StaticWithWhereSelf for Struct {} +} + +// https://github.com/dtolnay/async-trait/issues/45 +pub mod issue45 { + use crate::executor; + use async_trait::async_trait; + use std::fmt::Debug; + use std::sync::atomic::{AtomicU64, Ordering}; + use std::sync::{Arc, Mutex}; + use tracing::event::Event; + use tracing::field::{Field, Visit}; + use tracing::span::{Attributes, Id, Record}; + use tracing::{info, instrument, subscriber, Metadata, Subscriber}; + + #[async_trait] + pub trait Parent { + async fn foo(&mut self, v: usize); + } + + #[async_trait] + pub trait Child { + async fn bar(&self); + } + + #[derive(Debug)] + struct Impl(usize); + + #[async_trait] + impl Parent for Impl { + #[instrument] + async fn foo(&mut self, v: usize) { + self.0 = v; + self.bar().await; + } + } + + #[async_trait] + impl Child for Impl { + // Let's check that tracing detects the renaming of the `self` variable + // too, as tracing::instrument is not going to be able to skip the + // `self` argument if it can't find it in the function signature. + #[instrument(skip(self))] + async fn bar(&self) { + info!(val = self.0); + } + } + + // A simple subscriber implementation to test the behavior of async-trait + // with tokio-rs/tracing. This implementation is not robust against race + // conditions, but it's not an issue here as we are only polling on a single + // future at a time. + #[derive(Debug)] + struct SubscriberInner { + current_depth: AtomicU64, + // We assert that nested functions work. If the fix were to break, we + // would see two top-level functions instead of `bar` nested in `foo`. + max_depth: AtomicU64, + max_span_id: AtomicU64, + // Name of the variable / value / depth when the event was recorded. + value: Mutex<Option<(&'static str, u64, u64)>>, + } + + #[derive(Debug, Clone)] + struct TestSubscriber { + inner: Arc<SubscriberInner>, + } + + impl TestSubscriber { + fn new() -> Self { + TestSubscriber { + inner: Arc::new(SubscriberInner { + current_depth: AtomicU64::new(0), + max_depth: AtomicU64::new(0), + max_span_id: AtomicU64::new(1), + value: Mutex::new(None), + }), + } + } + } + + struct U64Visitor(Option<(&'static str, u64)>); + + impl Visit for U64Visitor { + fn record_debug(&mut self, _field: &Field, _value: &dyn Debug) {} + + fn record_u64(&mut self, field: &Field, value: u64) { + self.0 = Some((field.name(), value)); + } + } + + impl Subscriber for TestSubscriber { + fn enabled(&self, _metadata: &Metadata) -> bool { + true + } + fn new_span(&self, _span: &Attributes) -> Id { + Id::from_u64(self.inner.max_span_id.fetch_add(1, Ordering::AcqRel)) + } + fn record(&self, _span: &Id, _values: &Record) {} + fn record_follows_from(&self, _span: &Id, _follows: &Id) {} + fn event(&self, event: &Event) { + let mut visitor = U64Visitor(None); + event.record(&mut visitor); + if let Some((s, v)) = visitor.0 { + let current_depth = self.inner.current_depth.load(Ordering::Acquire); + *self.inner.value.lock().unwrap() = Some((s, v, current_depth)); + } + } + fn enter(&self, _span: &Id) { + let old_depth = self.inner.current_depth.fetch_add(1, Ordering::AcqRel); + if old_depth + 1 > self.inner.max_depth.load(Ordering::Acquire) { + self.inner.max_depth.fetch_add(1, Ordering::AcqRel); + } + } + fn exit(&self, _span: &Id) { + self.inner.current_depth.fetch_sub(1, Ordering::AcqRel); + } + } + + #[test] + #[cfg_attr(miri, ignore)] // https://github.com/matklad/once_cell/pull/185 + fn tracing() { + // Create the future outside of the subscriber, as no call to tracing + // should be made until the future is polled. + let mut struct_impl = Impl(0); + let fut = struct_impl.foo(5); + let subscriber = TestSubscriber::new(); + subscriber::with_default(subscriber.clone(), || executor::block_on_simple(fut)); + // Did we enter bar inside of foo? + assert_eq!(subscriber.inner.max_depth.load(Ordering::Acquire), 2); + // Have we exited all spans? + assert_eq!(subscriber.inner.current_depth.load(Ordering::Acquire), 0); + // Did we create only two spans? Note: spans start at 1, hence the -1. + assert_eq!(subscriber.inner.max_span_id.load(Ordering::Acquire) - 1, 2); + // Was the value recorded at the right depth i.e. in the right function? + // If so, was it the expected value? + assert_eq!(*subscriber.inner.value.lock().unwrap(), Some(("val", 5, 2))); + } +} + +// https://github.com/dtolnay/async-trait/issues/46 +pub mod issue46 { + use async_trait::async_trait; + + macro_rules! implement_commands_workaround { + ($tyargs:tt : $ty:tt) => { + #[async_trait] + pub trait AsyncCommands1: Sized { + async fn f<$tyargs: $ty>(&mut self, x: $tyargs) { + self.f(x).await + } + } + }; + } + + implement_commands_workaround!(K: Send); + + macro_rules! implement_commands { + ($tyargs:ident : $ty:ident) => { + #[async_trait] + pub trait AsyncCommands2: Sized { + async fn f<$tyargs: $ty>(&mut self, x: $tyargs) { + self.f(x).await + } + } + }; + } + + implement_commands!(K: Send); +} + +// https://github.com/dtolnay/async-trait/issues/53 +pub mod issue53 { + use async_trait::async_trait; + + pub struct Unit; + pub struct Tuple(u8); + pub struct Struct { + pub x: u8, + } + + #[async_trait] + pub trait Trait { + async fn method(); + } + + #[async_trait] + impl Trait for Unit { + async fn method() { + let _ = Self; + } + } + + #[async_trait] + impl Trait for Tuple { + async fn method() { + let _ = Self(0); + } + } + + #[async_trait] + impl Trait for Struct { + async fn method() { + let _ = Self { x: 0 }; + } + } + + #[async_trait] + impl Trait for std::marker::PhantomData<Struct> { + async fn method() { + let _ = Self; + } + } +} + +// https://github.com/dtolnay/async-trait/issues/57 +#[cfg(async_trait_nightly_testing)] +pub mod issue57 { + use crate::executor; + use async_trait::async_trait; + + #[async_trait] + trait Trait { + async fn const_generic<T: Send, const C: usize>(_: [T; C]) {} + } + + struct Struct; + + #[async_trait] + impl Trait for Struct { + async fn const_generic<T: Send, const C: usize>(_: [T; C]) {} + } + + #[test] + fn test() { + let fut = Struct::const_generic([0; 10]); + executor::block_on_simple(fut); + } +} + +// https://github.com/dtolnay/async-trait/issues/68 +pub mod issue68 { + #[rustversion::since(1.40)] // procedural macros cannot expand to macro definitions in 1.39. + #[async_trait::async_trait] + pub trait Example { + async fn method(&self) { + macro_rules! t { + () => {{ + let _: &Self = self; + }}; + } + t!(); + } + } +} + +// https://github.com/dtolnay/async-trait/issues/73 +pub mod issue73 { + use async_trait::async_trait; + + #[async_trait] + pub trait Example { + const ASSOCIATED: &'static str; + + async fn associated(&self) { + println!("Associated:{}", Self::ASSOCIATED); + } + } +} + +// https://github.com/dtolnay/async-trait/issues/81 +pub mod issue81 { + use async_trait::async_trait; + + #[async_trait] + pub trait Trait { + async fn handle(&self); + } + + pub enum Enum { + Variant, + } + + #[async_trait] + impl Trait for Enum { + async fn handle(&self) { + let Enum::Variant = self; + let Self::Variant = self; + } + } +} + +// https://github.com/dtolnay/async-trait/issues/83 +pub mod issue83 { + #![allow(clippy::needless_arbitrary_self_type)] + + use async_trait::async_trait; + + #[async_trait] + pub trait Trait { + async fn f(&self) {} + async fn g(self: &Self) {} + } +} + +// https://github.com/dtolnay/async-trait/issues/85 +pub mod issue85 { + #![deny(non_snake_case)] + + use async_trait::async_trait; + + #[async_trait] + pub trait Trait { + #[allow(non_snake_case)] + async fn camelCase(); + } + + pub struct Struct; + + #[async_trait] + impl Trait for Struct { + async fn camelCase() {} + } +} + +// https://github.com/dtolnay/async-trait/issues/87 +pub mod issue87 { + use async_trait::async_trait; + + #[async_trait] + pub trait Trait { + async fn f(&self); + } + + pub enum Tuple { + V(), + } + + pub enum Struct { + V {}, + } + + #[async_trait] + impl Trait for Tuple { + async fn f(&self) { + let Tuple::V() = self; + let Self::V() = self; + let _ = Self::V; + let _ = Self::V(); + } + } + + #[async_trait] + impl Trait for Struct { + async fn f(&self) { + let Struct::V {} = self; + let Self::V {} = self; + let _ = Self::V {}; + } + } +} + +// https://github.com/dtolnay/async-trait/issues/89 +pub mod issue89 { + #![allow(bare_trait_objects)] + + use async_trait::async_trait; + + #[async_trait] + trait Trait { + async fn f(&self); + } + + #[async_trait] + impl Trait for Send + Sync { + async fn f(&self) {} + } + + #[async_trait] + impl Trait for dyn Fn(i8) + Send + Sync { + async fn f(&self) {} + } + + #[async_trait] + impl Trait for (dyn Fn(u8) + Send + Sync) { + async fn f(&self) {} + } +} + +// https://github.com/dtolnay/async-trait/issues/92 +pub mod issue92 { + use async_trait::async_trait; + + macro_rules! mac { + ($($tt:tt)*) => { + $($tt)* + }; + } + + pub struct Struct<T> { + _x: T, + } + + impl<T> Struct<T> { + const ASSOCIATED1: &'static str = "1"; + async fn associated1() {} + } + + #[async_trait] + pub trait Trait + where + mac!(Self): Send, + { + const ASSOCIATED2: &'static str; + type Associated2; + + #[allow(path_statements, clippy::let_underscore_future, clippy::no_effect)] + async fn associated2(&self) { + // trait items + mac!(let _: Self::Associated2;); + mac!(let _: <Self>::Associated2;); + mac!(let _: <Self as Trait>::Associated2;); + mac!(Self::ASSOCIATED2;); + mac!(<Self>::ASSOCIATED2;); + mac!(<Self as Trait>::ASSOCIATED2;); + mac!(let _ = Self::associated2(self);); + mac!(let _ = <Self>::associated2(self);); + mac!(let _ = <Self as Trait>::associated2(self);); + } + } + + #[async_trait] + impl<T: Send + Sync> Trait for Struct<T> + where + mac!(Self): Send, + { + const ASSOCIATED2: &'static str = "2"; + type Associated2 = (); + + #[allow(path_statements, clippy::let_underscore_future, clippy::no_effect)] + async fn associated2(&self) { + // inherent items + mac!(Self::ASSOCIATED1;); + mac!(<Self>::ASSOCIATED1;); + mac!(let _ = Self::associated1();); + mac!(let _ = <Self>::associated1();); + + // trait items + mac!(let _: <Self as Trait>::Associated2;); + mac!(Self::ASSOCIATED2;); + mac!(<Self>::ASSOCIATED2;); + mac!(<Self as Trait>::ASSOCIATED2;); + mac!(let _ = Self::associated2(self);); + mac!(let _ = <Self>::associated2(self);); + mac!(let _ = <Self as Trait>::associated2(self);); + } + } + + pub struct Unit; + + #[async_trait] + impl Trait for Unit { + const ASSOCIATED2: &'static str = "2"; + type Associated2 = (); + + async fn associated2(&self) { + mac!(let Self: Self = *self;); + } + } +} + +// https://github.com/dtolnay/async-trait/issues/92#issuecomment-683370136 +pub mod issue92_2 { + use async_trait::async_trait; + + macro_rules! mac { + ($($tt:tt)*) => { + $($tt)* + }; + } + + pub trait Trait1 { + fn func1(); + } + + #[async_trait] + pub trait Trait2: Trait1 { + async fn func2() { + mac!(Self::func1()); + + macro_rules! mac2 { + ($($tt:tt)*) => { + Self::func1(); + }; + } + mac2!(); + } + } +} + +// https://github.com/dtolnay/async-trait/issues/104 +pub mod issue104 { + use async_trait::async_trait; + + #[async_trait] + trait T1 { + async fn id(&self) -> i32; + } + + macro_rules! impl_t1 { + ($ty:ty, $id:expr) => { + #[async_trait] + impl T1 for $ty { + async fn id(&self) -> i32 { + $id + } + } + }; + } + + struct Foo; + + impl_t1!(Foo, 1); +} + +// https://github.com/dtolnay/async-trait/issues/106 +pub mod issue106 { + use async_trait::async_trait; + use std::future::Future; + + #[async_trait] + pub trait ProcessPool: Send + Sync { + type ThreadPool; + + async fn spawn<F, Fut, T>(&self, work: F) -> T + where + F: FnOnce(&Self::ThreadPool) -> Fut + Send, + Fut: Future<Output = T> + 'static; + } + + #[async_trait] + impl<P> ProcessPool for &P + where + P: ?Sized + ProcessPool, + { + type ThreadPool = P::ThreadPool; + + async fn spawn<F, Fut, T>(&self, work: F) -> T + where + F: FnOnce(&Self::ThreadPool) -> Fut + Send, + Fut: Future<Output = T> + 'static, + { + (**self).spawn(work).await + } + } +} + +// https://github.com/dtolnay/async-trait/issues/110 +pub mod issue110 { + use async_trait::async_trait; + use std::marker::PhantomData; + + #[async_trait] + pub trait Loader { + async fn load(&self, key: &str); + } + + pub struct AwsEc2MetadataLoader<'a> { + marker: PhantomData<&'a ()>, + } + + #[async_trait] + impl Loader for AwsEc2MetadataLoader<'_> { + async fn load(&self, _key: &str) {} + } +} + +// https://github.com/dtolnay/async-trait/issues/120 +pub mod issue120 { + #![deny(clippy::trivially_copy_pass_by_ref)] + + use async_trait::async_trait; + + #[async_trait] + trait Trait { + async fn f(&self); + } + + #[async_trait] + impl Trait for () { + async fn f(&self) {} + } +} + +// https://github.com/dtolnay/async-trait/issues/123 +pub mod issue123 { + use async_trait::async_trait; + + #[async_trait] + trait Trait<T = ()> { + async fn f(&self) -> &str + where + T: 'async_trait, + { + "default" + } + } + + #[async_trait] + impl<T> Trait<T> for () {} +} + +// https://github.com/dtolnay/async-trait/issues/129 +pub mod issue129 { + use async_trait::async_trait; + + #[async_trait] + pub trait TestTrait { + async fn a(_b: u8, c: u8) -> u8 { + c + } + } + + pub struct TestStruct; + + #[async_trait] + impl TestTrait for TestStruct { + async fn a(_b: u8, c: u8) -> u8 { + c + } + } +} + +// https://github.com/dtolnay/async-trait/issues/134 +#[cfg(async_trait_nightly_testing)] +pub mod issue134 { + use async_trait::async_trait; + + #[async_trait] + trait TestTrait { + async fn run<const DUMMY: bool>(self) + where + Self: Sized, + { + } + } + + pub struct TestStruct; + + #[async_trait] + impl TestTrait for TestStruct { + async fn run<const DUMMY: bool>(self) + where + Self: Sized, + { + } + } +} + +// https://github.com/dtolnay/async-trait/pull/125#pullrequestreview-491880881 +pub mod drop_order { + use crate::executor; + use async_trait::async_trait; + use std::sync::atomic::{AtomicBool, Ordering}; + + struct Flagger<'a>(&'a AtomicBool); + + impl Drop for Flagger<'_> { + fn drop(&mut self) { + self.0.fetch_xor(true, Ordering::AcqRel); + } + } + + #[async_trait] + trait Trait { + async fn async_trait(_: Flagger<'_>, flag: &AtomicBool); + } + + struct Struct; + + #[async_trait] + impl Trait for Struct { + async fn async_trait(_: Flagger<'_>, flag: &AtomicBool) { + flag.fetch_or(true, Ordering::AcqRel); + } + } + + async fn standalone(_: Flagger<'_>, flag: &AtomicBool) { + flag.fetch_or(true, Ordering::AcqRel); + } + + #[async_trait] + trait SelfTrait { + async fn async_trait(self, flag: &AtomicBool); + } + + #[async_trait] + impl SelfTrait for Flagger<'_> { + async fn async_trait(self, flag: &AtomicBool) { + flag.fetch_or(true, Ordering::AcqRel); + } + } + + #[test] + fn test_drop_order() { + // 0 : 0 ^ 1 = 1 | 1 = 1 (if flagger then block) + // 0 : 0 | 1 = 1 ^ 1 = 0 (if block then flagger) + + let flag = AtomicBool::new(false); + executor::block_on_simple(standalone(Flagger(&flag), &flag)); + assert!(!flag.load(Ordering::Acquire)); + + executor::block_on_simple(Struct::async_trait(Flagger(&flag), &flag)); + assert!(!flag.load(Ordering::Acquire)); + + executor::block_on_simple(Flagger(&flag).async_trait(&flag)); + assert!(!flag.load(Ordering::Acquire)); + } +} + +// https://github.com/dtolnay/async-trait/issues/145 +pub mod issue145 { + #![deny(clippy::type_complexity)] + + use async_trait::async_trait; + + #[async_trait] + pub trait ManageConnection: Sized + Send + Sync + 'static { + type Connection: Send + 'static; + type Error: Send + 'static; + + async fn connect(&self) -> Result<Self::Connection, Self::Error>; + } +} + +// https://github.com/dtolnay/async-trait/issues/147 +pub mod issue147 { + #![deny(clippy::let_unit_value)] + + use async_trait::async_trait; + + pub struct MyType; + + #[async_trait] + pub trait MyTrait { + async fn x(); + async fn y() -> (); + async fn z(); + } + + #[async_trait] + impl MyTrait for MyType { + async fn x() {} + async fn y() -> () {} + async fn z() { + unimplemented!() + } + } +} + +// https://github.com/dtolnay/async-trait/issues/149 +pub mod issue149 { + use async_trait::async_trait; + + pub struct Thing; + pub trait Ret {} + impl Ret for Thing {} + + pub async fn ok() -> &'static dyn Ret { + return &Thing; + } + + #[async_trait] + pub trait Trait { + async fn fail() -> &'static dyn Ret { + return &Thing; + } + } +} + +// https://github.com/dtolnay/async-trait/issues/152 +#[cfg(async_trait_nightly_testing)] +pub mod issue152 { + use async_trait::async_trait; + + #[async_trait] + trait Trait { + type Assoc; + + async fn f(&self) -> Self::Assoc; + } + + struct Struct; + + #[async_trait] + impl Trait for Struct { + type Assoc = impl Sized; + + async fn f(&self) -> Self::Assoc {} + } +} + +// https://github.com/dtolnay/async-trait/issues/154 +pub mod issue154 { + #![deny(clippy::items_after_statements)] + + use async_trait::async_trait; + + #[async_trait] + pub trait MyTrait { + async fn f(&self); + } + + pub struct Struct; + + #[async_trait] + impl MyTrait for Struct { + async fn f(&self) { + const MAX: u16 = 128; + println!("{}", MAX); + } + } +} + +// https://github.com/dtolnay/async-trait/issues/158 +pub mod issue158 { + use async_trait::async_trait; + + fn f() {} + + #[async_trait] + pub trait Trait { + async fn f(&self) { + self::f(); + } + } +} + +// https://github.com/dtolnay/async-trait/issues/161 +#[allow(clippy::mut_mut)] +pub mod issue161 { + use async_trait::async_trait; + use futures::future::FutureExt; + use std::sync::Arc; + + #[async_trait] + pub trait Trait { + async fn f(self: Arc<Self>); + } + + pub struct MyStruct(bool); + + #[async_trait] + impl Trait for MyStruct { + async fn f(self: Arc<Self>) { + futures::select! { + _ = async { + println!("{}", self.0); + }.fuse() => {} + } + } + } +} + +// https://github.com/dtolnay/async-trait/issues/169 +#[deny(where_clauses_object_safety)] +pub mod issue169 { + use async_trait::async_trait; + + #[async_trait] + pub trait Trait: ::core::marker::Sync { + async fn f(&self) {} + } + + pub fn test(_t: &dyn Trait) {} +} + +// https://github.com/dtolnay/async-trait/issues/177 +pub mod issue177 { + use async_trait::async_trait; + + #[async_trait] + pub trait Trait { + async fn foo(&self, _callback: impl FnMut(&str) + Send) {} + } + + pub struct Struct; + + #[async_trait] + impl Trait for Struct { + async fn foo(&self, _callback: impl FnMut(&str) + Send) {} + } +} + +// https://github.com/dtolnay/async-trait/issues/183 +pub mod issue183 { + #![deny(clippy::shadow_same)] + + use async_trait::async_trait; + + #[async_trait] + trait Foo { + async fn foo(_n: i32) {} + } +} + +// https://github.com/dtolnay/async-trait/issues/199 +pub mod issue199 { + use async_trait::async_trait; + use std::cell::Cell; + + struct IncrementOnDrop<'a>(&'a Cell<usize>); + + impl<'a> Drop for IncrementOnDrop<'a> { + fn drop(&mut self) { + self.0.set(self.0.get() + 1); + } + } + + #[async_trait(?Send)] + trait Trait { + async fn f(counter: &Cell<usize>, arg: IncrementOnDrop<'_>); + } + + struct Struct; + + #[async_trait(?Send)] + impl Trait for Struct { + async fn f(counter: &Cell<usize>, _: IncrementOnDrop<'_>) { + assert_eq!(counter.get(), 0); // second arg not dropped yet + } + } + + #[test] + fn test() { + let counter = Cell::new(0); + let future = Struct::f(&counter, IncrementOnDrop(&counter)); + assert_eq!(counter.get(), 0); + drop(future); + assert_eq!(counter.get(), 1); + } +} + +// https://github.com/dtolnay/async-trait/issues/204 +pub mod issue204 { + use async_trait::async_trait; + + #[async_trait] + pub trait Trait { + async fn f(arg: &impl Trait); + async fn g(arg: *const impl Trait); + } +} + +// https://github.com/dtolnay/async-trait/issues/210 +pub mod issue210 { + use async_trait::async_trait; + use std::sync::Arc; + + #[async_trait] + pub trait Trait { + async fn f(self: Arc<Self>) {} + } +} + +// https://github.com/dtolnay/async-trait/issues/226 +pub mod issue226 { + use async_trait::async_trait; + + #[async_trait] + pub trait Trait { + async fn cfg_param(&self, param: u8); + async fn cfg_param_wildcard(&self, _: u8); + async fn cfg_param_tuple(&self, (left, right): (u8, u8)); + } + + struct Struct; + + #[async_trait] + impl Trait for Struct { + async fn cfg_param(&self, #[cfg(any())] param: u8, #[cfg(all())] _unused: u8) {} + + async fn cfg_param_wildcard(&self, #[cfg(any())] _: u8, #[cfg(all())] _: u8) {} + + async fn cfg_param_tuple( + &self, + #[cfg(any())] (left, right): (u8, u8), + #[cfg(all())] (_left, _right): (u8, u8), + ) { + } + } +} + +// https://github.com/dtolnay/async-trait/issues/232 +pub mod issue232 { + use async_trait::async_trait; + + #[async_trait] + pub trait Generic<T> { + async fn take_ref(&self, thing: &T); + } + + pub struct One; + + #[async_trait] + impl<T> Generic<T> for One { + async fn take_ref(&self, _: &T) {} + } + + pub struct Two; + + #[async_trait] + impl<T: Sync> Generic<(T, T)> for Two { + async fn take_ref(&self, (a, b): &(T, T)) { + let _ = a; + let _ = b; + } + } + + pub struct Three; + + #[async_trait] + impl<T> Generic<(T, T, T)> for Three { + async fn take_ref(&self, (_a, _b, _c): &(T, T, T)) {} + } +} + +// https://github.com/dtolnay/async-trait/issues/234 +pub mod issue234 { + use async_trait::async_trait; + + pub struct Droppable; + + impl Drop for Droppable { + fn drop(&mut self) {} + } + + pub struct Tuple<T, U>(T, U); + + #[async_trait] + pub trait Trait { + async fn f(arg: Tuple<Droppable, i32>); + } + + pub struct UnderscorePattern; + + #[async_trait] + impl Trait for UnderscorePattern { + async fn f(Tuple(_, _int): Tuple<Droppable, i32>) {} + } + + pub struct DotDotPattern; + + #[async_trait] + impl Trait for DotDotPattern { + async fn f(Tuple { 1: _int, .. }: Tuple<Droppable, i32>) {} + } +} + +// https://github.com/dtolnay/async-trait/issues/236 +pub mod issue236 { + #![deny(clippy::async_yields_async)] + #![allow(clippy::manual_async_fn)] + + use async_trait::async_trait; + use std::future::{self, Future, Ready}; + + // Does not trigger the lint. + pub async fn async_fn() -> Ready<()> { + future::ready(()) + } + + #[allow(clippy::async_yields_async)] + pub fn impl_future_fn() -> impl Future<Output = Ready<()>> { + async { future::ready(()) } + } + + // The async_trait attribute turns the former into the latter, so we make it + // put its own allow(async_yeilds_async) to remain consistent with async fn. + #[async_trait] + pub trait Trait { + async fn f() -> Ready<()> { + future::ready(()) + } + } +} diff --git a/third_party/rust/async-trait/tests/ui/arg-implementation-detail.rs b/third_party/rust/async-trait/tests/ui/arg-implementation-detail.rs new file mode 100644 index 0000000000..b83aa72fcf --- /dev/null +++ b/third_party/rust/async-trait/tests/ui/arg-implementation-detail.rs @@ -0,0 +1,22 @@ +use async_trait::async_trait; + +pub struct Struct; + +#[async_trait] +pub trait Trait { + async fn f((_a, _b): (Struct, Struct)) { + // Expands to something like: + // + // fn f(__arg0: (Struct, Struct)) -> … { + // Box::pin(async move { + // let (_a, _b) = __arg0; + // … + // }) + // } + // + // but user's code must not be allowed to name that temporary argument: + let _ = __arg0; + } +} + +fn main() {} diff --git a/third_party/rust/async-trait/tests/ui/arg-implementation-detail.stderr b/third_party/rust/async-trait/tests/ui/arg-implementation-detail.stderr new file mode 100644 index 0000000000..e742688888 --- /dev/null +++ b/third_party/rust/async-trait/tests/ui/arg-implementation-detail.stderr @@ -0,0 +1,5 @@ +error[E0425]: cannot find value `__arg0` in this scope + --> tests/ui/arg-implementation-detail.rs:18:17 + | +18 | let _ = __arg0; + | ^^^^^^ not found in this scope diff --git a/third_party/rust/async-trait/tests/ui/bare-trait-object.rs b/third_party/rust/async-trait/tests/ui/bare-trait-object.rs new file mode 100644 index 0000000000..afcd6b44c3 --- /dev/null +++ b/third_party/rust/async-trait/tests/ui/bare-trait-object.rs @@ -0,0 +1,15 @@ +#![deny(bare_trait_objects)] + +use async_trait::async_trait; + +#[async_trait] +trait Trait { + async fn f(&self); +} + +#[async_trait] +impl Trait for Send + Sync { + async fn f(&self) {} +} + +fn main() {} diff --git a/third_party/rust/async-trait/tests/ui/bare-trait-object.stderr b/third_party/rust/async-trait/tests/ui/bare-trait-object.stderr new file mode 100644 index 0000000000..50b20484cb --- /dev/null +++ b/third_party/rust/async-trait/tests/ui/bare-trait-object.stderr @@ -0,0 +1,21 @@ +error: trait objects without an explicit `dyn` are deprecated + --> tests/ui/bare-trait-object.rs:11:16 + | +11 | impl Trait for Send + Sync { + | ^^^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> +note: the lint level is defined here + --> tests/ui/bare-trait-object.rs:1:9 + | +1 | #![deny(bare_trait_objects)] + | ^^^^^^^^^^^^^^^^^^ +help: use `dyn` + | +11 | impl Trait for dyn Send + Sync { + | +++ +help: alternatively use a blanket implementation to implement `Trait` for all types that also implement `Send + Sync` + | +11 | impl<T: Send + Sync> Trait for T { + | ++++++++++++++++ ~ diff --git a/third_party/rust/async-trait/tests/ui/consider-restricting.rs b/third_party/rust/async-trait/tests/ui/consider-restricting.rs new file mode 100644 index 0000000000..e23c8b1539 --- /dev/null +++ b/third_party/rust/async-trait/tests/ui/consider-restricting.rs @@ -0,0 +1,26 @@ +// https://github.com/rust-lang/rust/issues/93828 + +use async_trait::async_trait; + +pub trait IntoUrl {} + +#[async_trait] +pub trait ClientExt { + async fn publish<T: IntoUrl>(&self, url: T); +} + +struct Client; + +#[async_trait] +impl ClientExt for Client { + async fn publish<T: IntoUrl>(&self, url: T) {} +} + +struct Client2; + +#[async_trait] +impl ClientExt for Client2 { + async fn publish<T>(&self, url: T) {} +} + +fn main() {} diff --git a/third_party/rust/async-trait/tests/ui/consider-restricting.stderr b/third_party/rust/async-trait/tests/ui/consider-restricting.stderr new file mode 100644 index 0000000000..62ff894ed5 --- /dev/null +++ b/third_party/rust/async-trait/tests/ui/consider-restricting.stderr @@ -0,0 +1,33 @@ +error: future cannot be sent between threads safely + --> tests/ui/consider-restricting.rs:16:49 + | +16 | async fn publish<T: IntoUrl>(&self, url: T) {} + | ^^ future created by async block is not `Send` + | +note: captured value is not `Send` + --> tests/ui/consider-restricting.rs:16:41 + | +16 | async fn publish<T: IntoUrl>(&self, url: T) {} + | ^^^ has type `T` which is not `Send` + = note: required for the cast from `[async block@$DIR/tests/ui/consider-restricting.rs:16:49: 16:51]` to the object type `dyn Future<Output = ()> + Send` +help: consider further restricting this bound + | +16 | async fn publish<T: IntoUrl + std::marker::Send>(&self, url: T) {} + | +++++++++++++++++++ + +error: future cannot be sent between threads safely + --> tests/ui/consider-restricting.rs:23:40 + | +23 | async fn publish<T>(&self, url: T) {} + | ^^ future created by async block is not `Send` + | +note: captured value is not `Send` + --> tests/ui/consider-restricting.rs:23:32 + | +23 | async fn publish<T>(&self, url: T) {} + | ^^^ has type `T` which is not `Send` + = note: required for the cast from `[async block@$DIR/tests/ui/consider-restricting.rs:23:40: 23:42]` to the object type `dyn Future<Output = ()> + Send` +help: consider further restricting this bound + | +23 | async fn publish<T + std::marker::Send>(&self, url: T) {} + | +++++++++++++++++++ diff --git a/third_party/rust/async-trait/tests/ui/delimiter-span.rs b/third_party/rust/async-trait/tests/ui/delimiter-span.rs new file mode 100644 index 0000000000..51a44a24b5 --- /dev/null +++ b/third_party/rust/async-trait/tests/ui/delimiter-span.rs @@ -0,0 +1,24 @@ +#![allow(unused_macro_rules)] + +use async_trait::async_trait; + +macro_rules! picky { + ($(t:tt)*) => {}; +} + +#[async_trait] +trait Trait { + async fn method(); +} + +struct Struct; + +#[async_trait] +impl Trait for Struct { + async fn method() { + picky!({ 123, self }); + picky!({ 123 }); + } +} + +fn main() {} diff --git a/third_party/rust/async-trait/tests/ui/delimiter-span.stderr b/third_party/rust/async-trait/tests/ui/delimiter-span.stderr new file mode 100644 index 0000000000..f03da4c97c --- /dev/null +++ b/third_party/rust/async-trait/tests/ui/delimiter-span.stderr @@ -0,0 +1,21 @@ +error: no rules expected the token `{` + --> tests/ui/delimiter-span.rs:19:16 + | +5 | macro_rules! picky { + | ------------------ when calling this macro +... +19 | picky!({ 123, self }); + | ^ no rules expected this token in macro call + | + = note: while trying to match sequence start + +error: no rules expected the token `{` + --> tests/ui/delimiter-span.rs:20:16 + | +5 | macro_rules! picky { + | ------------------ when calling this macro +... +20 | picky!({ 123 }); + | ^ no rules expected this token in macro call + | + = note: while trying to match sequence start diff --git a/third_party/rust/async-trait/tests/ui/lifetime-defined-here.rs b/third_party/rust/async-trait/tests/ui/lifetime-defined-here.rs new file mode 100644 index 0000000000..237cf667f1 --- /dev/null +++ b/third_party/rust/async-trait/tests/ui/lifetime-defined-here.rs @@ -0,0 +1,23 @@ +use async_trait::async_trait; + +#[async_trait] +trait Foo { + async fn bar(&self, x: &str, y: &'_ str) -> &'static str; +} + +struct S(String); + +#[async_trait] +impl Foo for S { + async fn bar(&self, x: &str, y: &'_ str) -> &'static str { + if false { + &self.0 + } else if false { + x + } else { + y + } + } +} + +fn main() {} diff --git a/third_party/rust/async-trait/tests/ui/lifetime-defined-here.stderr b/third_party/rust/async-trait/tests/ui/lifetime-defined-here.stderr new file mode 100644 index 0000000000..9ffef5b4ab --- /dev/null +++ b/third_party/rust/async-trait/tests/ui/lifetime-defined-here.stderr @@ -0,0 +1,29 @@ +error: lifetime may not live long enough + --> tests/ui/lifetime-defined-here.rs:12:49 + | +12 | async fn bar(&self, x: &str, y: &'_ str) -> &'static str { + | - ^^^^^^^^^^^^ type annotation requires that `'life0` must outlive `'static` + | | + | lifetime `'life0` defined here + +error: lifetime may not live long enough + --> tests/ui/lifetime-defined-here.rs:12:49 + | +12 | async fn bar(&self, x: &str, y: &'_ str) -> &'static str { + | - ^^^^^^^^^^^^ type annotation requires that `'life1` must outlive `'static` + | | + | lifetime `'life1` defined here + +error: lifetime may not live long enough + --> tests/ui/lifetime-defined-here.rs:12:49 + | +12 | async fn bar(&self, x: &str, y: &'_ str) -> &'static str { + | -- ^^^^^^^^^^^^ type annotation requires that `'life2` must outlive `'static` + | | + | lifetime `'life2` defined here + +help: the following changes may resolve your lifetime errors + | + = help: replace `'life0` with `'static` + = help: replace `'life1` with `'static` + = help: replace `'life2` with `'static` diff --git a/third_party/rust/async-trait/tests/ui/lifetime-span.rs b/third_party/rust/async-trait/tests/ui/lifetime-span.rs new file mode 100644 index 0000000000..01981e6de4 --- /dev/null +++ b/third_party/rust/async-trait/tests/ui/lifetime-span.rs @@ -0,0 +1,36 @@ +use async_trait::async_trait; + +struct A; +struct B; + +#[async_trait] +pub trait Trait<'r> { + async fn method(&'r self); +} + +#[async_trait] +impl Trait for A { + async fn method(&self) {} +} + +#[async_trait] +impl<'r> Trait<'r> for B { + async fn method(&self) {} +} + +#[async_trait] +pub trait Trait2 { + async fn method<'r>(&'r self); +} + +#[async_trait] +impl Trait2 for A { + async fn method(&self) {} +} + +#[async_trait] +impl<'r> Trait2<'r> for B { + async fn method(&'r self) {} +} + +fn main() {} diff --git a/third_party/rust/async-trait/tests/ui/lifetime-span.stderr b/third_party/rust/async-trait/tests/ui/lifetime-span.stderr new file mode 100644 index 0000000000..999da04c30 --- /dev/null +++ b/third_party/rust/async-trait/tests/ui/lifetime-span.stderr @@ -0,0 +1,25 @@ +error[E0726]: implicit elided lifetime not allowed here + --> tests/ui/lifetime-span.rs:12:6 + | +12 | impl Trait for A { + | ^^^^^ expected lifetime parameter + | + = note: assuming a `'static` lifetime... +help: indicate the anonymous lifetime + | +12 | impl Trait<'_> for A { + | ++++ + +error[E0107]: this trait takes 0 lifetime arguments but 1 lifetime argument was supplied + --> tests/ui/lifetime-span.rs:32:10 + | +32 | impl<'r> Trait2<'r> for B { + | ^^^^^^---- help: remove these generics + | | + | expected 0 lifetime arguments + | +note: trait defined here, with 0 lifetime parameters + --> tests/ui/lifetime-span.rs:22:11 + | +22 | pub trait Trait2 { + | ^^^^^^ diff --git a/third_party/rust/async-trait/tests/ui/missing-async-in-impl.rs b/third_party/rust/async-trait/tests/ui/missing-async-in-impl.rs new file mode 100644 index 0000000000..3a5f58c3ac --- /dev/null +++ b/third_party/rust/async-trait/tests/ui/missing-async-in-impl.rs @@ -0,0 +1,15 @@ +use async_trait::async_trait; + +#[async_trait] +pub trait Trait { + async fn method(); +} + +pub struct Struct; + +#[async_trait] +impl Trait for Struct { + fn method() {} +} + +fn main() {} diff --git a/third_party/rust/async-trait/tests/ui/missing-async-in-impl.stderr b/third_party/rust/async-trait/tests/ui/missing-async-in-impl.stderr new file mode 100644 index 0000000000..e461c85d8d --- /dev/null +++ b/third_party/rust/async-trait/tests/ui/missing-async-in-impl.stderr @@ -0,0 +1,8 @@ +error[E0195]: lifetime parameters or bounds on method `method` do not match the trait declaration + --> tests/ui/missing-async-in-impl.rs:12:14 + | +5 | async fn method(); + | -------- lifetimes in impl do not match this method in trait +... +12 | fn method() {} + | ^ lifetimes do not match method in trait diff --git a/third_party/rust/async-trait/tests/ui/missing-async-in-trait.rs b/third_party/rust/async-trait/tests/ui/missing-async-in-trait.rs new file mode 100644 index 0000000000..56fea7a1f8 --- /dev/null +++ b/third_party/rust/async-trait/tests/ui/missing-async-in-trait.rs @@ -0,0 +1,15 @@ +use async_trait::async_trait; + +#[async_trait] +pub trait Trait { + fn method(); +} + +pub struct Struct; + +#[async_trait] +impl Trait for Struct { + async fn method() {} +} + +fn main() {} diff --git a/third_party/rust/async-trait/tests/ui/missing-async-in-trait.stderr b/third_party/rust/async-trait/tests/ui/missing-async-in-trait.stderr new file mode 100644 index 0000000000..c92c38da5e --- /dev/null +++ b/third_party/rust/async-trait/tests/ui/missing-async-in-trait.stderr @@ -0,0 +1,8 @@ +error[E0195]: lifetime parameters or bounds on method `method` do not match the trait declaration + --> tests/ui/missing-async-in-trait.rs:12:14 + | +5 | fn method(); + | - lifetimes in impl do not match this method in trait +... +12 | async fn method() {} + | ^^^^^^^^ lifetimes do not match method in trait diff --git a/third_party/rust/async-trait/tests/ui/missing-body.rs b/third_party/rust/async-trait/tests/ui/missing-body.rs new file mode 100644 index 0000000000..f3e1126d1d --- /dev/null +++ b/third_party/rust/async-trait/tests/ui/missing-body.rs @@ -0,0 +1,15 @@ +use async_trait::async_trait; + +#[async_trait] +trait Trait { + async fn f(&self); +} + +struct Thing; + +#[async_trait] +impl Trait for Thing { + async fn f(&self); +} + +fn main() {} diff --git a/third_party/rust/async-trait/tests/ui/missing-body.stderr b/third_party/rust/async-trait/tests/ui/missing-body.stderr new file mode 100644 index 0000000000..e6ddb425f9 --- /dev/null +++ b/third_party/rust/async-trait/tests/ui/missing-body.stderr @@ -0,0 +1,7 @@ +error: associated function in `impl` without body + --> tests/ui/missing-body.rs:12:5 + | +12 | async fn f(&self); + | ^^^^^^^^^^^^^^^^^- + | | + | help: provide a definition for the function: `{ <body> }` diff --git a/third_party/rust/async-trait/tests/ui/must-use.rs b/third_party/rust/async-trait/tests/ui/must-use.rs new file mode 100644 index 0000000000..7ad0d9bf33 --- /dev/null +++ b/third_party/rust/async-trait/tests/ui/must-use.rs @@ -0,0 +1,21 @@ +#![deny(unused_must_use)] + +use async_trait::async_trait; + +#[async_trait] +trait Interface { + async fn f(&self); +} + +struct Thing; + +#[async_trait] +impl Interface for Thing { + async fn f(&self) {} +} + +pub async fn f() { + Thing.f(); +} + +fn main() {} diff --git a/third_party/rust/async-trait/tests/ui/must-use.stderr b/third_party/rust/async-trait/tests/ui/must-use.stderr new file mode 100644 index 0000000000..fd6fc31d60 --- /dev/null +++ b/third_party/rust/async-trait/tests/ui/must-use.stderr @@ -0,0 +1,11 @@ +error: unused return value of `Interface::f` that must be used + --> tests/ui/must-use.rs:18:5 + | +18 | Thing.f(); + | ^^^^^^^^^ + | +note: the lint level is defined here + --> tests/ui/must-use.rs:1:9 + | +1 | #![deny(unused_must_use)] + | ^^^^^^^^^^^^^^^ diff --git a/third_party/rust/async-trait/tests/ui/self-span.rs b/third_party/rust/async-trait/tests/ui/self-span.rs new file mode 100644 index 0000000000..b01f247032 --- /dev/null +++ b/third_party/rust/async-trait/tests/ui/self-span.rs @@ -0,0 +1,30 @@ +use async_trait::async_trait; + +pub struct S {} + +pub enum E { + V {}, +} + +#[async_trait] +pub trait Trait { + async fn method(self); +} + +#[async_trait] +impl Trait for S { + async fn method(self) { + let _: () = self; + let _: Self = Self; + } +} + +#[async_trait] +impl Trait for E { + async fn method(self) { + let _: () = self; + let _: Self = Self::V; + } +} + +fn main() {} diff --git a/third_party/rust/async-trait/tests/ui/self-span.stderr b/third_party/rust/async-trait/tests/ui/self-span.stderr new file mode 100644 index 0000000000..8743e57934 --- /dev/null +++ b/third_party/rust/async-trait/tests/ui/self-span.stderr @@ -0,0 +1,27 @@ +error[E0308]: mismatched types + --> tests/ui/self-span.rs:17:21 + | +17 | let _: () = self; + | -- ^^^^ expected `()`, found struct `S` + | | + | expected due to this + +error: the `Self` constructor can only be used with tuple or unit structs + --> tests/ui/self-span.rs:18:23 + | +18 | let _: Self = Self; + | ^^^^ help: use curly brackets: `Self { /* fields */ }` + +error[E0308]: mismatched types + --> tests/ui/self-span.rs:25:21 + | +25 | let _: () = self; + | -- ^^^^ expected `()`, found enum `E` + | | + | expected due to this + +error[E0533]: expected value, found struct variant `Self::V` + --> tests/ui/self-span.rs:26:23 + | +26 | let _: Self = Self::V; + | ^^^^^^^ not a value diff --git a/third_party/rust/async-trait/tests/ui/send-not-implemented.rs b/third_party/rust/async-trait/tests/ui/send-not-implemented.rs new file mode 100644 index 0000000000..d8883fb498 --- /dev/null +++ b/third_party/rust/async-trait/tests/ui/send-not-implemented.rs @@ -0,0 +1,22 @@ +use async_trait::async_trait; +use std::sync::Mutex; + +async fn f() {} + +#[async_trait] +trait Test { + async fn test(&self) { + let mutex = Mutex::new(()); + let _guard = mutex.lock().unwrap(); + f().await; + } + + async fn test_ret(&self) -> bool { + let mutex = Mutex::new(()); + let _guard = mutex.lock().unwrap(); + f().await; + true + } +} + +fn main() {} diff --git a/third_party/rust/async-trait/tests/ui/send-not-implemented.stderr b/third_party/rust/async-trait/tests/ui/send-not-implemented.stderr new file mode 100644 index 0000000000..d68fc43c36 --- /dev/null +++ b/third_party/rust/async-trait/tests/ui/send-not-implemented.stderr @@ -0,0 +1,47 @@ +error: future cannot be sent between threads safely + --> tests/ui/send-not-implemented.rs:8:26 + | +8 | async fn test(&self) { + | __________________________^ +9 | | let mutex = Mutex::new(()); +10 | | let _guard = mutex.lock().unwrap(); +11 | | f().await; +12 | | } + | |_____^ future created by async block is not `Send` + | + = help: within `[async block@$DIR/tests/ui/send-not-implemented.rs:8:26: 12:6]`, the trait `Send` is not implemented for `MutexGuard<'_, ()>` +note: future is not `Send` as this value is used across an await + --> tests/ui/send-not-implemented.rs:11:12 + | +10 | let _guard = mutex.lock().unwrap(); + | ------ has type `MutexGuard<'_, ()>` which is not `Send` +11 | f().await; + | ^^^^^^ await occurs here, with `_guard` maybe used later +12 | } + | - `_guard` is later dropped here + = note: required for the cast from `[async block@$DIR/tests/ui/send-not-implemented.rs:8:26: 12:6]` to the object type `dyn Future<Output = ()> + Send` + +error: future cannot be sent between threads safely + --> tests/ui/send-not-implemented.rs:14:38 + | +14 | async fn test_ret(&self) -> bool { + | ______________________________________^ +15 | | let mutex = Mutex::new(()); +16 | | let _guard = mutex.lock().unwrap(); +17 | | f().await; +18 | | true +19 | | } + | |_____^ future created by async block is not `Send` + | + = help: within `[async block@$DIR/tests/ui/send-not-implemented.rs:14:38: 19:6]`, the trait `Send` is not implemented for `MutexGuard<'_, ()>` +note: future is not `Send` as this value is used across an await + --> tests/ui/send-not-implemented.rs:17:12 + | +16 | let _guard = mutex.lock().unwrap(); + | ------ has type `MutexGuard<'_, ()>` which is not `Send` +17 | f().await; + | ^^^^^^ await occurs here, with `_guard` maybe used later +18 | true +19 | } + | - `_guard` is later dropped here + = note: required for the cast from `[async block@$DIR/tests/ui/send-not-implemented.rs:14:38: 19:6]` to the object type `dyn Future<Output = bool> + Send` diff --git a/third_party/rust/async-trait/tests/ui/unreachable.rs b/third_party/rust/async-trait/tests/ui/unreachable.rs new file mode 100644 index 0000000000..cac2826444 --- /dev/null +++ b/third_party/rust/async-trait/tests/ui/unreachable.rs @@ -0,0 +1,20 @@ +#![deny(warnings)] + +use async_trait::async_trait; + +#[async_trait] +pub trait Trait { + async fn f() { + unimplemented!() + } +} + +#[async_trait] +pub trait TraitFoo { + async fn f() { + let _y = unimplemented!(); + let _z = _y; + } +} + +fn main() {} diff --git a/third_party/rust/async-trait/tests/ui/unreachable.stderr b/third_party/rust/async-trait/tests/ui/unreachable.stderr new file mode 100644 index 0000000000..08595e5af7 --- /dev/null +++ b/third_party/rust/async-trait/tests/ui/unreachable.stderr @@ -0,0 +1,14 @@ +error: unreachable statement + --> tests/ui/unreachable.rs:16:9 + | +15 | let _y = unimplemented!(); + | ---------------- any code following this expression is unreachable +16 | let _z = _y; + | ^^^^^^^^^^^^ unreachable statement + | +note: the lint level is defined here + --> tests/ui/unreachable.rs:1:9 + | +1 | #![deny(warnings)] + | ^^^^^^^^ + = note: `#[deny(unreachable_code)]` implied by `#[deny(warnings)]` diff --git a/third_party/rust/async-trait/tests/ui/unsupported-self.rs b/third_party/rust/async-trait/tests/ui/unsupported-self.rs new file mode 100644 index 0000000000..5868c614ad --- /dev/null +++ b/third_party/rust/async-trait/tests/ui/unsupported-self.rs @@ -0,0 +1,15 @@ +use async_trait::async_trait; + +#[async_trait] +pub trait Trait { + async fn method(); +} + +#[async_trait] +impl Trait for &'static str { + async fn method() { + let _ = Self; + } +} + +fn main() {} diff --git a/third_party/rust/async-trait/tests/ui/unsupported-self.stderr b/third_party/rust/async-trait/tests/ui/unsupported-self.stderr new file mode 100644 index 0000000000..14939459e1 --- /dev/null +++ b/third_party/rust/async-trait/tests/ui/unsupported-self.stderr @@ -0,0 +1,5 @@ +error: the `Self` constructor can only be used with tuple or unit structs + --> tests/ui/unsupported-self.rs:11:17 + | +11 | let _ = Self; + | ^^^^ |