Skip to content

refactor(hm-vm): SnapshotId exposes a public String field, allowing arbitrary IDs to be minted anywhere#119

Merged
markovejnovic merged 4 commits into
mainfrom
cq/hm-vm-snapshotid-exposes-a-public-string-field-11
Jun 10, 2026
Merged

refactor(hm-vm): SnapshotId exposes a public String field, allowing arbitrary IDs to be minted anywhere#119
markovejnovic merged 4 commits into
mainfrom
cq/hm-vm-snapshotid-exposes-a-public-string-field-11

Conversation

@markovejnovic

Copy link
Copy Markdown
Contributor

Smell

SnapshotId was declared as pub struct SnapshotId(pub String). The public tuple field meant any code could:

  • mint a snapshot handle from an arbitrary string (SnapshotId(some_string)), and
  • reach into the raw representation via .0 (done across docker.rs, vm.rs, and registry.rs).

A domain handle that exposes its raw String for free construction and mutation carries no invariant and is interchangeable with any other String, defeating the point of the newtype.

Change

  • Made the inner field private: pub struct SnapshotId(String).
  • Added SnapshotId::new(impl Into<String>) as the single construction entry point.
  • Added an as_str() accessor and a Deref<Target = str> impl for read access (the type already derives Display).
  • Updated internal call sites to construct via SnapshotId::new(...) and read via .as_str() instead of .0.

Behavior is unchanged: every .0 read becomes .as_str() (same &str), and every SnapshotId(x) becomes SnapshotId::new(x) (same value). No public-API capability is lost — construction and read are still available, just routed through named methods.

Pattern

This applies rust-analyzer's "distinct id newtypes per domain" doctrine: a domain handle should encapsulate its representation rather than expose it for free construction. rust-analyzer's FileId, CrateId, and the various interned ids follow exactly this shape — opaque newtypes constructed through dedicated constructors, not bare pub fields.

Validation

Only cargo check -p hm-vm (and --tests) was run locally, both pass. Full CI runs on this PR.

This is a low-blast-radius change, but it is a draft pending review.

… as_str

Replace the inherent as_str method with an idiomatic impl AsRef<str>; call
sites use as_ref() for &str args, Display for formatting, and a typed binding
for the rusqlite param.
@markovejnovic markovejnovic marked this pull request as ready for review June 10, 2026 20:12
@markovejnovic markovejnovic merged commit f1368ca into main Jun 10, 2026
17 checks passed
@markovejnovic markovejnovic deleted the cq/hm-vm-snapshotid-exposes-a-public-string-field-11 branch June 10, 2026 20:12
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