@@ -680,11 +680,27 @@ public function isIterableAtLeastOnce(): TrinaryLogic
680
680
681
681
public function getIterableKeyType (): Type
682
682
{
683
- $ classReflection = $ this ->getClassReflection ();
684
- if ($ classReflection === null ) {
685
- return new ErrorType ();
683
+ $ isTraversable = false ;
684
+ if ($ this ->isInstanceOf (Traversable::class)->yes ()) {
685
+ $ isTraversable = true ;
686
+ $ tKey = GenericTypeVariableResolver::getType ($ this , Traversable::class, 'TKey ' );
687
+ if ($ tKey !== null ) {
688
+ if (!$ tKey instanceof MixedType || $ tKey ->isExplicitMixed ()) {
689
+ $ classReflection = $ this ->getClassReflection ();
690
+ if ($ classReflection === null ) {
691
+ return $ tKey ;
692
+ }
693
+
694
+ return TypeTraverser::map ($ tKey , static function (Type $ type , callable $ traverse ) use ($ classReflection ): Type {
695
+ if ($ type instanceof StaticType) {
696
+ return $ type ->changeBaseClass ($ classReflection )->getStaticObjectType ();
697
+ }
698
+
699
+ return $ traverse ($ type );
700
+ });
701
+ }
702
+ }
686
703
}
687
-
688
704
if ($ this ->isInstanceOf (Iterator::class)->yes ()) {
689
705
return RecursionGuard::run ($ this , fn (): Type => ParametersAcceptorSelector::selectSingle (
690
706
$ this ->getMethod ('key ' , new OutOfClassScope ())->getVariants (),
@@ -695,17 +711,13 @@ public function getIterableKeyType(): Type
695
711
$ keyType = RecursionGuard::run ($ this , fn (): Type => ParametersAcceptorSelector::selectSingle (
696
712
$ this ->getMethod ('getIterator ' , new OutOfClassScope ())->getVariants (),
697
713
)->getReturnType ()->getIterableKeyType ());
714
+ $ isTraversable = true ;
698
715
if (!$ keyType instanceof MixedType || $ keyType ->isExplicitMixed ()) {
699
716
return $ keyType ;
700
717
}
701
718
}
702
719
703
- if ($ this ->isInstanceOf (Traversable::class)->yes ()) {
704
- $ tKey = GenericTypeVariableResolver::getType ($ this , Traversable::class, 'TKey ' );
705
- if ($ tKey !== null ) {
706
- return $ tKey ;
707
- }
708
-
720
+ if ($ isTraversable ) {
709
721
return new MixedType ();
710
722
}
711
723
@@ -714,6 +726,28 @@ public function getIterableKeyType(): Type
714
726
715
727
public function getIterableValueType (): Type
716
728
{
729
+ $ isTraversable = false ;
730
+ if ($ this ->isInstanceOf (Traversable::class)->yes ()) {
731
+ $ isTraversable = true ;
732
+ $ tValue = GenericTypeVariableResolver::getType ($ this , Traversable::class, 'TValue ' );
733
+ if ($ tValue !== null ) {
734
+ if (!$ tValue instanceof MixedType || $ tValue ->isExplicitMixed ()) {
735
+ $ classReflection = $ this ->getClassReflection ();
736
+ if ($ classReflection === null ) {
737
+ return $ tValue ;
738
+ }
739
+
740
+ return TypeTraverser::map ($ tValue , static function (Type $ type , callable $ traverse ) use ($ classReflection ): Type {
741
+ if ($ type instanceof StaticType) {
742
+ return $ type ->changeBaseClass ($ classReflection )->getStaticObjectType ();
743
+ }
744
+
745
+ return $ traverse ($ type );
746
+ });
747
+ }
748
+ }
749
+ }
750
+
717
751
if ($ this ->isInstanceOf (Iterator::class)->yes ()) {
718
752
return RecursionGuard::run ($ this , fn (): Type => ParametersAcceptorSelector::selectSingle (
719
753
$ this ->getMethod ('current ' , new OutOfClassScope ())->getVariants (),
@@ -724,17 +758,13 @@ public function getIterableValueType(): Type
724
758
$ valueType = RecursionGuard::run ($ this , fn (): Type => ParametersAcceptorSelector::selectSingle (
725
759
$ this ->getMethod ('getIterator ' , new OutOfClassScope ())->getVariants (),
726
760
)->getReturnType ()->getIterableValueType ());
761
+ $ isTraversable = true ;
727
762
if (!$ valueType instanceof MixedType || $ valueType ->isExplicitMixed ()) {
728
763
return $ valueType ;
729
764
}
730
765
}
731
766
732
- if ($ this ->isInstanceOf (Traversable::class)->yes ()) {
733
- $ tValue = GenericTypeVariableResolver::getType ($ this , Traversable::class, 'TValue ' );
734
- if ($ tValue !== null ) {
735
- return $ tValue ;
736
- }
737
-
767
+ if ($ isTraversable ) {
738
768
return new MixedType ();
739
769
}
740
770
0 commit comments