diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index 88a11de1331..58ab8694055 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -2893,16 +2893,28 @@ public function invalidateExpression(Expr $expressionToInvalidate, bool $require $invalidated = true; continue; } - foreach ($holders as $holder) { + $filteredHolders = []; + foreach ($holders as $key => $holder) { + $shouldKeep = true; $conditionalTypeHolders = $holder->getConditionExpressionTypeHolders(); foreach ($conditionalTypeHolders as $conditionalTypeHolderExprString => $conditionalTypeHolder) { if ($this->shouldInvalidateExpression($exprStringToInvalidate, $expressionToInvalidate, $conditionalTypeHolder->getExpr(), $conditionalTypeHolderExprString, false, $invalidatingClass)) { $invalidated = true; - continue 3; + $shouldKeep = false; + break; } } + if (!$shouldKeep) { + continue; + } + + $filteredHolders[$key] = $holder; + } + if (count($filteredHolders) <= 0) { + continue; } - $newConditionalExpressions[$conditionalExprString] = $holders; + + $newConditionalExpressions[$conditionalExprString] = $filteredHolders; } if (!$invalidated) { diff --git a/tests/PHPStan/Rules/Variables/DefinedVariableRuleTest.php b/tests/PHPStan/Rules/Variables/DefinedVariableRuleTest.php index 2dde59f1423..add6c66beb2 100644 --- a/tests/PHPStan/Rules/Variables/DefinedVariableRuleTest.php +++ b/tests/PHPStan/Rules/Variables/DefinedVariableRuleTest.php @@ -1403,6 +1403,28 @@ public function testBug14019(): void $this->analyse([__DIR__ . '/../../Analyser/nsrt/bug-14019.php'], []); } + #[RequiresPhp('>= 8.0')] + public function testBug14274(): void + { + $this->cliArgumentsVariablesRegistered = true; + $this->polluteScopeWithLoopInitialAssignments = false; + $this->checkMaybeUndefinedVariables = true; + $this->polluteScopeWithAlwaysIterableForeach = true; + + $this->analyse([__DIR__ . '/data/bug-14274.php'], []); + } + + #[RequiresPhp('>= 8.0')] + public function testBug12373(): void + { + $this->cliArgumentsVariablesRegistered = true; + $this->polluteScopeWithLoopInitialAssignments = false; + $this->checkMaybeUndefinedVariables = true; + $this->polluteScopeWithAlwaysIterableForeach = true; + + $this->analyse([__DIR__ . '/data/bug-12373.php'], []); + } + public function testBug14117(): void { $this->cliArgumentsVariablesRegistered = true; diff --git a/tests/PHPStan/Rules/Variables/data/bug-12373.php b/tests/PHPStan/Rules/Variables/data/bug-12373.php new file mode 100644 index 00000000000..456068d4df3 --- /dev/null +++ b/tests/PHPStan/Rules/Variables/data/bug-12373.php @@ -0,0 +1,29 @@ += 8.0 + +declare(strict_types=1); + +namespace Bug12373; + +class HelloWorld +{ + public function sayHello(int $id): void + { + $foo = []; + + if ($id) + { + $foo = 'foo'; + } + else + { + $value = 'my value'; + } + + $foo = "foo"; + + if (!$id) + { + echo 'value: ' . $value; + } + } +} diff --git a/tests/PHPStan/Rules/Variables/data/bug-14274.php b/tests/PHPStan/Rules/Variables/data/bug-14274.php new file mode 100644 index 00000000000..36d70a29fc4 --- /dev/null +++ b/tests/PHPStan/Rules/Variables/data/bug-14274.php @@ -0,0 +1,49 @@ += 8.0 + +declare(strict_types=1); + +namespace Bug14274; + +class PreApplyEvent {} + +final class ComposerPatchesValidator { + /** + * Validates the status of the patcher plugin. + */ + public function validate(mixed $event): void { + $messages = []; + + [$plugin_installed_in_active, $is_active_root_requirement, $active_configuration_ok] = $this->computePatcherStatus(); + if ($event instanceof PreApplyEvent) { + [$plugin_installed_in_stage, $is_stage_root_requirement, $stage_configuration_ok] = $this->computePatcherStatus(); + $has_staged_update = TRUE; + } + else { + // No staged update exists. + $has_staged_update = FALSE; + } + + if ($has_staged_update && $plugin_installed_in_active !== $plugin_installed_in_stage) { + $messages[] = 'package-manager-faq-composer-patches-installed-or-removed'; + } + + // If the patcher is not listed in the runtime or dev dependencies, that's + // an error as well. + if (($plugin_installed_in_active && !$is_active_root_requirement) || ($has_staged_update && $plugin_installed_in_stage && !$is_stage_root_requirement)) { + $messages[] = 'It must be a root dependency.'; + } + + // If the plugin is misconfigured in either the active or stage directories, + // flag an error. + if (($plugin_installed_in_active && !$active_configuration_ok) || ($has_staged_update && $plugin_installed_in_stage && !$stage_configuration_ok)) { + $messages[] = 'The composer-exit-on-patch-failure key is not set to true.'; + } + } + + /** + * @return bool[] + */ + private function computePatcherStatus(): array { + return []; + } +}