Azure / azure-sdk-for-rust

This repository is for the active development of the Azure SDK for Rust. For consumers of the SDK we recommend visiting Docs.rs and looking up the docs for any of libraries in the SDK.
MIT License
709 stars 246 forks source link

azure_core::Model derive macro doesn't infer `Deserialize` bounds in `impl` #1803

Open analogrelay opened 1 month ago

analogrelay commented 1 month ago

The derive macro for Model doesn't work for generic arguments. For example, this doesn't work:

#[derive(Model, Deserialize)]
pub struct Wrapper<T> {
    items: Vec<T>,
}

This is because our logic generates an impl like this:

impl<T> Model for Wrapper<T> {
}

But, serde's Deserialize derive macro generates this (effectively):

impl<T: Deserialize> Deserialize for Wrapper<T> {
}

Since our Model impl depends on the impl of Deserialize, we end up with an error:

the trait bound `T: Deserialize<'_>` is not satisfied
required for `container_client::Wrapper<T>` to implement `DeserializeOwned`

What we'd need to do is add logic to our derive macro that matches serde's logic to guess appropriate type parameter bounds for the impl. This isn't really blocking, since one can manually implement Model without too much trouble in this case. For example:

impl<M: DeserializeOwned> azure_core::Model for QueryResponseModel<M> {
    async fn from_response_body(
        body: azure_core::ResponseBody,
    ) -> typespec_client_core::Result<Self> {
        body.json().await
    }
}
analogrelay commented 1 month ago

Logging this because I hit it in implementing a query API for Cosmos. I'm working around it with the work-around posted above, but I wanted to track this issue for future reference (and to hopefully fix it later)