Skip to content

Commit

Permalink
Fix dumbed down arrays
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Dec 21, 2022
1 parent 51774ef commit 7c68a12
Show file tree
Hide file tree
Showing 7 changed files with 19 additions and 10 deletions.
4 changes: 4 additions & 0 deletions src/Analyser/MutatingScope.php
Expand Up @@ -68,6 +68,7 @@
use PHPStan\Type\Accessory\AccessoryLiteralStringType;
use PHPStan\Type\Accessory\HasOffsetValueType;
use PHPStan\Type\Accessory\NonEmptyArrayType;
use PHPStan\Type\Accessory\OversizedArrayType;
use PHPStan\Type\ArrayType;
use PHPStan\Type\BooleanType;
use PHPStan\Type\ClosureType;
Expand Down Expand Up @@ -4357,6 +4358,9 @@ private static function generalizeType(Type $a, Type $b): Type
if ($generalArraysA->isList()->yes() && $generalArraysB->isList()->yes()) {
$resultType = AccessoryArrayListType::intersectWith($resultType);
}
if ($generalArraysA->isOversizedArray()->yes() && $generalArraysB->isOversizedArray()->yes()) {
$resultType = TypeCombinator::intersect($resultType, new OversizedArrayType());
}
$resultTypes[] = $resultType;
}
} elseif (count($generalArrays['b']) > 0) {
Expand Down
5 changes: 5 additions & 0 deletions src/Type/TypeCombinator.php
Expand Up @@ -21,6 +21,7 @@
use PHPStan\Type\Generic\TemplateTypeFactory;
use PHPStan\Type\Generic\TemplateUnionType;
use function array_key_exists;
use function array_key_first;
use function array_map;
use function array_merge;
use function array_slice;
Expand Down Expand Up @@ -548,6 +549,10 @@ private static function processArrayAccessoryTypes(array $arrayTypes): array
$arrayTypeCount = count($arrayTypes);
foreach ($accessoryTypes as $accessoryType) {
if (count($accessoryType) !== $arrayTypeCount) {
$firstKey = array_key_first($accessoryType);
if ($accessoryType[$firstKey] instanceof OversizedArrayType) {
$commonAccessoryTypes[] = $accessoryType[$firstKey];
}
continue;
}

Expand Down
6 changes: 6 additions & 0 deletions tests/PHPStan/Analyser/AnalyserIntegrationTest.php
Expand Up @@ -1098,6 +1098,12 @@ public static function getAdditionalConfigFiles(): array
];
}

public function testBug8004(): void
{
$errors = $this->runAnalyse(__DIR__ . '/data/bug-8004.php');
$this->assertNoErrors($errors);
}

