Skip to content

[DeadCode] Keep generic @var/@return self<...> narrowing annotations#8147

Merged
TomasVotruba merged 1 commit into
mainfrom
fix-generic-var-return-self-annotation-9793
Jul 5, 2026
Merged

[DeadCode] Keep generic @var/@return self<...> narrowing annotations#8147
TomasVotruba merged 1 commit into
mainfrom
fix-generic-var-return-self-annotation-9793

Conversation

@TomasVotruba

@TomasVotruba TomasVotruba commented Jul 5, 2026

Copy link
Copy Markdown
Member

Fixes rectorphp/rector#9793

Two DeadCode rules stripped valid generic type annotations that narrow the return type of a generic class via template specialization. The @var self<...> / @return self<...> add information that the native self type / new self() cannot express, so they must be kept.

RemoveNonExistingVarAnnotationRector

An empty-name @var before return new self(...) was removed, because New_ returns were explicitly excluded (a plain @var array<...> on new stdClass really is unwanted). Now it is kept when the @var is a generic type over the instantiated class.

 final class Result
 {
     public static function success(mixed $value = null): self
     {
         /** @var self<TSuccessValue, never> */
         return new self(true, value: $value);
     }
 }

Before: the docblock was removed. After: kept.

A mismatched annotation such as /** @var array<string, string> */ return new stdClass; is still removed (base type array != stdClass).

RemoveDuplicatedReturnSelfDocblockRector

@return self<...> maps to a GenericObjectType (subclass of ObjectType) whose class name equals the current class, so it was treated as a duplicate of the native self return type and removed. Generic doc types are now skipped.

 final class Result
 {
     /**
      * @return self<TSuccessValue, never>
      */
     public function success(): self
     {
         return $this;
     }
 }

Before: the docblock was removed. After: kept. Bare @return self / @return $this / @return static are still removed as before.

Tests

New skip fixtures for both rules covering the generic case.

@TomasVotruba TomasVotruba merged commit 909090d into main Jul 5, 2026
65 checks passed
@TomasVotruba

Copy link
Copy Markdown
Member Author

LGTM 👍

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.

Incorrect behavior of RemoveDuplicatedReturnSelfDocblockRector, RemoveNonExistingVarAnnotationRector

1 participant