Skip to content

Commit

Permalink
Fixed ConstantArrayType::isSuperTypeOf()
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed May 3, 2020
1 parent 56eadce commit b55208e
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 13 deletions.
17 changes: 12 additions & 5 deletions src/Type/Constant/ConstantArrayType.php
Original file line number Diff line number Diff line change
Expand Up @@ -121,14 +121,21 @@ public function accepts(Type $type, bool $strictTypes): TrinaryLogic
public function isSuperTypeOf(Type $type): TrinaryLogic
{
if ($type instanceof self) {
if (count($this->keyTypes) !== count($type->keyTypes)) {
return TrinaryLogic::createNo();
if (count($this->keyTypes) === 0) {
if (count($type->keyTypes) > 0) {
return TrinaryLogic::createNo();
}

return TrinaryLogic::createYes();
}

$results = [];
foreach (array_keys($this->keyTypes) as $i) {
$results[] = $this->keyTypes[$i]->isSuperTypeOf($type->keyTypes[$i]);
$results[] = $this->valueTypes[$i]->isSuperTypeOf($type->valueTypes[$i]);
foreach ($this->keyTypes as $i => $keyType) {
$hasOffset = $type->hasOffsetValueType($keyType);
if ($hasOffset->no()) {
return TrinaryLogic::createNo();
}
$results[] = $this->valueTypes[$i]->isSuperTypeOf($type->getOffsetValueType($keyType));
}

return TrinaryLogic::createYes()->and(...$results);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,10 +118,6 @@ public function testStrictComparison(): void
'Strict comparison using === between array(\'X\' => 1, \'Y\' => 2) and array(\'X\' => 2, \'Y\' => 1) will always evaluate to false.',
300,
],
[
'Strict comparison using === between array(\'X\' => 1, \'Y\' => 2) and array(\'Y\' => 2, \'X\' => 1) will always evaluate to false.',
308,
],
[
'Strict comparison using === between \'/\'|\'\\\\\' and \'//\' will always evaluate to false.',
320,
Expand Down Expand Up @@ -300,10 +296,6 @@ public function testStrictComparisonWithoutAlwaysTrue(): void
'Strict comparison using === between array(\'X\' => 1, \'Y\' => 2) and array(\'X\' => 2, \'Y\' => 1) will always evaluate to false.',
300,
],
[
'Strict comparison using === between array(\'X\' => 1, \'Y\' => 2) and array(\'Y\' => 2, \'X\' => 1) will always evaluate to false.',
308,
],
[
'Strict comparison using === between \'/\'|\'\\\\\' and \'//\' will always evaluate to false.',
320,
Expand Down
24 changes: 24 additions & 0 deletions tests/PHPStan/Rules/Methods/data/method-signature.php
Original file line number Diff line number Diff line change
Expand Up @@ -457,3 +457,27 @@ public function processNode(\PhpParser\Node $node): void
}

}

interface ConstantArrayInterface
{

/**
* @return array{foo: string}
*/
public function foobar(): array;

}

class ConstantArrayClass implements ConstantArrayInterface
{
/**
* @return array{foo: string, bar: string}
*/
public function foobar(): array
{
return [
'foo' => '',
'bar' => '',
];
}
}
32 changes: 32 additions & 0 deletions tests/PHPStan/Type/Constant/ConstantArrayTypeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,38 @@ public function dataIsSuperTypeOf(): iterable
new IterableType(new MixedType(false), new MixedType(true)),
TrinaryLogic::createMaybe(),
];

yield [
new ConstantArrayType([
new ConstantStringType('foo'),
], [
new IntegerType(),
]),
new ConstantArrayType([
new ConstantStringType('foo'),
new ConstantStringType('bar'),
], [
new IntegerType(),
new IntegerType(),
]),
TrinaryLogic::createYes(),
];

yield [
new ConstantArrayType([
new ConstantStringType('foo'),
new ConstantStringType('bar'),
], [
new IntegerType(),
new IntegerType(),
]),
new ConstantArrayType([
new ConstantStringType('foo'),
], [
new IntegerType(),
]),
TrinaryLogic::createNo(),
];
}

/**
Expand Down

0 comments on commit b55208e

Please sign in to comment.