Serde - Enum variants with reference arguments fail to compile

I am using serde to make an enum deserializable, which I’ve done before. Two of the enum variants takes a reference to a struct that is also deserializable.

However, when I try this, I get a “trait bounds not satisfied” error saying that the struct taken by the enum variant does not implement Deserialize.

use serde::{Deserialize, Serialize};

#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub enum PropertyState<'a> {
    NotFound,
    Value(String),
    EmptyPlayable,
    SinglePlayable(&'a Playable),
    PlayableCollection(Vec<&'a Playable>),
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct Playable {
    name: String,
    description: String,
    vendor: String,
    version: String,
}

which fails to compile with

error[E0277]: the trait bound `&'a Playable: _IMPL_DESERIALIZE_FOR_PropertyState::_serde::Deserialize<'_>` is not satisfied
 --> src/lib.rs:8:20
  |
8 |     SinglePlayable(&'a Playable),
  |                    ^
  |                    |
  |                    the trait `_IMPL_DESERIALIZE_FOR_PropertyState::_serde::Deserialize<'_>` is not implemented for `&'a Playable`
  |                    help: consider removing 1 leading `&`-references
  |
  = help: the following implementations were found:
            <Playable as _IMPL_DESERIALIZE_FOR_PropertyState::_serde::Deserialize<'de>>
  = note: required by `_IMPL_DESERIALIZE_FOR_PropertyState::_serde::de::VariantAccess::newtype_variant`

When I remove the reference, and have the variant take ownership of the object directly, all works well

I get the same error for the vector, but it doesn’t give me the hint to remove the &.

I suppose I can: remove the reference there by implementing and using Copy or Clone, but that feels unidiomatic to me. Is there a way I can implement Deserialize for a reference? Or am I missing something else?

I am very open to restructuring my code if this is not “thinking as rust thinks” and can provide more information. Thank you.

For additional answer, see

You can’t implement Deserialize for a reference to an arbitrary type like Playable - there’s nowhere for the underlying value to live.

1 Like

@sfackler thanks for the quick reply. So, my options would be to remove the reference or not make that enum serializable (or use a customdeserializer where that field is found)?

I don’t know if it works on enums, but I would try annotating the borrowed field with #[serde(borrow)]

1 Like

Serialize should work without hassle on itself, but in case of deserialize you need to create your type from byte slice. PropertyState contains &Playable which must be owned by someone else. But for the PropertyState which is deserialized from byte slice, who owns the Playable?

1 Like