Skip to content

New PHPDoc type ClassConstantAccessType does not take subclasses into account #14556

@ondrejmirtes

Description

@ondrejmirtes

Bug report

Added in this PR phpstan/phpstan-src#5510 trying to solve #13828.

Some of the assertions are wrong. For example:

class FooBar
{
	const FOO_BAR = 'foo';

	/** @return static::FOO_BAR */
	public function test(): string
	{
		return static::FOO_BAR;
	}
}

class BarBaz extends FooBar
{
	const FOO_BAR = 'bar';
}

function test(FooBar $foo, BarBaz $bar): void
{
	assertType("'foo'", $foo->test());
	assertType("'bar'", $bar->test());
}

$foo can be a subclass of FooBar, meaning the value of FOO_BAR constant can be different. The type of the constant is constrained by a native class constant type (PHP 8.3+) or with PHPDoc type. For usual ClassConstFetch, the logic is implemented here: https://github.com/phpstan/phpstan-src/blob/0a4b3b5ac5719c19489b1b3f0e4bc9bb06be55c2/src/Reflection/InitializerExprTypeResolver.php#L2512-L2595

We can only infer the exact class constant value if the involved class is final, or if the constant is final.

Otherwise we need to use the combination of native + PHPDoc type.

The linked playground snippet is by no means comprehensive, but shows the problem. Also the return.type error shows the same issue I'm talking about.

Code snippet that reproduces the problem

https://phpstan.org/r/00b5c0ef-3180-40a2-9ca2-c267e8cdfbcc

Expected output

No errors

Did PHPStan help you today? Did it make you happy in any way?

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions