Example: https://psalm.dev/r/0f0ce4be1e
Just by changing return type of CovariantUserBuilder::create, psalm doesn't trace $data param correctly.
I found these snippets:
https://psalm.dev/r/0f0ce4be1e
<?php
declare(strict_types=1);
class User{}
class CovariantUser extends User{}
/**
* @psalm-template T
*/
interface BuilderInterface
{
/**
* @psalm-param T $data
*/
public function create($data): User;
}
/**
* @implements BuilderInterface<array{first_name: string}>
*/
class UserBuilder implements BuilderInterface
{
/** @psalm-suppress InvalidReturnType */
public function create($data): User
{
/** @psalm-trace $data */
}
}
/**
* @implements BuilderInterface<array{first_name: string}>
*/
class CovariantUserBuilder implements BuilderInterface
{
/** @psalm-suppress InvalidReturnType */
public function create($data): CovariantUser
{
/** @psalm-trace $data */
}
}
Psalm output (using commit f5dd6e7):
INFO: Trace - 27:0 - $data: array{first_name: string}
INFO: Trace - 39:0 - $data: T:BuilderInterface as mixed
Simplified a bit: https://psalm.dev/r/fc69cedcb9
I found these snippets:
https://psalm.dev/r/fc69cedcb9
<?php declare(strict_types=1);
/** @psalm-template T */
interface BuilderInterface {
/** @psalm-param T $data */
public function create($data): Exception;
}
/** @implements BuilderInterface<int> */
class CovariantUserBuilder implements BuilderInterface {
/** @psalm-suppress InvalidReturnType */
public function create($data): RuntimeException {
/** @psalm-trace $data */; // expected: int
}
}
Psalm output (using commit 8a76a43):
INFO: Trace - 13:34 - $data: T:BuilderInterface as mixed
This is a very buggy bug
If you need some more example, I believe there is a similar issue in phpDocumentor codebase with last psalm release. I could try to dig it out.
The fix, for now, is to use the same param types as would be evaluated when calling the method externally.
Because you're defining a different return type from the one you inherited, that means $data is now typed to mixed.
This follows the rule introduced in 4.2.0: a function signature (parameter and return types) can only come from one method. If you redefine either a parameter type or a return type in a child method, that method must also provide local param types.
that means $data is now typed to mixed
I set reportMixedIssues="true"; does this mean the fix will report problems?
You get a MissingParamType issue instead
Actually this code will be allowed just fine, sorry, false alarm.