1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-30 04:39:00 +01:00

Fix #2301 - do a naive projection of template params

This commit is contained in:
Brown 2019-11-05 12:59:56 -05:00
parent d8ae33957d
commit 5c8cb37b0f
2 changed files with 49 additions and 3 deletions

View File

@ -2066,11 +2066,22 @@ class AssertionReconciler extends \Psalm\Type\Reconciler
$atomic_comparison_results
);
if ($atomic_contained_by || $atomic_comparison_results->type_coerced) {
if ($atomic_contained_by) {
$has_local_match = true;
if ($atomic_comparison_results->type_coerced) {
$matching_atomic_types[] = $existing_type_part;
if ($atomic_comparison_results->type_coerced
&& get_class($new_type_part) === Type\Atomic\TNamedObject::class
&& $existing_type_part instanceof Type\Atomic\TGenericObject
) {
// this is a hack - it's not actually rigorous, as the params may be different
$matching_atomic_types[] = new Type\Atomic\TGenericObject(
$new_type_part->value,
$existing_type_part->type_params
);
}
} elseif ($atomic_comparison_results->type_coerced) {
$has_local_match = true;
$matching_atomic_types[] = $existing_type_part;
}
if (($new_type_part instanceof Type\Atomic\TGenericObject

View File

@ -2424,6 +2424,41 @@ class ClassTemplateExtendsTest extends TestCase
return new Right(new B());
}'
],
'refineGenericWithInstanceof' => [
'<?php
/** @template T */
interface Maybe {}
/**
* @template T
* @implements Maybe<T>
*/
class Some implements Maybe {
/** @var T */
private $value;
/** @psalm-param T $value */
public function __construct($value) {
$this->value = $value;
}
/** @psalm-return T */
public function extract() { return $this->value; }
}
/**
* @psalm-return Maybe<int>
*/
function repository(): Maybe {
return new Some(5);
}
$maybe = repository();
if ($maybe instanceof Some) {
$anInt = $maybe->extract();
}'
],
];
}