Skip to content

Commit

Permalink
Fixed collapsing of constant arrays
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Oct 6, 2023
1 parent 6348cc3 commit 746de74
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 2 deletions.
2 changes: 1 addition & 1 deletion phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -1549,7 +1549,7 @@ parameters:

-
message: "#^Doing instanceof PHPStan\\\\Type\\\\Constant\\\\ConstantArrayType is error\\-prone and deprecated\\. Use Type\\:\\:getConstantArrays\\(\\) instead\\.$#"
count: 12
count: 10
path: src/Type/TypeCombinator.php

-
Expand Down
2 changes: 1 addition & 1 deletion src/Type/TypeCombinator.php
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ private static function compareTypesInUnion(Type $a, Type $b): ?array
return [new HasOffsetValueType($a->getOffsetType(), self::union($a->getValueType(), $b->getValueType())), null];
}
}
if ($a instanceof ConstantArrayType && $b instanceof ConstantArrayType) {
if ($a->isConstantArray()->yes() && $b->isConstantArray()->yes()) {
return null;
}

Expand Down
1 change: 1 addition & 0 deletions tests/PHPStan/Analyser/NodeScopeResolverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ public function dataFileAsserts(): iterable
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-3915.php');

yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-2378.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-9985.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-6294.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-2580.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-9753.php');
Expand Down
25 changes: 25 additions & 0 deletions tests/PHPStan/Analyser/data/bug-9985.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

namespace Bug9985;

use function PHPStan\Testing\assertType;

function (): void {
$warnings = [];

if (rand(0, 100) >= 1) {
$warnings['a'] = true;
}

if (rand(0, 100) >= 2) {
$warnings['b'] = true;
} elseif (rand(0, 100) >= 3) {
$warnings['c'] = true;
}

assertType('array{}|array{a?: true, b: true}|array{a?: true, c?: true}', $warnings);

if (!empty($warnings)) {
assertType('array{a?: true, b: true}|(array{a?: true, c?: true}&non-empty-array)', $warnings);
}
};
104 changes: 104 additions & 0 deletions tests/PHPStan/Type/TypeCombinatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2450,6 +2450,50 @@ public function dataUnion(): iterable
NeverType::class,
'*NEVER*',
];
yield [
[
new ConstantArrayType([
new ConstantStringType('a'),
new ConstantStringType('b'),
], [
new ConstantBooleanType(true),
new ConstantBooleanType(true),
], [0], [0]),
new ConstantArrayType([
new ConstantStringType('a'),
new ConstantStringType('c'),
], [
new ConstantBooleanType(true),
new ConstantBooleanType(true),
], [0], [0, 1]),
],
UnionType::class,
'array{a?: true, b: true}|array{a?: true, c?: true}',
];

yield [
[
new ConstantArrayType([
new ConstantStringType('a'),
new ConstantStringType('b'),
], [
new ConstantBooleanType(true),
new ConstantBooleanType(true),
], [0], [0]),
new IntersectionType([
new ConstantArrayType([
new ConstantStringType('a'),
new ConstantStringType('c'),
], [
new ConstantBooleanType(true),
new ConstantBooleanType(true),
], [0], [0, 1]),
new NonEmptyArrayType(),
]),
],
UnionType::class,
'array{a?: true, b: true}|(array{a?: true, c?: true}&non-empty-array)',
];
}

/**
Expand Down Expand Up @@ -4030,6 +4074,66 @@ public function dataIntersect(): iterable
NonAcceptingNeverType::class,
'never=explicit',
];
yield [
[
new UnionType([
new ConstantArrayType([], []),
new ConstantArrayType([
new ConstantStringType('a'),
new ConstantStringType('b'),
], [
new ConstantBooleanType(true),
new ConstantBooleanType(true),
], [0], [0]),
new ConstantArrayType([
new ConstantStringType('a'),
new ConstantStringType('c'),
], [
new ConstantBooleanType(true),
new ConstantBooleanType(true),
], [0], [0, 1]),
]),
new NonEmptyArrayType(),
],
UnionType::class,
'array{a?: true, b: true}|(array{a?: true, c?: true}&non-empty-array)',
];
yield [
[
new ConstantArrayType([], []),
new NonEmptyArrayType(),
],
NeverType::class,
'*NEVER*=implicit',
];
yield [
[
new ConstantArrayType([
new ConstantStringType('a'),
new ConstantStringType('b'),
], [
new ConstantBooleanType(true),
new ConstantBooleanType(true),
], [0], [0]),
new NonEmptyArrayType(),
],
ConstantArrayType::class,
'array{a?: true, b: true}',
];
yield [
[
new ConstantArrayType([
new ConstantStringType('a'),
new ConstantStringType('c'),
], [
new ConstantBooleanType(true),
new ConstantBooleanType(true),
], [0], [0, 1]),
new NonEmptyArrayType(),
],
IntersectionType::class,
'array{a?: true, c?: true}&non-empty-array',
];
}

/**
Expand Down

0 comments on commit 746de74

Please sign in to comment.