RequiredPhpVersionVisitor: report native union types as requiring PHP 8.0#5872
Merged
VincentLanglet merged 1 commit intoJun 14, 2026
Merged
Conversation
… 8.0 - Emit a PHP 8.0 requirement for every `Node\UnionType` (native union type declarations such as `A|B` are a parse error on PHP 7.4 and lower). - The existing inner-type checks (DNF intersections -> 8.2, standalone `true` -> 8.2) still take precedence via the highest-version-wins `require()` logic. - Intersection types were already covered (`Node\IntersectionType` -> 8.1), so no change was needed there; the visitor's other type-syntax families (standalone null/false/true, mixed) are likewise unchanged. - Add `union type`, `union return type` and `nullable union type` cases to RequiredPhpVersionCommentTest::dataDetectedVersion. - Add `// lint >= 8.0` comments to the fixtures that newly trip the detector because they use native union types without advertising a minimum version. For nsrt fixtures that carried `declare(strict_types = 1)` on line 1, the comment is placed immediately after `<?php` (as TypeInferenceTestCase requires) and `declare` moves onto the previously-blank line 2, so existing line-sensitive assertions are preserved.
VincentLanglet
approved these changes
Jun 14, 2026
staabm
approved these changes
Jun 14, 2026
staabm
left a comment
Contributor
There was a problem hiding this comment.
We need another PR for intersection types on 8.1
Contributor
It was already supported I think, cf |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
RequiredPhpVersionVisitordetects the minimum PHP version a test fixture needs to parse, so CI can skip fixtures on older PHP versions instead of hitting hard parse errors. It already reported intersection types (PHP 8.1), DNF types (8.2) and the standalonetruetype (8.2), but it did not report native union types (A|B), which are a parse error on PHP 7.4 and lower. This change makes the visitor report a PHP 8.0 requirement for native union types.Changes
build/PHPStan/Build/RequiredPhpVersionVisitor.php: when visiting aNode\UnionType, callrequire(self::PHP_8_0, 'union types', $node). The pre-existing per-inner-type checks (intersection inside a union -> DNF -> 8.2, standalonetrue-> 8.2) still win becauserequire()keeps the highest version.tests/PHPStan/Build/RequiredPhpVersionCommentTest.php: addunion type,union return typeandnullable union type(A|null) cases asserting80000.// lint >= 8.0comments to the 26 fixtures that newly trip the detector because they use native union types in signatures without advertising a minimum PHP version (undertests/PHPStan/Analyser/data,tests/PHPStan/Analyser/nsrt, and severaltests/PHPStan/Rules/*/datadirectories).datafixtures the comment is appended to line 1 (the established pattern).nsrtfixtures the comment must immediately follow<?php(enforced byTypeInferenceTestCase). For the ones that haddeclare(strict_types = 1)on line 1,declarewas moved onto the formerly-blank line 2 so no line-sensitiveassertType()assertions shift.Node\IntersectionType-> 8.1), so the second half of the issue needed no code change. The visitor's other type-syntax families (standalonenull/false/true,mixed) were probed and are already correct.Root cause
The visitor enumerated several type-declaration syntactic features but omitted the most basic PHP 8.0 type-declaration feature: native union types. A
Node\UnionTypenode corresponds to syntax (A|B) that does not exist before PHP 8.0, so any fixture using it must be skipped on older PHP. Because the visitor never emitted a requirement for the union node itself (only for special inner types), fixtures relying solely on plain union types could slip through without a// lint >= 8.0guard and would have parse-errored on PHP 7.4 in CI.Test
RequiredPhpVersionCommentTest::testDetectedVersiongains three cases proving a native union type — in a parameter, in a return type, and the nullableA|nullform — is detected as requiring PHP 8.0. These fail without the visitor change.RequiredPhpVersionCommentTest::testFixtureHasRequiredLintCommentnow passes for the whole fixture corpus after the 26 fixtures gained their// lint >= 8.0comment; it would fail (26 fixtures) without those comments, proving the detector now catches the previously-missed syntax.NodeScopeResolverTestand the affected rule tests still pass, confirming the relocateddeclare/ appended comments did not shift any line-sensitive assertions.Fixes phpstan/phpstan#14824