Skip to content

Commit

Permalink
Fix resolving type of isset($arr['key'])
Browse files Browse the repository at this point in the history
It was buggy when $arr['key'] might be null.

Fixes phpstan/phpstan#1924
  • Loading branch information
jlherren authored and ondrejmirtes committed Oct 18, 2020
1 parent 2164616 commit 9ea485b
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 8 deletions.
19 changes: 11 additions & 8 deletions src/Analyser/MutatingScope.php
Original file line number Diff line number Diff line change
Expand Up @@ -552,23 +552,26 @@ private function resolveType(Expr $node): Type
$result = new ConstantBooleanType(true);
foreach ($node->vars as $var) {
if ($var instanceof Expr\ArrayDimFetch && $var->dim !== null) {
$hasOffset = $this->getType($var->var)->hasOffsetValueType(
$this->getType($var->dim)
)->toBooleanType();
if ($hasOffset instanceof ConstantBooleanType) {
if (!$hasOffset->getValue()) {
return $hasOffset;
$variableType = $this->getType($var->var);
$dimType = $this->getType($var->dim);
$hasOffset = $variableType->hasOffsetValueType($dimType);
$offsetValueType = $variableType->getOffsetValueType($dimType);
$offsetValueIsNotNull = (new NullType())->isSuperTypeOf($offsetValueType)->negate();
$isset = $hasOffset->and($offsetValueIsNotNull)->toBooleanType();
if ($isset instanceof ConstantBooleanType) {
if (!$isset->getValue()) {
return $isset;
}

continue;
}

$result = $hasOffset;
$result = $isset;
continue;
}

if ($var instanceof Expr\Variable && is_string($var->name)) {
$variableType = $this->resolveType($var);
$variableType = $this->getType($var);
$isNullSuperType = (new NullType())->isSuperTypeOf($variableType);
$has = $this->hasVariableType($var->name);
if ($has->no() || $isNullSuperType->yes()) {
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 @@ -10194,6 +10194,11 @@ public function dataBug3961(): array
return $this->gatherAssertTypes(__DIR__ . '/data/bug-3961.php');
}

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

/**
* @dataProvider dataBug2574
* @dataProvider dataBug2577
Expand Down Expand Up @@ -10275,6 +10280,7 @@ public function dataBug3961(): array
* @dataProvider dataNotEmptyArray
* @dataProvider dataClassConstantOnExpression
* @dataProvider dataBug3961
* @dataProvider dataBug1924
* @param string $assertType
* @param string $file
* @param mixed ...$args
Expand Down
27 changes: 27 additions & 0 deletions tests/PHPStan/Analyser/data/bug-1924.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace Bug1924;

use function PHPStan\Analyser\assertType;

class Bug1924
{

function getArrayOrNull(): ?array
{
return rand(0, 1) ? [1, 2, 3] : null;
}

function foo(): void
{
$arr = [
'a' => $this->getArrayOrNull(),
'b' => $this->getArrayOrNull(),
];
assertType('array(\'a\' => array|null, \'b\' => array|null)', $arr);

$cond = isset($arr['a']) && isset($arr['b']);
assertType('bool', $cond);
}

}

0 comments on commit 9ea485b

Please sign in to comment.