new $c when $c is a class string with a leading backslash"\\DateTimeImmutable" and "DateTimeImmutable" name the same class. A
lookup that keeps the slash misses the constructor and skips
InterfaceInstantiation for "\\Countable". The slash-free string is the
control: a diagnostic there means the tool does not instantiate from a
string at all, not that it mishandles the slash.
Source: vimeo/psalm#12039, from #5679.
References:
- psalm#12039| Analyzer | Version | Result | Diagnostics |
|---|---|---|---|
| phan | 6.0.10Phan 6.0.10 php-ast version 1.1.3 PHP version used to run Phan: 8.5.11 | Pass | regressions_new_class_string_leading_backslash.php:41: Unused result of new object creation expression in new $class() (this may be called for the side effects of the non-empty constructor or destructor) [PhanNoopNew] regressions_new_class_string_leading_backslash.php:41: Instantiation of abstract class \Countable [PhanTypeInstantiateAbstract] regressions_new_class_string_leading_backslash.php:47: Unused result of new object creation expression in new $class() (this may be called for the side effects of the non-empty constructor or destructor) [PhanNoopNew] regressions_new_class_string_leading_backslash.php:47: Instantiation of abstract class \Countable [PhanTypeInstantiateAbstract] |
| phpstan | 2.3.1PHPStan - PHP Static Analysis Tool 2.3.1 | Pass reported Lv.0+ | regressions_new_class_string_leading_backslash.php:41: Cannot instantiate interface Countable. [reported-from-level=0] regressions_new_class_string_leading_backslash.php:47: Cannot instantiate interface Countable. [reported-from-level=0] With strict-rulesregressions_new_class_string_leading_backslash.php:41: Cannot instantiate interface Countable. regressions_new_class_string_leading_backslash.php:47: Cannot instantiate interface Countable. |
| psalm | 6.20.0Psalm 6.20.0@804f03c0c183d149fcd4b8c7c0c9b3fbf836d34c next: 7.0.0-rc2 |
Pass (pzoom≠) | regressions_new_class_string_leading_backslash.php:29: String cannot be used as a class [InvalidStringClass] regressions_new_class_string_leading_backslash.php:35: String cannot be used as a class [InvalidStringClass] regressions_new_class_string_leading_backslash.php:41: String cannot be used as a class [InvalidStringClass] regressions_new_class_string_leading_backslash.php:41: Interface Countable cannot be instantiated [InterfaceInstantiation] regressions_new_class_string_leading_backslash.php:47: String cannot be used as a class [InvalidStringClass] regressions_new_class_string_leading_backslash.php:47: Interface Countable cannot be instantiated [InterfaceInstantiation] pzoom (Psalm port)regressions_new_class_string_leading_backslash.php:41: Cannot instantiate interface Countable [InterfaceInstantiation] regressions_new_class_string_leading_backslash.php:47: Cannot instantiate interface Countable [InterfaceInstantiation] |
| mago | 1.57.0mago 1.57.0 | Pass | regressions_new_class_string_leading_backslash.php:35: Class `\DateTimeImmutable` not found. [non-existent-class] regressions_new_class_string_leading_backslash.php:35: Argument #1 passed to function `Conformance\Tests\RegressionsNewClassStringLeadingBackslash\takesImmutable` has type `never`, meaning it cannot produce a value. [no-value] regressions_new_class_string_leading_backslash.php:41: Class `\Countable` not found. [non-existent-class] regressions_new_class_string_leading_backslash.php:47: Interface `Countable` cannot be instantiated with `new`. [interface-instantiation] |
| mir | 0.87.0mir 0.87.0 | Fail | No diagnostics reported. Expectation diffLine 41: Expected 1 error(s) Line 47: Expected 1 error(s) |
| phpantom | 0.11.1phpantom_lsp 0.11.1 | Fail | No diagnostics reported. Expectation diffLine 41: Expected 1 error(s) Line 47: Expected 1 error(s) |
| intelephense | 1.18.5intelephense 1.18.5 | Fail | regressions_new_class_string_leading_backslash.php:29: Expected type 'DateTimeImmutable'. Found 'object'. [P1006] regressions_new_class_string_leading_backslash.php:35: Expected type 'DateTimeImmutable'. Found 'object'. [P1006] Expectation diffLine 41: Expected 1 error(s) Line 47: Expected 1 error(s) |
| phpactor | 2026.10.07.0Phpactor 2026.10.07.0 | Fail | No diagnostics reported. Expectation diffLine 41: Expected 1 error(s) Line 47: Expected 1 error(s) |
| phpy | 1.0.19409phpy 1.0.19409 | Fail | No diagnostics reported. Expectation diffLine 41: Expected 1 error(s) Line 47: Expected 1 error(s) |
| qodana | 262.10968.76PhpStorm 262.10968.76 | Fail | No diagnostics reported. Expectation diffLine 41: Expected 1 error(s) Line 47: Expected 1 error(s) |
| noverify | 0.5.5NoVerify, version 0.5.5: built on: 2025.04.22 14:36:46 OS: r-kuchinskas arm64 Commit: 4774b82f8adc53fbef38f95e97af4b953b4d1529 | Pass | regressions_new_class_string_leading_backslash.php:41: Expression evaluated but not used [discardExpr] regressions_new_class_string_leading_backslash.php:47: Expression evaluated but not used [discardExpr] |
| steins | 0.1.8steins 0.1.8 (2026-09-21 revision 76306a9) | Fail | No diagnostics reported. Expectation diffLine 41: Expected 1 error(s) Line 47: Expected 1 error(s) |
| phpstan-strict | 2.3.1PHPStan - PHP Static Analysis Tool 2.3.1 | Pass | regressions_new_class_string_leading_backslash.php:41: Cannot instantiate interface Countable. regressions_new_class_string_leading_backslash.php:47: Cannot instantiate interface Countable. |
| psalm-next | 7.0.0-rc2Psalm 7.0.0-rc2@20339e3fe5b8d03bcd8061030eb2a83ad50e5783 | Pass | regressions_new_class_string_leading_backslash.php:29: String cannot be used as a class [InvalidStringClass] regressions_new_class_string_leading_backslash.php:35: String cannot be used as a class [InvalidStringClass] regressions_new_class_string_leading_backslash.php:41: String cannot be used as a class [InvalidStringClass] regressions_new_class_string_leading_backslash.php:41: Interface Countable cannot be instantiated [InterfaceInstantiation] regressions_new_class_string_leading_backslash.php:47: String cannot be used as a class [InvalidStringClass] regressions_new_class_string_leading_backslash.php:47: Interface Countable cannot be instantiated [InterfaceInstantiation] |
<?php
declare(strict_types=1);
namespace Conformance\Tests\RegressionsNewClassStringLeadingBackslash;
/**
* `new $c` when `$c` is a class string with a leading backslash.
*
* `"\\DateTimeImmutable"` and `"DateTimeImmutable"` name the same class. A
* lookup that keeps the slash misses the constructor and skips
* `InterfaceInstantiation` for `"\\Countable"`. The slash-free string is the
* control: a diagnostic there means the tool does not instantiate from a
* string at all, not that it mishandles the slash.
*
* Source: vimeo/psalm#12039, from #5679.
*
* References:
* - https://github.com/vimeo/psalm/pull/12039
*/
function takesImmutable(\DateTimeImmutable $value): void
{
}
function fromPlainString(): void
{
$class = 'DateTimeImmutable';
takesImmutable(new $class()); // Q?: some tools ban `new $string` entirely (`InvalidStringClass`); silence here is the slash-free control
}
function fromLeadingSlash(): void
{
$class = '\\DateTimeImmutable';
takesImmutable(new $class()); // Q?: a leading backslash still names DateTimeImmutable when `new $string` is allowed
}
function interfaceWithSlash(): void
{
$class = '\\Countable';
new $class(); // E: Countable is an interface
}
function interfaceWithoutSlash(): void
{
$class = 'Countable';
new $class(); // E: the same without a slash, so a hit here is not the slash bug
}