Skip to content

[TypeDeclaration] Drop AstResolver from NarrowObjectReturnTypeRector parent check#8100

Merged
TomasVotruba merged 1 commit into
mainfrom
drop-astresolver-narrow-return
Jun 28, 2026
Merged

[TypeDeclaration] Drop AstResolver from NarrowObjectReturnTypeRector parent check#8100
TomasVotruba merged 1 commit into
mainfrom
drop-astresolver-narrow-return

Conversation

@TomasVotruba

Copy link
Copy Markdown
Member

What

NarrowObjectReturnTypeRector::isNarrowingValidFromParent() resolved each ancestor's method into a full AST (AstResolver->resolveClassMethod()) only to read two things:

  1. the parent's native return type (must be a single bare class name), and
  2. whether the parent's @return is a generic type (e.g. Collection<int, Foo>), which blocks narrowing.

Both are available from PHPStan's ExtendedMethodReflection without re-parsing the source file:

$parametersAcceptor = ParametersAcceptorSelector::combineAcceptors(
    $ancestor->getNativeMethod($methodName)->getVariants()
);

$parentNativeReturnType = $parametersAcceptor->getNativeReturnType();   // native return
$parametersAcceptor->getReturnType();                                   // phpdoc-merged return
  • getNativeReturnType() → replaces the Identifier/FullyQualified node check. We keep only ObjectType (single bare class); object-keyword, union, nullable, scalar all map to non-ObjectType and are skipped exactly as before.
  • getReturnType() instanceof GenericObjectType → replaces reading the parent node's docblock via PhpDocInfoFactory. PHPStan resolves @return Collection<int, Foo> to a GenericObjectType, and @return T (template) to a non-generic type — matching the previous behaviour.

Why

AstResolver re-parses the declaring file of every ancestor on every matching method. The data needed here is pure type metadata that reflection already holds, so the parse was overhead. The earlier "docblock = AST-only" assumption only holds for raw docblock text; the semantic generic-type check is fully available via getReturnType().

Tests

All existing fixtures pass unchanged, including the parent-path cases (narrow_with_generic_parent, narrow_parent_has_specific_return_type, narrow_from_abstract_class, narrow_from_parent_to_child). vendor/bin/phpunit rules-tests/TypeDeclaration/Rector/ClassMethod/NarrowObjectReturnTypeRector → 14/14 green. ECS + PHPStan level 8 clean.

…parent check

The parent-method lookup only needs the parent's native return type and
whether its @return is a generic type. PHPStan's ExtendedMethodReflection
exposes both via getNativeReturnType() and getReturnType(), so resolve the
parent method through reflection instead of re-parsing its source file
with AstResolver.
@TomasVotruba TomasVotruba merged commit 069bb91 into main Jun 28, 2026
65 checks passed
@TomasVotruba TomasVotruba deleted the drop-astresolver-narrow-return branch June 28, 2026 20:59
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.

1 participant