Skip to content

Commit

Permalink
Update to syn 2
Browse files Browse the repository at this point in the history
  • Loading branch information
jsdw committed Oct 23, 2024
1 parent 90fd911 commit 7922aba
Show file tree
Hide file tree
Showing 12 changed files with 102 additions and 88 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ readme = "./README.md"
proc-macro = true

[dependencies]
syn = { version = "1.0.5", features = [ "full", "visit", "fold", "extra-traits" ] }
syn = { version = "2", features = [ "full", "visit", "fold", "extra-traits" ] }
quote = "1.0.2"
proc-macro2 = "1.0.3"

Expand Down
11 changes: 7 additions & 4 deletions src/full_automatic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use syn::{
spanned::Spanned,
visit::{self, Visit},
Error, FnArg, Generics, Ident, Index, ItemTrait, Pat, Result, ReturnType, Signature, TraitItem,
TraitItemMethod, Type,
TraitItemFn, Type,
};

use quote::quote;
Expand Down Expand Up @@ -69,7 +69,7 @@ const CHECK_ERROR_MSG: &str =
impl<'ast> Visit<'ast> for CheckTraitDeclaration {
fn visit_trait_item(&mut self, ti: &'ast TraitItem) {
match ti {
TraitItem::Method(m) => visit::visit_trait_item_method(self, m),
TraitItem::Fn(f) => visit::visit_trait_item_fn(self, f),
_ => self.add_error(ti),
}
}
Expand All @@ -92,7 +92,7 @@ fn generate_tuple_impl(definition: &ItemTrait, tuple_elements: &[Ident]) -> Toke
let ty_generics = definition.generics.split_for_impl().1;
let (impl_generics, _, where_clause) = generics.split_for_impl();
let fns = definition.items.iter().filter_map(|i| match i {
TraitItem::Method(method) => Some(generate_delegate_method(method, tuple_elements)),
TraitItem::Fn(f) => Some(generate_delegate_method(f, tuple_elements)),
_ => None,
});

Expand All @@ -110,6 +110,9 @@ struct CollectNonReferenceArgTypes {
}

impl<'ast> Visit<'ast> for CollectNonReferenceArgTypes {
fn visit_receiver(&mut self, _: &'ast syn::Receiver) {
// Do nothing: explicitly ignore any receiver type.
}
fn visit_type(&mut self, ty: &'ast Type) {
if !is_reference_type(ty) {
self.result.push(ty.clone());
Expand Down Expand Up @@ -146,7 +149,7 @@ fn generate_generics(definition: &ItemTrait, tuple_elements: &[Ident]) -> Generi
generics
}

fn generate_delegate_method(method: &TraitItemMethod, tuple_elements: &[Ident]) -> TokenStream {
fn generate_delegate_method(method: &TraitItemFn, tuple_elements: &[Ident]) -> TokenStream {
let name = repeat(&method.sig.ident);
let self_arg = method
.sig
Expand Down
94 changes: 37 additions & 57 deletions src/semi_automatic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,7 @@
use proc_macro2::TokenStream;

use syn::{
bracketed,
fold::{self, Fold},
parenthesized,
parse::{Parse, ParseStream},
parse_quote,
spanned::Spanned,
token, Block, Error, Expr, ExprField, FnArg, Ident, ImplItem, ImplItemMethod, Index, ItemImpl,
Macro, Member, Result, Stmt, Type, WhereClause, WherePredicate,
bracketed, fold::{self, Fold}, parenthesized, parse::{Parse, ParseStream}, parse_quote, spanned::Spanned, token, Block, Error, Expr, ExprField, FnArg, Ident, ImplItem, ImplItemFn, Index, ItemImpl, Macro, Member, Meta, Result, Stmt, Type, WhereClause, WherePredicate
};

use quote::{quote, ToTokens};
Expand All @@ -27,12 +20,12 @@ const TUPLE_TYPES_CUSTOM_TRAIT_BOUND: &str = "tuple_types_custom_trait_bound";
/// The supported separators in the `#( Tuple::test() )SEPARATOR*` syntax.
enum Separator {
Comma(token::Comma),
Add(token::Add),
Sub(token::Sub),
Plus(token::Plus),
Minus(token::Minus),
Or(token::Or),
And(token::And),
Star(token::Star),
Div(token::Div),
Slash(token::Slash),
}

impl Separator {
Expand All @@ -59,12 +52,12 @@ impl Separator {

match self {
Self::Comma(comma) => comma.to_token_stream(),
Self::Add(add) => empty_on_last(add),
Self::Sub(sub) => empty_on_last(sub),
Self::Plus(add) => empty_on_last(add),
Self::Minus(sub) => empty_on_last(sub),
Self::Or(or) => empty_on_last(or),
Self::And(and) => empty_on_last(and),
Self::Star(star) => empty_on_last(star),
Self::Div(div) => empty_on_last(div),
Self::Slash(div) => empty_on_last(div),
}
}
}
Expand All @@ -75,18 +68,18 @@ impl Parse for Separator {

if lookahead1.peek(token::Comma) {
Ok(Self::Comma(input.parse()?))
} else if lookahead1.peek(token::Add) {
Ok(Self::Add(input.parse()?))
} else if lookahead1.peek(token::Sub) {
Ok(Self::Sub(input.parse()?))
} else if lookahead1.peek(token::Plus) {
Ok(Self::Plus(input.parse()?))
} else if lookahead1.peek(token::Minus) {
Ok(Self::Minus(input.parse()?))
} else if lookahead1.peek(token::Or) {
Ok(Self::Or(input.parse()?))
} else if lookahead1.peek(token::And) {
Ok(Self::And(input.parse()?))
} else if lookahead1.peek(token::Star) {
Ok(Self::Star(input.parse()?))
} else if lookahead1.peek(token::Div) {
Ok(Self::Div(input.parse()?))
} else if lookahead1.peek(token::Slash) {
Ok(Self::Slash(input.parse()?))
} else {
Err(lookahead1.error())
}
Expand Down Expand Up @@ -673,23 +666,6 @@ struct ToTupleImplementation<'a> {
custom_where_clause: Option<TupleRepetition>,
}

// Struct to parse custom trait bounds
#[derive(Debug)]
struct BoundsStruct {
_paren_token: token::Paren,
bounds: syn::TypeTraitObject,
}

impl Parse for BoundsStruct {
fn parse(input: ParseStream) -> Result<Self> {
let content;
Ok(BoundsStruct {
_paren_token: parenthesized!(content in input),
bounds: content.parse()?,
})
}
}

impl<'a> ToTupleImplementation<'a> {
/// Generate the tuple implementation for the given `tuples`.
fn generate_implementation(
Expand Down Expand Up @@ -719,14 +695,21 @@ impl<'a> ToTupleImplementation<'a> {
let trait_ = if let Some(pos) = res
.attrs
.iter()
.position(|a| a.path.is_ident(TUPLE_TYPES_CUSTOM_TRAIT_BOUND))
.position(|a| a.path().is_ident(TUPLE_TYPES_CUSTOM_TRAIT_BOUND))
{
// Parse custom trait bound
let attr = &res.attrs[pos];
let input = attr.tokens.to_token_stream();
let result = syn::parse2::<BoundsStruct>(input);
let Meta::List(items) = &attr.meta else {
return Err(Error::new(
attr.span(),
"Expected #[tuple_types_custom_trait_bound($trait_bounds)]",
))
};

let input = items.tokens.to_token_stream();
let result = syn::parse2::<syn::TypeTraitObject>(input);
let trait_name = match result {
Ok(b) => b.bounds,
Ok(bounds) => bounds,
Err(e) => {
return Err(Error::new(
e.span(),
Expand All @@ -745,7 +728,7 @@ impl<'a> ToTupleImplementation<'a> {
let add_bound = if let Some(pos) = res
.attrs
.iter()
.position(|a| a.path.is_ident(TUPLE_TYPES_NO_DEFAULT_TRAIT_BOUND))
.position(|a| a.path().is_ident(TUPLE_TYPES_NO_DEFAULT_TRAIT_BOUND))
{
res.attrs.remove(pos);
None
Expand Down Expand Up @@ -843,20 +826,17 @@ impl<'a> Fold for ToTupleImplementation<'a> {
}

fn fold_stmt(&mut self, stmt: Stmt) -> Stmt {
let (expr, trailing_semi) = match stmt {
Stmt::Expr(expr) => (expr, None),
Stmt::Semi(expr, semi) => (expr, Some(semi)),
_ => return fold::fold_stmt(self, stmt),
};

let (expr, expanded) = self.custom_fold_expr(expr);

if expanded {
Stmt::Expr(expr)
} else if let Some(semi) = trailing_semi {
Stmt::Semi(expr, semi)
} else {
Stmt::Expr(expr)
match stmt {
Stmt::Expr(expr, semi) => {
let (expr, expanded) = self.custom_fold_expr(expr);
Stmt::Expr(expr, if expanded { None } else { semi })
},
Stmt::Macro(macro_stmt) => {
let expr = Expr::Macro(syn::ExprMacro { mac: macro_stmt.mac, attrs: macro_stmt.attrs });
let (expr, expanded) = self.custom_fold_expr(expr);
Stmt::Expr(expr, if expanded { None } else { macro_stmt.semi_token })
},
_ => fold::fold_stmt(self, stmt)
}
}

Expand All @@ -878,7 +858,7 @@ impl<'a> Fold for ToTupleImplementation<'a> {
}
}

fn fold_impl_item_method(&mut self, mut impl_item_method: ImplItemMethod) -> ImplItemMethod {
fn fold_impl_item_fn(&mut self, mut impl_item_method: ImplItemFn) -> ImplItemFn {
let has_self = impl_item_method
.sig
.inputs
Expand Down
2 changes: 2 additions & 0 deletions tests/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,7 @@ fn test_separators() {

#[test]
fn semi_automatic_tuple_with_custom_trait_bound() {
#[allow(dead_code)]
trait Trait {
type Arg;

Expand All @@ -536,6 +537,7 @@ fn semi_automatic_tuple_with_custom_trait_bound() {

#[test]
fn semi_automatic_tuple_with_custom_advanced_trait_bound() {
#[allow(dead_code)]
trait Trait {
type Arg;
type Output;
Expand Down
10 changes: 10 additions & 0 deletions tests/fail/custom_trait_bound_invalid.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ error[E0277]: the trait bound `(Impl, Impl): Test` is not satisfied
32 | test::<(Impl, Impl)>();
| ^^^^^^^^^^^^ the trait `Test` is not implemented for `(Impl, Impl)`
|
help: this trait has no implementations, consider adding one
--> tests/fail/custom_trait_bound_invalid.rs:1:1
|
1 | trait Test {
| ^^^^^^^^^^
note: required by a bound in `test`
--> tests/fail/custom_trait_bound_invalid.rs:30:12
|
Expand All @@ -22,6 +27,11 @@ error[E0277]: the trait bound `(Impl, Impl, Impl): Test` is not satisfied
33 | test::<(Impl, Impl, Impl)>();
| ^^^^^^^^^^^^^^^^^^ the trait `Test` is not implemented for `(Impl, Impl, Impl)`
|
help: this trait has no implementations, consider adding one
--> tests/fail/custom_trait_bound_invalid.rs:1:1
|
1 | trait Test {
| ^^^^^^^^^^
note: required by a bound in `test`
--> tests/fail/custom_trait_bound_invalid.rs:30:12
|
Expand Down
47 changes: 31 additions & 16 deletions tests/fail/trait_bound_not_added.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0046]: not all trait items implemented, missing: `test`
--> $DIR/trait_bound_not_added.rs:15:1
--> tests/fail/trait_bound_not_added.rs:15:1
|
2 | fn test();
| ---------- `test` from trait
Expand All @@ -8,61 +8,76 @@ error[E0046]: not all trait items implemented, missing: `test`
| ^^^^^^^^^^^^^^^^^^ missing `test` in implementation

error[E0599]: no function or associated item named `test` found for type parameter `TupleElement0` in the current scope
--> $DIR/trait_bound_not_added.rs:9:32
--> tests/fail/trait_bound_not_added.rs:9:32
|
5 | #[impl_trait_for_tuples::impl_for_tuples(5)]
| -------------------------------------------- function or associated item `test` not found for this type parameter
...
9 | for_tuples!( #( Tuple::test(); )* )
| ^^^^ function or associated item not found in `TupleElement0`
|
= help: items from traits can only be used if the type parameter is bounded by the trait
help: the following trait defines an item `test`, perhaps you need to restrict type parameter `TupleElement0` with it:
|
5 | TupleElement0: Test
|
5 | #[impl_trait_for_tuples::impl_for_tuples(5)]: Test
| ++++++

error[E0599]: no function or associated item named `test` found for type parameter `TupleElement1` in the current scope
--> $DIR/trait_bound_not_added.rs:9:32
--> tests/fail/trait_bound_not_added.rs:9:32
|
5 | #[impl_trait_for_tuples::impl_for_tuples(5)]
| -------------------------------------------- function or associated item `test` not found for this type parameter
...
9 | for_tuples!( #( Tuple::test(); )* )
| ^^^^ function or associated item not found in `TupleElement1`
|
= help: items from traits can only be used if the type parameter is bounded by the trait
help: the following trait defines an item `test`, perhaps you need to restrict type parameter `TupleElement1` with it:
|
5 | TupleElement1: Test
|
5 | #[impl_trait_for_tuples::impl_for_tuples(5)]: Test
| ++++++

error[E0599]: no function or associated item named `test` found for type parameter `TupleElement2` in the current scope
--> $DIR/trait_bound_not_added.rs:9:32
--> tests/fail/trait_bound_not_added.rs:9:32
|
5 | #[impl_trait_for_tuples::impl_for_tuples(5)]
| -------------------------------------------- function or associated item `test` not found for this type parameter
...
9 | for_tuples!( #( Tuple::test(); )* )
| ^^^^ function or associated item not found in `TupleElement2`
|
= help: items from traits can only be used if the type parameter is bounded by the trait
help: the following trait defines an item `test`, perhaps you need to restrict type parameter `TupleElement2` with it:
|
5 | TupleElement2: Test
|
5 | #[impl_trait_for_tuples::impl_for_tuples(5)]: Test
| ++++++

error[E0599]: no function or associated item named `test` found for type parameter `TupleElement3` in the current scope
--> $DIR/trait_bound_not_added.rs:9:32
--> tests/fail/trait_bound_not_added.rs:9:32
|
5 | #[impl_trait_for_tuples::impl_for_tuples(5)]
| -------------------------------------------- function or associated item `test` not found for this type parameter
...
9 | for_tuples!( #( Tuple::test(); )* )
| ^^^^ function or associated item not found in `TupleElement3`
|
= help: items from traits can only be used if the type parameter is bounded by the trait
help: the following trait defines an item `test`, perhaps you need to restrict type parameter `TupleElement3` with it:
|
5 | TupleElement3: Test
|
5 | #[impl_trait_for_tuples::impl_for_tuples(5)]: Test
| ++++++

error[E0599]: no function or associated item named `test` found for type parameter `TupleElement4` in the current scope
--> $DIR/trait_bound_not_added.rs:9:32
--> tests/fail/trait_bound_not_added.rs:9:32
|
5 | #[impl_trait_for_tuples::impl_for_tuples(5)]
| -------------------------------------------- function or associated item `test` not found for this type parameter
...
9 | for_tuples!( #( Tuple::test(); )* )
| ^^^^ function or associated item not found in `TupleElement4`
|
= help: items from traits can only be used if the type parameter is bounded by the trait
help: the following trait defines an item `test`, perhaps you need to restrict type parameter `TupleElement4` with it:
|
5 | TupleElement4: Test
|
5 | #[impl_trait_for_tuples::impl_for_tuples(5)]: Test
| ++++++
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ error[E0277]: the trait bound `(Impl, Impl): Test` is not satisfied
10 | test::<(Impl, Impl)>();
| ^^^^^^^^^^^^ the trait `Test` is not implemented for `(Impl, Impl)`
|
= help: the following other types implement trait `Test`:
(TupleElement0, TupleElement1, TupleElement2)
(TupleElement0, TupleElement1, TupleElement2, TupleElement3)
(TupleElement0, TupleElement1, TupleElement2, TupleElement3, TupleElement4)
note: required by a bound in `test`
--> tests/fail/tuple_impls_less_than_minimum_does_not_exists.rs:8:12
|
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/custom_where_clause_not_allowed.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error: Custom where clause not allowed at this position!
--> $DIR/custom_where_clause_not_allowed.rs:8:9
--> tests/ui/custom_where_clause_not_allowed.rs:8:9
|
8 | for_tuples!( where #( Tuple: Test ),* )
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^
4 changes: 2 additions & 2 deletions tests/ui/empty_for_tuples.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error: unexpected end of input, expected one of: `type`, `const`, parentheses, `#`, `where`
--> tests/ui/empty_for_tuples.rs:12:20
--> tests/ui/empty_for_tuples.rs:12:21
|
12 | for_tuples!()
| ^^
| ^
Loading

0 comments on commit 7922aba

Please sign in to comment.