On Thu, Mar 20, 2025, at 16:41, Bob Weinand wrote:
> 
>> Am 20.03.2025 um 16:28 schrieb Rob Landers <rob@bottled.codes>:
>> 
>> 
>> 
>> On Thu, Mar 20, 2025, at 16:12, Bob Weinand wrote:
>>> 
>>>> Am 20.03.2025 um 15:51 schrieb Rob Landers <rob@bottled.codes>:
>>>> 
>>>> 
>>>> 
>>>> On Wed, Mar 19, 2025, at 21:09, Bob Weinand wrote:
>>>>> 
>>>>> 
>>>>> On 19.3.2025 16:04:06, Rob Landers wrote:
>>>>>> On Tue, Mar 18, 2025, at 03:37, Bob Weinand wrote:
>>>>>>> Okay, I see the point with LSP. I'm not sure whether we need to 
>>>>>>> preserve LSP for that specific scenario, but neither can I say that we 
>>>>>>> should ignore it.
>>>>>>> 
>>>>>>> (Effectively implementing LSP would mean that there's an implicit 
>>>>>>> interface matching all public method signatures of the parent class, 
>>>>>>> for child classes - which is doable, but possibly too much for the 
>>>>>>> initial RFC.)
>>>>>>> 
>>>>>>> I would however ask, should we not implement LSP compatible inner 
>>>>>>> classes, to enforce that no child class may name a class the same than 
>>>>>>> any non-private inner class declared by any of its parents, until we 
>>>>>>> resolve this question (in possibly a future version of PHP).
>>>>>>> I do not think we should bar ourselves from allowing this in the future.
>>>>>> 
>>>>>> I'm not sure I understand what you are asking. But I think you are 
>>>>>> saying the following should be illegal?
>>>>>> 
>>>>>> class ParentOuter {
>>>>>>   class ParentInner {}
>>>>>> }
>>>>>> 
>>>>>> class ChildOuter extends ParentOuter {
>>>>>>   class ParentInner {} // not allowed
>>>>>> }
>>>>> Precisely.
>>>>> 
>>>>>>> And not pretending starts with using a different symbol than a 
>>>>>>> backslash.
>>>>>> 
>>>>>> I have been thinking about this for a couple of days now... When 
>>>>>> thinking through the ramifications of my decision to use :> over ::, 
>>>>>> this will also affect generics, most likely -- whenever that happens. 
>>>>>> This is because if this RFC passes, generics will want to be consistent 
>>>>>> with whatever exists currently.
>>>>>> 
>>>>>> If we were to use :>, then generics would probably look something like 
>>>>>> this to be consistent:
>>>>>> 
>>>>>> class Box<T> {
>>>>>>   public function add(self:>T $item) {}
>>>>>> }
>>>>>> 
>>>>>> The same thing would also probably apply to ::
>>>>>> 
>>>>>> class Box<T> {
>>>>>>   public function add(self::T $item) {}
>>>>>> }
>>>>>> 
>>>>>> With `\`, it nearly follows exactly what you would expect-ish:
>>>>>> 
>>>>>> use \Box\T as T;
>>>>>> 
>>>>>> class Box<T> {
>>>>>>   public function add(T $item) {}
>>>>>> 
>>>>>> // or without use
>>>>>>   public function add(Box\T $item) {}
>>>>>> }
>>>>>> 
>>>>>> With `\`, we can also just automatically check the current class as part 
>>>>>> of namespace resolution when compiling:
>>>>>> 
>>>>>> class Box<T> {
>>>>>>   public function add(T $item) {}
>>>>>> }
>>>>>> 
>>>>>> This would also make it easier to user inner classes:
>>>>>> 
>>>>>> class Outer {
>>>>>>   public class Inner {}
>>>>>>   public function foo(Inner $bar) {}
>>>>>> }
>>>>>> 
>>>>>> The other syntax options do not allow this; at least, I don't think so. 
>>>>>> I'm very heavily leaning towards `\` as the separator.
>>>>>> 
>>>>>> — Rob
>>>>> I'm failing to understand why you'd think this would be related at all?
>>>>> 
>>>>> If we get generics,
>>>>> 
>>>>> class Box<T> {
>>>>>   public function add(T $item) {}
>>>>> }
>>>>> 
>>>>> would just work, without any use or such. There will not be a symbol 
>>>>> Box::T or Box\T, just all mentions of T within the Box class will be 
>>>>> taken as "this is the generic placeholder" and the compiler takes care.
>>>>> It's not like that T will be directly accessible from outside of the 
>>>>> class or actually a proper type, unlike inner classes.
>>>>> 
>>>>> A generic is not an inner class nor will it look like it. Also, there's 
>>>>> no accessing of a parents generic - you write class Child<T> extends 
>>>>> ParentClass<T> - or something along these lines, getting the T available 
>>>>> for your class.
>>>>> 
>>>>> Bob
>>>> 
>>>> Yes, that is the question right? It might not affect anything there, but 
>>>> there would probably be an argument to keep it consistent with inner 
>>>> classes. In PHP, a class is a type; thus an inner class is an inner type, 
>>>> and generic types are also an inner type that only exist in the scope of 
>>>> their enclosing class, just like private inner classes.
>>>> 
>>>> If my logic is incorrect, let me know.
>>>> 
>>>> — Rob
>>> 
>>> The difference is that inner classes are a backed type; there's actually a 
>>> class/interface/enum/... behind it.
>>> 
>>> Generic placeholders are placeholders for another type, which is strictly 
>>> local to the compilation of the class.
>>> 
>>> Bob
>> 
>> If that were the case, then this would be an error:
>> 
>> function add(T $item) {
>>   if ($item instanceof T) {}
>> }
>> 
>> because T isn't a backed type. I don't think they are the same thing, but 
>> during runtime, T is most definitely a backed-type; not an empty box. You 
>> still have to refer to T in some way, and I'm of the opinion that self:>T is 
>> not ideal (I think we can probably all agree on that?). Even in inner 
>> classes, it seems to make more sense to just treat it like you would any 
>> other type in the current namespace.
> 
> It's a *placeholder* for a backed type.
> At runtime (or during monomorphization), the T will be replaced by the actual 
> type.
> 
> Whatever name T refers to is the actual backed type.
> 
> Bob

Right, my point is that you have to refer to T in the first place. If we use 
`\`, then T as-is is fine, because there is a clear resolution to what T you 
are referring to. If we use :> or ::, then when you write Box<T>, are you 
referring to T, as in the generic T; or T as in the class T in the same 
namespace. This is clear when we use "T" literally, but quickly becomes not so 
clear when using something else:

class Item {}

class Box<Item> {
  public function add(Item $item) {}
}

This is exactly why I said this matters! In the case above with the current :> 
syntax, we should probably use:

class Box<Item> {
  public function add(self:>Item $item) {
}

to explicitly define that we want the inner type "Item." To use the first 
example, you have to define inner types to allow that, but we are currently 
defining inner types in this RFC. I'd personally rather use the first example 
when it comes to generics, which means we need to define that now. In other 
words, I think you are on team "\" without realizing you are on team "\".

— Rob

Reply via email to