11 private function __construct(){}
13 public static function isCovariant(?\ReflectionType $acceptingType, ?\ReflectionType $givenType) :
bool{
15 if($acceptingType ===
null || ($acceptingType instanceof \ReflectionNamedType && $acceptingType->getName() === BuiltInType::VOID->value)){
20 if($givenType ===
null){
26 if(!$acceptingType->allowsNull() && $givenType->allowsNull()){
30 return self::isCompositeTypeCovariant($acceptingType, $givenType);
33 private static function isCompositeTypeCovariant(\ReflectionType $acceptingType, \ReflectionType $givenType) :
bool{
41 if($givenType instanceof \ReflectionUnionType){
42 foreach($givenType->getTypes() as $type){
43 if(!self::isCompositeTypeCovariant($acceptingType, $type)){
51 if($acceptingType instanceof \ReflectionNamedType){
55 if($givenType instanceof \ReflectionIntersectionType){
56 foreach($givenType->getTypes() as $type){
57 if(self::isCompositeTypeCovariant($acceptingType, $type)){
65 if($givenType instanceof \ReflectionNamedType){
66 $acceptingTypeName = $acceptingType->getName();
67 $givenTypeName = $givenType->getName();
68 if($acceptingTypeName === $givenTypeName){
73 if($acceptingTypeName === BuiltInType::MIXED->value && $givenTypeName !== BuiltInType::VOID->value){
78 if($acceptingTypeName === BuiltInType::FLOAT->value && $givenTypeName === BuiltInType::INT->value){
84 if($acceptingTypeName === BuiltInType::ITERABLE->value){
85 return $givenTypeName === BuiltInType::ARRAY->value
86 || $givenTypeName === \Traversable::class
87 || \is_subclass_of($givenTypeName, \Traversable::class);
91 if($acceptingTypeName === BuiltInType::CALLABLE->value){
92 return $givenTypeName === \Closure::class
93 || \method_exists($givenTypeName,
'__invoke')
94 || \is_subclass_of($givenTypeName, \Closure::class);
97 if($acceptingTypeName === BuiltInType::OBJECT->value){
99 return BuiltInType::tryFrom($givenTypeName) ===
null;
102 return is_string($givenTypeName) && is_string($acceptingTypeName) && \is_subclass_of($givenTypeName, $acceptingTypeName);
105 throw new \AssertionError(
"Unhandled reflection type " . get_class($givenType));
108 if($acceptingType instanceof \ReflectionUnionType){
110 foreach($acceptingType->getTypes() as $type){
111 if(self::isCompositeTypeCovariant($type, $givenType)){
119 if($acceptingType instanceof \ReflectionIntersectionType){
121 foreach($acceptingType->getTypes() as $type){
122 if(!self::isCompositeTypeCovariant($type, $givenType)){