Skip to content

Commit

Permalink
ArrayType::describe - explicit mixed should be stated explicitly
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Oct 12, 2024
1 parent a934639 commit 6cf2238
Show file tree
Hide file tree
Showing 50 changed files with 151 additions and 154 deletions.
2 changes: 1 addition & 1 deletion phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ parameters:
path: src/Analyser/AnalyserResultFinalizer.php

-
message: '#^Cannot assign offset ''realCount'' to array\|string\.$#'
message: '#^Cannot assign offset ''realCount'' to array\<mixed\>\|string\.$#'
identifier: offsetAssign.dimType
count: 1
path: src/Analyser/Ignore/IgnoredErrorHelperResult.php
Expand Down
8 changes: 4 additions & 4 deletions src/Type/ArrayType.php
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,8 @@ public function equals(Type $type): bool

public function describe(VerbosityLevel $level): string
{
$isMixedKeyType = $this->keyType instanceof MixedType && $this->keyType->describe(VerbosityLevel::precise()) === 'mixed';
$isMixedItemType = $this->itemType instanceof MixedType && $this->itemType->describe(VerbosityLevel::precise()) === 'mixed';
$isMixedKeyType = $this->keyType instanceof MixedType && $this->keyType->describe(VerbosityLevel::precise()) === 'mixed' && !$this->keyType->isExplicitMixed();
$isMixedItemType = $this->itemType instanceof MixedType && $this->itemType->describe(VerbosityLevel::precise()) === 'mixed' && !$this->itemType->isExplicitMixed();

$valueHandler = function () use ($level, $isMixedKeyType, $isMixedItemType): string {
if ($isMixedKeyType || $this->keyType instanceof NeverType) {
Expand Down Expand Up @@ -500,8 +500,8 @@ public function traverse(callable $cb): Type

public function toPhpDocNode(): TypeNode
{
$isMixedKeyType = $this->keyType instanceof MixedType && $this->keyType->describe(VerbosityLevel::precise()) === 'mixed';
$isMixedItemType = $this->itemType instanceof MixedType && $this->itemType->describe(VerbosityLevel::precise()) === 'mixed';
$isMixedKeyType = $this->keyType instanceof MixedType && $this->keyType->describe(VerbosityLevel::precise()) === 'mixed' && !$this->keyType->isExplicitMixed();
$isMixedItemType = $this->itemType instanceof MixedType && $this->itemType->describe(VerbosityLevel::precise()) === 'mixed' && !$this->itemType->isExplicitMixed();

if ($isMixedKeyType) {
if ($isMixedItemType) {
Expand Down
5 changes: 1 addition & 4 deletions src/Type/Php/ArraySearchFunctionTypeSpecifyingExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,7 @@
use PHPStan\Analyser\TypeSpecifierContext;
use PHPStan\Reflection\FunctionReflection;
use PHPStan\Type\Accessory\NonEmptyArrayType;
use PHPStan\Type\ArrayType;
use PHPStan\Type\FunctionTypeSpecifyingExtension;
use PHPStan\Type\MixedType;
use PHPStan\Type\TypeCombinator;
use function strtolower;

final class ArraySearchFunctionTypeSpecifyingExtension implements FunctionTypeSpecifyingExtension, TypeSpecifierAwareExtension
Expand Down Expand Up @@ -45,7 +42,7 @@ public function specifyTypes(

return $this->typeSpecifier->create(
$arrayArg,
TypeCombinator::intersect(new ArrayType(new MixedType(), new MixedType()), new NonEmptyArrayType()),
new NonEmptyArrayType(),
$context,
$scope,
);
Expand Down
2 changes: 1 addition & 1 deletion tests/PHPStan/Analyser/AnalyserIntegrationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1198,7 +1198,7 @@ public function testBug9459(): void
{
$errors = $this->runAnalyse(__DIR__ . '/data/bug-9459.php');
$this->assertCount(1, $errors);
$this->assertSame('PHPDoc tag @var with type callable(): array is not subtype of native type Closure(): array{}.', $errors[0]->getMessage());
$this->assertSame('PHPDoc tag @var with type callable(): array<mixed> is not subtype of native type Closure(): array{}.', $errors[0]->getMessage());
$this->assertSame(10, $errors[0]->getLine());
}

Expand Down
8 changes: 4 additions & 4 deletions tests/PHPStan/Analyser/LegacyNodeScopeResolverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1763,7 +1763,7 @@ public function dataProperties(): array
'$this->arrayPropertyOne',
],
[
'array',
'array<mixed>',
'$this->arrayPropertyOther',
],
[
Expand Down Expand Up @@ -3423,7 +3423,7 @@ public function dataTypeFromFunctionPhpDocs(): array
'$arrayParameterOne',
],
[
'array',
'array<mixed>',
'$arrayParameterOther',
],
[
Expand Down Expand Up @@ -5779,7 +5779,7 @@ public function dataSpecifiedTypesUsingIsFunctions(): array
'$null',
],
[
'array',
'array<mixed, mixed>',
'$array',
],
[
Expand Down Expand Up @@ -9252,7 +9252,7 @@ public function dataInferPrivatePropertyTypeFromConstructor(): array
'$this->bool',
],
[
'array',
'array<mixed, mixed>',
'$this->array',
],
];
Expand Down
10 changes: 5 additions & 5 deletions tests/PHPStan/Analyser/TypeSpecifierTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1218,8 +1218,8 @@ public function dataCondition(): iterable
),
new Identical(new Expr\ConstFetch(new Name('null')), new Variable('a')),
),
['$a' => 'non-empty-array|null'],
['$a' => 'mixed~non-empty-array & ~null'],
['$a' => 'non-empty-array<mixed, mixed>|null'],
['$a' => 'mixed~non-empty-array<mixed, mixed> & ~null'],
],
[
new Expr\BinaryOp\BooleanAnd(
Expand All @@ -1234,7 +1234,7 @@ public function dataCondition(): iterable
),
[
'$foo' => 'array<string, mixed>',
'array_filter($foo, \'is_string\', ARRAY_FILTER_USE_KEY)' => 'array', // could be 'array<string, mixed>'
'array_filter($foo, \'is_string\', ARRAY_FILTER_USE_KEY)' => 'array<mixed, mixed>', // could be 'array<string, mixed>'
],
[],
],
Expand All @@ -1250,7 +1250,7 @@ public function dataCondition(): iterable
),
),
[
'$foo' => 'non-empty-array',
'$foo' => 'non-empty-array<mixed, mixed>',
'count($foo)' => 'mixed~(0.0|int<min, 1>|false|null)',
],
[],
Expand All @@ -1267,7 +1267,7 @@ public function dataCondition(): iterable
),
),
[
'$foo' => 'non-empty-array',
'$foo' => 'non-empty-array<mixed, mixed>',
'count($foo)' => '2',
],
[],
Expand Down
6 changes: 3 additions & 3 deletions tests/PHPStan/Analyser/data/param-out.php
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ function testParseStr() {
echo $output['arr'][1];//baz
*/

\PHPStan\Testing\assertType('array<int|string, array|lowercase-string>', $output);
\PHPStan\Testing\assertType('array<int|string, array<mixed>|lowercase-string>', $output);
}

function fooSimilar() {
Expand Down Expand Up @@ -392,10 +392,10 @@ function fooHeadersSent() {

function fooMbParseStr() {
mb_parse_str("foo=bar", $output);
assertType('array<string, array|string>', $output);
assertType('array<string, array<mixed>|string>', $output);

mb_parse_str('email=mail@example.org&city=town&x=1&y[g]=3&f=1.23', $output);
assertType('array<string, array|string>', $output);
assertType('array<string, array<mixed>|string>', $output);
}

function fooPreg()
Expand Down
2 changes: 1 addition & 1 deletion tests/PHPStan/Analyser/nsrt/array-chunk.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public function generalArrays(array $arr): void
{
/** @var mixed[] $arr */
assertType('list<non-empty-list<mixed>>', array_chunk($arr, 2));
assertType('list<non-empty-array>', array_chunk($arr, 2, true));
assertType('list<non-empty-array<mixed>>', array_chunk($arr, 2, true));

/** @var array<string, int> $arr */
assertType('list<non-empty-list<int>>', array_chunk($arr, 2));
Expand Down
2 changes: 1 addition & 1 deletion tests/PHPStan/Analyser/nsrt/array-fill-keys-php8.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
function mixedAndSubtractedArray($mixed): void
{
if (is_array($mixed)) {
assertType("array<'b'>", array_fill_keys($mixed, 'b'));
assertType("array<mixed, 'b'>", array_fill_keys($mixed, 'b'));
} else {
assertType("*NEVER*", array_fill_keys($mixed, 'b'));
}
Expand Down
2 changes: 1 addition & 1 deletion tests/PHPStan/Analyser/nsrt/array-flip-php8.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ function mixedAndSubtractedArray($mixed)
if (is_array($mixed)) {
assertType('array<int|string, (int|string)>', array_flip($mixed));
} else {
assertType('mixed~array', $mixed);
assertType('mixed~array<mixed, mixed>', $mixed);
assertType('*NEVER*', array_flip($mixed));
}
}
2 changes: 1 addition & 1 deletion tests/PHPStan/Analyser/nsrt/array-intersect-key-php8.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public function mixedAndSubtractedArray($mixed, array $otherArrs): void
/** @var array<string, int> $otherArrs */
assertType('array<string, mixed>', array_intersect_key($mixed, $otherArrs));
} else {
assertType('mixed~array', $mixed);
assertType('mixed~array<mixed, mixed>', $mixed);
/** @var array<int, string> $otherArrs */
assertType('*NEVER*', array_intersect_key($mixed, $otherArrs));
/** @var array<string, int> $otherArrs */
Expand Down
2 changes: 1 addition & 1 deletion tests/PHPStan/Analyser/nsrt/array-pop.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public function foo1($mixed): void
if(is_array($mixed)) {
assertType('mixed', array_pop($mixed));
} else {
assertType('mixed~array', $mixed);
assertType('mixed~array<mixed, mixed>', $mixed);
assertType('mixed', array_pop($mixed));
assertType('*ERROR*', $mixed);
}
Expand Down
8 changes: 4 additions & 4 deletions tests/PHPStan/Analyser/nsrt/array-reverse.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ class Foo
*/
public function normalArrays(array $a, array $b): void
{
assertType('array', array_reverse($a));
assertType('array', array_reverse($a, true));
assertType('array<mixed>', array_reverse($a));
assertType('array<mixed>', array_reverse($a, true));

assertType('array<string, int>', array_reverse($b));
assertType('array<string, int>', array_reverse($b, true));
Expand Down Expand Up @@ -68,8 +68,8 @@ public function list(array $a, array $b): void

public function mixed(mixed $mixed): void
{
assertType('array', array_reverse($mixed));
assertType('array', array_reverse($mixed, true));
assertType('array<mixed, mixed>', array_reverse($mixed));
assertType('array<mixed, mixed>', array_reverse($mixed, true));

if (array_key_exists('foo', $mixed)) {
assertType('non-empty-array', array_reverse($mixed));
Expand Down
2 changes: 1 addition & 1 deletion tests/PHPStan/Analyser/nsrt/array-search-php8.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public function mixedAndSubtractedArray($mixed, string $string): void
assertType('int|string|false', array_search('foo', $mixed));
assertType('int|string|false', array_search($string, $mixed, true));
} else {
assertType('mixed~array', $mixed);
assertType('mixed~array<mixed, mixed>', $mixed);
assertType('*NEVER*', array_search('foo', $mixed, true));
assertType('*NEVER*', array_search('foo', $mixed));
assertType('*NEVER*', array_search($string, $mixed, true));
Expand Down
2 changes: 1 addition & 1 deletion tests/PHPStan/Analyser/nsrt/array-shift.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public function foo1($mixed): void
if(is_array($mixed)) {
assertType('mixed', array_shift($mixed));
} else {
assertType('mixed~array', $mixed);
assertType('mixed~array<mixed, mixed>', $mixed);
assertType('mixed', array_shift($mixed));
assertType('*ERROR*', $mixed);
}
Expand Down
2 changes: 1 addition & 1 deletion tests/PHPStan/Analyser/nsrt/array-slice.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public function nonEmpty(array $a, array $b, array $c): void
*/
public function fromMixed($arr): void
{
assertType('array', array_slice($arr, 1, 2));
assertType('array<mixed, mixed>', array_slice($arr, 1, 2));
}

public function normalArrays(array $arr): void
Expand Down
2 changes: 1 addition & 1 deletion tests/PHPStan/Analyser/nsrt/array_keys.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public function sayHello($mixed): void
if(is_array($mixed)) {
assertType('list<(int|string)>', array_keys($mixed));
} else {
assertType('mixed~array', $mixed);
assertType('mixed~array<mixed, mixed>', $mixed);
assertType('*NEVER*', array_keys($mixed));
}
}
Expand Down
2 changes: 1 addition & 1 deletion tests/PHPStan/Analyser/nsrt/array_values.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public function foo1($mixed): void
if(is_array($mixed)) {
assertType('list<mixed>', array_values($mixed));
} else {
assertType('mixed~array', $mixed);
assertType('mixed~array<mixed, mixed>', $mixed);
assertType('*NEVER*', array_values($mixed));
}
}
Expand Down
22 changes: 11 additions & 11 deletions tests/PHPStan/Analyser/nsrt/assert-docblock.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ function validateNotNull($value) : void {}
* @param mixed[] $arr
*/
function takesArray(array $arr) : void {
assertType('array', $arr);
assertType('array<mixed>', $arr);

validateStringArray($arr);
assertType('array<string>', $arr);
Expand All @@ -66,22 +66,22 @@ function takesArray(array $arr) : void {
* @param mixed[] $arr
*/
function takesArrayIfTrue(array $arr) : void {
assertType('array', $arr);
assertType('array<mixed>', $arr);

if (validateStringArrayIfTrue($arr)) {
assertType('array<string>', $arr);
} else {
assertType('array', $arr);
assertType('array<mixed>', $arr);
}
}
/**
* @param mixed[] $arr
*/
function takesArrayIfTrue1(array $arr) : void {
assertType('array', $arr);
assertType('array<mixed>', $arr);

if (!validateStringArrayIfTrue($arr)) {
assertType('array', $arr);
assertType('array<mixed>', $arr);
} else {
assertType('array<string>', $arr);
}
Expand All @@ -91,23 +91,23 @@ function takesArrayIfTrue1(array $arr) : void {
* @param mixed[] $arr
*/
function takesArrayIfFalse(array $arr) : void {
assertType('array', $arr);
assertType('array<mixed>', $arr);

if (!validateStringArrayIfFalse($arr)) {
assertType('array<string>', $arr);
} else {
assertType('array', $arr);
assertType('array<mixed>', $arr);
}
}

/**
* @param mixed[] $arr
*/
function takesArrayIfFalse1(array $arr) : void {
assertType('array', $arr);
assertType('array<mixed>', $arr);

if (validateStringArrayIfFalse($arr)) {
assertType('array', $arr);
assertType('array<mixed>', $arr);
} else {
assertType('array<string>', $arr);
}
Expand All @@ -117,7 +117,7 @@ function takesArrayIfFalse1(array $arr) : void {
* @param mixed[] $arr
*/
function takesStringOrIntArray(array $arr) : void {
assertType('array', $arr);
assertType('array<mixed>', $arr);

if (validateStringOrIntArray($arr)) {
assertType('array<string>', $arr);
Expand All @@ -130,7 +130,7 @@ function takesStringOrIntArray(array $arr) : void {
* @param mixed[] $arr
*/
function takesStringOrNonEmptyIntArray(array $arr) : void {
assertType('array', $arr);
assertType('array<mixed>', $arr);

if (validateStringOrNonEmptyIntArray($arr)) {
assertType('array<string>', $arr);
Expand Down
4 changes: 2 additions & 2 deletions tests/PHPStan/Analyser/nsrt/assert-methods.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public function doBar($mixed)
public function doBar2(array $objects)
{
self::doFoo($objects, stdClass::class);
assertType('array<stdClass>', $objects);
assertType('array<mixed, stdClass>', $objects);
}

/**
Expand All @@ -47,7 +47,7 @@ public function doBar2(array $objects)
public function doBar3(array $strings)
{
self::doFoo($strings, stdClass::class);
assertType('array<class-string<stdClass>>', $strings);
assertType('array<mixed, class-string<stdClass>>', $strings);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion tests/PHPStan/Analyser/nsrt/bug-1209.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public function sayHello($value): void
{
$isArray = is_array($value);
if($isArray){
assertType('array', $value);
assertType('array<mixed>', $value);
}
}

Expand Down
6 changes: 3 additions & 3 deletions tests/PHPStan/Analyser/nsrt/bug-1233.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,18 @@ public function toArray($value): array
{
assertType('mixed', $value);
if (is_array($value)) {
assertType('array', $value);
assertType('array<mixed, mixed>', $value);
return $value;
}

assertType('mixed~array', $value);
assertType('mixed~array<mixed, mixed>', $value);

if (is_iterable($value)) {
assertType('Traversable<mixed, mixed>', $value);
return iterator_to_array($value);
}

assertType('mixed~array', $value);
assertType('mixed~array<mixed, mixed>', $value);

throw new \LogicException();
}
Expand Down
Loading

0 comments on commit 6cf2238

Please sign in to comment.