@@ -2538,7 +2538,7 @@ private function createForExpr(
25382538 }
25392539 }
25402540
2541- if (!($ expr instanceof AlwaysRememberedExpr) && $ this ->expressionContainsNonPureCall ($ expr , $ scope )) {
2541+ if (!($ expr instanceof AlwaysRememberedExpr) && ! $ this ->expressionContainsNonPureCall ($ expr , $ scope)-> no ( )) {
25422542 if (isset ($ containsNull ) && !$ containsNull ) {
25432543 return $ this ->createNullsafeTypes ($ originalExpr , $ scope , $ context , $ type );
25442544 }
@@ -2574,76 +2574,84 @@ private function createForExpr(
25742574 return $ types ;
25752575 }
25762576
2577- private function expressionContainsNonPureCall (Expr $ expr , Scope $ scope ): bool
2577+ private function expressionContainsNonPureCall (Expr $ expr , Scope $ scope ): TrinaryLogic
25782578 {
25792579 $ nodeFinder = new NodeFinder ();
2580- $ found = $ nodeFinder ->findFirst ([$ expr ], function (Node $ node ) use ($ scope ): bool {
2581- if (!$ node instanceof Expr) {
2582- return false ;
2583- }
2580+ $ callNodes = $ nodeFinder ->find ([$ expr ], static function (Node $ node ): bool {
2581+ return $ node instanceof FuncCall || $ node instanceof MethodCall || $ node instanceof StaticCall;
2582+ });
25842583
2585- if ($ node instanceof FuncCall) {
2586- if ($ node ->name instanceof Name) {
2587- if (!$ this ->reflectionProvider ->hasFunction ($ node ->name , $ scope )) {
2588- return true ;
2584+ $ result = TrinaryLogic::createNo ();
2585+ foreach ($ callNodes as $ callNode ) {
2586+ if ($ callNode instanceof FuncCall) {
2587+ if ($ callNode ->name instanceof Name) {
2588+ if (!$ this ->reflectionProvider ->hasFunction ($ callNode ->name , $ scope )) {
2589+ $ result = $ result ->or (TrinaryLogic::createMaybe ());
2590+ continue ;
25892591 }
2590- $ hasSideEffects = $ this ->reflectionProvider ->getFunction ($ node ->name , $ scope )->hasSideEffects ();
2591- return $ hasSideEffects ->yes ()
2592- || (!$ this ->rememberPossiblyImpureFunctionValues && !$ hasSideEffects ->no ());
2593- }
2594-
2595- $ nameType = $ scope ->getType ($ node ->name );
2596- if ($ nameType ->isCallable ()->yes ()) {
2597- $ isPure = null ;
2598- foreach ($ nameType ->getCallableParametersAcceptors ($ scope ) as $ variant ) {
2599- $ variantIsPure = $ variant ->isPure ();
2600- $ isPure = $ isPure === null ? $ variantIsPure : $ isPure ->and ($ variantIsPure );
2592+ $ hasSideEffects = $ this ->reflectionProvider ->getFunction ($ callNode ->name , $ scope )->hasSideEffects ();
2593+ if ($ hasSideEffects ->yes ()
2594+ || (!$ this ->rememberPossiblyImpureFunctionValues && !$ hasSideEffects ->no ())) {
2595+ return TrinaryLogic::createYes ();
26012596 }
2602- if ($ isPure !== null ) {
2603- return $ isPure ->no ()
2604- || (!$ this ->rememberPossiblyImpureFunctionValues && !$ isPure ->yes ());
2597+ } else {
2598+ $ nameType = $ scope ->getType ($ callNode ->name );
2599+ if ($ nameType ->isCallable ()->yes ()) {
2600+ $ isPure = null ;
2601+ foreach ($ nameType ->getCallableParametersAcceptors ($ scope ) as $ variant ) {
2602+ $ variantIsPure = $ variant ->isPure ();
2603+ $ isPure = $ isPure === null ? $ variantIsPure : $ isPure ->and ($ variantIsPure );
2604+ }
2605+ if ($ isPure !== null
2606+ && ($ isPure ->no () || (!$ this ->rememberPossiblyImpureFunctionValues && !$ isPure ->yes ()))) {
2607+ return TrinaryLogic::createYes ();
2608+ }
26052609 }
26062610 }
2607-
2608- return false ;
2609- }
2610-
2611- if ($ node instanceof MethodCall) {
2612- if ($ node ->name instanceof Identifier) {
2613- $ calledOnType = $ scope ->getType ($ node ->var );
2614- $ methodReflection = $ scope ->getMethodReflection ($ calledOnType , $ node ->name ->name );
2611+ } elseif ($ callNode instanceof MethodCall) {
2612+ if ($ callNode ->name instanceof Identifier) {
2613+ $ calledOnType = $ scope ->getType ($ callNode ->var );
2614+ $ methodReflection = $ scope ->getMethodReflection ($ calledOnType , $ callNode ->name ->name );
26152615 if ($ methodReflection === null ) {
2616- return true ;
2616+ $ result = $ result ->or (TrinaryLogic::createMaybe ());
2617+ continue ;
26172618 }
26182619 $ hasSideEffects = $ methodReflection ->hasSideEffects ();
2619- return $ hasSideEffects ->yes ()
2620- || (!$ this ->rememberPossiblyImpureFunctionValues && !$ hasSideEffects ->no ());
2620+ if ($ hasSideEffects ->yes ()
2621+ || (!$ this ->rememberPossiblyImpureFunctionValues && !$ hasSideEffects ->no ())) {
2622+ return TrinaryLogic::createYes ();
2623+ }
2624+ } else {
2625+ $ result = $ result ->or (TrinaryLogic::createMaybe ());
26212626 }
2622- return true ;
2623- }
2624-
2625- if ($ node instanceof StaticCall) {
2626- if ($ node ->name instanceof Identifier) {
2627- if ($ node ->class instanceof Name) {
2628- $ calledOnType = $ scope ->resolveTypeByName ($ node ->class );
2627+ } elseif ($ callNode instanceof StaticCall) {
2628+ if ($ callNode ->name instanceof Identifier) {
2629+ if ($ callNode ->class instanceof Name) {
2630+ $ calledOnType = $ scope ->resolveTypeByName ($ callNode ->class );
26292631 } else {
2630- $ calledOnType = $ scope ->getType ($ node ->class );
2632+ $ calledOnType = $ scope ->getType ($ callNode ->class );
26312633 }
2632- $ methodReflection = $ scope ->getMethodReflection ($ calledOnType , $ node ->name ->name );
2634+ $ methodReflection = $ scope ->getMethodReflection ($ calledOnType , $ callNode ->name ->name );
26332635 if ($ methodReflection === null ) {
2634- return true ;
2636+ $ result = $ result ->or (TrinaryLogic::createMaybe ());
2637+ continue ;
26352638 }
26362639 $ hasSideEffects = $ methodReflection ->hasSideEffects ();
2637- return $ hasSideEffects ->yes ()
2638- || (!$ this ->rememberPossiblyImpureFunctionValues && !$ hasSideEffects ->no ());
2640+ if ($ hasSideEffects ->yes ()
2641+ || (!$ this ->rememberPossiblyImpureFunctionValues && !$ hasSideEffects ->no ())) {
2642+ return TrinaryLogic::createYes ();
2643+ }
2644+ } else {
2645+ $ result = $ result ->or (TrinaryLogic::createMaybe ());
26392646 }
2640- return true ;
26412647 }
26422648
2643- return false ;
2644- });
2649+ if ($ result ->yes ()) {
2650+ return $ result ;
2651+ }
2652+ }
26452653
2646- return $ found !== null ;
2654+ return $ result ;
26472655 }
26482656
26492657 private function createNullsafeTypes (Expr $ expr , Scope $ scope , TypeSpecifierContext $ context , ?Type $ type ): SpecifiedTypes
0 commit comments