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

reset() modifies the array, but Psalm does not detect it #9840

Closed
BenMorel opened this issue May 30, 2023 · 4 comments · Fixed by #10505
Closed

reset() modifies the array, but Psalm does not detect it #9840

BenMorel opened this issue May 30, 2023 · 4 comments · Fixed by #10505

Comments

@BenMorel
Copy link
Contributor

The following code:

final readonly class Foo
{
    private array $values;
    
    public function __construct(array $values)
    {
        $this->values = $values;
    }

    public function bar(): mixed
    {
        return reset($this->values);
    }
}

$x = new Foo([]);
$x->bar();

Yields the following error:

Fatal error: Uncaught Error: Cannot modify readonly property Foo::$values

But Psalm does not detect it: https://psalm.dev/r/e9d0177183
Same with array_shift(): https://psalm.dev/r/b37bb7be31

This probably applies to all functions with a parameter passed by reference.

@psalm-github-bot
Copy link

I found these snippets:

https://psalm.dev/r/e9d0177183
<?php

final readonly class Foo
{
    private array $values;
    
    public function __construct(array $values)
    {
        $this->values = $values;
    }

    public function bar(): mixed
    {
        return reset($this->values);
    }
}

$x = new Foo([]);
$x->bar();
Psalm output (using commit 2bbfca6):

No issues!
https://psalm.dev/r/b37bb7be31
<?php

final readonly class Foo
{
    private array $values;
    
    public function __construct(array $values)
    {
        $this->values = $values;
    }

    public function bar(): mixed
    {
        return array_shift($this->values);
    }
}

$x = new Foo(['1']);
$x->bar();
Psalm output (using commit 2bbfca6):

No issues!

@orklah
Copy link
Collaborator

orklah commented May 30, 2023

Oh that's a tough one.

Internal function is one thing but any reference on a readonly property is dangerous (but not necessarily, there are performance reasons why you would want references, even on a readonly property)

Maybe some kind of RiskyReferenceUsage would be needed here. That would warn for everything and it would be easier than to have some difference between references on internal function and reference on userland functions (and I'm pretty sure we would end up finding a perfectly fine case with an internal function that takes a reference but don't crash on readonly properties :p)

@BenMorel
Copy link
Contributor Author

I’d personally be fine with RiskyReferenceUsage for any reference to a readonly property! 👍

I’m not aware of performance improvements when using references as PHP uses copy-on-write, so I don’t think there are many legitimate use cases anyway?

@orklah
Copy link
Collaborator

orklah commented May 31, 2023

I’m not aware of performance improvements when using references as PHP uses copy-on-write, so I don’t think there are many legitimate use cases anyway?

Really? I was convinced that it made a difference! Good to know!

kkmuffme added a commit to kkmuffme/psalm that referenced this issue Dec 19, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants