rfc:sum_types

This is an old revision of the document!


PHP RFC: Sum Types

Introduction

In PHP 5.1 the ability to provide explicit types for parameters was added to PHP. It supported classes, interfaces and arrays. In PHP 5.4 the callable pseudo-type was added. The ability to provide explicit return types was added in PHP 7 but did not allow returning something or null, a commonly requested feature. Later an RFC for adding explicit scalar types was proposed and a few people wanted to know why there isn't a numeric type to handle the case where int and float are both accepted. I have personally wanted the ability to type against both array and Traversable in some of my libraries.

All of these requests and discussions suggest that the ability to accept multiple types for a parameter or return type could be useful. This RFC is an investigation into the feasibility of this idea and to flesh out the impact it would have on other parts of PHP.

Proposal

This RFC proposes the ability to define multiple types for a parameter or return type and calls them “sum types”. Here is an example of a parameter accepting both array and Traversable simultaneously:

function (array|Traversable $in) {
    foreach ($in as $value) {
        echo $value, PHP_EOL;
    }
}

Assuming that we allow a type of null we could use this feature to avoid special syntax for explicit nullable types; instead of ?Foo we can use Foo|null.

Proposed PHP Version(s)

It is not yet known if this requires backwards compatibility breaks. It could theoretically target PHP 7.NEXT but possibly should wait until PHP 8 (or whatever we call it).

RFC Impact To Opcache

There is not yet an implementation, but this will certainly necessitate changes in opcache.

Open Issues

Weak Scalar Types

If PHP adds explicit weak scalar types there is a question of how things will get converted in some situations. As an example, if we have a sum type of int and float and are passed the string “10” how is it converted?

function f(int|float $number) {
    return $number * 2;
}
f("10");

Would it be converted to int(10) or float(10), since either is acceptable? Does it matter given they are both acceptable?

This issue would be avoided if a parameter type exactly matches the input type or if PHP has strict scalar types.

Long Type Names

Since you can create a chain of types the names can get quite lengthy. Even the fairly short sum type of array|Traversable can be repetitive to type out. Should a method to provide type aliases exist? It may be helpful to look at HHVM's Type Aliasing.

Reflection

There isn't any part of our current Reflection extension that can deal with sum types and I have not yet given it any thought.

Or False

Peter Cowburn (salathe) has suggested that being able to explicitly use |false for return types could be helpful as this is a common idiom in PHP's standard functions. As an example, the function signature for strpos could change:

// from
strpos ( string $haystack , mixed $needle [, int $offset = 0 ] ): mixed
// to
strpos ( string $haystack , mixed $needle [, int $offset = 0 ] ): int|false

Future Scope

This sections details areas where the feature might be improved in future, but that are not currently proposed in this RFC.

Proposed Voting Choices

This RFC requires that two-thirds of voters vote in favor of the RFC to pass.

Patches and Tests

Presently no patch.

References

Links to external references, discussions or RFCs

Rejected Features

Keep this updated with features that were discussed on the mail lists.

rfc/sum_types.1424104711.txt.gz · Last modified: 2017/09/22 13:28 (external edit)