Skip to content

Commit

Permalink
Merge #5
Browse files Browse the repository at this point in the history
5: Update proc-macro2, syn, and quote to 1.0 r=taiki-e a=taiki-e

Tracking issues:
* quote: dtolnay/quote#124
* syn: dtolnay/syn#687

Co-authored-by: Taiki Endo <te316e89@gmail.com>
  • Loading branch information
bors[bot] and taiki-e committed Aug 13, 2019
2 parents f971b1e + 822909c commit 8f919c5
Show file tree
Hide file tree
Showing 11 changed files with 67 additions and 92 deletions.
1 change: 0 additions & 1 deletion ci/azure-test.yml
Expand Up @@ -33,6 +33,5 @@ jobs:

- script: |
cargo update -Zminimal-versions
cat Cargo.lock
cargo check --all --all-features
displayName: cargo check -Zminimal-versions
6 changes: 3 additions & 3 deletions futures-async-stream-macro/Cargo.toml
Expand Up @@ -18,6 +18,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 = "1.0"
quote = "1.0"
syn = { version = "1.0", features = ["full", "visit-mut"] }
8 changes: 5 additions & 3 deletions futures-async-stream-macro/src/elision.rs
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
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
74 changes: 32 additions & 42 deletions futures-async-stream-macro/src/stream.rs
@@ -1,11 +1,11 @@
use proc_macro2::{Span, TokenStream};
use quote::{quote, ToTokens};
use proc_macro2::TokenStream;
use quote::{format_ident, quote, ToTokens};
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, 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());
let ident = format_ident!("__arg_{}", i);
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
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>(tokens: &T) -> (Span, Span)
where
Expand Down Expand Up @@ -47,7 +43,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 @@ -63,16 +59,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
31 changes: 14 additions & 17 deletions futures-async-stream-macro/src/visitor.rs
@@ -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 @@ -93,7 +94,7 @@ impl Visitor {
}
Closure => {
*expr = expr_compile_error(&error!(
expr.clone(),
&expr,
"for await may not be allowed outside of \
async blocks, functions, closures, async stream blocks, and functions",
));
Expand Down Expand Up @@ -130,12 +131,12 @@ impl Visitor {
}

/// Visits `async_stream_block!` macro.
fn visit_macro(&mut self, expr: &mut Expr) {
fn visit_macro(&self, expr: &mut Expr) {
replace_expr(expr, |expr| {
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 @@ -152,18 +153,13 @@ impl Visitor {
/// It needs to adjust the type yielded by the macro because generators used internally by
/// async fn yield `()` type, but generators used internally by `async_stream` yield
/// `Poll<U>` type.
fn visit_await(&mut self, expr: &mut Expr) {
fn visit_await(&self, expr: &mut Expr) {
if self.scope != Stream {
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 All @@ -210,6 +206,7 @@ impl VisitMut for Visitor {
self.scope = tmp;
}

// Stop at item bounds
fn visit_item_mut(&mut self, _: &mut Item) {}
fn visit_item_mut(&mut self, _: &mut Item) {
// Do not recurse into nested items.
}
}
1 change: 0 additions & 1 deletion tests/compiletest.rs
Expand Up @@ -13,7 +13,6 @@ fn run_mode(mode: &'static str) {
-Z unstable-options \
--extern futures_async_stream \
--extern futures \
--cfg procmacro2_semver_exempt \
-L {}",
me.display()
));
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/invalid-arguments.stderr
Expand Up @@ -2,7 +2,7 @@ error: unexpected token
--> $DIR/invalid-arguments.rs:11:16
|
11 | #[for_await(bar)] //~ ERROR unexpected token
| ^^^^^
| ^

error: expected `item`
--> $DIR/invalid-arguments.rs:17:16
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/invalid-function.rs
Expand Up @@ -9,7 +9,7 @@ use futures_async_stream::async_stream;
const fn constness() {} //~ ERROR async stream may not be const

#[async_stream(item = ())]
fn variadic(...) {} //~ ERROR async stream may not be variadic
fn variadic(_: ...) {} //~ ERROR async stream may not be variadic

#[async_stream(item = ())]
fn asyncness() {} //~ ERROR async stream must be declared as async
Expand Down
12 changes: 8 additions & 4 deletions tests/ui/invalid-function.stderr
@@ -1,16 +1,20 @@
error: only foreign functions are allowed to be C-variadic
--> $DIR/invalid-function.rs:12:13
--> $DIR/invalid-function.rs:12:16
|
12 | fn variadic(...) {} //~ ERROR async stream may not be variadic
| ^^^
12 | fn variadic(_: ...) {} //~ ERROR async stream may not be variadic
| ^^^

error: async stream may not be const
--> $DIR/invalid-function.rs:9:1
|
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 8f919c5

Please sign in to comment.