Skip to content

Incorrect handling of optional fields with String #7

Description

@ghostinushanka

Hello @benhall-7 ,

Playing with the lib I've come across inconsistent behavior for structs containing String types.
Example:

use diff::Diff;

#[derive(Debug, PartialEq, Diff)]
#[diff(attr(
    #[derive(Debug, PartialEq)]
))]
struct OptionalInteger {
    x: i32,
    ox: Option<i32>,
}

#[derive(Debug, PartialEq, Diff)]
#[diff(attr(
    #[derive(Debug, PartialEq)]
))]
struct OptionalString {
    x: String,
    ox: Option<String>,
}

fn main() {
    let empty_integer = OptionalInteger { x: 42, ox: None };
    let filled_integer = OptionalInteger { x: 42, ox: Some(42)};
    let di = empty_integer.diff(&filled_integer);
    println!("{:#?}", di);

    let empty_string = OptionalString { x: "42".to_string(), ox: None};
    let filled_string = OptionalString { x: "42".to_string(), ox: Some("42".to_string())};
    let ds = empty_string.diff(&filled_string);
    println!("{:#?}", ds);
}

Expected output:

OptionalIntegerDiff {
    x: 0,
    ox: Some(
        42,
    ),
}
OptionalStringDiff {
    x: None,
    ox: Some(
        "42",
    ),
}

Actual output (note how instead of Some(String) we're getting Some(Some(String))

OptionalIntegerDiff {
    x: 0,
    ox: Some(
        42,
    ),
}
OptionalStringDiff {
    x: None,
    ox: Some(
        Some(
            "42",
        ),
    ),
}

Make it Option<Vec<String>> (or other compound type for that matter) and the end result is even more interesting.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions