Skip to content

Always-annotate types in option/result/empty list literals#15

Merged
colinrozzi merged 1 commit into
mainfrom
lossless-type-annotations
May 8, 2026
Merged

Always-annotate types in option/result/empty list literals#15
colinrozzi merged 1 commit into
mainfrom
lossless-type-annotations

Conversation

@colinrozzi
Copy link
Copy Markdown
Owner

Summary

Make the value literal format truly lossless for chain replay.

The format added in #13 had a hidden lossiness: two Value instances with different stored type info could produce identical Display output. For example:

  • Value::Result { ok_type: String, err_type: String, value: Ok(Tuple([])) } displays as ok<string>(())
  • Value::Result { ok_type: Tuple([]), err_type: String, value: Ok(Tuple([])) } also displays as ok<string>(())

Different stored types → different CGRF bytes → different chain hashes → replay diverges.

Fix

Always annotate the type info that can't be inferred from the value:

Before After
none none<list<u8>>
some(42u32) some<u32>(42u32)
ok(42u32) ok<u32, string>(42u32)
err("bad") err<u32, string>("bad")
[] []<u8>

Non-empty lists still infer elem_type from the first item.

Verification

  • All 24 packr-abi tests pass, including new test_cgrf_round_trip that asserts byte-identical CGRF after Display → parse → encode for the cases that previously diverged.
  • cargo clippy -p packr-abi -- -D warnings clean.
  • End-to-end: a recorded theater chain now replays with full hash verification (Replay complete: 4/4 events verified via streaming).

🤖 Generated with Claude Code

@colinrozzi colinrozzi enabled auto-merge (squash) May 8, 2026 04:16
@colinrozzi colinrozzi merged commit 163ad91 into main May 8, 2026
2 checks passed
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