Skip to content

Validate @phpstan-sealed types are subtypes of the annotated type - #6425

Open
klimick wants to merge 5 commits into
phpstan:2.2.xfrom
klimick:validate-sealed-subtypes
Open

Validate @phpstan-sealed types are subtypes of the annotated type#6425
klimick wants to merge 5 commits into
phpstan:2.2.xfrom
klimick:validate-sealed-subtypes

Conversation

@klimick

@klimick klimick commented Sep 12, 2026

Copy link
Copy Markdown

Validate that every type listed in @phpstan-sealed is a subtype of the annotated class or interface.
Invalid entries are reported with the sealed.notSubtype error identifier.

Add regression coverage for valid and invalid enum, interface, abstract-class, and final-class sealed subtype declarations, including the reflexive case.

Closes #15204

@VincentLanglet

Copy link
Copy Markdown
Contributor

@klimick

klimick commented Sep 12, 2026

Copy link
Copy Markdown
Author

You're right, my original constraint was too strict. I agree that a non-final class can represent an open branch of the hierarchy, even if it is not itself a subtype of the annotated type.

I relaxed the validation accordingly: PHPStan now reports an error only when a listed final class or enum is not a subtype of the annotated type. I also added regression tests covering both the valid non-final branch and the invalid final-class case.

I also agree that this should be introduced in bleeding edge, and added the check there.

$sealedTypeReflection = $this->reflectionProvider->getClass($class);

if (
BleedingEdgeToggle::isBleedingEdge()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

If you look at conf/bleedingEdge.neon, you can see that we use dedicated featureToggle for this "new feature".

Juste add one toggle in conf/config.neon, with a default value of false, then enable in bleedingEdge.neon.

Inject the param here and use it.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

So that's how bleeding edge works...
Fixed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants