vimeo / psalm

A static analysis tool for finding errors in PHP applications
https://psalm.dev
MIT License
5.55k stars 659 forks source link

@psalm-assert not using inherited template type, throwing TypeDoesNotContainType #10299

Open declankirk opened 1 year ago

declankirk commented 1 year ago

Recreated here - https://psalm.dev/r/de6890e50b

If a templated parent class has a function with an assertion for type T (in this case @psalm-assert T $value), the child class type isn't used for the inherited function.

psalm-github-bot[bot] commented 1 year ago

I found these snippets:

https://psalm.dev/r/de6890e50b ```php */ class ChildClass extends ParentClass {} $string = 'string'; ChildClass::parentFunction($string); ``` ``` Psalm output (using commit 24168f6): ERROR: TypeDoesNotContainType - 20:13 - Cannot resolve types for $string - 'string' does not contain T ```
robchett commented 11 months ago

Psalm doesn't use class template parameters on static methods or properties.

I can't find any documentation to that and it stems from https://github.com/vimeo/psalm/commit/797a059a84f86f66518c8b6c61870f165fcc27d1 which doesn't explain the reasons.

@muglug, I'm happy to add this to the documentation and/or throw a distinct error, but as I don't quite understand the reasoning could you clarify slightly? My assumption is the shared state makes any access of static properties inherently unsafe, and implementation of a static method would need knowledge of child types.

Other annotations (param) will throw:

ERROR: UndefinedDocblockClass - Docblock-defined class, interface or enum named T does not exist

I can get assert to do the same at the very least.

Perhaps a message such as this would be better?

ERROR: InvalidStaticClassTemplateUsage - Class template type T is only available for instance methods/variables and cannot be used in a static context.