-
Notifications
You must be signed in to change notification settings - Fork 659
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
False-positive InvalidTemplateParam
with @template-covariant T
when a callable parameter accepts T
#10848
Comments
I found these snippets: https://psalm.dev/r/2eb66f01fe<?php
/**
* @template-covariant T
*/
class Example
{
/**
* @param T $value
*/
function __construct(private mixed $value)
{}
/**
* @param callable(T):void $callback
*/
function call(callable $callback): void
{
$callback($this->value);
}
}
https://psalm.dev/r/3ebad94817<?php
/**
* @template-covariant T
*/
class Example
{
/**
* @param T $value
*/
function __construct(private mixed $value)
{}
/**
* @psalm-suppress InvalidTemplateParam
* @param callable(T):void $callback
*/
function call(callable $callback): void
{
$callback($this->value);
}
}
class Animal {}
class Cat extends Animal {}
class Dog extends Animal {}
/** @psalm-suppress UnusedClosureParam */
function exampleWithObjects(): void
{
$example = new Example(new Cat());
$example->call(function (Animal $animal) {});
$example->call(function (Cat $animal) {});
$example->call(function (Dog $animal) {}); // OK (expected error)
}
/**
* @param Cat[] $cats
* @param callable(Animal[]):void $takesAnimals
* @param callable(Cat[]):void $takesCats
* @param callable(Dog[]):void $takesDogs
*/
function exampleWithArrays(
array $cats,
callable $takesAnimals,
callable $takesCats,
callable $takesDogs,
): void {
$example = new Example($cats);
$example->call($takesAnimals);
$example->call($takesCats);
$example->call($takesDogs); // OK (expected error)
}
/**
* @param \ArrayObject<int, Cat> $cats
* @param callable(\ArrayObject<int, Animal>):void $takesAnimals
* @param callable(\ArrayObject<int, Cat>):void $takesCats
* @param callable(\ArrayObject<int, Dog>):void $takesDogs
*/
function exampleWithArrayObjects(
\ArrayObject $cats,
callable $takesAnimals,
callable $takesCats,
callable $takesDogs,
): void {
$example = new Example($cats);
$example->call($takesAnimals); // OK (expected error)
$example->call($takesCats);
$example->call($takesDogs); // OK (expected error)
}
|
Note to future me: |
It would be awesome if Psalm supported this Scala machinery on callables and variance: https://scastie.scala-lang.org/ZbzouFbvRHGPSwwB8OrNoA |
When a class defines
@template-covariant T
and one of the methods has acallable
parameter which acceptsT
as an argument, I'm getting anInvalidTemplateParam
error:https://psalm.dev/r/2eb66f01fe
I'm not sure the error is valid in this case. (And it seems to work fine otherwise.)
PHPStan doesn't seem to mind this: https://phpstan.org/r/ac9be5aa-4437-40c3-b55d-3ffaa236cb67
But will also error when it's an actual issue: https://phpstan.org/r/96d33c99-1ff7-4541-b024-c8cfaea34e30
I've also tried it in C# (as a language with native generics support) and it seems to allow this as well:
(
out
is equivalent to@template-covariant
here)The text was updated successfully, but these errors were encountered: