Hello Internals,
I’d like to request your comments on type aliases (not to be confused with typedefs) at https://wiki.php.net/rfc/typed-aliases
TL;DR (it’s actually rather short):
Following the same syntax as other use'ing statements, you can alias a type:
use type int|float as Number;
function sum(Number $a, Number $b): Number { return $a + $b; }
You can also include types, with some restrictions:
include types 'math-types.php';
function sum(Number $a, Number $b): Number { return $a + $b; }
These are compile-time replacements that serve to make code more readable and reduce repetition with no runtime overhead. Type aliases follow the same scoping rules as other use imports.
— Rob
Can we follow the approach other languages used for their type alias
implementation?
typedef UserType: string|null;
// or
typedef UserType = UserStatus|AlternativeType|null;
We could also introduce a way to group multiple type alias in a single file:
namespace App;
typedef TypeGroup {
typedef UserType: string|null;
typedef CustomType: \MyCustomType|\AnotherType|null;
}
Then, it can be imported by using:
// single
use type UserType;
// group
use type App\TypeGroup;
This feels more familiar, nice and structured.
NOTE: it's just a suggestion from my own view.
Hello Internals,
I’d like to request your comments on type aliases (not to be confused with
typedefs) at https://wiki.php.net/rfc/typed-aliasesTL;DR (it’s actually rather short):
Following the same syntax as other use'ing statements, you can alias a
type:use type int|float as Number;
function sum(Number $a, Number $b): Number { return $a + $b; }
You can also include types, with some restrictions:
include types 'math-types.php';
function sum(Number $a, Number $b): Number { return $a + $b; }
These are compile-time replacements that serve to make code more readable
and reduce repetition with no runtime overhead. Type aliases follow the
same scoping rules as other use imports.— Rob
Can we follow the approach other languages used for their type alias implementation?
typedef UserType: string|null; // or typedef UserType = UserStatus|AlternativeType|null;We could also introduce a way to group multiple type alias in a single file:
namespace App; typedef TypeGroup { typedef UserType: string|null; typedef CustomType: \MyCustomType|\AnotherType|null; }Then, it can be imported by using:
// single use type UserType; // group use type App\TypeGroup;This feels more familiar, nice and structured.
NOTE: it's just a suggestion from my own view.
__
Hello Internals,I’d like to request your comments on type aliases (not to be confused with typedefs) at https://wiki.php.net/rfc/typed-aliases
TL;DR (it’s actually rather short):
Following the same syntax as other use'ing statements, you can alias a type:
use type int|float as Number;
function sum(Number $a, Number $b): Number { return $a + $b; }
You can also include types, with some restrictions:
include types 'math-types.php';
function sum(Number $a, Number $b): Number { return $a + $b; }
These are compile-time replacements that serve to make code more readable and reduce repetition with no runtime overhead. Type aliases follow the same scoping rules as other use imports.
— Rob
A typedef is a bit different. It’s a real type.
I’m working on combining my Records RFC and the pattern matching RFC (assuming it gets accepted). Thus you’ll be able to do something like:
typedef UserID: int is > 0;
Which would basically compile into the previous Record:
record UserID(int $value) { $value > 0 }
-ish.
That gets you value semantics and with a bit more work, inherited operators (numbers act like numbers, arrays act like arrays, strings like strings, etc).
It doesn’t need pattern matching, but it really helps. This is just aliases, which are complementary but separate.
PS: please remember to bottom post (write your reply under the person you are replying to).
— Rob
Hello Internals,
I’d like to request your comments on type aliases (not to be confused
with typedefs) at https://wiki.php.net/rfc/typed-aliasesTL;DR (it’s actually rather short):
Following the same syntax as other use'ing statements, you can alias a type:
use type int|float as Number;
function sum(Number $a, Number $b): Number { return $a + $b; }
You can also include types, with some restrictions:
include types 'math-types.php';
function sum(Number $a, Number $b): Number { return $a + $b; }
These are compile-time replacements that serve to make code more
readable and reduce repetition with no runtime overhead. Type aliases
follow the same scoping rules as other use imports.— Rob
Thanks, Rob! This does seem like a good low-hanging fruit piece to attack. Most importantly, I don't see anything here that would preclude more formal TypeDef structures in the future.
A few other notes:
-
Should
mixedbe allowed as in an alias definition? Sincemixedmatches anything, it would render the entire alias redundant as it's then equivalent tomixed. -
What if any conflict resolution is there if you include two different type files that declare the same alias?
-
Because it's all compile time, I assume two aliases with the same source but different names become compatible?
Eg:
use type string|Stringable as Stringy;
use type string|Stringable as Stringish;
Those are mutually compatible in practice, yes?
-
Are aliases case sensitive? You're using Capitalized names in the RFC, but I don't know if that means anything... (Please state in the RFC.)
-
The "include type" syntax implies that it would not be possible to pre-load aliases via Composer autoload or opcache preloading. (Well, maybe the latter.) That feels like an unnecessary limitation, and is my main issue with the current design. Some way to have project-wide or package-wide definitions would be very helpful, without needing a manual include statement in every file.
-
Does it matter where the
include typestatement goes? Must it be at the top under theusestatements, or could it be anywhere? -
Not allowing
usestatements in type include files: This feels like a very unfortunate limitation. Is there any way to obviate that? It's all compile time, as you said...
Overall, I am tentatively in favor.
--Larry Garfield
Thanks, Rob! This does seem like a good low-hanging fruit piece to attack. Most importantly, I don't see anything here that would preclude more formal TypeDef structures in the future.
A few other notes:
- Should
mixedbe allowed as in an alias definition? Sincemixedmatches anything, it would render the entire alias redundant as it's then equivalent tomixed.
This is already a compiler error: "Type mixed can only be used as a standalone type." That being said, I guess this could be used to rename "mixed" to something else, but I don't know why you'd want to do that. I'd be open to throwing it in with "never" and "void", but "mixed" is an actual type that can be returned, which is why it wasn't.
- What if any conflict resolution is there if you include two different type files that declare the same alias?
It works the same as use in other ways:
"Cannot use type DateTimeImmutable as DT because the name is already in use"
- Because it's all compile time, I assume two aliases with the same source but different names become compatible?
Eg:use type string|Stringable as Stringy;
use type string|Stringable as Stringish;Those are mutually compatible in practice, yes?
That's correct. You'd need typedefs to be able to enforce a difference there.
- Are aliases case sensitive? You're using Capitalized names in the RFC, but I don't know if that means anything... (Please state in the RFC.)
Good catch; will do. For the record, it's as type-sensitive as any other type in PHP (as in not case-sensitive at all).
- The "include type" syntax implies that it would not be possible to pre-load aliases via Composer autoload or opcache preloading. (Well, maybe the latter.) That feels like an unnecessary limitation, and is my main issue with the current design. Some way to have project-wide or package-wide definitions would be very helpful, without needing a manual include statement in every file.
Currently, we don't have packages or even "real" namespaces, so as much as I'd want this, there'd need to be some settling on what authority a namespace really has. The amount of pushback that I got on the namespace-private RFC indicates to me that people don't want namespaces to have any authority, but they want "packages" but nobody knows what a package is ... but clearly, namespaces aren't anything.
I digress. Sadly, no, this isn't possible with the current design. That doesn't mean it can't be possible in the future, though, with some autoloading overhaul or changes (see: Gina's Core Autoloading RFC under Drafts). But currently, it has to pull off some shenanigans to compile the file in the file (instead of during runtime like require and include). Hence why type-files may only contain types and no other code.
Basically, we just have to have some way to tell the compiler "also include these type aliases when compiling this file" -- that could be "every file from here on out gets the aliases" (ie, a use global type float|int as Number -- or something like that), or "include this type file" into this source file.
The former would work best with today's current autoloader, but it would be "trapped" in that paradigm and would make it harder to eventually create a "type autoloader". I could be wrong, though, and I'm open to other people's ideas and opinions. I don't like the current implementation very much, and while the former is much simpler to implement, I'm reasonably confident the current implementation can be improved.
- Does it matter where the
include typestatement goes? Must it be at the top under theusestatements, or could it be anywhere?
It's basically a "copy this file right here", so it doesn't need to necessarily be at the top, but trying to include it in a function would create a syntax issue. I should clarify this in the RFC.
- Not allowing
usestatements in type include files: This feels like a very unfortunate limitation. Is there any way to obviate that? It's all compile time, as you said...
I had to go make sure I didn't have a typo in there. I assume you mean namespaces? Namespaces in type files have a very weird problem once they get included. For instance, namespaces are also compile-time prefixes, and using statements are per namespace, not per file. By eliminating the namespace, it becomes unambiguous that it’s per-file. That prevents shenanigans like:
// my-types.php
namespace Hello {
use int|float as Number; // at the end of the namespace, the "use" is lost
}
namespace World {
use Number as Foo; // Number isn't a thing, neither is Hello\Number
}
Even just declaring a namespace for resolving types would create interesting effects:
// my-types.php
namespace Foo;
use int|float as Number;
// alias actually becomes Foo\Number and gets cleared at the end of the file
In all reality, I generally expect tooling to make this easier. Like right-click the alias in your IDE and select: "move to type file" or something like that and have it automatically appended to your project's type file. Same with typing a type in a type file and having it automatically include it, just like it will automatically "use" a type outside of the current namespace for you.
Overall, I am tentatively in favor.
--Larry Garfield
Thanks!
— Rob
Thanks, Rob! This does seem like a good low-hanging fruit piece to attack. Most importantly, I don't see anything here that would preclude more formal TypeDef structures in the future.
A few other notes:
- Should
mixedbe allowed as in an alias definition? Sincemixedmatches anything, it would render the entire alias redundant as it's then equivalent tomixed.This is already a compiler error: "Type mixed can only be used as a
standalone type." That being said, I guess this could be used to rename
"mixed" to something else, but I don't know why you'd want to do that.
I'd be open to throwing it in with "never" and "void", but "mixed" is
an actual type that can be returned, which is why it wasn't.
Since it would never be meaningful, I would agree with tossing it into the no pile with never and void.
- The "include type" syntax implies that it would not be possible to pre-load aliases via Composer autoload or opcache preloading. (Well, maybe the latter.) That feels like an unnecessary limitation, and is my main issue with the current design. Some way to have project-wide or package-wide definitions would be very helpful, without needing a manual include statement in every file.
Currently, we don't have packages or even "real" namespaces, so as much
as I'd want this, there'd need to be some settling on what authority a
namespace really has. The amount of pushback that I got on the
namespace-private RFC indicates to me that people don't want namespaces
to have any authority, but they want "packages" but nobody knows what a
package is ... but clearly, namespaces aren't anything.I digress. Sadly, no, this isn't possible with the current design. That
doesn't mean it can't be possible in the future, though, with some
autoloading overhaul or changes (see: Gina's Core Autoloading RFC under
Drafts). But currently, it has to pull off some shenanigans to compile
the file in the file (instead of during runtime like require and
include). Hence why type-files may only contain types and no other code.Basically, we just have to have some way to tell the compiler "also
include these type aliases when compiling this file" -- that could be
"every file from here on out gets the aliases" (ie, ause global type float|int as Number-- or something like that), or "include this type
file" into this source file.The former would work best with today's current autoloader, but it
would be "trapped" in that paradigm and would make it harder to
eventually create a "type autoloader". I could be wrong, though, and
I'm open to other people's ideas and opinions. I don't like the current
implementation very much, and while the former is much simpler to
implement, I'm reasonably confident the current implementation can be
improved.
- Does it matter where the
include typestatement goes? Must it be at the top under theusestatements, or could it be anywhere?It's basically a "copy this file right here", so it doesn't need to
necessarily be at the top, but trying to include it in a function would
create a syntax issue. I should clarify this in the RFC.
Since use statements have to be before any executable code, doesn't that therefore imply that the include type directive must go there as well?
Which then leads me to asking if we shouldn't just use use for that as well. Something like:
use type string|Stringable as Stringy;
use types /some/file/here.php; // Pull in all the types from this file.
Might that help with the autoloading issues? (I dunno, just thinking aloud here.)
- Not allowing
usestatements in type include files: This feels like a very unfortunate limitation. Is there any way to obviate that? It's all compile time, as you said...I had to go make sure I didn't have a typo in there. I assume you mean
namespaces? Namespaces in type files have a very weird problem once
they get included. For instance, namespaces are also compile-time
prefixes, and using statements are per namespace, not per file. By
eliminating the namespace, it becomes unambiguous that it’s per-file.
That prevents shenanigans like:
No no, I'm talking about use statements. One of the examples you show is:
// types.php - correct usage
use type \App\Models\User|\App\Models\Admin as AuthUser;
Which... eew. I totally understand not allowing a namespace declaration in the type file, but it would be much nicer to be able to type:
<?php
use App\Models\User;
use App\Models\Admin;
use type User|Admin as AuthUser;
That's what I'm talking about.
--Larry Garfield
Good catch; will do. For the record, it's as type-sensitive as any other
type in PHP (as in not case-sensitive at all).
Well, provided you stick to ASCII-only identifiers...
class Thïng {}
class THÏNG {}
class thïng {}
Good catch; will do. For the record, it's as type-sensitive as any other
type in PHP (as in not case-sensitive at all).Well, provided you stick to ASCII-only identifiers...
class Thïng {} class THÏNG {} class thïng {}
Classes are not case-sensitive: https://3v4l.org/PLb4J#v8.5.0
If you are using PSR-4 + a case-sensitive filesystem, then they appear to be, but that's due to the filesystem, not PHP.
— Rob
Well, provided you stick to ASCII-only identifiers...
class Thïng {} class THÏNG {} class thïng {}Classes are not case-sensitive: https://3v4l.org/PLb4J#v8.5.0
Morgan is right that the case folding is only applied to ASCII letters. In the example, "Thïng" and "thïng" are the same, because they differ only by "T" vs "t", but "THÏNG" is different, because "ï" and "Ï" are not case folded. https://3v4l.org/PLb4J#v8.5.0
In fact, they're not treated as letters at all. If I remember correctly, they're not even analysed as code points, each individual byte above 0x7F is treated as completely opaque.
Rowan Tommins
[IMSoP]
Well, provided you stick to ASCII-only identifiers...
class Thïng {} class THÏNG {} class thïng {}Classes are not case-sensitive: https://3v4l.org/PLb4J#v8.5.0
Morgan is right that the case folding is only applied to ASCII letters. In the example, "Thïng" and "thïng" are the same, because they differ only by "T" vs "t", but "THÏNG" is different, because "ï" and "Ï" are not case folded. https://3v4l.org/PLb4J#v8.5.0
In fact, they're not treated as letters at all. If I remember correctly, they're not even analysed as code points, each individual byte above 0x7F is treated as completely opaque.
Rowan Tommins
[IMSoP]
Ah, thanks! I missed the little dots on the i. It’s worth pointing out that the behaviour here isn’t changed, just my understanding of what the current behaviour actually is. :) It's using the same stuff everywhere else is using, so there isn't any new behaviour here, just the same behaviour in new places.
— Rob
Hi Rob,
(We've been using a lot of PHPStan type aliasing lately in the Star-Interop work, so this topic is timely.)
Is there some possibility of making the aliases more classlike so they can be autoloaded? A la:
namespace Foo;
type number { as int|float; }
Then elsewhere:
use Foo\number;
function sum(number $a, number $b): number { return $a + $b; }
Let me know if I've missed something fundamental.
-- pmj
Hi Rob,
(We've been using a lot of PHPStan type aliasing lately in the Star-Interop work, so this topic is timely.)
Is there some possibility of making the aliases more classlike so they can be autoloaded? A la:
namespace Foo;
type number { as int|float; }Then elsewhere:
use Foo\number;
function sum(number $a, number $b): number { return $a + $b; }Let me know if I've missed something fundamental.
-- pmj
They fundamentally cannot be autoloaded because autoloading happens at runtime, not compile time. At least, with the current autoloader. Autoloading type aliases would need to have a fundamentally different type of autoloading that doesn’t exist today.
— Rob
Hi Rob,
(We've been using a lot of PHPStan type aliasing lately in the Star-Interop work, so this topic is timely.)
Is there some possibility of making the aliases more classlike so they can be autoloaded? A la:
namespace Foo;
type number { as int|float; }Then elsewhere:
use Foo\number;
function sum(number $a, number $b): number { return $a + $b; }Let me know if I've missed something fundamental.
-- pmj
They fundamentally cannot be autoloaded because autoloading happens at runtime, not compile time. At least, with the current autoloader. Autoloading type aliases would need to have a fundamentally different type of autoloading that doesn’t exist today.
Got it; thanks for the clarification.
-- pmj
Hey Rob & all,
One objection, one question.
The objection is to include types 'types.php'. You've clarified why types cannot be autoloaded (thanks again!) and so this is a way to let the compiler know where the types are. But I have to say I've spent a huge part of my career removing include/require when refactoring legacy code, and introducing it here causes me great heartache.
The question is a little more complicated, and also involves autoloading. Given a class Number that can be autoloaded ...
namespace Foo;
class Number { /* ... */ }
... and another class in the same namespace, that creates a "number" type alias...
namespace Foo;
use type int|float as Number;
class Bar { public function add(Number $a, Number $b) : Number { /* ... */ }
... which one "wins" -- the runtime autoloaded class, or the compile-time type alias?
(Apologies if this is covered in the RFC and I missed it.)
-- pmj
Hey Rob & all,
One objection, one question.
The objection is to
include types 'types.php'. You've clarified why types cannot be autoloaded (thanks again!) and so this is a way to let the compiler know where the types are. But I have to say I've spent a huge part of my career removing include/require when refactoring legacy code, and introducing it here causes me great heartache.
A new way of autoloading is out of scope... :D It doesn't preclude it from being autoloaded in the future, but currently, the only other reason to refactor autoloading would be to get function autoloading. That in itself would be nice, having another reason wouldn't necessarily be a bad thing either.
Further up-thread, I mentioned there were two ways to do this: this way, and making aliases "global". For example, a "use global type ... as ..." or something like that. I'm not opposed to this, per se, and if that’s the consensus, I'm fine with it.
The question is a little more complicated, and also involves autoloading. Given a class Number that can be autoloaded ...
namespace Foo;
class Number { /* ... */ }
... and another class in the same namespace, that creates a "number" type alias...
namespace Foo;
use type int|float as Number;
class Bar { public function add(Number $a, Number $b) : Number { /* ... */ }
... which one "wins" -- the runtime autoloaded class, or the compile-time type alias?
(Apologies if this is covered in the RFC and I missed it.)
It works just like it works today if you were to do this:
namespace Foo {
class Number {}
}
namespace Foo {
use GMP as Number;
class Bar { public function add Number $a, \Foo\Number $b): Number {}
}
In other words, the alias shadows the original and you have to use the FQN to resolve the real one.
— Rob
HI Rob,
Thanks for the RFC. I’m really happy to see a proposal for typed aliases,
but to be honest, I have some major concerns about the implementation
strategy, specifically the use types mechanism.
The proposed syntax (use types 'file.php') feels like a step backward. We
are essentially re-introducing the same autoloading pain points we
currently have with functions. I strongly believe type aliases should just
be first-class citizens like classes, interfaces, or enums, they should
live in the same symbol table (so you can't have a class User and a type
User) and follow standard namespacing and autoloading rules.
It should look like this:
namespace App\Aliases;
type UserIdentifier = string|int|Uuid;
And be used just like any other symbol:
use App\Aliases\UserIdentifier;
function greet(UserIdentifier $uid): void { ... }
I also want to highlight a specific issue from a tooling perspective. I
maintain a static analyzer (Mago - https://github.com/carthage-software/mago),
which uses a multi-threaded, and has an architecture similar to Psalm.
The use types <file> directive would be a massive headache. If an alias
is being imported from a file that was not configured in the source paths,
our analyzer would have to pause all analysis threads to fetch, parse, and
index that one file and make it available globally. This would severely
impact performance and concurrency. This is not a total blocker, and we
would probably find a workaround, but it would add significant complexity
and slow down analysis for everyone.
I recommend looking at how Hack handles this. They successfully implement
type (aliasing) and newtype (opaque types) in a way that feels natural
and integrates with the autoloader. Adopting a similar approach type Foo = ... would future-proof PHP for potential newtype additions later without
requiring a clunky import syntax now.
Regards,
Seifeddine Gmati.
Hello Internals,
I’d like to request your comments on type aliases (not to be confused with
typedefs) at https://wiki.php.net/rfc/typed-aliasesTL;DR (it’s actually rather short):
Following the same syntax as other use'ing statements, you can alias a
type:use type int|float as Number;
function sum(Number $a, Number $b): Number { return $a + $b; }
You can also include types, with some restrictions:
include types 'math-types.php';
function sum(Number $a, Number $b): Number { return $a + $b; }
These are compile-time replacements that serve to make code more readable
and reduce repetition with no runtime overhead. Type aliases follow the
same scoping rules as other use imports.— Rob
HI Rob,
Thanks for the RFC. I’m really happy to see a proposal for typed aliases, but to be honest, I have some major concerns about the implementation strategy, specifically the
use typesmechanism.The proposed syntax (
use types 'file.php') feels like a step backward. We are essentially re-introducing the same autoloading pain points we currently have with functions. I strongly believe type aliases should just be first-class citizens like classes, interfaces, or enums, they should live in the same symbol table (so you can't have a classUserand a typeUser) and follow standard namespacing and autoloading rules.It should look like this:
namespace App\Aliases; type UserIdentifier = string|int|Uuid;And be used just like any other symbol:
use App\Aliases\UserIdentifier; function greet(UserIdentifier $uid): void { ... }I also want to highlight a specific issue from a tooling perspective. I maintain a static analyzer (Mago - https://github.com/carthage-software/mago), which uses a multi-threaded, and has an architecture similar to Psalm.
The
use types <file>directive would be a massive headache. If an alias is being imported from a file that was not configured in the source paths, our analyzer would have to pause all analysis threads to fetch, parse, and index that one file and make it available globally. This would severely impact performance and concurrency. This is not a total blocker, and we would probably find a workaround, but it would add significant complexity and slow down analysis for everyone.I recommend looking at how Hack handles this. They successfully implement
type(aliasing) andnewtype(opaque types) in a way that feels natural and integrates with the autoloader. Adopting a similar approachtype Foo = ...would future-proof PHP for potentialnewtypeadditions later without requiring a clunky import syntax now.Regards,
Seifeddine Gmati.Hello Internals,
I’d like to request your comments on type aliases (not to be confused with typedefs) at https://wiki.php.net/rfc/typed-aliases
TL;DR (it’s actually rather short):
Following the same syntax as other use'ing statements, you can alias a type:
use type int|float as Number;
function sum(Number $a, Number $b): Number { return $a + $b; }
You can also include types, with some restrictions:
include types 'math-types.php';
function sum(Number $a, Number $b): Number { return $a + $b; }
These are compile-time replacements that serve to make code more readable and reduce repetition with no runtime overhead. Type aliases follow the same scoping rules as other use imports.
— Rob
Hi again!
I saw that you mentioned in previous emails that implementing
autoloading for type aliases isn't possible, so I wanted to verify
that, I spent some time digging to see if I could get the syntax I
proposed earlier working and I managed to get a working
implementation.
ref: https://github.com/carthage-software/php-src/tree/type-aliases
This approach would resolve the static analysis issues I mentioned
earlier, give us a cleaner mechanism for autoloading, and keep PHP's
behavior consistent.
Note that my implementation above is not complete, and would probably
need to be double and triple checked.
Regards,
Seifeddine Gmati.
Hi
Am 2025-12-02 23:23, schrieb Rob Landers:
I’d like to request your comments on type aliases (not to be confused
with typedefs) at https://wiki.php.net/rfc/typed-aliases
I'm generally in favor of having type aliases available, provided that
the design is sound. I believe there have been some discussions and
efforts before and my understanding is that getting them to work with a
sound design is complicated - or at least raises many edge case
questions.
As for your RFC, I have the following notes:
I also was wondering why the special include types syntax exists. You
answered that in a sibling thread, but it should also be in the RFC.
I feel that the include types syntax doesn't really fit PHP with two
consecutive keywords without any clear delimiters to indicate that the
second keyword effectively acts as a parameter to the first keyword.
I'm seeing in the PR that include types must use a string literal.
That should be mentioned in the RFC. I believe it's a significant
limitation in the developer experience.
In combination with (3), you are effectively reliant on relative paths
to include a types file. This raises questions about what the “base
path” is. Is it FILE? Is it the include_path INI? Is it the cwd?
The “copy and paste” semantics of include types also results in
backwards compatibility issues for libraries, because any time I add a
new type alias to my type file, it could conflict with another type that
the user of my library also needs.
The RFC doesn't explain where type aliases work. In the RFC I'm seeing
parameter and return type declarations. What about:
- Property Type Declarations
- The right side of
instanceof -
new TypeAlias()
The latter very likely doesn't work, but what will the error message be?
Will it be a “class not found”? Will it be “Cannot instantiate type
alias TypeAlias”?
How will type aliases appear in error messages more generally? Say I
have:
use type Foo|Bar as FooOrBar;
function foo(FooOrBar $x) { }
foo(1); // Will the error message reference FooOrBar or will it
reference Foo|Bar
What about Reflection?
For nested aliases, how will that work with “DNF types”? Consider:
use type Foo|Bar as FooOrBar;
use type Baz&FooOrBar as BazAndFooOrBar;
This would result in Baz&(Foo|Bar) which is not in DNF.
That's all I can think of for now, but I believe it already shows that
there are quite a number of questions that need to be answered and I
feel that the answers to those questions are likely not going to be
satisfactory by either resulting in a questionable developer experience
or by preventing a clean implementation of the future scope (e.g.
autoloading semantics).
Best regards
Tim Düsterhus