mirror of
https://github.com/danog/psalm.git
synced 2024-11-30 04:39:00 +01:00
Fix #4545 - allow intersections in more places
This commit is contained in:
parent
63bf00513b
commit
5219932408
@ -758,6 +758,12 @@ class Methods
|
||||
return clone $overridden_storage->return_type;
|
||||
}
|
||||
|
||||
if ($candidate_type->getId() === $overridden_storage->return_type->getId()) {
|
||||
$self_class = $appearing_fq_class_storage->name;
|
||||
|
||||
return clone $candidate_type;
|
||||
}
|
||||
|
||||
$old_contained_by_new = UnionTypeComparator::isContainedBy(
|
||||
$source_analyzer->getCodebase(),
|
||||
$candidate_type,
|
||||
@ -770,7 +776,9 @@ class Methods
|
||||
$candidate_type
|
||||
);
|
||||
|
||||
if (!$old_contained_by_new && !$new_contained_by_old) {
|
||||
if ((!$old_contained_by_new && !$new_contained_by_old)
|
||||
|| ($old_contained_by_new && $new_contained_by_old)
|
||||
) {
|
||||
$attempted_intersection = Type::intersectUnionTypes(
|
||||
$overridden_storage->return_type,
|
||||
$candidate_type,
|
||||
@ -847,7 +855,9 @@ class Methods
|
||||
$candidate_type
|
||||
);
|
||||
|
||||
if (!$old_contained_by_new && !$new_contained_by_old) {
|
||||
if ((!$old_contained_by_new && !$new_contained_by_old)
|
||||
|| ($old_contained_by_new && $new_contained_by_old)
|
||||
) {
|
||||
$attempted_intersection = Type::intersectUnionTypes(
|
||||
$candidate_type,
|
||||
$overridden_return_type,
|
||||
|
@ -534,7 +534,21 @@ abstract class Type
|
||||
if ($type_1_atomic instanceof TNamedObject
|
||||
&& $type_2_atomic instanceof TNamedObject
|
||||
) {
|
||||
if (AtomicTypeComparator::isContainedBy(
|
||||
if (($type_1_atomic->value === $type_2_atomic->value
|
||||
&& get_class($type_1_atomic) === TNamedObject::class
|
||||
&& get_class($type_2_atomic) !== TNamedObject::class)
|
||||
) {
|
||||
$combined_type->removeType($t1_key);
|
||||
$combined_type->addType(clone $type_2_atomic);
|
||||
$intersection_performed = true;
|
||||
} elseif (($type_1_atomic->value === $type_2_atomic->value
|
||||
&& get_class($type_2_atomic) === TNamedObject::class
|
||||
&& get_class($type_1_atomic) !== TNamedObject::class)
|
||||
) {
|
||||
$combined_type->removeType($t2_key);
|
||||
$combined_type->addType(clone $type_1_atomic);
|
||||
$intersection_performed = true;
|
||||
} elseif (AtomicTypeComparator::isContainedBy(
|
||||
$codebase,
|
||||
$type_2_atomic,
|
||||
$type_1_atomic
|
||||
|
@ -2764,9 +2764,6 @@ class ClassTemplateExtendsTest extends TestCase
|
||||
*/
|
||||
protected $c;
|
||||
|
||||
/**
|
||||
* @param T $p
|
||||
*/
|
||||
public function filter($p) : C {
|
||||
return $this->c->filter($p);
|
||||
}
|
||||
@ -4131,6 +4128,55 @@ class ClassTemplateExtendsTest extends TestCase
|
||||
return $f::of($s);
|
||||
}'
|
||||
],
|
||||
'functor' => [
|
||||
'<?php
|
||||
/**
|
||||
* @template T
|
||||
*/
|
||||
interface Functor
|
||||
{
|
||||
/**
|
||||
* @template F
|
||||
* @param callable(T): F $function
|
||||
* @return Functor<F>
|
||||
*/
|
||||
public function map(callable $function): Functor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @implements Functor<T>
|
||||
*/
|
||||
class FakeFunctor implements Functor
|
||||
{
|
||||
/**
|
||||
* @var T
|
||||
*/
|
||||
private $value;
|
||||
|
||||
/**
|
||||
* @psalm-param T $value
|
||||
*/
|
||||
public function __construct($value)
|
||||
{
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
public function map(callable $function): Functor
|
||||
{
|
||||
return new FakeFunctor($function($this->value));
|
||||
}
|
||||
}
|
||||
|
||||
/** @return Functor<int> */
|
||||
function foo(string $s) : Functor {
|
||||
$foo = new FakeFunctor($s);
|
||||
$function = function (string $a): int {
|
||||
return strlen($a);
|
||||
};
|
||||
return $foo->map($function);
|
||||
}'
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -3093,6 +3093,18 @@ class ClassTemplateTest extends TestCase
|
||||
public $traversable;
|
||||
}'
|
||||
],
|
||||
'simpleTemplate' => [
|
||||
'<?php
|
||||
/** @template T */
|
||||
interface F {}
|
||||
|
||||
/** @param F<mixed> $f */
|
||||
function takesFMixed(F $f) : void {}
|
||||
|
||||
function sendsF(F $f) : void {
|
||||
takesFMixed($f);
|
||||
}'
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user