psalm
psalm copied to clipboard
String variable created in `catch` is mixed type but psalm-trace reports string
When a variable is created in catch (Exception $e)
it always seems to be of mixed type, but later, @psalm-trace
reports correct type, but it cannot be passed to a method that requires the same type that trace reports.
This is probably better explained by the code here https://psalm.dev/r/ee865b58ff
It works when I create the variable before the try
/catch
block with $param = null;
like this
https://psalm.dev/r/7e897e5348
I found these snippets:
https://psalm.dev/r/ee865b58ff
<?php
class Foo
{
public function __construct(?string $stringOrNullParam) {}
}
try {
if (rand()) {
throw new Exception();
}
} catch (Exception $e) {
$param = 'a';
}
if (!isset($param)) {
$param = null; // to highlight trace inconsistency, no change with new Foo($param ?? null)
}
/** @psalm-trace $param */
new Foo($param);
Psalm output (using commit 3600d51):
INFO: MixedArgument - 17:9 - Argument 1 of Foo::__construct cannot be mixed|null, expecting null|string
INFO: Trace - 17:1 - $param: null|string
https://psalm.dev/r/7e897e5348
<?php
class Foo
{
public function __construct(?string $stringOrNullParam) {}
}
$param = null;
try {
if (rand()) {
throw new Exception();
}
} catch (Exception $e) {
$param = 'a';
}
/** @psalm-trace $param */
new Foo($param);
Psalm output (using commit 3600d51):
INFO: Trace - 15:1 - $param: 'a'|null
but later, @psalm-trace reports correct type
That's because you traced the type after the constructor call. You need to use /** @psalm-trace $param */;
(note the semicolon) to trace the variable before the call.