Hi Jordi,

> Does the RFC allow referencing constants in type positions, or only raw
literal values?
>
> ```
> function foo(STATUS_ACTIVE|STATUS_INACTIVE $sort): void {}
> ```

Regarding your first point, referencing constants in type positions is not
supported. This RFC focuses specifically on scalar literals. A constant
access is not a literal itself, and allowing something like `FOO` in a type
position could cause ambiguity; at first sight, it's unclear whether it
refers to a class name or a constant. While casing might suggest one or the
other to a human, PHP allows both classes and constants to use any casing
style, which could lead to confusion.

This would also be a BC break, as the following is currently permitted in
PHP:

```
const Foo = 1;
class Foo {}

function bar(Foo $hello): void {}
```

If `Foo` were changed to mean `1` instead of an instance of `Foo` depending
on the surrounding context, this would break existing applications.

> ```
> What about enum values? For example:
>
> function bar(Status::Active->value $status): void {}
> // or simply as
> function bar(Status::Active $status): void {}
> ```

For the second point, using enum values is also out of scope.
`Status::Active->value` is a runtime expression, not a literal: the engine
would have to confirm that `Status` is an enum, that the case exists, and
that it is backed before reading `->value`. And `Status::Active` by itself
is an object, a single enum case, which would be a single-case type, a
separate feature from scalar literals. In both situations, requiring the
enum type itself is usually the better fit.

>  Also, I'm not really a fan of mixing literal types with unions.
>
> ```
> function foo(int|'bar' $param): void {}
> ```

Finally, regarding mixing literal types with wider types like `int|'bar'`,
this is supported by design. I believe restricting what may appear in a
union is the wrong approach; PHP should treat types uniformly, with
exceptions only for types that aren't value types and so are meaningless in
a union (`void`, `never`) or that are redundant (`mixed|T`, or a literal
already covered by its base type like `int|1`). If a union like
`float|'cold'|'hot'` lets a user express a real requirement for their API,
the type system should allow it.

Cheers,
Seifeddine.

Reply via email to