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

Fix #2874 - understand doubly-inherited interface templates

This commit is contained in:
Brown 2020-02-24 17:58:44 -05:00
parent 234a6ba4b4
commit 712806b452
2 changed files with 76 additions and 5 deletions

View File

@ -753,12 +753,17 @@ class Populator
}
if ($implemented_interface_storage->template_type_extends) {
foreach ($implemented_interface_storage->template_type_extends as $e_i => $type) {
if (isset($storage->template_type_extends[$e_i])) {
foreach ($implemented_interface_storage->template_type_extends as $e_i => $type_map) {
foreach ($type_map as $i => $type) {
if (is_int($i)) {
continue;
}
$storage->template_type_extends[$e_i] = $type;
$storage->template_type_extends[$e_i][$i] = self::extendType(
$type,
$storage
);
}
}
}
} else {

View File

@ -3021,6 +3021,72 @@ class ClassTemplateExtendsTest extends TestCase
}
}'
],
'extendsTemplatedInterface' => [
'<?php
class Animal {}
/**
* @template DC1 of Animal
*/
interface IStroker {
/**
* @psalm-param DC1 $animal
*/
public function stroke(Animal $animal): void;
}
/**
* @template DC2 of Animal
* @template-extends IStroker<DC2>
*/
interface IStroker2 extends IStroker {}
class Dog extends Animal {}
/**
* @implements IStroker2<Dog>
*/
class DogStroker implements IStroker2 {
public function stroke(Animal $animal): void {
$this->doDeletePerson($animal);
}
private function doDeletePerson(Dog $animal): void {}
}'
],
'extendsTemplatedClass' => [
'<?php
class Animal {}
/**
* @template DC1 of Animal
*/
class IStroker {
/**
* @psalm-param DC1 $animal
*/
public function stroke(Animal $animal): void {}
}
/**
* @template DC2 of Animal
* @template-extends IStroker<DC2>
*/
class IStroker2 extends IStroker {}
class Dog extends Animal {}
/**
* @extends IStroker2<Dog>
*/
class DogStroker extends IStroker2 {
public function stroke(Animal $animal): void {
$this->doDeletePerson($animal);
}
private function doDeletePerson(Dog $animal): void {}
}'
],
];
}