Skip to content

ReadonlyPropertyReassignment ​

error native on by default PHP ≥ 8.1

Group: Probable bugs

Detect assignment to a resolved readonly instance property already initialized on every reachable incoming path.

Example ​

php
<?php
class Item { public readonly int $id; public function __construct() {$this->id=1; $this->id=2;} }

Reported:

  • line 2: Initialize this readonly property only once.

Detection ​

  • Report assignment to a resolved readonly instance property already initialized on every reachable incoming path.
  • Every writing assignment operator counts as a repeated write: plain = and the compound operators (+=, -=, .=, ...) all fail on an initialized readonly property. The null-coalescing assignment ??= is the exception, see E3.
  • Resolve builtin calls and named arguments before checking the contract. Project-local callees are considered only when their bodies or immutable summaries establish the required facts. The default is enabled, with positive proof required.
  • For flow-dependent conditions, require a reachable source-to-use path with no intervening invalidation. Unknown calls, ambiguous aliases, recursion or analysis-budget exhaustion cannot establish definite facts.

Exceptions (no report) ​

  • A first permitted initialization, version-permitted clone reinitialization, unknown initialization state and reflection operations are excluded.

  • Unresolved targets, incomplete required facts, suppressed findings and PHP versions lacking the referenced API or language feature produce no report. User declarations shadowing builtin names are not builtin contracts.

  • E3. A ??= assignment is never reported. It writes only when the stored value is null, and the adjacent-assignment proof establishes that the property is initialized, not that it holds null; on a non-null value the statement is a no-op and PHP raises nothing.

Fix ​

No automatic fix: removing an assignment may conceal a missing design change.

PHP versions ​

Available from PHP 8.1. Builtin behavior and argument contracts follow the configured PHP version. Extension-specific calls require resolved extension API symbols; do not treat same-named application functions as extension calls.

Options ​

None. Enable or disable this rule through normal rule configuration.

Configure ​

In custos.json:

json
{
  "rules": {
    "ReadonlyPropertyReassignment": {
      "enabled": false
    }
  }
}

Suppress ​

Before the statement or declaration (or the first statement of the file):

php
// @custos-ignore ReadonlyPropertyReassignment

Released under the MIT License. Native rules and rules modeled on Php Inspections (EA Extended); independent clean-room implementation.