diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticMethod/AtomicStaticCallAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticMethod/AtomicStaticCallAnalyzer.php index 4c57dfaf9c1..4e85c2c0f70 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticMethod/AtomicStaticCallAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/StaticMethod/AtomicStaticCallAnalyzer.php @@ -481,14 +481,15 @@ private static function handleNamedCall( $class_storage->final ); - $context->vars_in_scope['$tmp_mixin_var'] = $new_lhs_type; + $mixin_context = clone $context; + $mixin_context->vars_in_scope['$__tmp_mixin_var__'] = $new_lhs_type; return self::forwardCallToInstanceMethod( $statements_analyzer, $stmt, $stmt_name, - $context, - 'tmp_mixin_var', + $mixin_context, + '__tmp_mixin_var__', true ); } @@ -694,18 +695,21 @@ function (PhpParser\Node\Arg $arg): PhpParser\Node\Expr\ArrayItem { // with nonexistent method, we try to forward to instance method call for resolve pseudo method. // Use parent type as static type for the method call - $context->vars_in_scope['$tmp_parent_var'] = new Union([$lhs_type_part]); + $tmp_context = clone $context; + $tmp_context->vars_in_scope['$__tmp_parent_var__'] = new Union([$lhs_type_part]); if (self::forwardCallToInstanceMethod( $statements_analyzer, $stmt, $stmt_name, - $context, - 'tmp_parent_var' + $tmp_context, + '__tmp_parent_var__' ) === false) { return false; } + unset($tmp_context); + // Resolve actual static return type according to caller (i.e. $this) static type if (isset($context->vars_in_scope['$this']) && $method_call_type = $statements_analyzer->node_data->getType($stmt) diff --git a/tests/MagicMethodAnnotationTest.php b/tests/MagicMethodAnnotationTest.php index 46f8e0db842..edde62ee191 100644 --- a/tests/MagicMethodAnnotationTest.php +++ b/tests/MagicMethodAnnotationTest.php @@ -1119,6 +1119,29 @@ class B extends A {} class C {}', 'error_message' => 'InvalidDocblock', ], + 'magicParentCallShouldNotPolluteContext' => [ + ' 'UndefinedVariable', + ] ]; } diff --git a/tests/MixinAnnotationTest.php b/tests/MixinAnnotationTest.php index 37d04f70404..12755d3309a 100644 --- a/tests/MixinAnnotationTest.php +++ b/tests/MixinAnnotationTest.php @@ -687,6 +687,30 @@ function test() : FooGrandChild { }', 'error_message' => 'LessSpecificReturnStatement' ], + 'mixinStaticCallShouldNotPolluteContext' => [ + ' + */ + class Bar + { + public function baz(): self + { + self::foobar(); + return $__tmp_mixin_var__; + } + }', + 'error_message' => 'UndefinedVariable' + ], ]; } }