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

callable(&int) should not be a subtype of callable(int) #8300

Open
AndrolGenhald opened this issue Jul 21, 2022 · 1 comment
Open

callable(&int) should not be a subtype of callable(int) #8300

AndrolGenhald opened this issue Jul 21, 2022 · 1 comment

Comments

@AndrolGenhald
Copy link
Collaborator

Closure could still take its argument by reference though, and again mutate it. https://psalm.dev/r/3423b8e3e9

Originally posted by @someniatko in #8212 (comment)

@someniatko huh, you're right. I'd consider that a separate bug though. I think we need to add annotation for references in callables and make callable(&int) not be a subtype of callable(int), because the example I just gave crashes...

Originally posted by @AndrolGenhald in #8212 (comment)

I don't believe we even have a way to annotate callables that take arguments by ref right now, so this is probably going to take a bit of work.

@psalm-github-bot
Copy link

I found these snippets:

https://psalm.dev/r/3423b8e3e9
<?php

/**
 * @psalm-template-covariant T of string|int|float
 * @psalm-immutable
 */
final class ValueReference {
    /**
     * @param T $value
     */
    public function __construct(
        public readonly mixed $value
    ) {}

    /**
     * @template Tu of string|int|float
     *
     * @param (Closure(T): Tu) $f
     *
     * @return ValueReference<Tu>
     */
    public function map(Closure $f): ValueReference
    {
        $new = $f($this->value);

        return new ValueReference($new);
    }
}

$a = new ValueReference('hello');
$b = $a->map(/** @param-out string $val */ function(string &$val) { $val = $val . ' world'; return $val; });

print $b->value; // hello world
Psalm output (using commit 85fe7e8):

ERROR: ImpureFunctionCall - 24:16 - Cannot call an impure function from a mutation-free context
https://psalm.dev/r/e59d68ba57
<?php

/** @param callable(int): int $closure */
function takesClosure($closure): int
{
    return $closure(123);
}

function takesIntByRef(int &$i): int
{
    return $i**2;
}

takesClosure("takesIntByRef");
Psalm output (using commit 85fe7e8):

No issues!

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

1 participant