Skip to content

Commit

Permalink
futures-macro: improve diagnostics on type mismatch (#2433)
Browse files Browse the repository at this point in the history
  • Loading branch information
taiki-e committed May 10, 2021
1 parent 5ea04ca commit 961af12
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 12 deletions.
2 changes: 1 addition & 1 deletion futures-macro/Cargo.toml
Expand Up @@ -23,4 +23,4 @@ autocfg = "1"
proc-macro2 = "1.0"
proc-macro-hack = "0.5.19"
quote = "1.0"
syn = { version = "1.0", features = ["full"] }
syn = { version = "1.0.56", features = ["full"] }
45 changes: 34 additions & 11 deletions futures-macro/src/executor.rs
@@ -1,5 +1,6 @@
use proc_macro::TokenStream;
use quote::quote;
use proc_macro2::Span;
use quote::{quote, quote_spanned, ToTokens};

pub(crate) fn test(args: TokenStream, item: TokenStream) -> TokenStream {
if !args.is_empty() {
Expand All @@ -9,23 +10,45 @@ pub(crate) fn test(args: TokenStream, item: TokenStream) -> TokenStream {
}

let mut input = syn::parse_macro_input!(item as syn::ItemFn);
let attrs = &input.attrs;
let vis = &input.vis;
let sig = &mut input.sig;
let body = &input.block;

if sig.asyncness.take().is_none() {
return syn::Error::new_spanned(sig.fn_token, "Only async functions are supported")
if input.sig.asyncness.take().is_none() {
return syn::Error::new_spanned(input.sig.fn_token, "Only async functions are supported")
.to_compile_error()
.into();
}

// If type mismatch occurs, the current rustc points to the last statement.
let (last_stmt_start_span, last_stmt_end_span) = {
let mut last_stmt = input
.block
.stmts
.last()
.map(ToTokens::into_token_stream)
.unwrap_or_default()
.into_iter();
// `Span` on stable Rust has a limitation that only points to the first
// token, not the whole tokens. We can work around this limitation by
// using the first/last span of the tokens like
// `syn::Error::new_spanned` does.
let start = last_stmt.next().map_or_else(Span::call_site, |t| t.span());
let end = last_stmt.last().map_or(start, |t| t.span());
(start, end)
};

let path = quote_spanned! {last_stmt_start_span=>
::futures_test::__private
};
let body = &input.block;
input.block.stmts = vec![syn::Stmt::Expr(
syn::parse2(quote_spanned! {last_stmt_end_span=>
#path::block_on(async #body)
})
.unwrap(),
)];

let gen = quote! {
#[::core::prelude::v1::test]
#(#attrs)*
#vis #sig {
::futures_test::__private::block_on(async move #body)
}
#input
};

gen.into()
Expand Down
5 changes: 5 additions & 0 deletions futures/tests/test_macro.rs
Expand Up @@ -13,3 +13,8 @@ async fn it_is_being_run() {
let fut = async { false };
assert!(fut.await);
}

#[futures_test::test]
async fn return_ty() -> Result<(), ()> {
Ok(())
}

0 comments on commit 961af12

Please sign in to comment.