serde icon indicating copy to clipboard operation
serde copied to clipboard

remote attribute should implement a trait instead of an associated function.

Open yogevm15 opened this issue 10 months ago • 1 comments

I'm using the remote attribute in my derive proc macro within serde_many, and I've encountered an issue with constraining the implementation bounds added by the Serialize derive macro.

This is how my derive proc macro works:

/// Marker.
struct Many1;

/// Marker.
struct Many2;

#[derive(SerializeMany)]
#[serde_many(many1 = "Many1", many2 = "Many2")] // Declaring the implementation markers.
struct Point<X, Y> {
    #[serde(many2(rename = "x_value"))]
    x: X,
    #[serde(many2(rename = "y_value"), many1(rename = "y2"))]
    y: Y,
}

expands to:

const _: () = {
    type __Derived<X, Y> = Point<X, Y>;
    const _: () = {
        #[derive(::serde_many::__private::serde::Serialize)]
        #[serde(remote = "__Derived")]
        #[serde(crate = "::serde_many::__private::serde")]
        struct Point<X, Y> {
            #[serde(serialize_with = ":: serde_many :: SerializeMany :: < Many1 > :: serialize")]
            x: X,
            #[serde(rename = "y2")]
            #[serde(
                serialize_with = ":: serde_many :: SerializeMany :: < Many1 > :: serialize"
            )] y: Y,
        }
        impl<X, Y> ::serde_many::SerializeMany<Many1> for __Derived<X, Y> {
            fn serialize<S: ::serde_many::__private::serde::Serializer>(&self, serializer: S) -> ::core::result::Result<S::Ok, S::Error> { Point::serialize(self, serializer) }
        }
    };
    const _: () = {
        #[derive(::serde_many::__private::serde::Serialize)]
        #[serde(remote = "__Derived")]
        #[serde(crate = "::serde_many::__private::serde")]
        struct Point<X, Y> {
            #[serde(rename = "x_value")]
            #[serde(
                serialize_with = ":: serde_many :: SerializeMany :: < Many2 > :: serialize"
            )] x: X,
            #[serde(rename = "y_value")]
            #[serde(
                serialize_with = ":: serde_many :: SerializeMany :: < Many2 > :: serialize"
            )] y: Y,
        }
        impl<X, Y> ::serde_many::SerializeMany<Many2> for __Derived<X, Y> {
            fn serialize<S: ::serde_many::__private::serde::Serializer>(&self, serializer: S) -> ::core::result::Result<S::Ok, S::Error> { Point::serialize(self, serializer) }
        }
    };
};

The core issue is that I cannot call Point::serialize because it is subject to bounds generated by the Serialize derive macro. Normally, one would rely on the Point: Serialize constraint, but the use of the remote attribute prevents this.

I suggest introducing a new trait, RemoteSerialize, which would be defined as:

trait RemoteSerialize<Origin> {
    fn serialize<S: Serializer>(origin: Origin, serializer: S) -> Result<S::Ok, S::Error>;
}

With this approach, the remote attribute will implement the RemoteSerialize trait, and one could use constrain his implementation with the bounds of the trait implmentation (Point: RemoteSerialize<__Derived>). Of course a similar change would be made for RemoteDeserialize.

What do you think about this change? Would you accept a PR for this?

Thanks!

yogevm15 avatar Feb 22 '25 15:02 yogevm15

Just bumping this @dtolnay

yogevm15 avatar Jun 02 '25 16:06 yogevm15