@@ -2708,6 +2708,7 @@ public function processClosureNode(
27082708 callable $ nodeCallback ,
27092709 ExpressionContext $ context ,
27102710 ?Type $ passedToType ,
2711+ ?Type $ nativePassedToType = null ,
27112712 ): ProcessClosureResult
27122713 {
27132714 foreach ($ expr ->params as $ param ) {
@@ -2773,7 +2774,7 @@ public function processClosureNode(
27732774 $ this ->callNodeCallback ($ nodeCallback , $ expr ->returnType , $ scope , $ storage );
27742775 }
27752776
2776- $ nativeCallableParameters = $ this ->createNativeCallableParameters ($ scope , $ expr );
2777+ $ nativeCallableParameters = $ this ->createNativeCallableParameters ($ scope , $ expr, $ closureCallArgs , $ nativePassedToType );
27772778 $ closureScope = $ scope ->enterAnonymousFunction ($ expr , $ callableParameters , $ nativeCallableParameters );
27782779 $ closureScope = $ closureScope ->processClosureScope ($ scope , null , $ byRefUses );
27792780 $ closureType = $ closureScope ->getAnonymousFunctionReflection ();
@@ -2921,6 +2922,7 @@ public function processArrowFunctionNode(
29212922 ExpressionResultStorage $ storage ,
29222923 callable $ nodeCallback ,
29232924 ?Type $ passedToType ,
2925+ ?Type $ nativePassedToType = null ,
29242926 ): ExpressionResult
29252927 {
29262928 foreach ($ expr ->params as $ param ) {
@@ -2931,7 +2933,7 @@ public function processArrowFunctionNode(
29312933 }
29322934
29332935 $ arrowFunctionCallArgs = $ expr ->getAttribute (ArrowFunctionArgVisitor::ATTRIBUTE_NAME );
2934- $ nativeCallableParameters = $ this ->createNativeCallableParameters ($ scope , $ expr );
2936+ $ nativeCallableParameters = $ this ->createNativeCallableParameters ($ scope , $ expr, $ arrowFunctionCallArgs , $ nativePassedToType );
29352937 $ arrowFunctionScope = $ scope ->enterArrowFunction ($ expr , $ this ->createCallableParameters (
29362938 $ scope ,
29372939 $ expr ,
@@ -2949,14 +2951,52 @@ public function processArrowFunctionNode(
29492951 }
29502952
29512953 /**
2952- * @param Node\Arg[] $args
2954+ * @param Node\Arg[]|null $args
29532955 * @return ParameterReflection[]|null
29542956 */
29552957 public function createCallableParameters (Scope $ scope , Expr $ closureExpr , ?array $ args , ?Type $ passedToType ): ?array
2958+ {
2959+ return $ this ->doCreateCallableParameters ($ scope , $ closureExpr , $ args , $ passedToType , static fn (Scope $ s , Expr $ e ) => $ s ->getType ($ e ));
2960+ }
2961+
2962+ /**
2963+ * @param Node\Arg[]|null $args
2964+ * @return ParameterReflection[]|null
2965+ */
2966+ public function createNativeCallableParameters (Scope $ scope , Expr $ closureExpr , ?array $ args , ?Type $ nativePassedToType ): ?array
2967+ {
2968+ $ result = $ this ->doCreateCallableParameters ($ scope , $ closureExpr , $ args , $ nativePassedToType , static fn (Scope $ s , Expr $ e ) => $ s ->getNativeType ($ e ));
2969+ if ($ result !== null ) {
2970+ return $ result ;
2971+ }
2972+
2973+ $ arrayMapArgs = $ closureExpr ->getAttribute (ArrayMapArgVisitor::ATTRIBUTE_NAME );
2974+ if ($ arrayMapArgs !== null ) {
2975+ $ nativeCallableParameters = [];
2976+ foreach ($ arrayMapArgs as $ funcCallArg ) {
2977+ $ nativeCallableParameters [] = new DummyParameter ('item ' , $ scope ->getNativeType ($ funcCallArg ->value )->getIterableValueType (), optional: false , passedByReference: PassedByReference::createNo (), variadic: false , defaultValue: null );
2978+ }
2979+ return $ nativeCallableParameters ;
2980+ }
2981+
2982+ $ arrayFilterArrayArg = $ closureExpr ->getAttribute (ArrayFilterArgVisitor::CALLBACK_ATTRIBUTE_NAME );
2983+ if ($ arrayFilterArrayArg !== null ) {
2984+ return [new DummyParameter ('item ' , $ scope ->getNativeType ($ arrayFilterArrayArg )->getIterableValueType (), optional: false , passedByReference: PassedByReference::createNo (), variadic: false , defaultValue: null )];
2985+ }
2986+
2987+ return null ;
2988+ }
2989+
2990+ /**
2991+ * @param Node\Arg[]|null $args
2992+ * @param Closure(Scope, Expr): Type $typeGetter
2993+ * @return ParameterReflection[]|null
2994+ */
2995+ private function doCreateCallableParameters (Scope $ scope , Expr $ closureExpr , ?array $ args , ?Type $ passedToType , Closure $ typeGetter ): ?array
29562996 {
29572997 $ callableParameters = null ;
29582998 if ($ args !== null ) {
2959- $ closureType = $ scope -> getType ( $ closureExpr );
2999+ $ closureType = $ typeGetter ( $ scope , $ closureExpr );
29603000
29613001 if ($ closureType ->isCallable ()->no ()) {
29623002 return null ;
@@ -2971,7 +3011,7 @@ public function createCallableParameters(Scope $scope, Expr $closureExpr, ?array
29713011 continue ;
29723012 }
29733013
2974- $ type = $ scope -> getType ( $ args [$ index ]->value );
3014+ $ type = $ typeGetter ( $ scope , $ args [$ index ]->value );
29753015 $ callableParameters [$ index ] = new NativeParameterReflection (
29763016 $ callableParameter ->getName (),
29773017 $ callableParameter ->isOptional (),
@@ -3029,28 +3069,6 @@ public function createCallableParameters(Scope $scope, Expr $closureExpr, ?array
30293069 return $ callableParameters ;
30303070 }
30313071
3032- /**
3033- * @return ParameterReflection[]|null
3034- */
3035- public function createNativeCallableParameters (MutatingScope $ scope , Expr $ closureExpr ): ?array
3036- {
3037- $ arrayMapArgs = $ closureExpr ->getAttribute (ArrayMapArgVisitor::ATTRIBUTE_NAME );
3038- if ($ arrayMapArgs !== null ) {
3039- $ nativeCallableParameters = [];
3040- foreach ($ arrayMapArgs as $ funcCallArg ) {
3041- $ nativeCallableParameters [] = new DummyParameter ('item ' , $ scope ->getNativeType ($ funcCallArg ->value )->getIterableValueType (), optional: false , passedByReference: PassedByReference::createNo (), variadic: false , defaultValue: null );
3042- }
3043- return $ nativeCallableParameters ;
3044- }
3045-
3046- $ arrayFilterArrayArg = $ closureExpr ->getAttribute (ArrayFilterArgVisitor::CALLBACK_ATTRIBUTE_NAME );
3047- if ($ arrayFilterArrayArg !== null ) {
3048- return [new DummyParameter ('item ' , $ scope ->getNativeType ($ arrayFilterArrayArg )->getIterableValueType (), optional: false , passedByReference: PassedByReference::createNo (), variadic: false , defaultValue: null )];
3049- }
3050-
3051- return null ;
3052- }
3053-
30543072 /**
30553073 * @param callable(Node $node, Scope $scope): void $nodeCallback
30563074 */
@@ -3411,7 +3429,7 @@ public function processArgs(
34113429 }
34123430
34133431 $ this ->callNodeCallbackWithExpression ($ nodeCallback , $ arg ->value , $ scopeToPass , $ storage , $ context );
3414- $ closureResult = $ this ->processClosureNode ($ stmt , $ arg ->value , $ scopeToPass , $ storage , $ nodeCallback , $ context , $ parameterType ?? null );
3432+ $ closureResult = $ this ->processClosureNode ($ stmt , $ arg ->value , $ scopeToPass , $ storage , $ nodeCallback , $ context , $ parameterType ?? null , $ parameterNativeType );
34153433 if ($ this ->callCallbackImmediately ($ parameter , $ parameterType , $ calleeReflection )) {
34163434 $ throwPoints = array_merge ($ throwPoints , array_map (static fn (InternalThrowPoint $ throwPoint ) => $ throwPoint ->isExplicit () ? InternalThrowPoint::createExplicit ($ scope , $ throwPoint ->getType (), $ arg ->value , $ throwPoint ->canContainAnyThrowable ()) : InternalThrowPoint::createImplicit ($ scope , $ arg ->value ), $ closureResult ->getThrowPoints ()));
34173435 $ impurePoints = array_merge ($ impurePoints , $ closureResult ->getImpurePoints ());
@@ -3470,7 +3488,7 @@ public function processArgs(
34703488 }
34713489
34723490 $ this ->callNodeCallbackWithExpression ($ nodeCallback , $ arg ->value , $ scopeToPass , $ storage , $ context );
3473- $ arrowFunctionResult = $ this ->processArrowFunctionNode ($ stmt , $ arg ->value , $ scopeToPass , $ storage , $ nodeCallback , $ parameterType ?? null );
3491+ $ arrowFunctionResult = $ this ->processArrowFunctionNode ($ stmt , $ arg ->value , $ scopeToPass , $ storage , $ nodeCallback , $ parameterType ?? null , $ parameterNativeType );
34743492 if ($ this ->callCallbackImmediately ($ parameter , $ parameterType , $ calleeReflection )) {
34753493 $ throwPoints = array_merge ($ throwPoints , array_map (static fn (InternalThrowPoint $ throwPoint ) => $ throwPoint ->isExplicit () ? InternalThrowPoint::createExplicit ($ scope , $ throwPoint ->getType (), $ arg ->value , $ throwPoint ->canContainAnyThrowable ()) : InternalThrowPoint::createImplicit ($ scope , $ arg ->value ), $ arrowFunctionResult ->getThrowPoints ()));
34763494 $ impurePoints = array_merge ($ impurePoints , $ arrowFunctionResult ->getImpurePoints ());
0 commit comments