Skip to content
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

PHP 8.0 and PHP 8.1 support, BetterReflection 5.x upgrade #324

Merged
merged 13 commits into from
Dec 6, 2021

Conversation

Ocramius
Copy link
Member

@Ocramius Ocramius commented Nov 6, 2021

This patch brings in PHP 8.0 and 8.1 support through the massive work done by @kukulich on
roave/better-reflection over the past few months.

The upgrade is mostly smooth, but we have some rough edges with:

Fixes #283

composer.json Show resolved Hide resolved
composer.json Show resolved Hide resolved
src/CompareApi.php Show resolved Hide resolved
src/DetectChanges/Variance/TypeIsContravariant.php Outdated Show resolved Hide resolved
src/DetectChanges/Variance/TypeIsContravariant.php Outdated Show resolved Hide resolved
src/DetectChanges/Variance/TypeIsCovariant.php Outdated Show resolved Hide resolved
src/DetectChanges/Variance/TypeIsCovariant.php Outdated Show resolved Hide resolved
@Ocramius
Copy link
Member Author

Ocramius commented Nov 6, 2021

Test failures are caused by Psl\Iter\Iterator::current() not having : mixed declared:

Deprecated: Return type of Psl\Iter\Iterator::current() should either be compatible with Iterator::current(): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /github/workspace/vendor/azjezz/psl/src/Psl/Iter/Iterator.php on line 90

Problem is: azjezz/psl:1.9.0 has php:~8.0.0 || ~8.1.0 support, while the current azjezz/psl:2.0.0 has php:~8.1.0 support.

@azjezz do you think we could fix that in azjezz/psl:1.9.1 perhaps?

@Ocramius Ocramius mentioned this pull request Nov 6, 2021
@Ocramius Ocramius changed the title PHP 8 support and BetterReflection 5.x upgrade PHP 8.0 and PHP 8.1 support, BetterReflection 5.x upgrade Nov 6, 2021
@azjezz
Copy link
Contributor

azjezz commented Nov 6, 2021

1.9.1 is on the way 👍

done https://github.com/azjezz/psl/releases/tag/1.9.1

@Ocramius
Copy link
Member Author

Ocramius commented Nov 6, 2021

Whoa, that was fast, @azjezz and @kukulich!

I'll work on this some more tonight, trying out both patches ASAP! 💪

@Ocramius
Copy link
Member Author

Ocramius commented Nov 6, 2021

Interesting, PHPUnit with lowest dependencies still fails 🤔

EDIT:

Deprecated: Return type of Symfony\Component\Process\Process::getIterator($flags = 0) should either be compatible with IteratorAggregate::getIterator(): Traversable, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /github/workspace/vendor/symfony/process/Process.php on line 612

