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

Prevent inheritance of class template types in static methods #2738

Open
muglug opened this issue Dec 14, 2019 · 5 comments
Open

Prevent inheritance of class template types in static methods #2738

muglug opened this issue Dec 14, 2019 · 5 comments

Comments

@muglug
Copy link
Contributor

muglug commented Dec 14, 2019

Instance template parameters should not be made available to static methods – this was a flaw in my implementation, now fixed. If/when generics are available at the language level this can be re-evaluated.

/**
 * @template T
 */
class C {
    /**
     * @param T $t
     */
    public static function foo($t) : void {}
}

https://phpstan.org/r/e00cd9e1-3aba-4e6c-ab9a-8e63da122b94

Expected: some sort of error (in Psalm for now it just treats it as a missing docblock class, you may want something more helpful).

@ondrejmirtes
Copy link
Member

So I've stumbled upon this interesting example: https://phpstan.org/r/81f2efd0-b769-4685-a5aa-a8f914fda95a

And it seems to work in Psalm too, although it's about class-level T that's used above a static method which contradicts this feature request. What do you think is the difference @muglug?

@muglug
Copy link
Contributor Author

muglug commented Jul 18, 2020

Yeah, I decided against this in the end (hence why the example now works in Psalm) because penalising a legitimate usage was unfair

@ondrejmirtes
Copy link
Member

@muglug So what's the difference that this one still marks T as unknown? https://psalm.dev/r/c93629faa3

@dktapps
Copy link
Contributor

dktapps commented Jul 19, 2020

Maybe a better option is to allow this, but report static usages where the type can't be inferred (e.g. Class::thing() can't be inferred but $someObject::thing() should be able to).
For example: https://phpstan.org/r/acf73820-4728-426f-9d38-7d479eb22af0

@vhenzl
Copy link
Contributor

vhenzl commented Nov 17, 2021

I have just run into this problem.

Let's assume code like this (a simplified version of this Maybe type implementation):

/**
 * @template T
 */
final class Maybe
{
    private function __construct(
        /** @var T */
        public mixed $value = null,
    ) {
    }

    /**
     * @param T $value
     * @return Maybe<T>
     */
    public static function just(mixed $value): self
    {
        return new self($value);
    }
}

And example use:

$ms = Maybe::just('abc');
$mi = Maybe::just(123);

The code of Maybe class is wrong, the static method just() shouldn't use T template but define its own @template V, accept parameter V $value and return Maybe<V>.

Because PHPStan didn't complain about "unknown type T" (or whatever the error message should be), I assumed that the code is correct and that the inferred type of $ms and $mi is Maybe<string> and Maybe<int> respectively.

To my surprise, I later found out that for PHPStan the return type of just() is always Maybe<mixed>. And since the type is mixed, PHPStan allows any operation with the value, hiding errors further down in the code.

This is rather dangerous behaviour because PHPStan doesn't complain about anything and gives a false feeling that everything works correctly.

kenjis added a commit to kenjis/CodeIgniter4 that referenced this issue Jan 23, 2024
Psalm does not support class @template in static methods.
And in PHPStan it does not protect.
See
- vimeo/psalm#2697
- phpstan/phpstan#2738
kenjis added a commit to kenjis/CodeIgniter4 that referenced this issue Jan 23, 2024
Psalm does not support class @template in static methods.
And in PHPStan it does not protect.
See
- vimeo/psalm#2697
- phpstan/phpstan#2738
kenjis added a commit to kenjis/CodeIgniter4 that referenced this issue Jan 23, 2024
Psalm does not support class @template in static methods.
And in PHPStan it does not protect.
See
- vimeo/psalm#2697
- phpstan/phpstan#2738
kenjis added a commit to kenjis/CodeIgniter4 that referenced this issue Jan 23, 2024
Psalm does not support class @template in static methods.
And in PHPStan it does not protect.
See
- vimeo/psalm#2697
- phpstan/phpstan#2738
kenjis added a commit to kenjis/CodeIgniter4 that referenced this issue Jan 23, 2024
Psalm does not support class @template in static methods.
And in PHPStan it does not protect.
See
- vimeo/psalm#2697
- phpstan/phpstan#2738
kenjis added a commit to kenjis/CodeIgniter4 that referenced this issue Jan 23, 2024
Psalm does not support class @template in static methods.
And in PHPStan it does not protect.
See
- vimeo/psalm#2697
- phpstan/phpstan#2738
kenjis added a commit to kenjis/CodeIgniter4 that referenced this issue Jan 23, 2024
Psalm does not support class @template in static methods.
And in PHPStan it does not protect.
See
- vimeo/psalm#2697
- phpstan/phpstan#2738
kenjis added a commit to kenjis/CodeIgniter4 that referenced this issue Jan 29, 2024
Psalm does not support class @template in static methods.
And in PHPStan it does not protect.
See
- vimeo/psalm#2697
- phpstan/phpstan#2738
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants