psalm icon indicating copy to clipboard operation
psalm copied to clipboard

Optional property type of object is being forgotten

Open M393 opened this issue 9 months ago • 2 comments

https://psalm.dev/r/65da587980 Compare output for f1 through f4. Here it is handily organized in a table:

array object
non-optional f1
$a1: array{p: bool}
$a1['p']: bool
f2
$o1: object{p:mixed}
$o1->p: bool
optional f3
$a2: array{p?: mixed}
$a2['p']: bool
 
f4
$o2: object{p?:mixed}
$o2->p: mixed
MixedReturnStatement

the type in f3 should be $a2: array{p?: bool} and I'd expect objects to have more detailed types like arrays. Psalm should not show an error for the f4 case.

M393 avatar Apr 10 '25 15:04 M393

I found these snippets:

https://psalm.dev/r/65da587980
<?php
/** @param array{p: mixed} $a1 */
function f1(array $a1): bool {
    if (!is_bool($a1['p'])) {
        throw new RuntimeException();
    }
    /** @psalm-trace $a1 $a1['p'] */
    return $a1['p'];
}

/** @param object{p: mixed} $o1 */
function f2(object $o1): bool {
    if (!is_bool($o1->p)) {
        throw new RuntimeException();
    }
    /** @psalm-trace $o1 $o1->p */
    return $o1->p;
}

/** @param array{p?: mixed} $a2 */
function f3(array $a2): bool {
    if (array_key_exists('p', $a2) && !is_bool($a2['p'])) {
        throw new RuntimeException();
    }
    /** @psalm-trace $a2 $a2['p'] */
    return $a2['p'];
}

/** @param object{p?: mixed} $o2 */
function f4(object $o2): bool {
    if (property_exists($o2, 'p') && !is_bool($o2->p)) {
        throw new RuntimeException();
    }
    /** @psalm-trace $o2 $o2->p */
    return $o2->p ?? false;
}
Psalm output (using commit c65b0f0):

INFO: Trace - 8:5 - $a1: array{p: bool}

INFO: Trace - 8:5 - $a1['p']: bool

INFO: Trace - 17:5 - $o1: object{p:mixed}

INFO: Trace - 17:5 - $o1->p: bool

INFO: Trace - 26:5 - $a2: array{p?: mixed}

INFO: Trace - 26:5 - $a2['p']: bool

INFO: MixedReturnStatement - 35:12 - Possibly-mixed return value

INFO: MixedReturnStatement - 35:12 - Could not infer a return type

INFO: Trace - 35:5 - $o2: object{p?:mixed}

INFO: Trace - 35:5 - $o2->p: mixed

psalm-github-bot[bot] avatar Apr 10 '25 15:04 psalm-github-bot[bot]

I just noticed that in the f3 case psalm should complain that the property may be unset, but it didn't.

M393 avatar Apr 10 '25 15:04 M393