Add compile-time-checked ghost/observe layer - #56
Merged
Conversation
Add an optional layer on top of the existing API for writing read-only test properties and ghost state: - `observe!` runs a property block that may call any precept API and may optionally borrow one or more `GhostState`s. Its `Fn` bound makes it easier to avoid unintentionally mutating the system under test. - `GhostState<T>` is opaque auxiliary state that exists only to express properties. Its only mutator is `GhostState::mutate` and its only reader is `observe!`, and it is compiled out entirely (to a zero-sized type) when the `enabled` feature is off. Ported from antithesis-sdk-rust#34, adapted to precept's `enabled` feature gate and `expect_*` macros. Co-Authored-By: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds an optional layer on top of the existing API for writing read-only test properties and ghost state, ported from antithesis-sdk-rust#34 and adapted to precept's
enabledfeature gate andexpect_*macros.observe!runs a property block that may call any precept API and may optionally borrow one or moreGhostStates. ItsFnbound makes it easier to avoid unintentionally mutating the system under test — the borrow checker rejects&mutcaptures, reassignment, and moves inside the block. This is a best-effort guardrail rather than a hard guarantee: it can't stop interior mutability (Cell,RefCell,Mutex, atomics) orunsafe, and the module docs call that out explicitly.GhostState<T>is opaque auxiliary state that exists only to express properties. Its only mutator isGhostState::mutateand its only reader isobserve!, so it can't leak into or perturb the system it describes. When theenabledfeature is off it becomes a zero-sized type and every access compiles out, while the read-only and type checks still happen in every build configuration.Everything is implemented in safe Rust with a plain
Fnbound — nounsafe, proc macros, or AST inspection. The layer is exercised by unit tests (gated behavior plus an always-on smoke test) and doctests, includingcompile_faildoctests that prove mutation attempts don't compile. Verified against the full CI matrix — build, tests, doctests, clippy, and fmt — with and without--all-features.