Skip to content

Support for generic type constraints in function signatures #10296

@devnix

Description

@devnix

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!

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions