Skip to content

Psalm does not understand variable initialization order when initialized within array. #6061

Closed
@simPod

Description

@simPod
Contributor

https://psalm.dev/r/d4185292b9

I'd expect not errors about variable $timestamp being not found or unused.

Activity

psalm-github-bot

psalm-github-bot commented on Jul 8, 2021

@psalm-github-bot

I found these snippets:

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

[
    $timestamp = (new DateTimeImmutable('2017-08-06 00:00:00'))->getTimestamp() => [
        'timestamp' => $timestamp,
    ],
    $timestamp = (new DateTimeImmutable('2017-08-06 01:00:00'))->getTimestamp() => [
        'timestamp' => $timestamp,
    ],
    $timestamp = (new DateTimeImmutable('2017-08-06 02:00:00'))->getTimestamp() => [
        'timestamp' => $timestamp,
    ]
];
Psalm output (using commit 0257752):

ERROR: UndefinedGlobalVariable - 5:24 - Cannot find referenced variable $timestamp in global scope

ERROR: InvalidArrayOffset - 3:1 - Cannot create offset of type false|int, expecting array-key

INFO: UnusedVariable - 4:5 - $timestamp is never referenced or the value is not used

INFO: UnusedVariable - 7:5 - $timestamp is never referenced or the value is not used

INFO: UnusedVariable - 10:5 - $timestamp is never referenced or the value is not used
muglug

muglug commented on Jul 9, 2021

@muglug
Collaborator

Few comments:

  • IMO this is bad code and should be rewritten as https://psalm.dev/r/366293c0e1
  • the bug is caused by evaluation order — currently all keys are evaluated first, which is wrong. It should be possible instead to do it by key and value
psalm-github-bot

psalm-github-bot commented on Jul 9, 2021

@psalm-github-bot

I found these snippets:

https://psalm.dev/r/366293c0e1
<?php

$dates = ['2017-08-06 00:00:00', '2017-08-06 01:00:00', '2017-08-06 02:00:00'];

$arr = [];

foreach ($dates as $date) {
    $timestamp = (new DateTimeImmutable($date))->getTimestamp();
    $arr[$timestamp] = ['timestamp' => $timestamp];
}
Psalm output (using commit f94f3b8):

No issues!
simPod

simPod commented on Jul 12, 2021

@simPod
ContributorAuthor

Definitely agree the code is not perfect though it's still valid or is it not?

Stumbled upon it in legacy code base where there's complex array structure in tests and the lowest level array is constructed like this. Hard to squeeze foreach inside. I would have to wrap it in a function, call it and unpack ... or sth like that.

[22=>[
    $timestamp = (new DateTimeImmutable('2017-08-06 00:00:00'))->getTimestamp() => [
        'timestamp' => $timestamp,
    ],
    $timestamp = (new DateTimeImmutable('2017-08-06 01:00:00'))->getTimestamp() => [
        'timestamp' => $timestamp,
    ],
    $timestamp = (new DateTimeImmutable('2017-08-06 02:00:00'))->getTimestamp() => [
        'timestamp' => $timestamp,
    ]
]];

->

<?php

[22=>(function() {
    $dates = ['2017-08-06 00:00:00', '2017-08-06 01:00:00', '2017-08-06 02:00:00'];

    $arr = [];

    foreach ($dates as $date) {
        $timestamp = (new DateTimeImmutable($date))->getTimestamp();
        $arr[$timestamp] = ['timestamp' => $timestamp];
    }

    return $arr;
})()]
added a commit that references this issue on Jul 12, 2021

Fix #6061 — delay analysis of array value except when unpacking

370ef19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @simPod@muglug@orklah

        Issue actions

          Psalm does not understand variable initialization order when initialized within array. · Issue #6061 · vimeo/psalm