diff --git a/src/Type/ObjectType.php b/src/Type/ObjectType.php index 25ee53d4e9..78e4473410 100644 --- a/src/Type/ObjectType.php +++ b/src/Type/ObjectType.php @@ -1228,14 +1228,14 @@ public function hasOffsetValueType(Type $offsetType): TrinaryLogic public function getOffsetValueType(Type $offsetType): Type { - if (!$this->isExtraOffsetAccessibleClass()->no()) { - return new MixedType(); - } - if ($this->isInstanceOf(ArrayAccess::class)->yes()) { return RecursionGuard::run($this, fn (): Type => $this->getMethod('offsetGet', new OutOfClassScope())->getOnlyVariant()->getReturnType()); } + if (!$this->isExtraOffsetAccessibleClass()->no()) { + return new MixedType(); + } + return new ErrorType(); } diff --git a/tests/PHPStan/Analyser/nsrt/bug-12125.php b/tests/PHPStan/Analyser/nsrt/bug-12125.php new file mode 100644 index 0000000000..815e3cb701 --- /dev/null +++ b/tests/PHPStan/Analyser/nsrt/bug-12125.php @@ -0,0 +1,37 @@ +|array $bug */ +$bug = []; + +assertType('stdClass|null', $bug['key'] ?? null); + +interface MyInterface { + /** @return array | ArrayAccess */ + public function getStrings(): array | ArrayAccess; +} + +function myFunction(MyInterface $container): string { + $strings = $container->getStrings(); + assertType('array|ArrayAccess', $strings); + assertType('string|null', $strings['test']); + return $strings['test']; +} + +function myOtherFunction(MyInterface $container): string { + $strings = $container->getStrings(); + assertType('array|ArrayAccess', $strings); + if (isset($strings['test'])) { + assertType('string', $strings['test']); + return $strings['test']; + } else { + throw new Exception(); + } +} diff --git a/tests/PHPStan/Analyser/nsrt/bug-13144.php b/tests/PHPStan/Analyser/nsrt/bug-13144.php new file mode 100644 index 0000000000..fb47f4d862 --- /dev/null +++ b/tests/PHPStan/Analyser/nsrt/bug-13144.php @@ -0,0 +1,23 @@ + 1, 'b' => 2]); + +assertType('ArrayObject', $arr); // correctly inferred as `ArrayObject` + +$a = $arr['a']; // ok +$b = $arr['b']; // ok + +assertType('int|null', $a); // correctly inferred as `int|null` +assertType('int|null', $b); // correctly inferred as `int|null` + + +['a' => $a, 'b' => $b] = $arr; // ok + +assertType('int|null', $a); // incorrectly inferred as `mixed` +assertType('int|null', $b); // incorrectly inferred as `mixed` diff --git a/tests/PHPStan/Analyser/nsrt/bug-9456.php b/tests/PHPStan/Analyser/nsrt/bug-9456.php new file mode 100644 index 0000000000..22b5e4dad8 --- /dev/null +++ b/tests/PHPStan/Analyser/nsrt/bug-9456.php @@ -0,0 +1,71 @@ += 8.0 + +namespace Bug9456; + +use ArrayAccess; + +use function PHPStan\Testing\assertType; + +/** + * @template TKey of array-key + * @template TValue of mixed + * + * @implements ArrayAccess + */ +class Collection implements ArrayAccess { + /** + * @param (callable(TValue, TKey): bool)|TValue|string $key + * @param TValue|string|null $operator + * @param TValue|null $value + * @return static, static> + */ + public function partition($key, $operator = null, $value = null) {} // @phpstan-ignore-line + + /** + * @param TKey $key + * @return TValue + */ + public function offsetGet($key): mixed { return null; } // @phpstan-ignore-line + + /** + * @param TKey $key + * @return bool + */ + public function offsetExists($key): bool { return true; } + + /** + * @param TKey|null $key + * @param TValue $value + * @return void + */ + public function offsetSet($key, $value): void {} + + /** + * @param TKey $key + * @return void + */ + public function offsetUnset($key): void {} +} + +class HelloWorld +{ + /** + * @param Collection $collection + */ + public function sayHello(Collection $collection): void + { + $result = $collection->partition('key'); + + assertType( + 'Bug9456\Collection, Bug9456\Collection>', + $result + ); + assertType('Bug9456\Collection', $result[0]); + assertType('Bug9456\Collection', $result[1]); + + [$one, $two] = $collection->partition('key'); + + assertType('Bug9456\Collection', $one); + assertType('Bug9456\Collection', $two); + } +} diff --git a/tests/PHPStan/Analyser/nsrt/bug-9575.php b/tests/PHPStan/Analyser/nsrt/bug-9575.php new file mode 100644 index 0000000000..fb19202e4f --- /dev/null +++ b/tests/PHPStan/Analyser/nsrt/bug-9575.php @@ -0,0 +1,22 @@ + + 1 + +XML; + +$xml = new SimpleXMLElement($string); +foreach($xml->foo[0]->attributes() as $a => $b) { + echo $a,'="',$b,"\"\n"; +} + +assertType('(SimpleXMLElement|null)', $xml->foo); +assertType('(SimpleXMLElement|null)', $xml->foo[0]); +assertType('(SimpleXMLElement|null)', $xml->foobar); +assertType('(SimpleXMLElement|null)', $xml->foo->attributes());