Giter VIP home page Giter VIP logo

Comments (3)

dtolnay avatar dtolnay commented on June 25, 2024 1

@mystor has a promising implementation in abomonation_derive which he plans to factor into a separate crate. I will keep this ticket open until we have something to point people to. Thanks Michael!

from syn.

mcarton avatar mcarton commented on June 25, 2024

Just one remark though: @mystor's implementation currently only allows bindings to be named __binding_{i} where i starts at 0.
In order to implement something like PartialEq you need two matches like that:

    fn eq(&self, __arg_0: &Foo<T>) -> bool {
        match *__arg_0 {
            Foo { foo: ref __self_1_0, bar: ref __self_1_1 } =>
            match *self {
                Foo { foo: ref __self_0_0, bar: ref __self_0_1 } =>
                true && (*__self_0_0) == (*__self_1_0) &&
                    (*__self_0_1) == (*__self_1_1),
            },
        }
    }

(this is what derive(PartialEq) actually generates)

It would be nice if such a helper allowed for a custom placeholder name.

from syn.

mystor avatar mystor commented on June 25, 2024

Firstly, I split my first implementation into its own crate, you can find it here: https://github.com/mystor/synstructure or on crates.io.

@mcarton: I don't currently have support for that, but you can kinda do it yourself, by generating your own let bindings in the outer scope, so you would generate code which looks something like:

    fn eq(&self, __arg_0: &Foo<T>) -> bool {
        match *__arg_0 {
            Foo { foo: ref __binding_0, bar: ref __binding_1 } => {
                let __self_1_0 = __binding_0;
                let __self_1_1 = __binding_1;
                match *self {
                    Foo { foo: ref __binding_0, bar: ref __binding_1 } =>
                    true && (*__binding_0) == (*__self_1_0) &&
                        (*__binding_1) == (*__self_1_1),
                }
            }
        }
    }

I'll admit that that is pretty gross though. I don't really want to add a ton of arguments to these methods because that feels like it will clutter up the interface. It might be easier to just add some sort of helper method which just "renames" the bindings for you with let bindings (I can't imagine those have any performance overhead after optimization). If such a method existed, an eq derive would look something like the following (I haven't tested this, so no promises that I didn't screw something up):

fn derive_partialeq(input: TokenStream) -> TokenStream {
    let source = input.to_string();
    let mut ast = syn::parse_macro_input(&source).unwrap();
    // We need to copy the AST for the inner body, because match_substructs
    // takes a mutable reference. It's kinda gross, and optimized for the case
    // where we want to be able to remove attributes from within the callback.
    // I might change this in the future.
    let mut ast2 = ast.clone();

    let body = match_substructs(&mut ast, bind, |outer_bis| {
        let (renaming, outer_bis) = rename_bindings(outer_bis, "outer");
        let inner_body = match_substructs(&mut ast, bind, |inner_bis| {
            let mut zipped = outer_bis.into_iter().zip(inner_bis.into_iter());
            let eqs = zipped.map(|(x, y)| quote!((#x == #y)));
            quote!(true #(&& #eqs)*)
        })
        quote!{
            #renaming
            match *self { #inner_body }
        }
    }):

    let name = &ast.ident;
    let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
    let result = quote! {
        #ast

        impl #impl_generics PartialEq for #name #ty_generics #where_clause {
            fn eq(&self, __arg_0: &Self) -> bool {
                match *__arg_0 { #body }
            }
        }
    };

    result.to_string().parse().unwrap()
}

from syn.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.