mirror of
https://github.com/danog/psalm.git
synced 2024-11-26 20:34:47 +01:00
Fix #3289 - treat property on non-generic type like actual value
This commit is contained in:
parent
618a54ff41
commit
bf5e178d16
@ -827,6 +827,26 @@ class PropertyFetchAnalyzer
|
|||||||
$declaring_class_storage->parent_class
|
$declaring_class_storage->parent_class
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if ($declaring_class_storage->template_types) {
|
||||||
|
if (!$lhs_type_part instanceof TGenericObject) {
|
||||||
|
$type_params = [];
|
||||||
|
|
||||||
|
foreach ($declaring_class_storage->template_types as $type_map) {
|
||||||
|
$type_params[] = clone array_values($type_map)[0][0];
|
||||||
|
}
|
||||||
|
|
||||||
|
$lhs_type_part = new TGenericObject($lhs_type_part->value, $type_params);
|
||||||
|
}
|
||||||
|
|
||||||
|
$class_property_type = self::localizePropertyType(
|
||||||
|
$codebase,
|
||||||
|
$class_property_type,
|
||||||
|
$lhs_type_part,
|
||||||
|
$class_storage,
|
||||||
|
$declaring_class_storage
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if ($lhs_type_part instanceof TGenericObject) {
|
if ($lhs_type_part instanceof TGenericObject) {
|
||||||
$class_property_type = self::localizePropertyType(
|
$class_property_type = self::localizePropertyType(
|
||||||
$codebase,
|
$codebase,
|
||||||
|
@ -885,7 +885,10 @@ class AnnotationTest extends TestCase
|
|||||||
function bat(array $arr) : void {
|
function bat(array $arr) : void {
|
||||||
$item = null;
|
$item = null;
|
||||||
|
|
||||||
/** @var string $item */
|
/**
|
||||||
|
* @psalm-suppress MixedArrayAccess
|
||||||
|
* @var string $item
|
||||||
|
*/
|
||||||
foreach ($arr as list($item)) {}
|
foreach ($arr as list($item)) {}
|
||||||
|
|
||||||
if (is_null($item)) {}
|
if (is_null($item)) {}
|
||||||
@ -894,7 +897,10 @@ class AnnotationTest extends TestCase
|
|||||||
function baz(array $arr) : void {
|
function baz(array $arr) : void {
|
||||||
$item = null;
|
$item = null;
|
||||||
|
|
||||||
/** @var string $item */
|
/**
|
||||||
|
* @psalm-suppress MixedArrayAccess
|
||||||
|
* @var string $item
|
||||||
|
*/
|
||||||
foreach ($arr as list($item => $_)) {}
|
foreach ($arr as list($item => $_)) {}
|
||||||
|
|
||||||
if (is_null($item)) {}
|
if (is_null($item)) {}
|
||||||
|
@ -61,7 +61,10 @@ class ListTest extends TestCase
|
|||||||
/** @psalm-suppress MissingReturnType */
|
/** @psalm-suppress MissingReturnType */
|
||||||
function getMixed() {}
|
function getMixed() {}
|
||||||
|
|
||||||
/** @psalm-suppress MixedAssignment */
|
/**
|
||||||
|
* @psalm-suppress MixedArrayAccess
|
||||||
|
* @psalm-suppress MixedAssignment
|
||||||
|
*/
|
||||||
list($a, list($b, $c)) = getMixed();',
|
list($a, list($b, $c)) = getMixed();',
|
||||||
'assertions' => [
|
'assertions' => [
|
||||||
'$a' => 'mixed',
|
'$a' => 'mixed',
|
||||||
|
@ -2673,6 +2673,32 @@ class ClassTemplateTest extends TestCase
|
|||||||
}
|
}
|
||||||
}'
|
}'
|
||||||
],
|
],
|
||||||
|
'templatePropertyWithoutParams' => [
|
||||||
|
'<?php
|
||||||
|
/**
|
||||||
|
* @template T of object
|
||||||
|
*/
|
||||||
|
class Batch {
|
||||||
|
/**
|
||||||
|
* @var iterable<T>
|
||||||
|
*/
|
||||||
|
public iterable $objects = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var callable(T): void
|
||||||
|
*/
|
||||||
|
public $onEach;
|
||||||
|
|
||||||
|
public function __construct() {
|
||||||
|
$this->onEach = function (): void {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handle(Batch $message, object $o): void {
|
||||||
|
$fn = $message->onEach;
|
||||||
|
$fn($o);
|
||||||
|
}'
|
||||||
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user