Skip to content

PHP 8.2 — Disjunctive Normal Form (DNF) types #49

@s2x

Description

@s2x

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:

  1. src/Reboot/Strategy/StackRebootStrategy.phpiterable $strategies parameter
  2. src/config/compilerpass.php — service definitions
  3. 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:

  1. Simple architecture with few complex types
  2. No need to precisely describe conjunctions of interfaces in unions
  3. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    code-qualityCode quality improvementsminorMinor priority - code quality

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions