Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Analyser/ExprHandler/NewHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ public function processExpr(NodeScopeResolver $nodeScopeResolver, Stmt $stmt, Ex
$constructorResult = $node;
}, StatementContext::createTopLevel());
if ($constructorResult !== null) {
$throwPoints = array_map(static fn (ThrowPoint $point) => InternalThrowPoint::createFromPublic($point), $constructorResult->getStatementResult()->getThrowPoints());
$throwPoints = array_map(static fn (ThrowPoint $point): InternalThrowPoint => InternalThrowPoint::createFromPublic($point, $scope), $constructorResult->getStatementResult()->getThrowPoints());
$impurePoints = $constructorResult->getImpurePoints();
}
} else {
Expand Down
10 changes: 6 additions & 4 deletions src/Analyser/InternalThrowPoint.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,13 @@ public static function createImplicit(MutatingScope $scope, Node $node): self
return new self($scope, new ObjectType(Throwable::class), $node, explicit: false, canContainAnyThrowable: true);
}

public static function createFromPublic(ThrowPoint $throwPoint): self
public static function createFromPublic(ThrowPoint $throwPoint, ?MutatingScope $scope = null): self
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the $scope parameter is not optional and cannot be null.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Already handled — all 11,571 tests passed, and the fix has been committed and pushed.

{
$scope = $throwPoint->getScope();
if (!$scope instanceof MutatingScope) {
throw new ShouldNotHappenException();
if ($scope === null) {
$scope = $throwPoint->getScope();
if (!$scope instanceof MutatingScope) {
throw new ShouldNotHappenException();
}
}

return new self($scope, $throwPoint->getType(), $throwPoint->getNode(), $throwPoint->isExplicit(), $throwPoint->canContainAnyThrowable());
Expand Down
10 changes: 10 additions & 0 deletions tests/PHPStan/Rules/Variables/DefinedVariableRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1425,6 +1425,16 @@ public function testBug12373(): void
$this->analyse([__DIR__ . '/data/bug-12373.php'], []);
}

public function testBug13920(): void
{
$this->cliArgumentsVariablesRegistered = true;
$this->polluteScopeWithLoopInitialAssignments = true;
$this->checkMaybeUndefinedVariables = true;
$this->polluteScopeWithAlwaysIterableForeach = true;

$this->analyse([__DIR__ . '/data/bug-13920.php'], []);
}

public function testBug14117(): void
{
$this->cliArgumentsVariablesRegistered = true;
Expand Down
26 changes: 26 additions & 0 deletions tests/PHPStan/Rules/Variables/data/bug-13920.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php declare(strict_types = 1);

namespace Bug13920;

class TestOutput {
public function __construct() {}
}

final class MyTest
{
public function testRun(): void
{
$savedArgv = $_SERVER['argv'];

try {
$output = new class() extends TestOutput {
public function __construct()
{
parent::__construct();
}
};
} finally {
$_SERVER['argv'] = $savedArgv;
}
}
}
Loading