Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

compilation failure when mixing default with NonZeroU8 #390

Closed
ahl opened this issue Sep 6, 2023 · 0 comments · Fixed by #608
Closed

compilation failure when mixing default with NonZeroU8 #390

ahl opened this issue Sep 6, 2023 · 0 comments · Fixed by #608
Labels
compile-fail generated code doesn't compile

Comments

@ahl
Copy link
Collaborator

ahl commented Sep 6, 2023

A schema like this...

    {
      "type": "object",
      "properties": {
        "x": {
          "type": "integer",
          "format": "uint8",
          "minimum": 1,
          "default": 1
        }
      }
    }

... turns into code like this...

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct X {
    #[serde(default = "defaults::default_u64::<std::num::NonZeroU8, 1>")]
    pub x: std::num::NonZeroU8,
}
impl From<&X> for X {
    fn from(value: &X) -> Self {
        value.clone()
    }
}
pub mod defaults {
    pub(super) fn default_u64<T, const V: u64>() -> T
    where
        T: std::convert::TryFrom<u64>,
        <T as std::convert::TryFrom<u64>>::Error: std::fmt::Debug,
    {
        T::try_from(V).unwrap()
    }
}

Which is as-intended: defaults::default_u64 is intended to produce the default value that we want.

However!

error[E0277]: the trait bound `NonZeroU8: From<u64>` is not satisfied

The NonZero* types implement TryFrom for their corresponding primitive type, but not other primitive types. This appears to be a point of principle: rust-lang/rust#72712 (comment)

So: cute as this would be, we need a different approach. Some options:

  1. Use some new trait that takes the place of TryFrom but has more implementations. This might be kind of annoying because we'd probably dump all this code into the mod defaults by default (no pun intended).
  2. We could generate default_non_zero_u64... it would only create a little bit of annoying code to determine which one to use.
  3. We could generate a function for each default. This would be fine, but it's been nice to share the integer implementations
  4. Parameterize default_u64 with two types (rather than one) i.e. the output type and an "intermediate type": defaults::default_u64::<NonZeroU8, u8>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compile-fail generated code doesn't compile
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant