Skip to content

Commit

Permalink
Improve SpecifiedTypes::inverse
Browse files Browse the repository at this point in the history
The previous assumption was incorrect, it is not enough to just swap the sureTypes and sureNotTypes, as this can easily lead to a NeverType.
In this change a SubtractableType is created instead for both which makes retains more type information in follow-up operations like union or intersect.
  • Loading branch information
herndlm committed Feb 21, 2022
1 parent f255672 commit 522af3e
Showing 1 changed file with 19 additions and 1 deletion.
20 changes: 19 additions & 1 deletion src/Analyser/SpecifiedTypes.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@
namespace PHPStan\Analyser;

use PhpParser\Node\Expr;
use PHPStan\Type\MixedType;
use PHPStan\Type\SubtractableType;
use PHPStan\Type\Type;
use PHPStan\Type\TypeCombinator;
use function array_map;

class SpecifiedTypes
{
Expand Down Expand Up @@ -122,7 +125,22 @@ public function unionWith(SpecifiedTypes $other): self

public function inverse(): self
{
return new self($this->sureNotTypes, $this->sureTypes, $this->overwrite, $this->newConditionalExpressionHolders);
$normalized = $this->normalize();

$inverseType = static function (Type $subtractedType) {
if ($subtractedType instanceof SubtractableType && $subtractedType->getSubtractedType() !== null) {
return TypeCombinator::union($subtractedType->getTypeWithoutSubtractedType(), $subtractedType->getSubtractedType());
}

return new MixedType(false, $subtractedType);
};

return new self(
array_map(static fn (array $sureType) => [$sureType[0], $inverseType($sureType[1])], $normalized->sureTypes),
array_map(static fn (array $sureNotType) => [$sureNotType[0], $inverseType($sureNotType[1])], $normalized->sureNotTypes),
$normalized->overwrite,
$normalized->newConditionalExpressionHolders,
);
}

private function normalize(): self
Expand Down

0 comments on commit 522af3e

Please sign in to comment.