Skip to content

ProperNullCoalescingOperatorUsage ​

info on by default quick-fix PHP ≥ 7.0

Group: Code style · PhpStorm name: ProperNullCoalescingOperatorUsageInspection

Two misuses of ??: (a) call() ?? null — a call result never triggers an undefined-index/variable notice, so ?? null does nothing; (b) a fallback whose type has nothing in common with the left operand's type, which usually signals a bug or a confusing API.

Example ​

With ALLOW_OVERLAPPING_TYPES = false:

php
<?php
interface Shape {}
class Square implements Shape {}
class Disc implements Shape {}
class Engine {}
class Turbo extends Engine {}

class Garage {
    /** @var Engine|null */
    private $engine;

    public function lookup(): ?Engine { return null; }

    public function demo(Engine $e, Turbo $t, Square $s, Disc $d, ?int $n = null, string $label = null) {
        return [
            $this->lookup() ?? null,
            strrev($label) ?? NULL,
            $this->engine ?? 'none',
            $n ?? 'n/a',                    // scalar placeholder (D5a)
            $this->engine ?? null,
            $label ?? null,
            $t ?? $e,
            $e ?? $t,
            $s ?? $d,                       // related through Shape
            $n ?? 42,
            (int) ($label ?? $e),
        ];
    }
}
php
<?php
interface Shape {}
class Square implements Shape {}
class Disc implements Shape {}
class Engine {}
class Turbo extends Engine {}

class Garage {
    /** @var Engine|null */
    private $engine;

    public function lookup(): ?Engine { return null; }

    public function demo(Engine $e, Turbo $t, Square $s, Disc $d, ?int $n = null, string $label = null) {
        return [
            $this->lookup(),
            strrev($label),
            $this->engine ?? 'none',
            $n ?? 'n/a',                    // scalar placeholder (D5a)
            $this->engine ?? null,
            $label ?? null,
            $t ?? $e,
            $e ?? $t,
            $s ?? $d,                       // related through Shape
            $n ?? 42,
            (int) ($label ?? $e),
        ];
    }
}

Reported:

  • line 16: '$this->lookup()' alone is equivalent; drop the '?? null' fallback.
  • line 17: 'strrev($label)' alone is equivalent; drop the '?? null' fallback.
  • line 18: Operand types of '??' do not match ([\Engine] vs [string]).

Options ​

OptionTypeDefaultEffect
ANALYZE_TYPESbooltrueEnables Case B (type complementarity).
ALLOW_OVERLAPPING_TYPESbooltrueWhen true, any shared type makes operands complementary; when false, the right operand's types must cover all of the left operand's types.

Upstream fixtures run with ANALYZE_TYPES = true and ALLOW_OVERLAPPING_TYPES = false.

Configure ​

In custos.json:

json
{
  "rules": {
    "ProperNullCoalescingOperatorUsage": {
      "enabled": false,
      "options": {
        "ANALYZE_TYPES": true,
        "ALLOW_OVERLAPPING_TYPES": true
      }
    }
  }
}

Suppress ​

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

php
// @custos-ignore ProperNullCoalescingOperatorUsage

/**
 * @noinspection ProperNullCoalescingOperatorUsageInspection
 */

Released under the MIT License. Rule catalogue modelled on Php Inspections (EA Extended); independent clean-room implementation.