Skip to content

Commit

Permalink
Fix false positive with isset() and empty()
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Oct 24, 2020
1 parent d7957d8 commit 05942ca
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 6 deletions.
14 changes: 13 additions & 1 deletion src/Analyser/EnsuredNonNullabilityResultExpression.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,17 @@ class EnsuredNonNullabilityResultExpression

private Type $originalType;

public function __construct(Expr $expression, Type $originalType)
private Type $originalNativeType;

public function __construct(
Expr $expression,
Type $originalType,
Type $originalNativeType
)
{
$this->expression = $expression;
$this->originalType = $originalType;
$this->originalNativeType = $originalNativeType;
}

public function getExpression(): Expr
Expand All @@ -28,4 +35,9 @@ public function getOriginalType(): Type
return $this->originalType;
}

public function getOriginalNativeType(): Type
{
return $this->originalNativeType;
}

}
8 changes: 6 additions & 2 deletions src/Analyser/MutatingScope.php
Original file line number Diff line number Diff line change
Expand Up @@ -2958,7 +2958,7 @@ public function unsetExpression(Expr $expr): self
return $this;
}

public function specifyExpressionType(Expr $expr, Type $type): self
public function specifyExpressionType(Expr $expr, Type $type, ?Type $nativeType = null): self
{
if ($expr instanceof Node\Scalar || $expr instanceof Array_) {
return $this;
Expand Down Expand Up @@ -2998,8 +2998,12 @@ public function specifyExpressionType(Expr $expr, Type $type): self
$variableTypes = $this->getVariableTypes();
$variableTypes[$variableName] = VariableTypeHolder::createYes($type);

if ($nativeType === null) {
$nativeType = $type;
}

$nativeTypes = $this->nativeExpressionTypes;
$nativeTypes[sprintf('$%s', $variableName)] = $type;
$nativeTypes[sprintf('$%s', $variableName)] = $nativeType;

return $this->scopeFactory->create(
$this->context,
Expand Down
15 changes: 12 additions & 3 deletions src/Analyser/NodeScopeResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -1231,8 +1231,13 @@ private function ensureNonNullability(MutatingScope $scope, Expr $expr, bool $fi
$exprType = $scope->getType($exprToSpecify);
$exprTypeWithoutNull = TypeCombinator::removeNull($exprType);
if (!$exprType->equals($exprTypeWithoutNull)) {
$specifiedExpressions[] = new EnsuredNonNullabilityResultExpression($exprToSpecify, $exprType);
$scope = $scope->specifyExpressionType($exprToSpecify, $exprTypeWithoutNull);
$nativeType = $scope->getNativeType($exprToSpecify);
$specifiedExpressions[] = new EnsuredNonNullabilityResultExpression($exprToSpecify, $exprType, $nativeType);
$scope = $scope->specifyExpressionType(
$exprToSpecify,
$exprTypeWithoutNull,
TypeCombinator::removeNull($nativeType)
);
}

if ($exprToSpecify instanceof PropertyFetch) {
Expand All @@ -1259,7 +1264,11 @@ private function ensureNonNullability(MutatingScope $scope, Expr $expr, bool $fi
private function revertNonNullability(MutatingScope $scope, array $specifiedExpressions): MutatingScope
{
foreach ($specifiedExpressions as $specifiedExpressionResult) {
$scope = $scope->specifyExpressionType($specifiedExpressionResult->getExpression(), $specifiedExpressionResult->getOriginalType());
$scope = $scope->specifyExpressionType(
$specifiedExpressionResult->getExpression(),
$specifiedExpressionResult->getOriginalType(),
$specifiedExpressionResult->getOriginalNativeType()
);
}

return $scope;
Expand Down
6 changes: 6 additions & 0 deletions tests/PHPStan/Analyser/NodeScopeResolverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10235,6 +10235,11 @@ public function dataBug3990(): array
return $this->gatherAssertTypes(__DIR__ . '/data/bug-3990.php');
}

public function dataBug3991(): array
{
return $this->gatherAssertTypes(__DIR__ . '/data/bug-3991.php');
}

/**
* @dataProvider dataBug2574
* @dataProvider dataBug2577
Expand Down Expand Up @@ -10324,6 +10329,7 @@ public function dataBug3990(): array
* @dataProvider dataBug3985
* @dataProvider dataArraySliceNonEmpty
* @dataProvider dataBug3990
* @dataProvider dataBug3991
* @param string $assertType
* @param string $file
* @param mixed ...$args
Expand Down
31 changes: 31 additions & 0 deletions tests/PHPStan/Analyser/data/bug-3991.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

namespace Bug3991;

use function PHPStan\Analyser\assertNativeType;
use function PHPStan\Analyser\assertType;

class Foo
{
/**
* @param \stdClass|array|null $config
*
* @return \stdClass
*/
public static function email($config = null)
{
assertNativeType('mixed', $config);
assertType('array|stdClass|null', $config);
if (empty($config))
{
assertNativeType('mixed', $config);
assertType('array|stdClass|null', $config);
$config = new \stdClass();
} elseif (! (is_array($config) || $config instanceof \stdClass)) {
assertNativeType('mixed~array|stdClass|false|null', $config);
assertType('*NEVER*', $config);
}

return new \stdClass($config);
}
}

0 comments on commit 05942ca

Please sign in to comment.