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

Support for generic type constraints in function signatures #10296

Open
devnix opened this issue Dec 13, 2023 · 1 comment
Open

Support for generic type constraints in function signatures #10296

devnix opened this issue Dec 13, 2023 · 1 comment

Comments

@devnix
Copy link

devnix commented Dec 13, 2023

Feature request

Concerning this discussion, here is a feature request (I'm not very sure about the name of the feature itself)

After a few tries and thanks to the help of Copilot (this is my first time working with Hacklang) I've been able to replicate the feature request:

class Ref<T>
{
    public function __construct(private T $value)
    {
    }

    public function zip<TOther>(Ref<TOther> $other) : Ref<(T, TOther)>
    {
        return new Ref(tuple($this->value, $other->value));
    }

    public function unzip<T1, T2>() : (Ref<T1>, Ref<T2>) where T = (T1, T2)
    {
        return tuple(
            new Ref($this->value[0]),
            new Ref($this->value[1]),
        );
    }
}

function example1(): void
{
    $a = new Ref(1); // Ref<int>
    $b = new Ref('foo'); // Ref<string>

    $c = $a->zip($b); // Ref<(int, string)>
    $d = $c->unzip(); // (Ref<int>, Ref<string>)
}

function example2(): void
{
    $a = new Ref(1); // Ref<int>
    
    // Typing[4323] A where type constraint is violated here [1]
    // -> This is the method with where type constraints [2]
    // -> Expected (_, _) [3]
    // -> But got int [4]
    $b = $a->unzip(); 
}

function example3(): void
{
    $a = new Ref(tuple(1, tuple(false, 4.20))); // Ref<(int, (bool, float))>

    $b = $a->unzip(); // (Ref<int>, Ref<(bool, float)>)

    // Typing[4323] A where type constraint is violated here [1]
    // -> This is the method with where type constraints [2]
    // -> Expected (_, _) [3]
    // -> But got int [4]
    $c = $b[0]->unzip();
    
    $d = $b[1]->unzip(); // (Ref<bool>, Ref<float>)
}

I still think this is similar to @psalm-if-this-is in practice, as it's a way to set the template type based on a condition.

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

It raises the quality bar of all the projects that I love!

@ondrejmirtes
Copy link
Member

ondrejmirtes commented Dec 13, 2023

Hey @arnaud-lb @JanTvrdik, do you think it's already possible to achieve this behaviour? See also the linked discussion.

If not, how would you design this? Thanks!

@ondrejmirtes ondrejmirtes added this to the Generics milestone Jan 5, 2024
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

2 participants