@@ -2837,6 +2837,7 @@ public function processClosureNode(
28372837 callable $ nodeCallback ,
28382838 ExpressionContext $ context ,
28392839 ?Type $ passedToType ,
2840+ ?Type $ nativePassedToType = null ,
28402841 ): ProcessClosureResult
28412842 {
28422843 foreach ($ expr ->params as $ param ) {
@@ -2846,12 +2847,8 @@ public function processClosureNode(
28462847 $ byRefUses = [];
28472848
28482849 $ closureCallArgs = $ expr ->getAttribute (ClosureArgVisitor::ATTRIBUTE_NAME );
2849- $ callableParameters = $ this ->createCallableParameters (
2850- $ scope ,
2851- $ expr ,
2852- $ closureCallArgs ,
2853- $ passedToType ,
2854- );
2850+ $ callableParameters = $ this ->createCallableParameters ($ scope , $ expr , $ closureCallArgs , $ passedToType );
2851+ $ nativeCallableParameters = $ this ->createNativeCallableParameters ($ scope , $ expr , $ closureCallArgs , $ nativePassedToType );
28552852
28562853 $ useScope = $ scope ;
28572854 foreach ($ expr ->uses as $ use ) {
@@ -2902,7 +2899,7 @@ public function processClosureNode(
29022899 $ this ->callNodeCallback ($ nodeCallback , $ expr ->returnType , $ scope , $ storage );
29032900 }
29042901
2905- $ closureScope = $ scope ->enterAnonymousFunction ($ expr , $ callableParameters );
2902+ $ closureScope = $ scope ->enterAnonymousFunction ($ expr , $ callableParameters, $ nativeCallableParameters );
29062903 $ closureScope = $ closureScope ->processClosureScope ($ scope , null , $ byRefUses );
29072904 $ closureType = $ closureScope ->getAnonymousFunctionReflection ();
29082905 if (!$ closureType instanceof ClosureType) {
@@ -2984,7 +2981,7 @@ public function processClosureNode(
29842981 break ;
29852982 }
29862983
2987- $ closureScope = $ scope ->enterAnonymousFunction ($ expr , $ callableParameters );
2984+ $ closureScope = $ scope ->enterAnonymousFunction ($ expr , $ callableParameters, $ nativeCallableParameters );
29882985 $ closureScope = $ closureScope ->processClosureScope ($ intermediaryClosureScope , $ prevScope , $ byRefUses );
29892986
29902987 if ($ closureScope ->equals ($ prevScope )) {
@@ -3049,6 +3046,7 @@ public function processArrowFunctionNode(
30493046 ExpressionResultStorage $ storage ,
30503047 callable $ nodeCallback ,
30513048 ?Type $ passedToType ,
3049+ ?Type $ nativePassedToType = null ,
30523050 ): ExpressionResult
30533051 {
30543052 foreach ($ expr ->params as $ param ) {
@@ -3059,12 +3057,9 @@ public function processArrowFunctionNode(
30593057 }
30603058
30613059 $ arrowFunctionCallArgs = $ expr ->getAttribute (ArrowFunctionArgVisitor::ATTRIBUTE_NAME );
3062- $ arrowFunctionScope = $ scope ->enterArrowFunction ($ expr , $ this ->createCallableParameters (
3063- $ scope ,
3064- $ expr ,
3065- $ arrowFunctionCallArgs ,
3066- $ passedToType ,
3067- ));
3060+ $ callableParameters = $ this ->createCallableParameters ($ scope , $ expr , $ arrowFunctionCallArgs , $ passedToType );
3061+ $ nativeCallableParameters = $ this ->createNativeCallableParameters ($ scope , $ expr , $ arrowFunctionCallArgs , $ nativePassedToType );
3062+ $ arrowFunctionScope = $ scope ->enterArrowFunction ($ expr , $ callableParameters , $ nativeCallableParameters );
30683063 $ arrowFunctionType = $ arrowFunctionScope ->getAnonymousFunctionReflection ();
30693064 if ($ arrowFunctionType === null ) {
30703065 throw new ShouldNotHappenException ();
@@ -3076,14 +3071,33 @@ public function processArrowFunctionNode(
30763071 }
30773072
30783073 /**
3079- * @param Node\Arg[] $args
3074+ * @param Node\Arg[]|null $args
30803075 * @return ParameterReflection[]|null
30813076 */
30823077 public function createCallableParameters (Scope $ scope , Expr $ closureExpr , ?array $ args , ?Type $ passedToType ): ?array
3078+ {
3079+ return $ this ->doCreateCallableParameters ($ scope , $ closureExpr , $ args , $ passedToType , static fn (Scope $ s , Expr $ e ) => $ s ->getType ($ e ));
3080+ }
3081+
3082+ /**
3083+ * @param Node\Arg[]|null $args
3084+ * @return ParameterReflection[]|null
3085+ */
3086+ public function createNativeCallableParameters (Scope $ scope , Expr $ closureExpr , ?array $ args , ?Type $ nativePassedToType ): ?array
3087+ {
3088+ return $ this ->doCreateCallableParameters ($ scope , $ closureExpr , $ args , $ nativePassedToType , static fn (Scope $ s , Expr $ e ) => $ s ->getNativeType ($ e ));
3089+ }
3090+
3091+ /**
3092+ * @param Node\Arg[]|null $args
3093+ * @param Closure(Scope, Expr): Type $typeGetter
3094+ * @return ParameterReflection[]|null
3095+ */
3096+ private function doCreateCallableParameters (Scope $ scope , Expr $ closureExpr , ?array $ args , ?Type $ passedToType , Closure $ typeGetter ): ?array
30833097 {
30843098 $ callableParameters = null ;
30853099 if ($ args !== null ) {
3086- $ closureType = $ scope -> getType ( $ closureExpr );
3100+ $ closureType = $ typeGetter ( $ scope , $ closureExpr );
30873101
30883102 if ($ closureType ->isCallable ()->no ()) {
30893103 return null ;
@@ -3100,12 +3114,13 @@ public function createCallableParameters(Scope $scope, Expr $closureExpr, ?array
31003114
31013115 if ($ callableParameter ->isVariadic ()) {
31023116 $ argTypes = [];
3103- for ($ j = $ index ; $ j < count ($ args ); $ j ++) {
3104- $ argTypes [] = $ scope ->getType ($ args [$ j ]->value );
3117+ $ argNumber = count ($ args );
3118+ for ($ j = $ index ; $ j < $ argNumber ; $ j ++) {
3119+ $ argTypes [] = $ typeGetter ($ scope , $ args [$ j ]->value );
31053120 }
31063121 $ type = TypeCombinator::union (...$ argTypes );
31073122 } else {
3108- $ type = $ scope -> getType ( $ args [$ index ]->value );
3123+ $ type = $ typeGetter ( $ scope , $ args [$ index ]->value );
31093124 }
31103125 $ callableParameters [$ index ] = new NativeParameterReflection (
31113126 $ callableParameter ->getName (),
@@ -3524,7 +3539,7 @@ public function processArgs(
35243539 }
35253540
35263541 $ this ->callNodeCallbackWithExpression ($ nodeCallback , $ arg ->value , $ scopeToPass , $ storage , $ context );
3527- $ closureResult = $ this ->processClosureNode ($ stmt , $ arg ->value , $ scopeToPass , $ storage , $ nodeCallback , $ context , $ parameterType ?? null );
3542+ $ closureResult = $ this ->processClosureNode ($ stmt , $ arg ->value , $ scopeToPass , $ storage , $ nodeCallback , $ context , $ parameterType ?? null , $ parameterNativeType );
35283543 if ($ this ->callCallbackImmediately ($ parameter , $ parameterType , $ calleeReflection )) {
35293544 $ 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 ()));
35303545 $ impurePoints = array_merge ($ impurePoints , $ closureResult ->getImpurePoints ());
@@ -3583,7 +3598,7 @@ public function processArgs(
35833598 }
35843599
35853600 $ this ->callNodeCallbackWithExpression ($ nodeCallback , $ arg ->value , $ scopeToPass , $ storage , $ context );
3586- $ arrowFunctionResult = $ this ->processArrowFunctionNode ($ stmt , $ arg ->value , $ scopeToPass , $ storage , $ nodeCallback , $ parameterType ?? null );
3601+ $ arrowFunctionResult = $ this ->processArrowFunctionNode ($ stmt , $ arg ->value , $ scopeToPass , $ storage , $ nodeCallback , $ parameterType ?? null , $ parameterNativeType );
35873602 if ($ this ->callCallbackImmediately ($ parameter , $ parameterType , $ calleeReflection )) {
35883603 $ 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 ()));
35893604 $ impurePoints = array_merge ($ impurePoints , $ arrowFunctionResult ->getImpurePoints ());
0 commit comments