Skip to content

Commit

Permalink
Preserve accessory types in MutatingScope::generalizeType
Browse files Browse the repository at this point in the history
  • Loading branch information
herndlm committed Sep 19, 2022
1 parent 9ec53eb commit f44e6d6
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 2 deletions.
32 changes: 31 additions & 1 deletion src/Analyser/MutatingScope.php
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@
use function array_key_exists;
use function array_keys;
use function array_map;
use function array_merge;
use function array_pop;
use function array_slice;
use function count;
Expand Down Expand Up @@ -4843,7 +4844,36 @@ private static function generalizeType(Type $a, Type $b): Type
$resultTypes[] = TypeCombinator::union(...$integerRanges['b']);
}

return TypeCombinator::union(...$resultTypes, ...$otherTypes);
$accessoryTypes = [];
$aAccessoryTypes = TypeUtils::getAccessoryTypes($a);
$bAccessoryTypes = TypeUtils::getAccessoryTypes($b);
if (count($aAccessoryTypes) > 0) {
if (count($bAccessoryTypes) === 0) {
$accessoryTypes = $aAccessoryTypes;
} else {
$accessoryTypesToUnion = [];
foreach (array_merge($aAccessoryTypes, $bAccessoryTypes) as $accessoryType) {
if ($accessoryType instanceof HasOffsetValueType) {
$accessoryTypesToUnion[sprintf('hasOffsetValue(%s)', $accessoryType->getOffsetType()->describe(VerbosityLevel::cache()))][] = $accessoryType;
continue;
}

$accessoryTypesToUnion[$accessoryType->describe(VerbosityLevel::cache())][] = $accessoryType;
}

$accessoryTypes = array_map(
static fn (array $accessoryTypes): Type => TypeCombinator::union(...$accessoryTypes)->generalize(GeneralizePrecision::moreSpecific()),
$accessoryTypesToUnion,
);
}
} elseif (count($bAccessoryTypes) > 0) {
$accessoryTypes = $bAccessoryTypes;
}

return TypeCombinator::intersect(
TypeCombinator::union(...$resultTypes, ...$otherTypes),
...$accessoryTypes,
);
}

private static function getArrayDepth(ArrayType $type): int
Expand Down
2 changes: 1 addition & 1 deletion src/Parallel/ParallelAnalyser.php
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ public function analyse(
$this->processPool->quitAll();
}

if (count($jobs) === 0) {
if (count($jobs) === 0) { // @phpstan-ignore-line
$this->processPool->tryQuitProcess($processIdentifier);
return;
}
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 @@ -1031,6 +1031,7 @@ public function dataFileAsserts(): iterable
yield from $this->gatherAssertTypes(__DIR__ . '/../Rules/Arrays/data/bug-7954.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-7993.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-7141.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-8015.php');
}

/**
Expand Down
30 changes: 30 additions & 0 deletions tests/PHPStan/Analyser/data/bug-8015.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php declare(strict_types = 1);

namespace Bug8015;

use function PHPStan\Testing\assertType;

/**
* @param array<string, string|string[]> $items
* @return array<string, mixed>
*/
function extractParameters(array $items): array
{
$config = [];
foreach ($items as $itemName => $item) {
if (is_array($item)) {
$config['things'] = [];
assertType('array{}', $config['things']);
foreach ($item as $thing) {
assertType('array<int, string>', $config['things']);
$config['things'][] = (string) $thing;
}
assertType('array<int, string>', $config['things']);
} else {
$config[$itemName] = (string) $item;
}
}
assertType('array<int, string>|string', $config['things']);

return $config;
}
6 changes: 6 additions & 0 deletions tests/PHPStan/Rules/Arrays/OffsetAccessAssignmentRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -150,4 +150,10 @@ public function testBug1714(): void
$this->analyse([__DIR__ . '/data/bug-1714.php'], []);
}

public function testBug8015(): void
{
$this->checkUnionTypes = true;
$this->analyse([__DIR__ . '/../../Analyser/data/bug-8015.php'], []);
}

}

0 comments on commit f44e6d6

Please sign in to comment.