Re: [RFC] [Discussion] Literal Scalar Types

From: Date: Mon, 15 Jun 2026 16:44:16 +0000
Subject: Re: [RFC] [Discussion] Literal Scalar Types
References: 1 2  Groups: php.internals 
Request: Send a blank email to internals+get-131285@lists.php.net to get a copy of this message
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.

« previous php.internals (#131285) next »