@@ -179,6 +179,8 @@ final class MutatingScope implements Scope
179179
180180 private const KEEP_VOID_ATTRIBUTE_NAME = 'keepVoid ' ;
181181
182+ private const IS_GLOBAL_ATTRIBUTE_NAME = 'isGlobal ' ;
183+ 182184 /** @var Type[] */
183185 private array $ resolvedTypes = [];
184186
@@ -609,10 +611,25 @@ public function afterOpenSslCall(string $openSslFunctionName): self
609611 );
610612 }
611613
614+ /** @api */
615+ public function isGlobalVariable (string $ variableName ): bool
616+ {
617+ if ($ this ->isSuperglobalVariable ($ variableName )) {
618+ return true ;
619+ }
620+ 621+ $ varExprString = '$ ' . $ variableName ;
622+ if (!isset ($ this ->expressionTypes [$ varExprString ])) {
623+ return false ;
624+ }
625+ 626+ return $ this ->expressionTypes [$ varExprString ]->getExpr ()->getAttribute (self ::IS_GLOBAL_ATTRIBUTE_NAME ) === true ;
627+ }
628+ 612629 /** @api */
613630 public function hasVariableType (string $ variableName ): TrinaryLogic
614631 {
615- if ($ this ->isGlobalVariable ($ variableName )) {
632+ if ($ this ->isSuperglobalVariable ($ variableName )) {
616633 return TrinaryLogic::createYes ();
617634 }
618635
@@ -653,7 +670,7 @@ public function getVariableType(string $variableName): Type
653670
654671 $ varExprString = '$ ' . $ variableName ;
655672 if (!array_key_exists ($ varExprString , $ this ->expressionTypes )) {
656- if ($ this ->isGlobalVariable ($ variableName )) {
673+ if ($ this ->isSuperglobalVariable ($ variableName )) {
657674 return new ArrayType (new BenevolentUnionType ([new IntegerType (), new StringType ()]), new MixedType (true ));
658675 }
659676 return new MixedType ();
@@ -704,7 +721,7 @@ public function getMaybeDefinedVariables(): array
704721 return $ variables ;
705722 }
706723
707- private function isGlobalVariable (string $ variableName ): bool
724+ private function isSuperglobalVariable (string $ variableName ): bool
708725 {
709726 return in_array ($ variableName , self ::SUPERGLOBAL_VARIABLES , true );
710727 }
@@ -4204,9 +4221,13 @@ public function isUndefinedExpressionAllowed(Expr $expr): bool
42044221 return array_key_exists ($ exprString , $ this ->currentlyAllowedUndefinedExpressions );
42054222 }
42064223
4207- public function assignVariable (string $ variableName , Type $ type , Type $ nativeType , TrinaryLogic $ certainty ): self
4224+ public function assignVariable (string $ variableName , Type $ type , Type $ nativeType , TrinaryLogic $ certainty, bool $ isGlobal = false ): self
42084225 {
42094226 $ node = new Variable ($ variableName );
4227+ if ($ isGlobal || $ this ->isGlobalVariable ($ variableName )) {
4228+ $ node ->setAttribute (self ::IS_GLOBAL_ATTRIBUTE_NAME , true );
4229+ }
4230+ 42104231 $ scope = $ this ->assignExpression ($ node , $ type , $ nativeType );
42114232 if ($ certainty ->no ()) {
42124233 throw new ShouldNotHappenException ();
@@ -4979,7 +5000,7 @@ private function createConditionalExpressions(
49795000 private function mergeVariableHolders (array $ ourVariableTypeHolders , array $ theirVariableTypeHolders ): array
49805001 {
49815002 $ intersectedVariableTypeHolders = [];
4982- $ globalVariableCallback = fn (Node $ node ) => $ node instanceof Variable && is_string ($ node ->name ) && $ this ->isGlobalVariable ($ node ->name );
5003+ $ globalVariableCallback = fn (Node $ node ) => $ node instanceof Variable && is_string ($ node ->name ) && $ this ->isSuperglobalVariable ($ node ->name );
49835004 $ nodeFinder = new NodeFinder ();
49845005 foreach ($ ourVariableTypeHolders as $ exprString => $ variableTypeHolder ) {
49855006 if (isset ($ theirVariableTypeHolders [$ exprString ])) {
0 commit comments