Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/1.8.x' into 1.9.x
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Oct 18, 2022
2 parents c074ceb + 600e9e1 commit bfcef68
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 15 deletions.
36 changes: 21 additions & 15 deletions src/Type/ArrayType.php
Original file line number Diff line number Diff line change
Expand Up @@ -322,24 +322,30 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $uni
$offsetType = $offsetType->toArrayKey();
}

if (
($offsetType instanceof ConstantStringType || $offsetType instanceof ConstantIntegerType)
&& $offsetType->isSuperTypeOf($this->keyType)->yes()
) {
$builder = ConstantArrayTypeBuilder::createEmpty();
$builder->setOffsetValueType($offsetType, $valueType);
return $builder->getArray();
}
if ($offsetType instanceof ConstantStringType || $offsetType instanceof ConstantIntegerType) {
if ($offsetType->isSuperTypeOf($this->keyType)->yes()) {
$builder = ConstantArrayTypeBuilder::createEmpty();
$builder->setOffsetValueType($offsetType, $valueType);
return $builder->getArray();
}

$array = new self(
TypeCombinator::union($this->keyType, $offsetType),
$unionValues ? TypeCombinator::union($this->itemType, $valueType) : $valueType,
);
if ($offsetType instanceof ConstantIntegerType || $offsetType instanceof ConstantStringType) {
return TypeCombinator::intersect($array, new HasOffsetValueType($offsetType, $valueType), new NonEmptyArrayType());
return TypeCombinator::intersect(
new self(
TypeCombinator::union($this->keyType, $offsetType),
TypeCombinator::union($this->itemType, $valueType),
),
new HasOffsetValueType($offsetType, $valueType),
new NonEmptyArrayType(),
);
}

return TypeCombinator::intersect($array, new NonEmptyArrayType());
return TypeCombinator::intersect(
new self(
TypeCombinator::union($this->keyType, $offsetType),
$unionValues ? TypeCombinator::union($this->itemType, $valueType) : $valueType,
),
new NonEmptyArrayType(),
);
}

public function unsetOffset(Type $offsetType): Type
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 @@ -1084,6 +1084,7 @@ public function dataFileAsserts(): iterable
yield from $this->gatherAssertTypes(__DIR__ . '/../Rules/Methods/data/bug-8174.php');
yield from $this->gatherAssertTypes(__DIR__ . '/../Rules/Comparison/data/bug-8169.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-7519.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-8087.php');
}

/**
Expand Down
27 changes: 27 additions & 0 deletions tests/PHPStan/Analyser/data/bug-8087.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace Bug8087;

use function PHPStan\Testing\assertType;

class HelloWorld
{
/**
* @param array<string, mixed> $data
**/
public function sayHello(array $data): bool
{
\PHPStan\dumpType($data);
assertType('array<string, mixed>', $data);

$data['uses'] = [''];

assertType("non-empty-array<string, mixed>&hasOffsetValue('uses', array{''})", $data);

$data['uses'][] = '';

assertType("non-empty-array<string, mixed>&hasOffsetValue('uses', array{'', ''})", $data);

return count($data['foo']) > 0;
}
}

0 comments on commit bfcef68

Please sign in to comment.