PHP 8.2 — Disjunctive Normal Form (DNF) types
Problem Description
PHP 8.2 introduces support for Disjunctive Normal Form (DNF) types, i.e., types composed of alternatives (union) of conjunctions (intersection). Example: (A&B)|null means "either null, or something that implements both A and B".
The code should be analyzed for places where DNF types could improve type precision.
Location
Potential places to analyze:
src/Reboot/Strategy/StackRebootStrategy.php — iterable $strategies parameter
src/config/compilerpass.php — service definitions
- Other places with complex types
Analysis
StackRebootStrategy::__construct()
Current code:
final class StackRebootStrategy implements RebootStrategyInterface
{
/**
* @param iterable<RebootStrategyInterface> $strategies
*/
public function __construct(private readonly iterable $strategies)
{
}
}
Potential DNF change:
public function __construct(private readonly (iterable&\Countable)|array $strategies)
Analysis: This change would require the passed argument to be countable (Countable). However, in the shouldReboot() method code, iteration occurs via foreach, which works on any iterable. Requiring Countable does not bring functional benefits, but only limits flexibility.
Conclusion: ❌ Not recommended — does not add value, limits flexibility.
Other classes and methods
Analyzed remaining classes in the project regarding complex types:
| File |
Type |
DNF possibility |
Justification |
src/Resolver.php |
ResolverInterface, array |
❌ |
Simple types, no intersection |
src/Scheduler/TaskHandler.php |
ContainerInterface, EventDispatcherInterface |
❌ |
Separate parameters, no union |
src/Http/HttpRequestHandler.php |
KernelInterface, RebootStrategyInterface |
❌ |
Separate parameters, no union |
src/ConfigLoader.php |
string, string, bool |
❌ |
Simple scalar types |
src/Middleware/SymfonyController.php |
KernelInterface |
❌ |
Single type |
Typical DNF use cases
DNF types are most useful in situations such as:
// External example — does not occur in the project
function process((Iterator&Countable)|array $items): void
In this project:
- No methods accept union types with intersection
- No complex type hierarchies requiring precise description
- Architecture relies on simple interfaces and types
Proposed Solution
No code changes.
DNF types have minimal applicability in this project due to:
- Simple architecture with few complex types
- No need to precisely describe conjunctions of interfaces in unions
- Design convention based on single, well-defined interfaces
Where DNF could be used (theoretically):
If the project had more complex type logic:
// Hypothetical example — does not occur in the project
function handleRequest((RequestInterface&CacheableInterface)|null $request): void
Such situations do not occur in the current project.
Priority
🔵 MINOR — no application in this project.
DNF types are an advanced PHP 8.2 feature that is most useful in projects with complex type hierarchies. In this project, the architecture is simple enough that DNF does not bring benefits.
Tests
Not applicable — no code changes.
Documentation
It is worth documenting that DNF types have been analyzed and are not used due to:
- Architecture based on simple interfaces
- No complex union types requiring intersection
- No need for more precise type description
If the project evolves towards more complex types in the future, DNF may become useful.
PHP 8.2 — Disjunctive Normal Form (DNF) types
Problem Description
PHP 8.2 introduces support for Disjunctive Normal Form (DNF) types, i.e., types composed of alternatives (union) of conjunctions (intersection). Example:
(A&B)|nullmeans "either null, or something that implements both A and B".The code should be analyzed for places where DNF types could improve type precision.
Location
Potential places to analyze:
src/Reboot/Strategy/StackRebootStrategy.php—iterable $strategiesparametersrc/config/compilerpass.php— service definitionsAnalysis
StackRebootStrategy::__construct()Current code:
Potential DNF change:
Analysis: This change would require the passed argument to be countable (Countable). However, in the
shouldReboot()method code, iteration occurs viaforeach, which works on anyiterable. RequiringCountabledoes not bring functional benefits, but only limits flexibility.Conclusion: ❌ Not recommended — does not add value, limits flexibility.
Other classes and methods
Analyzed remaining classes in the project regarding complex types:
src/Resolver.phpResolverInterface,arraysrc/Scheduler/TaskHandler.phpContainerInterface,EventDispatcherInterfacesrc/Http/HttpRequestHandler.phpKernelInterface,RebootStrategyInterfacesrc/ConfigLoader.phpstring,string,boolsrc/Middleware/SymfonyController.phpKernelInterfaceTypical DNF use cases
DNF types are most useful in situations such as:
In this project:
Proposed Solution
No code changes.
DNF types have minimal applicability in this project due to:
Where DNF could be used (theoretically):
If the project had more complex type logic:
Such situations do not occur in the current project.
Priority
🔵 MINOR — no application in this project.
DNF types are an advanced PHP 8.2 feature that is most useful in projects with complex type hierarchies. In this project, the architecture is simple enough that DNF does not bring benefits.
Tests
Not applicable — no code changes.
Documentation
It is worth documenting that DNF types have been analyzed and are not used due to:
If the project evolves towards more complex types in the future, DNF may become useful.