Skip to content

#[serde(other)] not working as expected on enum tuple-like variants #359

@b-zee

Description

@b-zee

I have a use case where I want to have the possibility to introduce a breaking change to a data structure. If my app currently only supports version 0, it will detect when a version 1 is used. I have written the following code, but I get an error instead of matching on the #[serde(other)] variant. (Inspiration taken from https://stackoverflow.com/a/70380491)

#[derive(serde::Serialize, serde::Deserialize)]
enum A {
    V0(String),
    #[serde(other)]
    Unsupported,
}

#[derive(serde::Serialize, serde::Deserialize)]
enum B {
    V0(String),
    V1(usize),
    #[serde(other)]
    Unsupported,
}

#[test]
fn test() {
    let b_v1 = rmp_serde::to_vec(&B::V1(1)).unwrap();

    // Yields `Err(rmp_serde::decode::Error::TypeMismatch(rmp::Marker::FixPos(1)))`
    let a_unsupported = rmp_serde::from_slice::<A>(b_v1.as_slice());
    // But instead, I would expect this to pass (`Ok(A::Unsupported)`):
    assert!(matches!(a_unsupported, Ok(A::Unsupported)));
}

The above code does work when I change the A and B enums to be unit-only:

 #[derive(serde::Serialize, serde::Deserialize)]
 enum A {
-    V0(String),
+    V0,
     #[serde(other)]
     Unsupported,
 }
 
 #[derive(serde::Serialize, serde::Deserialize)]
 enum B {
-    V0(String),
-    V1(usize),
+    V0,
+    V1,
     #[serde(other)]
     Unsupported,
 }
 
 #[test]
 fn test() {
-    let b_v1 = rmp_serde::to_vec(&B::V1(1)).unwrap();
+    let b_v1 = rmp_serde::to_vec(&B::V1).unwrap();
 
     // Yields `Err(rmp_serde::decode::Error::TypeMismatch(rmp::Marker::FixPos(1)))`
     let a_unsupported = rmp_serde::from_slice::<A>(b_v1.as_slice());

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions