Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/Rules/Arrays/AllowedArrayKeysTypes.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@ public static function narrowOffsetKeyType(Type $varType, Type $keyType): ?Type
return $narrowedKey;
} elseif ($varIterableKeyType->isInteger()->yes() && $keyType->isString()->yes()) {
return TypeCombinator::intersect($varIterableKeyType->toString(), $keyType);
} elseif ($varType->isList()->yes()) {
return TypeCombinator::intersect(
$varIterableKeyType,
$keyType,
);
}

return new MixedType(
Expand Down
8 changes: 4 additions & 4 deletions tests/PHPStan/Analyser/nsrt/bug-12274.php
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,9 @@ function testShouldLooseListbyAst(array $list, int $i): void

assertType('list<int>', $list);
$list[1+$i] = 21;
assertType('non-empty-array<int, int>', $list);
assertType('non-empty-array<int<0, max>, int>', $list);
}
assertType('array<int, int>', $list);
assertType('array<int<0, max>, int>', $list);
}

/** @param list<int> $list */
Expand All @@ -103,7 +103,7 @@ function testShouldLooseListbyAst2(array $list, int $i): void
if (isset($list[$i])) {
assertType('list<int>', $list);
$list[2+$i] = 21;
assertType('non-empty-array<int, int>', $list);
assertType('non-empty-array<int<0, max>, int>', $list);
}
assertType('array<int, int>', $list);
assertType('array<int<0, max>, int>', $list);
}
48 changes: 48 additions & 0 deletions tests/PHPStan/Analyser/nsrt/bug-12933.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php // lint >= 8.0

namespace Bug12933;

use function PHPStan\Testing\assertType;

/**
* @phpstan-type record array{id: positive-int, name: string}
*/
class Collection
{
/** @param list<record> $list */
public function __construct(
public array $list
)
{
}

public function updateNameIsset(int $index, string $name): void
{
assert(isset($this->list[$index]));
assertType('int<0, max>', $index);
}

public function updateNameArrayKeyExists(int $index, string $name): void
{
assert(array_key_exists($index, $this->list));
assertType('int<0, max>', $index);
}

/**
* @param int<-5, 5> $index
*/
public function issetNarrowsIntRange(int $index, string $name): void
{
assert(isset($this->list[$index]));
assertType('int<0, 5>', $index);
}

/**
* @param int<5, 15> $index
*/
public function issetNotWidensIntRange(int $index, string $name): void
{
assert(isset($this->list[$index]));
assertType('int<5, 15>', $index);
}
}
Loading