Skip to content

[Php80] Skip mixed and untyped calls in TernaryToNullsafeCoalesceRector - #8531

Merged
TomasVotruba merged 1 commit into
rectorphp:mainfrom
roxblnfk:fix/ternary-nullsafe-coalesce-mixed
Oct 6, 2026
Merged

TomasVotruba merged 1 commit into
rectorphp:mainfrom
roxblnfk:fix/ternary-nullsafe-coalesce-mixed

Conversation

@roxblnfk

@roxblnfk roxblnfk commented Oct 6, 2026

Copy link
Copy Markdown
Contributor

🔍 What was changed

TernaryToNullsafeCoalesceRector no longer rewrites a ternary to ?->… ?? $fallback when the call or property fetch returns mixed or has no declared type. Only calls whose type excludes null for sure are rewritten now.

Why?

The guard shouldSkipCoalesceFallback() relied on TypeCombinator::containsNull(), which returns false for MixedType — it only detects an explicit NullType or a union containing it. A null returned by such a call then fell through to the fallback, changing behavior:

// before: core returning null yields null
return $this->core === null
    ? $this->handler->handle($context)
    : $this->core->callAction(...); // callAction(): mixed

// after the rule: core returning null calls $this->handler, which is null here → Error
return $this->core?->callAction(...) ?? $this->handler->handle($context);

This broke InterceptorPipeline::handle() in spiral/framework (spiral/framework#1307).

Checklist

  • How was this tested:
    • Unit tests added
    • rules-tests/Php80 suite and PHPStan on the rule run locally

TypeCombinator::containsNull() is false for MixedType, so a call returning mixed (or declaring no return type) was rewritten to "?->... ?? $fallback", and a null result started falling through to the fallback.

Assisted-By: Claude Opus 5.5 <noreply@anthropic.com>

@samsonasik samsonasik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good

@TomasVotruba

Copy link
Copy Markdown
Member

LGTM

@TomasVotruba
TomasVotruba merged commit 0fd25f4 into rectorphp:main Oct 6, 2026
50 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants