On Fri, Sep 6, 2024, at 22:45, Larry Garfield wrote:
> Hi Rob.
>
> First of all, I'm very much in favor of type aliases generally, so thank you for taking a swing at this.
>
> Second, it looks like you've run into the main design issue that has always prevented them in the past: Should aliases be file-local and thus not reusable, or global and thus we need to figure out autoloading for them? It looks like your answer to that question at the moment is "yes". :-) While I can see the appeal, I don't think that's the best approach. Or rather, if we go that route, they shouldn't be quite so similar syntactically.
>
> There seems to be two different implementations living in the same RFC, uncomfortably. In one, it's a compiler-time replacement. In the other, it's a special class-like. But the RFC seems to go back and forth on what happens in which case, and I'm not sure which is which.
>
> However, you have demonstrated a working class-like for it, which is frankly the biggest hurdle. So I think the direction has promise, but should be adjusted to go all-in on that approach.
>
> To wit:
>
> typealias Stringy: string|Stringable;
> typealias UserID: Int;
> typealias TIme: Hour|Minute|Second;
> typealias FilterCallback: callable(mixed $a): bool; (eventually...)
>
> (etc.)
>
> Each of those produces a class-like, which can therefore be autoloaded like a class. The syntax is also a bit closer to a class (or an Enum, I suppose), so it's much more self-evident that they are defining a reusable thing (whereas "use" does not do that currently). And the syntax is not stringy, like the proposed type_alias(), so it's easier to write. I wouldn't even include type_alias() at that point. It exists at runtime, so reflection is meaningful.
>
> Aliases can then be used only in parameter, return, property, and instanceof types. Extends and implements are out of scope entirely.
>
> (Whether the keyword is typealias or typedef, uses : or =, or whatever, is its own bikeshed I won't dive into at the moment.)
>
> Then, as a separate, entirely optional, maybe even separate RFC (or second vote, or whatever), we have a `use string|Stringable as Stringy` syntax. Like all other `use` declarations, these are compile-time only, single-file only, and do not exist at runtime, so no reflection. They compile away just like all other use-statements now.
>
> I'm not personally convinced the second is really necessary if we do a good enough job on the first, but I'd probably not stand in the way of having both.
That's a really good point and would clear up quite a bit of confusion and complexity.
>
> Having typealias/typedef as a class-like also opens up some interesting potential in the future, because classes have all sorts of other things they do, but that is probably too complex scope creepy to get into here so I will not go further than that mention.
>
> I suspect there's also other edge case bits to worry about, particularly if trying to combine a complex alias with a complex type, which could lead to violating the DNF rule. For example:
Oh, DNF is the bane of my existence with this RFC—I don't want to mess this up. I'll see you at the end of the example, though.
>
> typealias Foo: (Bar&Baz)|Beep;
>
> use (Bar&Baz)|Beep as Foo;
>
> function narf(Foo&Stringable $s) {}
>
> With the compile time approach, that would expand to `(Bar&Baz)|Beep&Stringable`, which is not a valid type def.
I can see how you arrived at this, but I think you may have missed a step, since the entirety of Foo will be &'d with Stringable.
Foo = (Bar & Baz) | Beep
want: (Foo) & Stringable
expand Foo: ((Bar & Baz) | Beep) & Stringable
Which can be reduced to the following in proper DNF (at least, it compiles—https://3v4l.org/0bMlP):
(Beep & Stringable) | (Bar & Baz & Stringable)
It's probably a good idea to update the RFC explaining how expansion works.
>
> With the runtime approach, I don't know if that could be handled gracefully or if it would still cause an error.
>
> I'm not sure what the right solution is on this one, just pointing it out as a thing to resolve.
>
> --Larry Garfield
>
— Rob