Call Stack:
    0.0001     389552   1. {main}() /github/workspace/bin/roave-backward-compatibility-check:0
    0.0006     464800   2. require_once('/github/workspace/bin/roave-backward"

I'll add a "conflict": {"symfony/process": "<5.3.7"}

@Ocramius
Copy link
Member Author

Ocramius commented Nov 6, 2021

Funny, lowest dependency runs now run forever:

Selection_824

This patch brings in PHP 8.0 and 8.1 support through the massive work done by @kukulich on
`roave/better-reflection` over the past few months.

The upgrade is mostly smooth, but we have some rough edges with:

 * [x] `TypeIsCovariant`, which needs `ReflectionType`s as well as `Reflector`s
 * [x] `TypeIsContravariant`, which needs `ReflectionType`s as well as `Reflector`s
 * [ ] `ReturnTypeCovarianceChanged` uses hacky reflection to get a `Reflector` from a `ReflectionFunctionAbstract` (internal state!)
 * [ ] `ParameterTypeContravarianceChanged` uses hacky reflection to get a `Reflector` from a `ReflectionFunctionAbstract` (internal state!)
 * [ ] we miss tests for covariance/contravariance with `ReflectionUnionType` and `ReflectionIntersectionType` (`infection/infection` will highlight that)
Sadly, `symfony/symfony` declared `php:>=7.1` compatibility many moons ago: that is generally
technical lack of vision and responsibility on their end, but that ship has sailed.

This means that a `composer update` can and **will** install a dependency graph that is incompatible
with your system's dependencies.

This change prevents installation of `symfony/process` in versions too archaic to actually function.

As a side-effect, `vimeo/psalm` was also upgraded to its latest and greatest.

Ref: https://github.com/vimeo/psalm/releases/tag/4.12.0
@Ocramius Ocramius force-pushed the feature/php-8-compatibility branch from d52e4f5 to cfc9528 Compare December 5, 2021 02:13
…Reflection@1f7a13b

This also handles the upcoming BC break of Roave/BetterReflection#900

Some big changes:

 * `PropertyDocumentedTypeChanged` no longer exists: we use only `PropertyTypeChanged` for now. This
   is a step backwards, but it is needed to prevent issues around docblocks being too advanced for
   this library to parse them, for now.
    * see CuyZ/Valinor#6
    * see https://github.com/phpstan/phpstan-src/tree/447cd102d946a2d9883ac82793195275f54296a9/src/Type
    * see https://github.com/vimeo/psalm/tree/f1d47cc662500589e200a978e3af85488a5236cf/src/Psalm/Type
    * see https://github.com/phpDocumentor/ReflectionDocBlock/blob/622548b623e81ca6d78b721c5e029f4ce664f170/src/DocBlock/Tags/Param.php#L35
    * see https://github.com/phpstan/phpdoc-parser/blob/d639142cf83e91a07b4862217a6f8aa65ee10d08/tests/PHPStan/Parser/TypeParserTest.php#L64
    * /cc @tomasnorre this sadly effectively reverts #340 - it
      is too much effort to dive into further advanced types :-(
 * `PropertyTypeChanged` only expects the property to be both covariant and contravariant: if not,
   then a BC break was introduced (this re-uses some internal variance checks, simplifying code
   substantially)
 * usage of `ReflectionFunctionAbstract` is no longer present in the library: always using an union
   of `ReflectionMethod|ReflectionFunction` instead (as in `roave/better-reflection:^5`)
 * `FunctionName` is now `@internal`, since it's only used for internal rendering purposes
…-phpunit`

This change ensures that we don't use `@internal` symbols in `src/` (too dangerous,
for long-term usage), and makes the type checking much stricter, thanks to `psalm/plugin-phpunit`.

Since `vimeo/psalm` has been upgraded, and vimeo/psalm#2772
no longer applies, we can also remove a lot of manually written code that was safe
to clean up.
Ocramius added a commit to Roave/BetterReflection that referenced this pull request Dec 5, 2021
…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 )
Ocramius added a commit to Roave/BetterReflection that referenced this pull request Dec 5, 2021
…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 )
Ocramius added a commit to Roave/BetterReflection that referenced this pull request Dec 5, 2021
…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
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.
… necessary with union types

As per previous commit, `roave/better-reflection` has been upgraded so that nullable types are
always represented as union types: this simplifies the logic massively, because, except for
some edge cases, all nullability problems become a set intersection problem, rather than some
ad-hoc conditionals.

This further demonstrates that nullable types as union types is really valuable.

Ref: https://twitter.com/Ocramius/status/1467392834558992390
@Ocramius Ocramius requested a review from asgrim December 5, 2021 13:06
@Ocramius Ocramius removed the WIP label Dec 5, 2021
@Ocramius
Copy link
Member Author

Ocramius commented Dec 5, 2021

@WyriHaximus since this is your favorite overall github project, can I have your review too, please? :D

@WyriHaximus
Copy link

@Ocramius Sure, it seems that your CI is failing 😜 . Just kidding, let me go over the thing :)

@Ocramius
Copy link
Member Author

Ocramius commented Dec 5, 2021

Haha, yeah, CI is failing because the 6.0.x branch contains BC breaks (compared to the last 5.0.x release), so that bit is kinda normal

Copy link

@WyriHaximus WyriHaximus left a comment

Choose a reason for hiding this comment

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

composer.json Show resolved Hide resolved
src/Changes.php Show resolved Hide resolved
@WyriHaximus
Copy link

WyriHaximus commented Dec 5, 2021

@Ocramius Ow yeah, I didn't even look at that. Just wanted to joke about it :P. Jokes aside, this is one reason why I want to use this package more: Make it comment on PR's about what BC would be introduced where.

@Ocramius Ocramius self-assigned this Dec 6, 2021
@Ocramius
Copy link
Member Author

Ocramius commented Dec 6, 2021

🚢

@Ocramius Ocramius merged commit 565f6e6 into 6.0.x Dec 6, 2021
@Ocramius Ocramius deleted the feature/php-8-compatibility branch December 6, 2021 03:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

PHP 8 support
4 participants