closed-resourceopen-resource, and in PHPStan literally the same type: both
spellings share one case and resolve to ResourceType, so the analyzer that
defines the vocabulary does not itself distinguish them. This file records
whether anyone else does, by offering an open handle where a closed one is
required.
References:
- PHPStan TypeNodeResolver open-resource and closed-resource share one case, both resolving to ResourceType| Analyzer | Version | Result | Diagnostics |
|---|---|---|---|
| phan | 6.0.7Phan 6.0.7 php-ast version 1.1.3 PHP version used to run Phan: 8.5.9 | Unrecognized | phpdoc_advanced_fallback_closed_resource.php:21: Saw possibly unextractable annotation for a fragment of comment '* @param closed-resource $value': after closed, did not see an element name (will guess based on comment order) [PhanUnextractableAnnotationElementName] phpdoc_advanced_fallback_closed_resource.php:21: Saw a token Phan may have failed to parse after '* @param closed-resource $value': after closed, saw '-' [PhanUnextractableAnnotationSuffix] phpdoc_advanced_fallback_closed_resource.php:23: Parameter $value has undeclared type \Conformance\Tests\PhpdocAdvancedFallbackClosedResource\closed [PhanUndeclaredTypeParameter] phpdoc_advanced_fallback_closed_resource.php:32: Argument 1 ($value) is $closed of type resource but \Conformance\Tests\PhpdocAdvancedFallbackClosedResource\acceptsClosedResource() takes \Conformance\Tests\PhpdocAdvancedFallbackClosedResource\closed defined at /Users/megurine/repo/php/php-typing-conformance/conformance/tests/phpdoc_advanced_fallback_closed_resource.php:23 [PhanTypeMismatchArgument] phpdoc_advanced_fallback_closed_resource.php:35: Argument 1 ($value) is 'not a resource' of type string but \Conformance\Tests\PhpdocAdvancedFallbackClosedResource\acceptsClosedResource() takes \Conformance\Tests\PhpdocAdvancedFallbackClosedResource\closed (no real type) defined at /Users/megurine/repo/php/php-typing-conformance/conformance/tests/phpdoc_advanced_fallback_closed_resource.php:23 (the inferred real argument type has nothing in common with the parameter's phpdoc type) [PhanTypeMismatchArgumentProbablyReal] phpdoc_advanced_fallback_closed_resource.php:41: Argument 1 ($value) is $open of type resource but \Conformance\Tests\PhpdocAdvancedFallbackClosedResource\acceptsClosedResource() takes \Conformance\Tests\PhpdocAdvancedFallbackClosedResource\closed defined at /Users/megurine/repo/php/php-typing-conformance/conformance/tests/phpdoc_advanced_fallback_closed_resource.php:23 [PhanTypeMismatchArgument]
Expectation diffLine 32: Expected valid value to be accepted, got ["Argument 1 ($value) is $closed of type resource but \\Conformance\\Tests\\PhpdocAdvancedFallbackClosedResource\\acceptsClosedResource() takes \\Conformance\\Tests\\PhpdocAdvancedFallbackClosedResource\\closed defined at /Users/megurine/repo/php/php-typing-conformance/conformance/tests/phpdoc_advanced_fallback_closed_resource.php:23 [PhanTypeMismatchArgument]"] |
| phpstan | 2.2.8PHPStan - PHP Static Analysis Tool 2.2.8 | Partly enforced (1/2) reported Lv.5+ | phpdoc_advanced_fallback_closed_resource.php:35: Parameter #1 $value of function Conformance\Tests\PhpdocAdvancedFallbackClosedResource\acceptsClosedResource expects resource, string given. [identifier=argument.type] [reported-from-level=5] With strict-rulesphpdoc_advanced_fallback_closed_resource.php:35: Parameter #1 $value of function Conformance\Tests\PhpdocAdvancedFallbackClosedResource\acceptsClosedResource expects resource, string given. [identifier=argument.type]
|
| psalm | 6.16.1Psalm 6.16.1@f1f5de594dc76faf8784e02d3dc4716c91c6f6ac next: 7.0.0-beta19 |
Enforced | phpdoc_advanced_fallback_closed_resource.php:35: Argument 1 of Conformance\Tests\PhpdocAdvancedFallbackClosedResource\acceptsClosedResource expects closed-resource, but 'not a resource' provided [InvalidArgument] phpdoc_advanced_fallback_closed_resource.php:41: Argument 1 of Conformance\Tests\PhpdocAdvancedFallbackClosedResource\acceptsClosedResource expects closed-resource, but resource provided [InvalidArgument]
|
| mago | 1.46.0mago 1.46.0 | Incidental (2/2) | phpdoc_advanced_fallback_closed_resource.php:32: Invalid argument type for argument #1 of `Conformance\Tests\PhpdocAdvancedFallbackClosedResource\acceptsClosedResource`: expected `closed-resource`, but found `open-resource`. [invalid-argument]
phpdoc_advanced_fallback_closed_resource.php:35: Invalid argument type for argument #1 of `Conformance\Tests\PhpdocAdvancedFallbackClosedResource\acceptsClosedResource`: expected `closed-resource`, but found `string('not a resource')`. [invalid-argument]
phpdoc_advanced_fallback_closed_resource.php:41: Invalid argument type for argument #1 of `Conformance\Tests\PhpdocAdvancedFallbackClosedResource\acceptsClosedResource`: expected `closed-resource`, but found `open-resource`. [invalid-argument]
Expectation diffLine 32: Expected valid value to be accepted, got ["Invalid argument type for argument #1 of `Conformance\\Tests\\PhpdocAdvancedFallbackClosedResource\\acceptsClosedResource`: expected `closed-resource`, but found `open-resource`. [invalid-argument]"] |
| mir | 0.70.1mir 0.70.1 | Partly enforced (1/2) | phpdoc_advanced_fallback_closed_resource.php:35: InvalidArgument: Argument $value of acceptsClosedResource() expects 'Conformance\Tests\PhpdocAdvancedFallbackClosedResource\closed-resource', got '"not a resource"' [MIR0201]
|
| phpantom | 0.9.0phpantom_lsp 0.9.0 | Not enforced | No diagnostics reported.
|
| intelephense | 1.18.5intelephense 1.18.5 | Not enforced | No diagnostics reported.
|
| phpy | 0.2.0phpy 0.2.0 | Unrecognized | phpdoc_advanced_fallback_closed_resource.php:21: Use of unknown class: 'Conformance\Tests\PhpdocAdvancedFallbackClosedResource\closed-resource' phpdoc_advanced_fallback_closed_resource.php:32: Argument '1' passed to Conformance\Tests\PhpdocAdvancedFallbackClosedResource\acceptsClosedResource() is expected to be of type Conformance\Tests\PhpdocAdvancedFallbackClosedResource\closed-resource, bool|resource given phpdoc_advanced_fallback_closed_resource.php:35: Argument '1' passed to Conformance\Tests\PhpdocAdvancedFallbackClosedResource\acceptsClosedResource() is expected to be of type Conformance\Tests\PhpdocAdvancedFallbackClosedResource\closed-resource, string given phpdoc_advanced_fallback_closed_resource.php:41: Argument '1' passed to Conformance\Tests\PhpdocAdvancedFallbackClosedResource\acceptsClosedResource() is expected to be of type Conformance\Tests\PhpdocAdvancedFallbackClosedResource\closed-resource, bool|resource given
Expectation diffLine 32: Expected valid value to be accepted, got ["Argument '1' passed to Conformance\\Tests\\PhpdocAdvancedFallbackClosedResource\\acceptsClosedResource() is expected to be of type Conformance\\Tests\\PhpdocAdvancedFallbackClosedResource\\closed-resource, bool|resource given"] |
| qodana | 262.8665.325Qodana 262.8665.325 | Partly enforced (1/2) | phpdoc_advanced_fallback_closed_resource.php:35: Parameter ''not a resource'' type is not compatible with declaration [PhpParamsInspection]
|
| noverify | 0.5.5NoVerify, version 0.5.5: built on: 2025.04.22 14:36:46 OS: r-kuchinskas arm64 Commit: 4774b82f8adc53fbef38f95e97af4b953b4d1529 | Partly enforced (1/2) ⚠ 2 false positives | phpdoc_advanced_fallback_closed_resource.php:12: Class or interface named \Conformance\Tests\PhpdocAdvancedFallbackClosedResource\closed-resource does not exist [undefinedClass] phpdoc_advanced_fallback_closed_resource.php:29: potentially not safe call in function fclose signature of param stream [notSafeCall] phpdoc_advanced_fallback_closed_resource.php:32: potentially not safe call in function Conformance\Tests\PhpdocAdvancedFallbackClosedResource\acceptsClosedResource signature of param value [notSafeCall] phpdoc_advanced_fallback_closed_resource.php:41: potentially not safe call in function Conformance\Tests\PhpdocAdvancedFallbackClosedResource\acceptsClosedResource signature of param value [notSafeCall]
Expectation diffLine 32: Expected valid value to be accepted, got ["potentially not safe call in function Conformance\\Tests\\PhpdocAdvancedFallbackClosedResource\\acceptsClosedResource signature of param value [notSafeCall]"] Line 12: Unexpected errors ["Class or interface named \\Conformance\\Tests\\PhpdocAdvancedFallbackClosedResource\\closed-resource does not exist [undefinedClass]"] Line 29: Unexpected errors ["potentially not safe call in function fclose signature of param stream [notSafeCall]"] |
| steins | 0.1.5steins 0.1.5 (2026-08-12 revision 39b4cc1) | Widened to a nonexistent-class reference | No diagnostics reported.
Notes: `closed-resource` lowers to `ContractTy::Class("closed-resource")` (no `lower_identifier` entry), the same non-existent-class treatment as `resource` (divergence-registry.md entry 4) — open/closed handle state is not modeled. |
| phpstan-strict | 2.2.8PHPStan - PHP Static Analysis Tool 2.2.8 | Partly enforced (1/2) | phpdoc_advanced_fallback_closed_resource.php:35: Parameter #1 $value of function Conformance\Tests\PhpdocAdvancedFallbackClosedResource\acceptsClosedResource expects resource, string given. [identifier=argument.type]
|
| psalm-next | 7.0.0-beta19Psalm 7.0.0-beta19@7e751c06a756fa64dc4c759c09fe4a173afcb433 | Enforced | phpdoc_advanced_fallback_closed_resource.php:35: Argument 1 of Conformance\Tests\PhpdocAdvancedFallbackClosedResource\acceptsClosedResource expects closed-resource, but 'not a resource' provided [InvalidArgument] phpdoc_advanced_fallback_closed_resource.php:41: Argument 1 of Conformance\Tests\PhpdocAdvancedFallbackClosedResource\acceptsClosedResource expects closed-resource, but resource provided [InvalidArgument]
|
<?php
declare(strict_types=1);
namespace Conformance\Tests\PhpdocAdvancedFallbackClosedResource;
/**
* `closed-resource`
*
* The mirror of `open-resource`, and in PHPStan literally the same type: both
* spellings share one `case` and resolve to ResourceType, so the analyzer that
* defines the vocabulary does not itself distinguish them. This file records
* whether anyone else does, by offering an open handle where a closed one is
* required.
*
* References:
* - PHPStan TypeNodeResolver `open-resource` and `closed-resource` share one case, both resolving to ResourceType
*/
/**
* @param closed-resource $value
*/
function acceptsClosedResource($value): void // T: closed-resource
{
}
$closed = \fopen('php://memory', 'r');
\assert($closed !== false);
\fclose($closed);
// A closed handle satisfies the parameter.
acceptsClosedResource($closed); // V
// A non-resource does not.
acceptsClosedResource('not a resource'); // E?: a string is not a closed-resource
$open = \fopen('php://memory', 'r');
\assert($open !== false);
// Still a resource, not yet closed.
acceptsClosedResource($open); // E?: an open handle is not a closed-resource