@@ -725,7 +725,46 @@ public function specifyTypesInCondition(
725725
726726 if ($ context ->null ()) {
727727 $ specifiedTypes = $ this ->specifyTypesInCondition ($ scope ->exitFirstLevelStatements (), $ expr ->expr , $ context )->setRootExpr ($ expr );
728+ } else {
729+ $ specifiedTypes = $ this ->specifyTypesInCondition ($ scope ->exitFirstLevelStatements (), $ expr ->var , $ context )->setRootExpr ($ expr );
730+ }
731+
732+ // infer $arr[$key] after $key = array_key_first/last($arr)
733+ if (
734+ $ expr ->expr instanceof FuncCall
735+ && $ expr ->expr ->name instanceof Name
736+ && in_array ($ expr ->expr ->name ->toLowerString (), ['array_key_first ' , 'array_key_last ' ], true )
737+ && count ($ expr ->expr ->getArgs ()) >= 1
738+ ) {
739+ $ arrayArg = $ expr ->expr ->getArgs ()[0 ]->value ;
740+ $ arrayType = $ scope ->getType ($ arrayArg );
741+
742+ if ($ arrayType ->isArray ()->yes ()) {
743+ if ($ context ->true ()) {
744+ $ specifiedTypes = $ specifiedTypes ->unionWith (
745+ $ this ->create ($ arrayArg , new NonEmptyArrayType (), TypeSpecifierContext::createTrue (), $ scope ),
746+ );
747+ $ isNonEmpty = true ;
748+ } else {
749+ $ isNonEmpty = $ arrayType ->isIterableAtLeastOnce ()->yes ();
750+ }
728751
752+ if (
753+ $ isNonEmpty
754+ ) {
755+ $ dimFetch = new ArrayDimFetch ($ arrayArg , $ expr ->var );
756+ $ iterableValueType = $ expr ->expr ->name ->toLowerString () === 'array_key_first '
757+ ? $ arrayType ->getIterableValueType ()
758+ : $ arrayType ->getIterableValueType ();
759+
760+ $ specifiedTypes = $ specifiedTypes ->unionWith (
761+ $ this ->create ($ dimFetch , $ iterableValueType , TypeSpecifierContext::createTrue (), $ scope ),
762+ );
763+ }
764+ }
765+ }
766+
767+ if ($ context ->null ()) {
729768 // infer $arr[$key] after $key = array_rand($arr)
730769 if (
731770 $ expr ->expr instanceof FuncCall
@@ -755,30 +794,6 @@ public function specifyTypesInCondition(
755794 }
756795 }
757796
758- // infer $arr[$key] after $key = array_key_first/last($arr)
759- if (
760- $ expr ->expr instanceof FuncCall
761- && $ expr ->expr ->name instanceof Name
762- && in_array ($ expr ->expr ->name ->toLowerString (), ['array_key_first ' , 'array_key_last ' ], true )
763- && count ($ expr ->expr ->getArgs ()) >= 1
764- ) {
765- $ arrayArg = $ expr ->expr ->getArgs ()[0 ]->value ;
766- $ arrayType = $ scope ->getType ($ arrayArg );
767- if (
768- $ arrayType ->isArray ()->yes ()
769- && $ arrayType ->isIterableAtLeastOnce ()->yes ()
770- ) {
771- $ dimFetch = new ArrayDimFetch ($ arrayArg , $ expr ->var );
772- $ iterableValueType = $ expr ->expr ->name ->toLowerString () === 'array_key_first '
773- ? $ arrayType ->getIterableValueType ()
774- : $ arrayType ->getIterableValueType ();
775-
776- return $ specifiedTypes ->unionWith (
777- $ this ->create ($ dimFetch , $ iterableValueType , TypeSpecifierContext::createTrue (), $ scope ),
778- );
779- }
780- }
781-
782797 // infer $list[$count] after $count = count($list) - 1
783798 if (
784799 $ expr ->expr instanceof Expr \BinaryOp \Minus
@@ -806,8 +821,6 @@ public function specifyTypesInCondition(
806821 return $ specifiedTypes ;
807822 }
808823
809- $ specifiedTypes = $ this ->specifyTypesInCondition ($ scope ->exitFirstLevelStatements (), $ expr ->var , $ context )->setRootExpr ($ expr );
810-
811824 if ($ context ->true ()) {
812825 // infer $arr[$key] after $key = array_search($needle, $arr)
813826 if (
0 commit comments