Resources
PHP's resource is a runtime handle to an external resource: a file, a database connection, a stream, a curl handle. The type system models this as the resource family, with optional refinements for the resource's open-or-closed state and its named kind.
The two axes
A resource carries two refinement axes:
State
Three values:
- Unspecified — the analyser has no knowledge of openness. PHP-side:
resource. - Open — the resource is open. PHP-side:
open-resource. - Closed — the resource is closed. PHP-side:
closed-resource.
Open and Closed are disjoint. Unspecified is the join.
The state tracks the result of fclose($f) and similar calls in the analyser: after fclose($f), the analyser narrows $f from open-resource to closed-resource.
Kind
An optional named kind — resource<curl>, resource<gd image>, resource<stream>. The name corresponds to PHP's get_resource_type($r) return value.
A resource without a named kind admits any kind. With a name, it admits only that specific kind.
Subtyping
graph BT
OpenCurl["open-resource<curl>"] --> Open["open-resource"]
OpenCurl --> Curl["resource<curl>"]
Open --> R[resource]
Curl --> R
Closed["closed-resource"] --> R
OpenrefinesUnspecified;ClosedrefinesUnspecified; both refine the unrefined.- A named kind refines the unnamed;
open-resource<curl>(state =Open, kind =curl) refines bothopen-resourceandresource<curl>.
A worked example
/**
* @param open-resource $r
*/
function read($r): string { /* ... */ }
$f = fopen('/tmp/x', 'r'); // open-resource<stream>
read($f); // OK: open-resource<stream> <: open-resource
fclose($f); // narrows $f to closed-resource<stream>
read($f); // analyser warns: passed a closed resource
The lattice answers each refines query straightforwardly. The narrowing on fclose is the narrow operation with an analyser-supplied assertion that the resource is now Closed.
See also: refines for the per-pair rules; narrow for state-flip narrowing.