/**
* @param string[]|null $allAnalysedFiles
* @return Error[]
Expand Down
1 change: 0 additions & 1 deletion tests/PHPStan/Analyser/NodeScopeResolverTest.php
Expand Up @@ -1069,7 +1069,6 @@ public function dataFileAsserts(): iterable
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-7987.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-7963-three.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-8017.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-8004.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/global-namespace.php');

if (PHP_VERSION_ID >= 80000) {
Expand Down
2 changes: 1 addition & 1 deletion tests/PHPStan/Analyser/data/bug-8004.php
Expand Up @@ -73,7 +73,7 @@ public function getErrorsOnInvalidQuestions(array $importQuiz, int $key): array
}
}

assertType("list<non-empty-array<literal-string&non-falsy-string, 'empty_answer'|'empty_question'|'invalid_answer_1_too_long'|'invalid_answer_1_type'|'invalid_answer_2_too_long'|'invalid_answer_2_type'|'invalid_answer_3_too_long'|'invalid_answer_3_type'|'invalid_answer_4_too_long'|'invalid_answer_4_type'|'invalid_question_too_long'|'invalid_right_answer'|int>>", $errors);
assertType("list<non-empty-array<literal-string&non-falsy-string, 'empty_answer'|'empty_question'|'invalid_answer_1_too_long'|'invalid_answer_1_type'|'invalid_answer_2_too_long'|'invalid_answer_2_type'|'invalid_answer_3_too_long'|'invalid_answer_3_type'|'invalid_answer_4_too_long'|'invalid_answer_4_type'|'invalid_question_too_long'|'invalid_right_answer'|int>&oversized-array>&oversized-array", $errors);

return $errors;
}
Expand Down
7 changes: 1 addition & 6 deletions tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php
Expand Up @@ -812,12 +812,7 @@ public function testBug8223(): void
public function testBug8146bErrors(): void
{
$this->checkBenevolentUnionTypes = true;
$this->analyse([__DIR__ . '/data/bug-8146b-errors.php'], [
[
'Method Bug8146bError\LocationFixtures::getData() should return array<non-empty-string, array<non-empty-string, array{constituencies: non-empty-list<non-empty-string>, coordinates: array{lat: float, lng: float}}>> but returns array{Bács-Kiskun: array{Ágasegyháza: array{constituencies: array{\'Bács-Kiskun 4.\', true, false, Bug8146bError\X, null}, coordinates: array{lat: 46.8386043, lng: 19.4502899}}, Akasztó: array{constituencies: array{\'Bács-Kiskun 3.\'}, coordinates: array{lat: 46.6898175, lng: 19.205086}}, Apostag: array{constituencies: array{\'Bács-Kiskun 3.\'}, coordinates: array{lat: 46.8812652, lng: 18.9648478}}, Bácsalmás: array{constituencies: array{\'Bács-Kiskun 5.\'}, coordinates: array{lat: 46.1250396, lng: 19.3357509}}, Bácsbokod: array{constituencies: array{\'Bács-Kiskun 6.\'}, coordinates: array{lat: 46.1234737, lng: 19.155708}}, Bácsborsód: array{constituencies: array{\'Bács-Kiskun 6.\'}, coordinates: array{lat: 46.0989373, lng: 19.1566725}}, Bácsszentgyörgy: array{constituencies: array{\'Bács-Kiskun 6.\'}, coordinates: array{lat: 45.9746039, lng: 19.0398066}}, Bácsszőlős: array{constituencies: array{\'Bács-Kiskun 5.\'}, coordinates: array{lat: 46.1352003, lng: 19.4215997}}, ...}, Baranya: non-empty-array<literal-string&non-falsy-string, array<literal-string&non-falsy-string, array<int<0, max>|(literal-string&non-falsy-string), float|(literal-string&non-falsy-string)>>>, Békés: array{Almáskamarás: array{constituencies: array{\'Békés 4.\'}, coordinates: array{lat: 46.4617785, lng: 21.092448}}, Battonya: array{constituencies: array{\'Békés 4.\'}, coordinates: array{lat: 46.2902462, lng: 21.0199215}}, Békés: array{constituencies: array{\'Békés 2.\'}, coordinates: array{lat: 46.6704899, lng: 21.0434996}}, Békéscsaba: array{constituencies: array{\'Békés 1.\'}, coordinates: array{lat: 46.6735939, lng: 21.0877309}}, Békéssámson: array{constituencies: array{\'Békés 4.\'}, coordinates: array{lat: 46.4208677, lng: 20.6176498}}, Békésszentandrás: array{constituencies: array{\'Békés 2.\'}, coordinates: array{lat: 46.8715996, lng: 20.48336}}, Bélmegyer: array{constituencies: array{\'Békés 3.\'}, coordinates: array{lat: 46.8726019, lng: 21.1832832}}, Biharugra: array{constituencies: array{\'Békés 3.\'}, coordinates: array{lat: 46.9691009, lng: 21.5987651}}, ...}, Borsod-Abaúj-Zemplén: non-empty-array<literal-string&non-falsy-string, array<literal-string&non-falsy-string, array<int<0, max>|(literal-string&non-falsy-string), float|(literal-string&non-falsy-string)>>>, Budapest: array{Budapest I. ker.: array{constituencies: array{\'Budapest 01.\'}, coordinates: array{lat: 47.4968219, lng: 19.037458}}, Budapest II. ker.: array{constituencies: array{\'Budapest 03.\', \'Budapest 04.\'}, coordinates: array{lat: 47.5393329, lng: 18.986934}}, Budapest III. ker.: array{constituencies: array{\'Budapest 04.\', \'Budapest 10.\'}, coordinates: array{lat: 47.5671768, lng: 19.0368517}}, Budapest IV. ker.: array{constituencies: array{\'Budapest 11.\', \'Budapest 12.\'}, coordinates: array{lat: 47.5648915, lng: 19.0913149}}, Budapest V. ker.: array{constituencies: array{\'Budapest 01.\'}, coordinates: array{lat: 47.5002319, lng: 19.0520181}}, Budapest VI. ker.: array{constituencies: array{\'Budapest 05.\'}, coordinates: array{lat: 47.509863, lng: 19.0625813}}, Budapest VII. ker.: array{constituencies: array{\'Budapest 05.\'}, coordinates: array{lat: 47.5027289, lng: 19.073376}}, Budapest VIII. ker.: array{constituencies: array{\'Budapest 01.\', \'Budapest 06.\'}, coordinates: array{lat: 47.4894184, lng: 19.070668}}, ...}, Csongrád-Csanád: array{Algyő: array{constituencies: array{\'Csongrád-Csanád 4.\'}, coordinates: array{lat: 46.3329625, lng: 20.207889}}, Ambrózfalva: array{constituencies: array{\'Csongrád-Csanád 4.\'}, coordinates: array{lat: 46.3501417, lng: 20.7313995}}, Apátfalva: array{constituencies: array{\'Csongrád-Csanád 4.\'}, coordinates: array{lat: 46.173317, lng: 20.5800472}}, Árpádhalom: array{constituencies: array{\'Csongrád-Csanád 3.\'}, coordinates: array{lat: 46.6158286, lng: 20.547733}}, Ásotthalom: array{constituencies: array{\'Csongrád-Csanád 2.\'}, coordinates: array{lat: 46.1995983, lng: 19.7833756}}, Baks: array{constituencies: array{\'Csongrád-Csanád 3.\'}, coordinates: array{lat: 46.5518708, lng: 20.1064166}}, Balástya: array{constituencies: array{\'Csongrád-Csanád 3.\'}, coordinates: array{lat: 46.4261828, lng: 20.004933}}, Bordány: array{constituencies: array{\'Csongrád-Csanád 2.\'}, coordinates: array{lat: 46.3194213, lng: 19.9227063}}, ...}, Fejér: array{Aba: array{constituencies: array{\'Fejér 5.\'}, coordinates: array{lat: 47.0328193, lng: 18.522359}}, Adony: array{constituencies: array{\'Fejér 4.\'}, coordinates: array{lat: 47.119831, lng: 18.8612469}}, Alap: array{constituencies: array{\'Fejér 5.\'}, coordinates: array{lat: 46.8075763, lng: 18.684028}}, Alcsútdoboz: array{constituencies: array{\'Fejér 3.\'}, coordinates: array{lat: 47.4277067, lng: 18.6030325}}, Alsószentiván: array{constituencies: array{\'Fejér 5.\'}, coordinates: array{lat: 46.7910573, lng: 18.732161}}, Bakonycsernye: array{constituencies: array{\'Fejér 2.\'}, coordinates: array{lat: 47.321719, lng: 18.0907379}}, Bakonykúti: array{constituencies: array{\'Fejér 2.\'}, coordinates: array{lat: 47.2458464, lng: 18.195769}}, Balinka: array{constituencies: array{\'Fejér 2.\'}, coordinates: array{lat: 47.3135736, lng: 18.1907168}}, ...}, Győr-Moson-Sopron: array{Abda: array{constituencies: array{\'Győr-Moson-Sopron 5.\'}, coordinates: array{lat: 47.6962149, lng: 17.5445786}}, Acsalag: array{constituencies: array{\'Győr-Moson-Sopron 3.\'}, coordinates: array{lat: 47.676095, lng: 17.1977771}}, Ágfalva: array{constituencies: array{\'Győr-Moson-Sopron 4.\'}, coordinates: array{lat: 47.688862, lng: 16.5110233}}, Agyagosszergény: array{constituencies: array{\'Győr-Moson-Sopron 3.\'}, coordinates: array{lat: 47.608545, lng: 16.9409912}}, Árpás: array{constituencies: array{\'Győr-Moson-Sopron 3.\'}, coordinates: array{lat: 47.5134127, lng: 17.3931579}}, Ásványráró: array{constituencies: array{\'Győr-Moson-Sopron 5.\'}, coordinates: array{lat: 47.8287695, lng: 17.499195}}, Babót: array{constituencies: array{\'Győr-Moson-Sopron 3.\'}, coordinates: array{lat: 47.5752269, lng: 17.0758604}}, Bágyogszovát: array{constituencies: array{\'Győr-Moson-Sopron 3.\'}, coordinates: array{lat: 47.5866036, lng: 17.3617273}}, ...}, ...}.',
12,
],
]);
$this->analyse([__DIR__ . '/data/bug-8146b-errors.php'], []); // there could be a valid error
}

}
4 changes: 2 additions & 2 deletions tests/PHPStan/Type/TypeCombinatorTest.php
Expand Up @@ -2327,8 +2327,8 @@ public function dataUnion(): iterable
new IntersectionType([new ArrayType(new IntegerType(), new StringType()), new OversizedArrayType()]),
new ArrayType(new IntegerType(), new StringType()),
],
ArrayType::class,
'array<int, string>',
IntersectionType::class,
'array<int, string>&oversized-array',
];
}

Expand Down

0 comments on commit 7c68a12

Please sign in to comment.