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

[11.x] Update PHPStan to 2.x #53716

Draft
wants to merge 6 commits into
base: 11.x
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@
"orchestra/testbench-core": "^9.6",
"pda/pheanstalk": "^5.0.6",
"php-http/discovery": "^1.15",
"phpstan/phpstan": "^1.11.5",
"phpstan/phpstan": "^2.0",
"phpunit/phpunit": "^10.5.35|^11.3.6",
"predis/predis": "^2.3",
"resend/resend-php": "^0.10.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1873,7 +1873,7 @@ protected function normalizeCastClassResponse($key, $value)
/**
* Get all of the current attributes on the model.
*
* @return array
* @return array<string, mixed>
*/
public function getAttributes()
{
Expand Down
3 changes: 1 addition & 2 deletions src/Illuminate/Process/PendingProcess.php
Original file line number Diff line number Diff line change
Expand Up @@ -246,9 +246,8 @@ public function run(array|string|null $command = null, ?callable $output = null)
{
$this->command = $command ?: $this->command;

$process = $this->toSymfonyProcess($command);
try {
$process = $this->toSymfonyProcess($command);

if ($fake = $this->fakeFor($command = $process->getCommandline())) {
return tap($this->resolveSynchronousFake($command, $fake), function ($result) {
$this->factory->recordIfRecording($this, $result);
Expand Down
6 changes: 3 additions & 3 deletions types/Cache/Repository.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@
assertType('mixed', $cache->pull('cache', function (): int {
return 30;
}));
assertType('int', $cache->sear('cache', function (): int {
assertType('33', $cache->sear('cache', function (): int {
return 33;
}));
assertType('int', $cache->remember('cache', now(), function (): int {
assertType('36', $cache->remember('cache', now(), function (): int {
return 36;
}));
Comment on lines +24 to 26
Copy link

Choose a reason for hiding this comment

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

I would assume that a callback with int return type would result in a type called int and not 36. There seems to be a problem elsewhere.

All these type assertions should remain unchanged.

Copy link
Contributor Author

@tamiroh tamiroh Dec 22, 2024

Choose a reason for hiding this comment

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

I think that since PHPStan 2.0, types are inferred more narrowly, in this case as 36 literal type.

https://phpstan.org/writing-php-code/phpdoc-types#literals-and-constants

Copy link

Choose a reason for hiding this comment

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

I hope that's something that can be configured somewhere, since the returned type is a string with the number, so the "literal" part is misleading.

assertType('int', $cache->rememberForever('cache', function (): int {
assertType('36', $cache->rememberForever('cache', function (): int {
return 36;
}));
8 changes: 4 additions & 4 deletions types/Collections/helpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

use function PHPStan\Testing\assertType;

assertType('string', value('foo', 42));
assertType('int', value(fn () => 42));
assertType('int', value(function ($foo) {
assertType('bool', $foo);
assertType("'foo'", value('foo', 42));
assertType('42', value(fn () => 42));
assertType('42', value(function ($foo) {
assertType('true', $foo);

return 42;
}, true));
10 changes: 5 additions & 5 deletions types/Contracts/Cache/Repository.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,16 @@
}));

assertType('mixed', $cache->pull('key'));
assertType('int', $cache->pull('cache', 28));
assertType('int', $cache->pull('cache', function (): int {
assertType('28', $cache->pull('cache', 28));
assertType('30', $cache->pull('cache', function (): int {
return 30;
}));
assertType('int', $cache->sear('cache', function (): int {
assertType('33', $cache->sear('cache', function (): int {
return 33;
}));
assertType('int', $cache->remember('cache', now(), function (): int {
assertType('36', $cache->remember('cache', now(), function (): int {
return 36;
}));
assertType('int', $cache->rememberForever('cache', function (): int {
assertType('36', $cache->rememberForever('cache', function (): int {
return 36;
}));
2 changes: 1 addition & 1 deletion types/Contracts/Validation/ValidationRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use function PHPStan\Testing\assertType;

new class implements ValidationRule
$class = new class implements ValidationRule
Copy link

Choose a reason for hiding this comment

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

Suggested change
$class = new class implements ValidationRule
new class implements ValidationRule

Copy link
Contributor Author

@tamiroh tamiroh Dec 22, 2024

Choose a reason for hiding this comment

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

The instance must be assigned to some variable to avoid the following error...

 ------ ----------------------------------------------------------------------------------------------------------------------------- 
  Line   ValidationRule.php                                                                                                           
 ------ ----------------------------------------------------------------------------------------------------------------------------- 
  7      Expression "new class implements \Illuminate\Contracts\Validation\ValidationRule…" on a separate line does not do anything.  
         🪪  expr.resultUnused                                                                                                        
 ------ ----------------------------------------------------------------------------------------------------------------------------- 

Copy link

Choose a reason for hiding this comment

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

The error is valid, but the real problem is something else

Looking at the entire file, it doesn't seem like it's testing anything. The class is being instantiated, but the assertion call is inside a method that isn't being called.

I'd rather see the test being reworked so there's a point in even having it.

{
public function validate(string $attribute, mixed $value, Closure $fail): void
{
Expand Down
8 changes: 4 additions & 4 deletions types/Database/Eloquent/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,11 @@ function test(
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $query->findOr([1], callback: fn () => 42));
assertType('User', $query->findOrFail(1));
assertType('User|null', $query->find(1));
assertType('int|User', $query->findOr(1, fn () => 42));
assertType('int|User', $query->findOr(1, callback: fn () => 42));
assertType('42|User', $query->findOr(1, fn () => 42));
assertType('42|User', $query->findOr(1, callback: fn () => 42));
assertType('User|null', $query->first());
assertType('int|User', $query->firstOr(fn () => 42));
assertType('int|User', $query->firstOr(callback: fn () => 42));
assertType('42|User', $query->firstOr(fn () => 42));
assertType('42|User', $query->firstOr(callback: fn () => 42));
assertType('User', $query->firstOrNew(['id' => 1]));
assertType('User', $query->findOrNew(1));
assertType('User', $query->firstOrCreate(['id' => 1]));
Expand Down
2 changes: 1 addition & 1 deletion types/Database/Eloquent/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection);

assertType('User|null', $collection->find(1));
assertType('string|User', $collection->find(1, 'string'));
assertType("'string'|User", $collection->find(1, 'string'));
assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->find([1]));

assertType('Illuminate\Database\Eloquent\Collection<int, User>', $collection->load('string'));
Expand Down
24 changes: 12 additions & 12 deletions types/Database/Eloquent/Relations.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,16 +46,16 @@ function test(User $user, Post $post, Comment $comment, ChildUser $child): void
assertType('Illuminate\Database\Eloquent\Collection<int, Illuminate\Types\Relations\Role>', $user->roles()->findMany([1, 2, 3]));
assertType('Illuminate\Database\Eloquent\Collection<int, Illuminate\Types\Relations\Role>', $user->roles()->findOrNew([1]));
assertType('Illuminate\Database\Eloquent\Collection<int, Illuminate\Types\Relations\Role>', $user->roles()->findOrFail([1]));
assertType('Illuminate\Database\Eloquent\Collection<int, Illuminate\Types\Relations\Role>|int', $user->roles()->findOr([1], fn () => 42));
assertType('Illuminate\Database\Eloquent\Collection<int, Illuminate\Types\Relations\Role>|int', $user->roles()->findOr([1], callback: fn () => 42));
assertType('42|Illuminate\Database\Eloquent\Collection<int, Illuminate\Types\Relations\Role>', $user->roles()->findOr([1], fn () => 42));
assertType('42|Illuminate\Database\Eloquent\Collection<int, Illuminate\Types\Relations\Role>', $user->roles()->findOr([1], callback: fn () => 42));
assertType('Illuminate\Types\Relations\Role', $user->roles()->findOrNew(1));
assertType('Illuminate\Types\Relations\Role', $user->roles()->findOrFail(1));
assertType('Illuminate\Types\Relations\Role|null', $user->roles()->find(1));
assertType('Illuminate\Types\Relations\Role|int', $user->roles()->findOr(1, fn () => 42));
assertType('Illuminate\Types\Relations\Role|int', $user->roles()->findOr(1, callback: fn () => 42));
assertType('42|Illuminate\Types\Relations\Role', $user->roles()->findOr(1, fn () => 42));
assertType('42|Illuminate\Types\Relations\Role', $user->roles()->findOr(1, callback: fn () => 42));
assertType('Illuminate\Types\Relations\Role|null', $user->roles()->first());
assertType('Illuminate\Types\Relations\Role|int', $user->roles()->firstOr(fn () => 42));
assertType('Illuminate\Types\Relations\Role|int', $user->roles()->firstOr(callback: fn () => 42));
assertType('42|Illuminate\Types\Relations\Role', $user->roles()->firstOr(fn () => 42));
assertType('42|Illuminate\Types\Relations\Role', $user->roles()->firstOr(callback: fn () => 42));
assertType('Illuminate\Types\Relations\Role|null', $user->roles()->firstWhere('foo'));
assertType('Illuminate\Types\Relations\Role', $user->roles()->firstOrNew());
assertType('Illuminate\Types\Relations\Role', $user->roles()->firstOrFail());
Expand All @@ -81,14 +81,14 @@ function test(User $user, Post $post, Comment $comment, ChildUser $child): void
assertType('Illuminate\Database\Eloquent\Relations\HasOneThrough<Illuminate\Types\Relations\Car, Illuminate\Types\Relations\Mechanic, Illuminate\Types\Relations\User>', $user->car());
assertType('Illuminate\Types\Relations\Car|null', $user->car()->getResults());
assertType('Illuminate\Database\Eloquent\Collection<int, Illuminate\Types\Relations\Car>', $user->car()->find([1]));
assertType('Illuminate\Database\Eloquent\Collection<int, Illuminate\Types\Relations\Car>|int', $user->car()->findOr([1], fn () => 42));
assertType('Illuminate\Database\Eloquent\Collection<int, Illuminate\Types\Relations\Car>|int', $user->car()->findOr([1], callback: fn () => 42));
assertType('42|Illuminate\Database\Eloquent\Collection<int, Illuminate\Types\Relations\Car>', $user->car()->findOr([1], fn () => 42));
assertType('42|Illuminate\Database\Eloquent\Collection<int, Illuminate\Types\Relations\Car>', $user->car()->findOr([1], callback: fn () => 42));
assertType('Illuminate\Types\Relations\Car|null', $user->car()->find(1));
assertType('Illuminate\Types\Relations\Car|int', $user->car()->findOr(1, fn () => 42));
assertType('Illuminate\Types\Relations\Car|int', $user->car()->findOr(1, callback: fn () => 42));
assertType('42|Illuminate\Types\Relations\Car', $user->car()->findOr(1, fn () => 42));
assertType('42|Illuminate\Types\Relations\Car', $user->car()->findOr(1, callback: fn () => 42));
assertType('Illuminate\Types\Relations\Car|null', $user->car()->first());
assertType('Illuminate\Types\Relations\Car|int', $user->car()->firstOr(fn () => 42));
assertType('Illuminate\Types\Relations\Car|int', $user->car()->firstOr(callback: fn () => 42));
assertType('42|Illuminate\Types\Relations\Car', $user->car()->firstOr(fn () => 42));
assertType('42|Illuminate\Types\Relations\Car', $user->car()->firstOr(callback: fn () => 42));
assertType('Illuminate\Support\LazyCollection<int, Illuminate\Types\Relations\Car>', $user->car()->lazy());
assertType('Illuminate\Support\LazyCollection<int, Illuminate\Types\Relations\Car>', $user->car()->lazyById());
assertType('Illuminate\Support\LazyCollection<int, Illuminate\Types\Relations\Car>', $user->car()->cursor());
Expand Down
4 changes: 2 additions & 2 deletions types/Database/Query/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ function test(Builder $query, EloquentBuilder $userQuery): void
{
assertType('object|null', $query->first());
assertType('object|null', $query->find(1));
assertType('int|object', $query->findOr(1, fn () => 42));
assertType('int|object', $query->findOr(1, callback: fn () => 42));
assertType('42|object', $query->findOr(1, fn () => 42));
assertType('42|object', $query->findOr(1, callback: fn () => 42));
assertType('Illuminate\Database\Query\Builder', $query->selectSub($userQuery, 'alias'));
assertType('Illuminate\Database\Query\Builder', $query->fromSub($userQuery, 'alias'));
assertType('Illuminate\Database\Query\Builder', $query->from($userQuery, 'alias'));
Expand Down
6 changes: 3 additions & 3 deletions types/Foundation/Configuration/Middleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
$middleware = new Middleware();

$middleware->convertEmptyStringsToNull(except: [
fn ($request) => $request->has('skip-all-1'),
fn ($request) => $request->has('skip-all-2'),
fn (Request $request): bool => $request->has('skip-all-1'),
fn (Request $request): bool => $request->has('skip-all-2'),
]);

$middleware->trimStrings(except: [
'aaa',
fn ($request) => $request->has('skip-all'),
fn (Request $request): bool => $request->has('skip-all'),
]);

$middleware->trustProxies(at: '*');
Expand Down
6 changes: 3 additions & 3 deletions types/Foundation/Helpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@
assertType('Illuminate\Log\LogManager', logs());
assertType('Psr\Log\LoggerInterface', logs('foo'));

assertType('int|null', rescue(fn () => 123));
assertType('int', rescue(fn () => 123, 345));
assertType('int', rescue(fn () => 123, fn () => 345));
assertType('123|null', rescue(fn () => 123));
assertType('123|345', rescue(fn () => 123, 345));
assertType('123|345', rescue(fn () => 123, fn () => 345));

assertType('Illuminate\Routing\Redirector', redirect());
assertType('Illuminate\Http\RedirectResponse', redirect('foo'));
Expand Down
26 changes: 13 additions & 13 deletions types/Support/Arr.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,20 @@
/** @var iterable<int, User> $iterable */
$iterable = [];
/** @var Traversable<int, User> $traversable */
$traversable = [];
$traversable = new ArrayIterator([new User]);

assertType('User|null', Arr::first($array));
assertType('User|null', Arr::first($array, function ($user) {
assertType('User', $user);

return true;
}));
assertType('string|User', Arr::first($array, function ($user) {
assertType("'string'|User", Arr::first($array, function ($user) {
assertType('User', $user);

return false;
}, 'string'));
assertType('string|User', Arr::first($array, null, function () {
assertType("'string'|User", Arr::first($array, null, function () {
return 'string';
}));

Expand All @@ -31,12 +31,12 @@

return true;
}));
assertType('string|User', Arr::first($iterable, function ($user) {
assertType("'string'|User", Arr::first($iterable, function ($user) {
assertType('User', $user);

return false;
}, 'string'));
assertType('string|User', Arr::first($iterable, null, function () {
assertType("'string'|User", Arr::first($iterable, null, function () {
return 'string';
}));

Expand All @@ -46,12 +46,12 @@

return true;
}));
assertType('string|User', Arr::first($traversable, function ($user) {
assertType("'string'|User", Arr::first($traversable, function ($user) {
assertType('User', $user);

return false;
}, 'string'));
assertType('string|User', Arr::first($traversable, null, function () {
assertType("'string'|User", Arr::first($traversable, null, function () {
return 'string';
}));

Expand All @@ -61,12 +61,12 @@

return true;
}));
assertType('string|User', Arr::last($array, function ($user) {
assertType("'string'|User", Arr::last($array, function ($user) {
assertType('User', $user);

return false;
}, 'string'));
assertType('string|User', Arr::last($array, null, function () {
assertType("'string'|User", Arr::last($array, null, function () {
return 'string';
}));

Expand All @@ -76,12 +76,12 @@

return true;
}));
assertType('string|User', Arr::last($iterable, function ($user) {
assertType("'string'|User", Arr::last($iterable, function ($user) {
assertType('User', $user);

return false;
}, 'string'));
assertType('string|User', Arr::last($iterable, null, function () {
assertType("'string'|User", Arr::last($iterable, null, function () {
return 'string';
}));

Expand All @@ -91,11 +91,11 @@

return true;
}));
assertType('string|User', Arr::last($traversable, function ($user) {
assertType("'string'|User", Arr::last($traversable, function ($user) {
assertType('User', $user);

return false;
}, 'string'));
assertType('string|User', Arr::last($traversable, null, function () {
assertType("'string'|User", Arr::last($traversable, null, function () {
return 'string';
}));
Loading