Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help


rfc: 0003 title: Field-hashing derive macro defaults to opt-in status: accepted created: 2026-09-14 supersedes:

Summary

#[derive(FoldbackHash)] (and its per-engine equivalents) hashes nothing until a field is explicitly marked #[foldback(hash)] — opt-in, not opt-out.

Motivation

Get this decided once, correctly, before four different engine bindings each have to mirror it independently. A mismatch between engines here (one opt-in, one opt-out) would be a confusing, undocumented inconsistency discovered by users the hard way, long after the first binding shipped.

Design

Full reasoning: Cookbook §5. #[derive(FoldbackHash)] marks no fields for hashing by default; a field must be explicitly annotated (#[foldback(hash)] in Rust, [FoldbackHash] in C#, the foldback_ name prefix in Godot — GDScript has no custom-attribute mechanism GDExtension can hook into, see Auto/Reflective Hashing, UPROPERTY(meta=(FoldbackHash)) in Unreal) to be included.

Drawbacks

More integration friction per field than an opt-out default would have — every field a user cares about tracking needs an explicit annotation. Mitigated, not eliminated, by foldback lint’s unmarked-field-surfacing (see the Cookbook) that surfaces unmarked fields rather than leaving the gap invisible.

Alternatives considered

Opt-out (hash everything by default, #[skip] to exclude) was rejected specifically because it silently turns any newly-added non-deterministic field (a timestamp, a debug name) into a permanent phantom divergence source with no signal that it happened. That’s the one failure mode most likely to teach users to distrust the tool’s own bisection results.

Prior art

Opt-in field selection for serialization/hashing purposes is the more conservative and more common choice in determinism-sensitive tooling generally (compare: explicit #[derive(Hash)] field inclusion conventions in other Rust serialization ecosystems) — erring toward “silently include too little, loudly lint it” over “silently include too much.”

Unresolved questions

None outstanding for the default itself — the foldback lint unmarked-field-surfacing mechanism referenced above has its own design detail in the cookbook, not repeated here.

History

  • 2026-09-14: accepted.