Skip to content

Create ShortCircuit validator and ShortCircuitable interface#1663

Merged
henriquemoody merged 1 commit intoRespect:mainfrom
henriquemoody:validator/short-circuit
Feb 5, 2026
Merged

Create ShortCircuit validator and ShortCircuitable interface#1663
henriquemoody merged 1 commit intoRespect:mainfrom
henriquemoody:validator/short-circuit

Conversation

@henriquemoody
Copy link
Member

@henriquemoody henriquemoody commented Feb 1, 2026

This commit introduces a mechanism for validators to return early once the validation outcome is determined, rather than evaluating all child validators.

The ShortCircuit validator evaluates validators sequentially and stops at the first failure, similar to how PHP's && operator works. This is useful when later validators depend on earlier ones passing, or when you want only the first error message.

The ShortCircuitCapable interface allows composite validators (AllOf, AnyOf, OneOf, NoneOf, Each, All) to implement their own short-circuit logic:

  • AllOf: stops at first failure (like &&)
  • AnyOf: stops at first success (like ||)
  • OneOf: stops when two validators pass (already invalid)
  • NoneOf: stops at first success (already invalid)
  • Each/All: stops at first failing item

Why "ShortCircuit" instead of "FailFast":

The name "FailFast" was initially considered but proved misleading. While AllOf stops on failure (fail fast), AnyOf stops on success (succeed fast), and OneOf stops on the second success. The common behavior is not about failing quickly, but about returning as soon as the outcome is determined—which is exactly what short-circuit evaluation means. This terminology is familiar to developers from boolean operators (&& and ||), making the behavior immediately understandable.


Local benchmark results

Before

Screenshot 2026-02-02 at 00 29 41

After

Screenshot 2026-02-02 at 00 29 09

@henriquemoody henriquemoody requested a review from alganet February 1, 2026 12:36
@codecov
Copy link

codecov bot commented Feb 1, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.55%. Comparing base (e636b63) to head (b701fac).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@             Coverage Diff              @@
##               main    #1663      +/-   ##
============================================
+ Coverage     99.54%   99.55%   +0.01%     
- Complexity      932      966      +34     
============================================
  Files           191      192       +1     
  Lines          2182     2269      +87     
============================================
+ Hits           2172     2259      +87     
  Misses           10       10              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@henriquemoody henriquemoody force-pushed the validator/short-circuit branch from e6287f2 to 2bc3837 Compare February 1, 2026 12:37
@henriquemoody henriquemoody force-pushed the validator/short-circuit branch from 2bc3837 to fdd7ce6 Compare February 1, 2026 12:56
Copy link
Member

@alganet alganet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall seems like a solid prototype of what #1633 also aims to achieve, with similar gains and more ambitious (tackling Each, for example).

