Skip to content

Fix handling of float default values#1033

Open
danieleades wants to merge 1 commit into
oxidecomputer:mainfrom
danieleades:fix/float-defaults
Open

Fix handling of float default values#1033
danieleades wants to merge 1 commit into
oxidecomputer:mainfrom
danieleades:fix/float-defaults

Conversation

@danieleades

Copy link
Copy Markdown
Contributor

Problem

Two related bugs in float default-value handling:

  1. In has_default (typify-impl/src/structs.rs) there were two consecutive match arms for TypeEntryDetails::Integer with a numeric default — the second arm (guarded by n.as_f64() == Some(0.0), commented "implicit default: 0.0") was clearly intended to match TypeEntryDetails::Float but matched Integer instead, making it unreachable. As a result, a property like {"type": "number", "default": 0.0} was not recognized as having the intrinsic default, and a bespoke defaults::xxx() function returning 0.0_f64 was generated instead of a plain #[serde(default)].

  2. In validate_value (typify-impl/src/defaults.rs), a non-zero float default returned DefaultKind::Generic(DefaultImpl::I64). That registers the shared default_i64 helper in the generated defaults module, but default_fn has no Float arm, so a bespoke function is generated anyway and default_i64 is emitted dead/unused (it couldn't be used for floats regardless, since f64: TryFrom<i64> doesn't hold). This shows up today as an unused default_i64 in the vega.out test output.

Fix

  • has_default: the first arm now matches integers with a zero default via n.as_f64() == Some(0.0) (subsuming the previous as_u64() == Some(0) check and also handling a default written as 0.0), and the second arm now matches Float as intended.
  • validate_value: non-zero float defaults now return DefaultKind::Specific, matching how default_fn actually handles them, so the unusable default_i64 helper is no longer registered.

Regression coverage: a MrDefaultFloats type (one zero and one non-zero float default) added to typify/tests/schemas/types-with-defaults.json, plus a test_default_float unit test in typify-impl/src/defaults.rs.

Trade-offs

Previously-generated bespoke zero-default functions (e.g. fn xxx_zfreq() -> f64 { 0.0_f64 }) disappear from output in favor of plain #[serde(default)], and the dead default_i64 helper is no longer emitted when only float defaults required it — a cosmetic change to generated code with identical runtime behavior.

Related to (but not fully fixing) #442, and a follow-up to #976.

Two related bugs in float default handling:

- In has_default, the match arm intended to treat a 0.0 default on a
  float property as the intrinsic default matched Integer instead of
  Float (an unreachable duplicate of the preceding arm), so a
  `{"type": "number", "default": 0.0}` property generated a bespoke
  defaults function rather than a plain #[serde(default)]. The integer
  arm now uses as_f64() == Some(0.0), which subsumes the previous
  as_u64() check and also accepts an integer default written as 0.0.

- In validate_value, a non-zero float default returned
  DefaultKind::Generic(DefaultImpl::I64), registering the shared
  default_i64 helper even though default_fn has no Float arm and
  generates a bespoke function anyway, leaving default_i64 emitted but
  unused (and unusable for floats, since f64 does not implement
  TryFrom<i64>). Non-zero float defaults now return
  DefaultKind::Specific.

Related to oxidecomputer#442; follow-up to oxidecomputer#976.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant