Description
In PHP, types are usually resolved at the latest possible point. For example, if you write
function foo(): Bar {}
then we will not load class Bar
when the function is declared. The type is only loaded when the type is checked, and even then only when necessary. This is fairly important, because we do not want to load a large number of classes that are ultimately unused (apart from appearing in type checks).
Generic arguments are just types, and the question is now: When should those be resolved? I think it's pretty clear that something like
function foo(): Bar<Baz> {}
should resolve neither Bar
nor Baz
when the function is declared and only do so when the type is checked. The most interesting case is what happens to generic class uses outside type declarations, for example when inheriting from a generic class:
abstract class Foo<T> {} // generic type param unused
class Bar extends Foo<UnknownClass> {}
$bar = new Bar;
Note that the type parameter T
is unused, so even if UnknownClass
doesn't exist, this code could still work fine. Should it though? This would be consistent with types being lazy-resolved in general and prevents unnecessary type loading, but based on chat feedback, people seem to prefer getting an undefined class error here.
A variation on this is something like Foo<DateTime|IntlDateTimeZone>
, where say the first type is known (builtin) but the second one may or may not be available (optional extension). Writing this kind of type would be precluded if types are resolved eagerly.
From an implementation point of view, it would probably be easier to early resolve types that are involved in inheritance, because it allows canonicalizing bound generic arguments...