Skip to content

Commit

Permalink
Update proc-macro2, syn, and quote to 1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
taiki-e committed Aug 7, 2019
1 parent b342e91 commit 65e300c
Show file tree
Hide file tree
Showing 7 changed files with 53 additions and 77 deletions.
6 changes: 3 additions & 3 deletions futures-async-stream-macro/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ proc-macro = true
[features]

[dependencies]
proc-macro2 = "0.4.13"
quote = "0.6.8"
syn = { version = "0.15.41", features = ["full", "visit-mut"] }
proc-macro2-next = "1.0.0-rc1"
quote-next = "1.0.0-rc1" # https://github.com/dtolnay/quote/issues/124
syn-next = { version = "1.0.0-rc2", features = ["full", "visit-mut"] } # https://github.com/dtolnay/syn/issues/687
8 changes: 5 additions & 3 deletions futures-async-stream-macro/src/elision.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use syn::{
punctuated::Punctuated,
token::Comma,
visit_mut::{self, VisitMut},
ArgSelfRef, FnArg, GenericArgument, GenericParam, Lifetime, LifetimeDef, TypeReference,
FnArg, GenericArgument, GenericParam, Lifetime, LifetimeDef, Receiver, TypeReference,
};

pub(super) fn unelide_lifetimes(
Expand Down Expand Up @@ -54,8 +54,10 @@ impl<'a> UnelideLifetimes<'a> {
}

impl VisitMut for UnelideLifetimes<'_> {
fn visit_arg_self_ref_mut(&mut self, arg: &mut ArgSelfRef) {
self.visit_opt_lifetime(&mut arg.lifetime);
fn visit_receiver_mut(&mut self, receiver: &mut Receiver) {
if let Some((_, lifetime)) = &mut receiver.reference {
self.visit_opt_lifetime(lifetime);
}
}

fn visit_type_reference_mut(&mut self, ty: &mut TypeReference) {
Expand Down
4 changes: 1 addition & 3 deletions futures-async-stream-macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ extern crate proc_macro;

use proc_macro::{Delimiter, Group, TokenStream, TokenTree};
use quote::ToTokens;
use syn::{Expr, ExprForLoop};
use syn::{parse::Nothing, Expr, ExprForLoop};

#[macro_use]
mod utils;
Expand All @@ -19,8 +19,6 @@ mod elision;
mod stream;
mod visitor;

use crate::utils::Nothing;

/// Processes streams using a for loop.
#[proc_macro_attribute]
pub fn for_await(args: TokenStream, input: TokenStream) -> TokenStream {
Expand Down
68 changes: 29 additions & 39 deletions futures-async-stream-macro/src/stream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ use syn::{
parse::{Parse, ParseStream},
token,
visit_mut::VisitMut,
ArgCaptured, Attribute, Block, Expr, FnArg, FnDecl, Ident, ItemFn, MethodSig, Pat, PatIdent,
Result, ReturnType, Token, TraitItemMethod, Type, TypeTuple, Visibility,
Attribute, Block, Expr, FnArg, Ident, ItemFn, Pat, PatIdent, PatType, Result, ReturnType,
Signature, Token, TraitItemMethod, Type, TypeTuple, Visibility,
};

use crate::{
Expand Down Expand Up @@ -107,27 +107,14 @@ impl Parse for Args {
struct FnSig {
attrs: Vec<Attribute>,
vis: Visibility,
sig: MethodSig,
sig: Signature,
block: Block,
semi: Option<Token![;]>,
}

impl From<ItemFn> for FnSig {
fn from(item: ItemFn) -> Self {
Self {
attrs: item.attrs,
vis: item.vis,
sig: MethodSig {
constness: item.constness,
asyncness: item.asyncness,
unsafety: item.unsafety,
abi: item.abi,
ident: item.ident,
decl: *item.decl,
},
block: *item.block,
semi: None,
}
Self { attrs: item.attrs, vis: item.vis, sig: item.sig, block: *item.block, semi: None }
}
}

Expand Down Expand Up @@ -164,15 +151,15 @@ fn parse_async_stream_fn(args: TokenStream, input: TokenStream) -> Result<TokenS
if let Some(constness) = item.sig.constness {
return Err(error!(constness, "async stream may not be const"));
}
if let Some(variadic) = item.sig.decl.variadic {
if let Some(variadic) = item.sig.variadic {
return Err(error!(variadic, "async stream may not be variadic"));
}

if item.sig.asyncness.is_none() {
return Err(error!(item.sig.decl.fn_token, "async stream must be declared as async"));
return Err(error!(item.sig.fn_token, "async stream must be declared as async"));
}

if let ReturnType::Type(_, ty) = &item.sig.decl.output {
if let ReturnType::Type(_, ty) = &item.sig.output {
match &**ty {
Type::Tuple(TypeTuple { elems, .. }) if elems.is_empty() => {}
_ => return Err(error!(ty, "async stream must return the unit type")),
Expand All @@ -184,8 +171,7 @@ fn parse_async_stream_fn(args: TokenStream, input: TokenStream) -> Result<TokenS

fn expand_async_stream_fn(item: FnSig, args: &Args) -> TokenStream {
let FnSig { attrs, vis, sig, mut block, semi } = item;
let MethodSig { unsafety, abi, ident, decl, .. } = sig;
let FnDecl { inputs, mut generics, fn_token, .. } = decl;
let Signature { unsafety, abi, fn_token, ident, mut generics, inputs, .. } = sig;
let where_clause = &generics.where_clause;

// Desugar `async fn`
Expand All @@ -212,29 +198,33 @@ fn expand_async_stream_fn(item: FnSig, args: &Args) -> TokenStream {
let mut patterns = Vec::new();
let mut temp_bindings = Vec::new();
for (i, input) in inputs.into_iter().enumerate() {
match input {
FnArg::Captured(ArgCaptured { pat: Pat::Ident(ref pat), .. })
if pat.ident == "self" =>
{
if let FnArg::Typed(PatType { attrs, pat, ty, colon_token }) = input {
let captured_naturally = match &*pat {
// `self: Box<Self>` will get captured naturally
inputs_no_patterns.push(input);
}
FnArg::Captured(ArgCaptured {
pat: pat @ Pat::Ident(PatIdent { by_ref: Some(_), .. }),
ty,
colon_token,
}) => {
Pat::Ident(pat) if pat.ident == "self" => true,
Pat::Ident(PatIdent { by_ref: Some(_), .. }) => false,
// Other arguments get captured naturally
_ => true,
};
if captured_naturally {
inputs_no_patterns.push(FnArg::Typed(PatType { attrs, pat, ty, colon_token }));
continue;
} else {
// `ref a: B` (or some similar pattern)
patterns.push(pat);
let ident = Ident::new(&format!("__arg_{}", i), Span::call_site());
temp_bindings.push(ident.clone());
let pat = PatIdent { by_ref: None, mutability: None, ident, subpat: None }.into();
inputs_no_patterns.push(ArgCaptured { pat, ty, colon_token }.into());
}
_ => {
// Other arguments get captured naturally
inputs_no_patterns.push(input);
let pat = Box::new(Pat::Ident(PatIdent {
attrs: Vec::new(),
by_ref: None,
mutability: None,
ident,
subpat: None,
}));
inputs_no_patterns.push(PatType { attrs, pat, ty, colon_token }.into());
}
} else {
inputs_no_patterns.push(input);
}
}

Expand Down
18 changes: 2 additions & 16 deletions futures-async-stream-macro/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@ use std::mem;

use proc_macro2::{Span, TokenStream, TokenTree};
use quote::ToTokens;
use syn::{
parse::{Parse, ParseStream},
punctuated::Punctuated,
token, Expr, ExprTuple, ExprVerbatim, Result,
};
use syn::{punctuated::Punctuated, token, Expr, ExprTuple};

pub(crate) fn first_last<T: ToTokens>(tokens: &T) -> (Span, Span) {
let mut spans = TokenStream::new();
Expand Down Expand Up @@ -44,7 +40,7 @@ pub(crate) fn replace_expr<F>(this: &mut Expr, f: F)
where
F: FnOnce(Expr) -> Expr,
{
*this = f(mem::replace(this, Expr::Verbatim(ExprVerbatim { tts: TokenStream::new() })));
*this = f(mem::replace(this, Expr::Verbatim(TokenStream::new())));
}

pub(super) fn replace_boxed_expr<F>(expr: &mut Option<Box<Expr>>, f: F)
Expand All @@ -60,16 +56,6 @@ where
}
}

// See https://github.com/dtolnay/syn/commit/82a3aed7ecfd07fc2f7f322b01d2413ffea6c5e7
/// An empty syntax tree node that consumes no tokens when parsed.
pub(crate) struct Nothing;

impl Parse for Nothing {
fn parse(_input: ParseStream<'_>) -> Result<Self> {
Ok(Nothing)
}
}

macro_rules! error {
($span:expr, $msg:expr) => {
syn::Error::new_spanned($span, $msg)
Expand Down
20 changes: 8 additions & 12 deletions futures-async-stream-macro/src/visitor.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
use quote::{quote, quote_spanned};
use syn::{
parse::Nothing,
spanned::Spanned,
visit_mut::{self, VisitMut},
Expr, ExprCall, ExprField, ExprForLoop, ExprYield, Item, Member,
Expr, ExprAwait, ExprCall, ExprForLoop, ExprYield, Item,
};

use crate::{
async_stream_block,
utils::{expr_compile_error, replace_boxed_expr, replace_expr, Nothing},
utils::{expr_compile_error, replace_boxed_expr, replace_expr},
};

pub(crate) use Scope::{Closure, Future, Stream};
Expand Down Expand Up @@ -56,7 +57,7 @@ impl Visitor {
return;
}
let attr = attrs.pop().unwrap();
if let Err(e) = syn::parse2::<Nothing>(attr.tts) {
if let Err(e) = syn::parse2::<Nothing>(attr.tokens) {
*expr = expr_compile_error(&e);
return;
}
Expand Down Expand Up @@ -135,7 +136,7 @@ impl Visitor {
if let Expr::Macro(mut expr) = expr {
if expr.mac.path.is_ident("async_stream_block") {
let mut e: ExprCall =
syn::parse(async_stream_block(expr.mac.tts.into())).unwrap();
syn::parse(async_stream_block(expr.mac.tokens.into())).unwrap();
e.attrs.append(&mut expr.attrs);
Expr::Call(e)
} else {
Expand All @@ -157,13 +158,8 @@ impl Visitor {
return;
}

if let Expr::Field(ExprField { base, member, .. }) = expr {
match &member {
Member::Named(x) if x == "await" => {}
_ => return,
}

*expr = syn::parse2(quote_spanned! { member.span() => {
if let Expr::Await(ExprAwait { base, await_token, .. }) = expr {
*expr = syn::parse2(quote_spanned! { await_token.span() => {
let mut __pinned = #base;
loop {
if let ::futures_async_stream::core_reexport::task::Poll::Ready(x) =
Expand Down Expand Up @@ -200,7 +196,7 @@ impl VisitMut for Visitor {
visit_mut::visit_expr_mut(self, expr);
match expr {
Expr::Yield(expr) => self.visit_yield(expr),
Expr::Field(_) => self.visit_await(expr),
Expr::Await(_) => self.visit_await(expr),
Expr::ForLoop(_) => self.visit_for_loop(expr),
Expr::Macro(_) => self.visit_macro(expr),
_ => {}
Expand Down
6 changes: 5 additions & 1 deletion tests/ui/invalid-function.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ error: async stream may not be const
9 | const fn constness() {} //~ ERROR async stream may not be const
| ^^^^^

error: async stream must be declared as async
error: expected `:`
--> $DIR/invalid-function.rs:11:1
|
11 | #[async_stream(item = ())]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^

error: async stream must be declared as async
--> $DIR/invalid-function.rs:15:1
Expand Down

0 comments on commit 65e300c

Please sign in to comment.