If we're aiming for completeness (no multi-step PRs), I do believe KeySet should also be available for global short circuit. Otherwise, I would prefer if you did it in smaller steps (logical AllOf/OneOf/NoneOf/AnyOf/Circuit first, then the others that require more heuristic to short circuit properly). It's up to you (single-shot or smaller PRs, I'm okay with either choice).

@henriquemoody henriquemoody force-pushed the validator/short-circuit branch 3 times, most recently from a69fddc to 9dc4e93 Compare February 1, 2026 23:29
@henriquemoody henriquemoody force-pushed the validator/short-circuit branch 6 times, most recently from 3f77b12 to 68593c2 Compare February 5, 2026 11:05
@henriquemoody henriquemoody changed the title Create ShortCircuit validator and ShortCircuitCapable interface Create ShortCircuit validator and ShortCircuitable interface Feb 5, 2026
@henriquemoody henriquemoody requested a review from Copilot February 5, 2026 11:06
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR renames the Circuit validator to ShortCircuit and introduces a ShortCircuitable interface that enables composite validators to implement optimized short-circuit evaluation. The renaming better reflects the concept of short-circuit evaluation (similar to boolean operators && and ||) rather than the misleading "fail fast" terminology.

Changes:

  • Renamed Circuit validator to ShortCircuit with updated documentation and all references
  • Added ShortCircuitable interface for validators that support short-circuit evaluation
  • Implemented short-circuit behavior in composite validators: AllOf, AnyOf, OneOf, NoneOf, Each, All, and KeySet
  • Added new check() method to ValidatorBuilder for short-circuit validation with exceptions
  • Modified isValid() to use short-circuit evaluation for performance optimization
  • Updated all mixin interfaces to reflect the naming change

Reviewed changes

Copilot reviewed 59 out of 59 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/Validators/ShortCircuit.php Renamed from Circuit, implements short-circuit evaluation of validators
src/Validators/Core/ShortCircuitable.php New interface for validators supporting short-circuit evaluation
src/Helpers/CanEvaluateShortCircuit.php Helper trait for delegating to short-circuit evaluation when available
src/ValidatorBuilder.php Added check() method and ShortCircuitable interface implementation
src/Validators/{AllOf,AnyOf,OneOf,NoneOf,Each,All,KeySet}.php Implemented short-circuit evaluation for composite validators
src/Validators/{Domain,Tld,Url}.php Updated to use ShortCircuit instead of Circuit
tests/unit/Validators/ShortCircuitTest.php Renamed and updated test class
tests/unit/Validators/{AllOf,AnyOf,OneOf,NoneOf,Each,All,KeySet}Test.php Added short-circuit behavior tests
tests/feature/Validators/*.php Comprehensive feature tests for short-circuit behavior
tests/benchmark/CompositeValidatorsBench.php New benchmark tests for performance comparison
src/Mixins/*.php Updated all mixin interfaces to use shortCircuit instead of circuit
docs/validators/ShortCircuit.md New documentation replacing Circuit.md
docs/validators/Circuit.md Removed old documentation
docs/validators/{AllOf,AnyOf,OneOf,NoneOf,After}.md Updated references from Circuit to ShortCircuit
docs/validators.md Updated validator listing and categorization
docs/migrating-from-v2-to-v3.md Updated migration guide with ShortCircuit information
docs/feature-guide.md Updated feature guide references

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@henriquemoody henriquemoody force-pushed the validator/short-circuit branch 3 times, most recently from 1820e37 to 7838e3a Compare February 5, 2026 12:02
@henriquemoody henriquemoody requested a review from alganet February 5, 2026 12:02
@henriquemoody henriquemoody marked this pull request as ready for review February 5, 2026 12:03
@henriquemoody
Copy link
Member Author

@alganet, I think this might be blocking our release, but I'm short on time in the upcoming days. I wanted to track the performance issue with each and all, but I don't have much time at moment, and I'm prioritizing reviewing your merge request. I think we could try working on performance of all and each later on, and merge this as is, but let me know if you think otherwise.

@henriquemoody henriquemoody force-pushed the validator/short-circuit branch from 7838e3a to f44e979 Compare February 5, 2026 12:09
@henriquemoody henriquemoody force-pushed the validator/short-circuit branch 4 times, most recently from ef966ae to c2957db Compare February 5, 2026 12:16
This commit introduces a mechanism for validators to return early once
the validation outcome is determined, rather than evaluating all child
validators.

The ShortCircuit validator evaluates validators sequentially and stops
at the first failure, similar to how PHP's && operator works. This is
useful when later validators depend on earlier ones passing, or when
you want only the first error message.

The ShortCircuitCapable interface allows composite validators (AllOf,
AnyOf, OneOf, NoneOf, Each, All) to implement their own short-circuit
logic.

Why "ShortCircuit" instead of "FailFast":

The name "FailFast" was initially considered but proved misleading.
While AllOf stops on failure (fail fast), AnyOf stops on success
(succeed fast), and OneOf stops on the second success. The common
behavior is not about failing quickly, but about returning as soon as
the outcome is determined—which is exactly what short-circuit
evaluation means. This terminology is familiar to developers from
boolean operators (&& and ||), making the behavior immediately
understandable.

Co-authored-by: Alexandre Gomes Gaigalas <alganet@gmail.com>
Assisted-by: Claude Code (Opus 4.5)
@henriquemoody henriquemoody force-pushed the validator/short-circuit branch from c2957db to b701fac Compare February 5, 2026 16:32
@henriquemoody henriquemoody merged commit b701fac into Respect:main Feb 5, 2026
7 checks passed
@henriquemoody henriquemoody deleted the validator/short-circuit branch February 5, 2026 16:37
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.

2 participants