Skip to content

Commit

Permalink
Merge pull request #12 from jsdw/master
Browse files Browse the repository at this point in the history
chore(deps): Update to syn 2
  • Loading branch information
bkchr authored Oct 24, 2024
2 parents 90fd911 + 83ae4ae commit 1207d23
Show file tree
Hide file tree
Showing 13 changed files with 209 additions and 90 deletions.
87 changes: 87 additions & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
name: Rust

on:
push:
# Run jobs when commits are pushed to
# main:
branches:
- main
pull_request:
# Run jobs for any external PR that wants
# to merge to main, too:
branches:
- main

env:
CARGO_TERM_COLOR: always

jobs:
build:
name: Cargo check
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v2

- name: Install Rust stable toolchain
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true

- name: Rust Cache
uses: Swatinem/rust-cache@v1.3.0

- name: Check all features
uses: actions-rs/cargo@v1.0.3
with:
command: check
args: --all-targets

fmt:
name: Cargo fmt
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v2

- name: Install Rust stable toolchain
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
components: rustfmt

- name: Rust Cache
uses: Swatinem/rust-cache@v1.3.0

- name: Cargo fmt
uses: actions-rs/cargo@v1.0.3
with:
command: fmt
args: --all -- --check

tests:
name: Cargo test
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v2

- name: Install Rust stable toolchain
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true

- name: Rust Cache
uses: Swatinem/rust-cache@v1.3.0

- name: Cargo test
uses: actions-rs/cargo@v1.0.3
with:
command: test
args: --all-targets
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.0.85", features = [ "full", "visit", "fold", "extra-traits" ] }
quote = "1.0.2"
proc-macro2 = "1.0.3"

Expand Down
14 changes: 8 additions & 6 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 @@ -62,14 +62,13 @@ impl CheckTraitDeclaration {
}
}

const CHECK_ERROR_MSG: &str =
"Not supported by full-automatic tuple implementation. \
const CHECK_ERROR_MSG: &str = "Not supported by full-automatic tuple implementation. \
Use semi-automatic tuple implementation for more control of the implementation.";

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 +91,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 +109,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 +148,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
113 changes: 56 additions & 57 deletions src/semi_automatic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ use syn::{
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,
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 +27,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 +59,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 +75,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 @@ -202,9 +202,13 @@ impl TupleRepetition {

for (i, tuple) in tuples.iter().enumerate() {
generated.extend(
ReplaceTuplePlaceholder::replace_ident_in_type(tuple_placeholder_ident, tuple, ty.clone())
.map(|s| s.to_token_stream())
.unwrap_or_else(|e| e.to_compile_error()),
ReplaceTuplePlaceholder::replace_ident_in_type(
tuple_placeholder_ident,
tuple,
ty.clone(),
)
.map(|s| s.to_token_stream())
.unwrap_or_else(|e| e.to_compile_error()),
);

if let Some(ref sep) = self.separator {
Expand Down Expand Up @@ -631,9 +635,7 @@ impl ForTuplesMacro {
tuple_repetition.expand_as_stmts(tuple_placeholder_ident, tuples, use_self);

match repetition {
Ok(rep) => {
paren_token.surround(&mut token_stream, |tokens| tokens.extend(rep))
}
Ok(rep) => paren_token.surround(&mut token_stream, |tokens| tokens.extend(rep)),
Err(e) => token_stream.extend(e.to_compile_error()),
}

Expand Down Expand Up @@ -673,23 +675,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 +704,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 +737,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 +835,27 @@ 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 +877,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
Loading

0 comments on commit 1207d23

Please sign in to comment.