Avoid reevaluating duplicate QuickCheck shrinks - #4150
Conversation
There was a problem hiding this comment.
Pull request overview
Adds an opt-in mechanism to avoid re-evaluating duplicate shrink candidates during QuickCheck shrinking by introducing a shrink_equal equivalence function and tracking previously seen candidates in the shrink driver.
Changes:
- Extend
@quickcheck.reportand@quickcheck.checkwith an optionalshrink_equal : (A, A) -> Boolparameter. - Update the shrink driver to skip property/filter evaluation for candidates considered equivalent to any previously examined candidate.
- Add regression tests covering a self-repeating shrinker and a 2-state shrink cycle.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| quickcheck/pkg.generated.mbti | Updates the public interface signatures for report/check to include shrink_equal. |
| quickcheck/driver.mbt | Implements deduplication in shrink_failure and threads shrink_equal through report and check (plus docs). |
| quickcheck/driver_test.mbt | Adds tests ensuring equivalent/cyclic shrink candidates are not re-evaluated. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
585bbc7 to
7a4baa3
Compare
|
Thanks for the PR — the implementation is clean and well-tested. Before growing the Our hesitation is that the benefit looks marginal in typical usage:
There's also a correctness footgun: a If the motivating case is expensive (integration-style) properties with heavily overlapping shrink streams, that's worth supporting — but then a keyed design ( |
Adds an optional
shrink_equalequivalence function toreportandcheck. When supplied, the shrink driver tracks candidates it has already examined and skips repeated property/filter evaluation.Duplicate candidates still count toward
max_shrinks, preserving termination for infinite shrink streams. The default comparator treats candidates as distinct, so existing callers and types withoutEqorHashremain unaffected.Tests cover both a self-repeating shrinker and an
A -> B -> Acycle.Validation:
moon test --target all,moon check --target all, andmoon info.