-
Notifications
You must be signed in to change notification settings - Fork 134
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Ensure that simple union types like A|null
yield a nullable ReflectionNamedType
#902
Ensure that simple union types like A|null
yield a nullable ReflectionNamedType
#902
Conversation
This makes a few tests fail, because of obvious translation details:
I fear this inconsistency between |
TBH, I really wish this was the complete opposite, and that nullable |
Ok, looking at this from the perspective of Roave/BackwardCompatibilityCheck#324, and I think it would be simpler to never have a mix of union and nullable type: only ever have union types, then change this behavior in the @kukulich WDYT? |
@Ocramius Yes, I don't like |
I'm currently working on:
|
…tionNamedType` Fixes #901 ## Context Currently, when running reflection on an `A|null` type, BetterReflection produces a `Roave\BetterReflection\Reflection\ReflectionUnionType`: ```php var_dump( get_class( (new DefaultReflector(new StringSourceLocator( <<<'PHP' <?php interface A {} final class AClass { private A|null $typed; } PHP , (new BetterReflection())->astLocator() ))) ->reflectClass('AClass') ->getProperty('typed') ->getType() ) ); ``` produces ``` string(53) "Roave\BetterReflection\Reflection\ReflectionUnionType" ``` In PHP-SRC, this behavior is different: https://3v4l.org/gMA4T#v8.1rc3 ```php <?php interface A {} interface B {} class Implementation { function foo(A|null $param) { throw new Exception(); } function bar(A|B|null $param) { throw new Exception(); } } var_dump((new ReflectionParameter([Implementation::class, 'foo'], 0))->getType()); var_dump((new ReflectionParameter([Implementation::class, 'bar'], 0))->getType()); ``` produces: ``` object(ReflectionNamedType)#2 (0) { } object(ReflectionUnionType)#1 (0) { } ``` This means that a `UnionType` AST node composed of just `null` plus another type should be converted into a `ReflectionNamedType`, for the sake of compatibility with upstream (this patch does that). This is ugly, but will (for now) avoid some bad issues in downstream handling (presently blocking Roave/BackwardCompatibilityCheck#324 )
…justing expectations in stubber tests
…on types When an union type of `T|null` or `?T` is met, BetterReflection will (from now on) keep a `ReflectionUnionType` internally, while exposing a `ReflectionNamedType` with `ReflectionNamedType#allowsNull() === true` only at adapter level. While this is a BC break, it leads to a much cleaner API around handling `null` types, and inspecting types for type analysis. Ref: #902 (comment) Ref: Roave/BackwardCompatibilityCheck#324
f86963a
to
14d3d5a
Compare
@kukulich I've now rewritten the patch:
|
…on suffices This test was breaking because `Roave\BetterReflection\Reflection\ReflectionUnionType::isBuiltin()` was being called: such a method does not exist though, because it only exists on `ReflectionNamedType`. That's because the test is designed without type inheritance in mind: removing the assertions is sufficient here.
…P 8.1 through the adapter layer (for compatibility) Nullable types in BetterReflection are represented as union types: using the adapter layer as part of the test, even if just for a small string cast, helps us avoiding custom code here.
b4c0c02
to
33a5645
Compare
This change strictly depends on Roave/BetterReflection#902, and once that's merged, new `infection/infection` mutations should appear, showing us code that can safely be removed.
LGTM. Just one idea: Shouldn't we normalize/sort types in |
@kukulich probably, but my batteries for this are depleted for today :D Core seems to be doing it: https://3v4l.org/jcq9S |
Thanks for the review, @kukulich! |
I know that phpcsfixer has a rule for that, here it is: https://github.com/FriendsOfPHP/PHP-CS-Fixer/blob/master/doc/rules/phpdoc/phpdoc_types_order.rst |
This change strictly depends on Roave/BetterReflection#902, and once that's merged, new `infection/infection` mutations should appear, showing us code that can safely be removed.
Fixes #901
Context
Currently, when running reflection on an
A|null
type, BetterReflection produces aRoave\BetterReflection\Reflection\ReflectionUnionType
:produces
In PHP-SRC, this behavior is different: https://3v4l.org/gMA4T#v8.1rc3
produces:
This means that a
UnionType
AST node composed of justnull
plus another type should be converted intoa
ReflectionNamedType
, for the sake of compatibility with upstream (this patch does that).This is ugly, but will (for now) avoid some bad issues in downstream handling (presently blocking Roave/BackwardCompatibilityCheck#324 )