Psalm don't detect inherit property type
https://psalm.dev/r/b667f563eb
I found these snippets:
https://psalm.dev/r/b667f563eb
<?php
class A
{
/**
* @var non-empty-string
*/
public string $var = 'test';
}
class B extends A {
public string $var = 'hello';
}
Psalm output (using commit a9e6444):
ERROR: NonInvariantDocblockPropertyType - 12:19 - Property B::$var has type string, not invariant with A::$var of type non-empty-string
This is correct, overridden properties must not be looser than the parent (it's an extension of the equivalent rule present in PHP, applied to docblock types as well).
This is correct, overridden properties must not be looser than the parent (it's an extension of the equivalent rule present in PHP, applied to docblock types as well).
But for method parameters type inherits correctly: https://psalm.dev/r/5afbcd2ec8
I found these snippets:
https://psalm.dev/r/5afbcd2ec8
<?php
class A
{
/**
* @var non-empty-string
*/
public string $var = 'test';
/**
* @param non-empty-string $var
*/
public function test(string $var): void {
echo $var;
}
}
final class B extends A {
public string $var = 'hello';
public function test(string $var): void {
/** @psalm-trace $var */
echo $var;
}
}
Psalm output (using commit a9e6444):
ERROR: NonInvariantDocblockPropertyType - 19:19 - Property B::$var has type string, not invariant with A::$var of type non-empty-string
INFO: Trace - 23:9 - $var: non-empty-string
Method parameters can be looser, per LSP contravariance rules.
"overridden properties must not be looser than the parent" - i agree, but see https://psalm.dev/r/b667f563eb :
Property A::$var is non-empty-string.
Why Psalm think that B::$var is string? Shouldn't he understand that B::$var also is non-empty-string?
Why does it understand this in the parameters of the method (https://psalm.dev/r/5afbcd2ec8), but not in the properties of the class?
I found these snippets:
https://psalm.dev/r/b667f563eb
<?php
class A
{
/**
* @var non-empty-string
*/
public string $var = 'test';
}
class B extends A {
public string $var = 'hello';
}
Psalm output (using commit a9e6444):
ERROR: NonInvariantDocblockPropertyType - 12:19 - Property B::$var has type string, not invariant with A::$var of type non-empty-string
https://psalm.dev/r/5afbcd2ec8
<?php
class A
{
/**
* @var non-empty-string
*/
public string $var = 'test';
/**
* @param non-empty-string $var
*/
public function test(string $var): void {
echo $var;
}
}
final class B extends A {
public string $var = 'hello';
public function test(string $var): void {
/** @psalm-trace $var */
echo $var;
}
}
Psalm output (using commit a9e6444):
ERROR: NonInvariantDocblockPropertyType - 19:19 - Property B::$var has type string, not invariant with A::$var of type non-empty-string
INFO: Trace - 23:9 - $var: non-empty-string
@danog WDYT?
Why does it understand this in the parameters of the method (https://psalm.dev/r/5afbcd2ec8), but not in the properties of the class?
It doesn't, because loosening types in method parameters is simply allowed.
I found these snippets:
https://psalm.dev/r/5afbcd2ec8
<?php
class A
{
/**
* @var non-empty-string
*/
public string $var = 'test';
/**
* @param non-empty-string $var
*/
public function test(string $var): void {
echo $var;
}
}
final class B extends A {
public string $var = 'hello';
public function test(string $var): void {
/** @psalm-trace $var */
echo $var;
}
}
Psalm output (using commit be0f41a):
ERROR: NonInvariantDocblockPropertyType - 19:19 - Property B::$var has type string, not invariant with A::$var of type non-empty-string
INFO: Trace - 23:9 - $var: non-empty-string
@danog I'll try to explain my pain again =)
Case with method parameter
class A
{
/**
* @param non-empty-string $var
*/
public function test(string $var): void {
echo $var;
}
}
final class B extends A {
public function test(string $var): void {
/** @psalm-trace $var */
echo $var;
}
}
Psalm without extra annotations in class B knows, that $var is non-empty-string. Not string. It's fine.
Case with class property
class A
{
/**
* @var non-empty-string
*/
public string $var = 'test';
}
final class B extends A {
public string $var = 'hello';
}
Psalm don't understand that B::$var is non-empty-string. Why?
Okay I see your point now, will fix
Any news?