Skip to content
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

Conditional return type including template type resolved in wrong place #12333

Open
jankal opened this issue Dec 29, 2024 · 4 comments
Open

Conditional return type including template type resolved in wrong place #12333

jankal opened this issue Dec 29, 2024 · 4 comments
Labels
Milestone

Comments

@jankal
Copy link

jankal commented Dec 29, 2024

Bug report

I am returning a class-string from a method which could also return null in the default generic case (using a conditional return type declaration). The returned class-string type is not checked in the context of the child class but in the generic context of the parent/definer and thus not part of the generic template variable.

Code snippet that reproduces the problem

https://phpstan.org/r/ea335711-73a7-4d4e-9647-9212eef29f75

Expected output

This code shouldn't have any issues as DeleteActionType implements DataClassAwareFormTypeInterface<DeleteActionParameters> and DeleteActionParameters is of Struct

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

Most of the time, PHPStan is more intelligent than I am - discovering issues with covariance and contravariance I otherwise would've missed :)

@jankal
Copy link
Author

jankal commented Dec 29, 2024

I would rather have used some kind of optional generic template syntax... like this:

/**
* @template ?TParam of Struct
*/
interface EmailActionInterface
{
    /** @return (TParams is null ? null : class-string<DataClassAwareFormTypeInterface<TParams>>) */
    public static function getParameterTypeClass(): ?string;

    /**
     * @param (TParams ?? null) $params
     * @return void
     */
    public function __invoke(?Struct $params = null): void;
}

But that syntax apparently does not work.

@jankal jankal changed the title Optional template parameter not resolved when used Conditional return inclusing template type resolved in wrong place Dec 29, 2024
@jankal jankal changed the title Conditional return inclusing template type resolved in wrong place Conditional return type including template type resolved in wrong place Dec 29, 2024
@staabm
Copy link
Contributor

staabm commented Dec 29, 2024

Not 100% sure, but I think you could use template defaults: phpstan/phpstan-src#3457

@jankal
Copy link
Author

jankal commented Dec 30, 2024

@staabm yeah, that works for setting the default in the generic and omitting the generic parameter when the default should be used.

The actual bug is about PHPStan apparently checking the return type in the wrong context (error says, the return type of that function is not part of the template parameter... which it is as it is of Struct).

@jankal
Copy link
Author

jankal commented Dec 30, 2024

It just occurred to me: when I add a @return class-string<...> annotation to the method, PHPStorm doesn't complain anymore...

https://phpstan.org/r/e47e606f-c444-45f6-aada-edf73d587f19

Looks like a bug to me.

@ondrejmirtes ondrejmirtes added this to the Generics milestone Jan 19, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants