@@ -875,15 +875,15 @@ public function specifyTypesInCondition(
875875 $ funcName = $ expr ->expr ->name ->toLowerString ();
876876 $ arrayArgIndex = null ;
877877 $ sentinelType = null ;
878- $ narrowToNonEmpty = false ;
878+ $ needleArgIndex = null ;
879879
880880 if ($ funcName === 'array_search ' ) {
881881 $ arrayArgIndex = 1 ;
882882 $ sentinelType = new ConstantBooleanType (false );
883+ $ needleArgIndex = 0 ;
883884 } elseif ($ funcName === 'array_find_key ' ) {
884885 $ arrayArgIndex = 0 ;
885886 $ sentinelType = new NullType ();
886- $ narrowToNonEmpty = true ;
887887 }
888888
889889 if ($ arrayArgIndex !== null ) {
@@ -892,23 +892,40 @@ public function specifyTypesInCondition(
892892
893893 if ($ arrayType ->isArray ()->yes ()) {
894894 if ($ context ->true ()) {
895- if ($ narrowToNonEmpty ) {
896- $ specifiedTypes = $ specifiedTypes ->unionWith (
897- $ this ->create ($ arrayArg , new NonEmptyArrayType (), TypeSpecifierContext::createTrue (), $ scope ),
898- );
899- }
895+ $ specifiedTypes = $ specifiedTypes ->unionWith (
896+ $ this ->create ($ arrayArg , new NonEmptyArrayType (), TypeSpecifierContext::createTrue (), $ scope ),
897+ );
900898
901899 $ dimFetch = new ArrayDimFetch ($ arrayArg , $ expr ->var );
902900
901+ $ dimFetchType = $ arrayType ->getIterableValueType ();
902+ if (
903+ $ needleArgIndex !== null
904+ && count ($ expr ->expr ->getArgs ()) >= 3
905+ && $ scope ->getType ($ expr ->expr ->getArgs ()[2 ]->value )->isTrue ()->yes ()
906+ ) {
907+ $ needleType = $ scope ->getType ($ expr ->expr ->getArgs ()[$ needleArgIndex ]->value );
908+ $ dimFetchType = TypeCombinator::intersect ($ needleType , $ dimFetchType );
909+ }
910+
903911 $ specifiedTypes = $ specifiedTypes ->unionWith (
904- $ this ->create ($ dimFetch , $ arrayType -> getIterableValueType () , TypeSpecifierContext::createTrue (), $ scope ),
912+ $ this ->create ($ dimFetch , $ dimFetchType , TypeSpecifierContext::createTrue (), $ scope ),
905913 );
906914 } elseif ($ expr ->var instanceof Expr \Variable && is_string ($ expr ->var ->name )) {
907915 $ keyType = $ scope ->getType ($ expr ->expr );
908916 $ narrowedKeyType = TypeCombinator::remove ($ keyType , $ sentinelType );
909917 if (!$ narrowedKeyType instanceof NeverType) {
918+ $ dimFetchType = null ;
919+ if (
920+ $ needleArgIndex !== null
921+ && count ($ expr ->expr ->getArgs ()) >= 3
922+ && $ scope ->getType ($ expr ->expr ->getArgs ()[2 ]->value )->isTrue ()->yes ()
923+ ) {
924+ $ needleType = $ scope ->getType ($ expr ->expr ->getArgs ()[$ needleArgIndex ]->value );
925+ $ dimFetchType = TypeCombinator::intersect ($ needleType , $ arrayType ->getIterableValueType ());
926+ }
910927 $ specifiedTypes = $ specifiedTypes ->unionWith (
911- $ this ->createArrayDimFetchConditionalExpressionHolder ($ expr ->var , $ arrayArg , $ arrayType , $ narrowedKeyType ),
928+ $ this ->createArrayDimFetchConditionalExpressionHolder ($ expr ->var , $ arrayArg , $ arrayType , $ narrowedKeyType, $ dimFetchType ),
912929 );
913930 }
914931 }
@@ -2421,6 +2438,7 @@ private function createArrayDimFetchConditionalExpressionHolder(
24212438 Expr $ arrayArg ,
24222439 Type $ arrayType ,
24232440 Type $ narrowedKeyType ,
2441+ ?Type $ dimFetchType = null ,
24242442 ): SpecifiedTypes
24252443 {
24262444 $ dimFetch = new ArrayDimFetch ($ arrayArg , $ keyVar );
@@ -2429,7 +2447,7 @@ private function createArrayDimFetchConditionalExpressionHolder(
24292447
24302448 $ holder = new ConditionalExpressionHolder (
24312449 [$ keyExprString => ExpressionTypeHolder::createYes ($ keyVar , $ narrowedKeyType )],
2432- ExpressionTypeHolder::createYes ($ dimFetch , $ arrayType ->getIterableValueType ()),
2450+ ExpressionTypeHolder::createYes ($ dimFetch , $ dimFetchType ?? $ arrayType ->getIterableValueType ()),
24332451 );
24342452
24352453 return (new SpecifiedTypes ([], []))->setNewConditionalExpressionHolders ([
0 commit comments