Skip to content
Permalink
Browse files

Allow using covariant template in mutation-free context

  • Loading branch information
muglug committed Nov 26, 2019
1 parent a91d2ef commit 532e2d64bebdbb691efa51193431f38310c63ac8
Showing with 66 additions and 10 deletions.
  1. +16 −10 src/Psalm/Type/Atomic/TTemplateParam.php
  2. +50 −0 tests/Template/ClassTemplateCovarianceTest.php
@@ -169,16 +169,22 @@ public function check(
&& isset($class_storage->template_covariants[$template_offset])
&& $class_storage->template_covariants[$template_offset]
) {
if (\Psalm\IssueBuffer::accepts(
new \Psalm\Issue\InvalidTemplateParam(
'Template param ' . $this->param_name . ' of '
. $this->defining_class . ' is marked covariant and cannot be used'
. ' as input to a function',
$code_location
),
$source->getSuppressedIssues()
)) {
// fall through
if ($source instanceof \Psalm\Internal\Analyzer\FunctionLikeAnalyzer
&& $source->getFunctionLikeStorage()->mutation_free
) {
// do nothing
} else {
if (\Psalm\IssueBuffer::accepts(
new \Psalm\Issue\InvalidTemplateParam(
'Template param ' . $this->param_name . ' of '
. $this->defining_class . ' is marked covariant and cannot be used'
. ' as input to a function',
$code_location
),
$source->getSuppressedIssues()
)) {
// fall through
}
}
}
}
@@ -279,6 +279,56 @@ function takesMyArrayOfException(MyArray $a) : void {
takesIteratorAggregate($a);
}'
],
'allowImmutableCovariance' => [
'<?php
class Animal {}
class Dog extends Animal{}
class Cat extends Animal{}
/**
* @psalm-immutable
* @template-covariant T
*/
class Collection {
/** @var list<T> */
private $arr = [];
/**
* @param T ...$a
*/
public function __construct(...$a) {
$this->arr = $a;
}
/**
* @param T $a
* @return Collection<T>
*/
public function add($a) : Collection
{
return new Collection(...$this->arr, $a);
}
}
/**
* @template T
* @param Collection<Animal> $c
* @return Collection<Animal>
*/
function covariant(Collection $c) : Collection
{
return $c->add(new Cat());
}
$dogs = new Collection(new Dog(), new Dog());
$cats = new Collection(new Cat(), new Cat());
$misc = new Collection(new Cat(), new Dog());
covariant($dogs);
covariant($cats);
covariant($misc);',
],
];
}

0 comments on commit 532e2d6

Please sign in to comment.
You can’t perform that action at this time.