Jesse Schalken wrote on 21/04/2016 04:18:
Sticking with your example for a moment, if the type parameter is an "int", then the only type that can /currently/ be expressed in the type language that is a subtype of "int" is "int", so it's not very useful /right now/. However, a possible introduction of integer literal types would change that, especially in combination with unions. This would enable you to express the type "1|2|3", i.e. only one of those three integers. This would be useful to typecheck enums, which are typically an "int" or "string" which only accepts a finite set of values. As such, the type parameter "T is int" could be filled with "int" or "1" or "0|1|2". (Imagine a class "Bar<T is int>" and various subclasses which each must select a single integer as kind of tag, "Foo extends Bar<1>", "Baz extends Bar<2>" etc. I do this in TypeScript with string literal types all the time.)
I'm struggling to follow this example; it seems like you are using the type parameter to supply actual data to the implementation, which goes rather beyond generics, and into full-blown template metaprogramming. I'm not sure why you'd ever need the sub-class to compile in a value that way rather than just overriding a method somewhere, and would need some convincing that PHP needed this kind of complexity.
Beside from that, the introduction of any one of union types, intersection types, generic array types or callable types would mean the type constraint for a generic type can usefully be something besides a single class/interface. For example, if "<T is array|Travarsable>" were written "<T instanceof array|Traversable>" I would expect to be able to do "$t instanceof array|Traversable", but I wouldn't be able to unless "instanceof" is intended to and is extended to support arbitrary types.
This is a stronger argument, although I think extending the instanceof operator might be a good idea in that case anyway - otherwise, we would have a constraint that you can assert (produce a TypeError at a function boundary) but not easily test for. To avoid replicating the engine's entire checking routine, you'd end up doing this:
function ugly_instance_of<T>($value): boolean { try { return (function(T $checked) { return true; })($value); } catch ( TypeError $e ) { return false; } } if ( ugly_instance_of<array<Foo>>($x) ) // if ( $x instanceof array<Foo> ) *shudder* ;) Regards, -- Rowan Collins [IMSoP]