Skip to content

Add test for async specialization #29

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 16, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ matrix:
include:
- rust: nightly-2019-09-10
script: cargo test
env: RUSTFLAGS='--cfg async_trait_nightly_testing'
- rust: stable
script: cargo check
35 changes: 35 additions & 0 deletions tests/executor/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
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).
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"),
}
}
51 changes: 51 additions & 0 deletions tests/test.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
#![cfg_attr(async_trait_nightly_testing, feature(specialization))]

use async_trait::async_trait;

pub mod executor;

#[async_trait]
trait Trait {
type Assoc;
Expand Down Expand Up @@ -251,3 +255,50 @@ mod issue23 {

fn do_something<T>(_: &mut T) {}
}

// https://github.com/dtolnay/async-trait/issues/25
#[cfg(async_trait_nightly_testing)]
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");
}
}