Skip to content
Merged
2 changes: 2 additions & 0 deletions src/Reflection/ParametersAcceptorSelector.php
Original file line number Diff line number Diff line change
Expand Up @@ -674,7 +674,7 @@
$winningAcceptors[] = $acceptableAcceptor;
$winningCertainty = $isSuperType;
} else {
$comparison = $winningCertainty->compareTo($isSuperType);

Check failure on line 677 in src/Reflection/ParametersAcceptorSelector.php

View workflow job for this annotation

GitHub Actions / PHPStan (7.4, ubuntu-latest)

PHPDoc tag `@return` with type ($acceptors is array<PHPStan\Reflection\Callables\CallableParametersAcceptor> ? PHPStan\Reflection\Callables\CallableParametersAcceptor : PHPStan\Reflection\ExtendedParametersAcceptor) is not subtype of native type PHPStan\Reflection\ExtendedParametersAcceptor.

Check failure on line 677 in src/Reflection/ParametersAcceptorSelector.php

View workflow job for this annotation

GitHub Actions / PHPStan (7.4, windows-latest)

PHPDoc tag `@return` with type ($acceptors is array<PHPStan\Reflection\Callables\CallableParametersAcceptor> ? PHPStan\Reflection\Callables\CallableParametersAcceptor : PHPStan\Reflection\ExtendedParametersAcceptor) is not subtype of native type PHPStan\Reflection\ExtendedParametersAcceptor.
if ($comparison === $isSuperType) {
$winningAcceptors = [$acceptableAcceptor];
$winningCertainty = $isSuperType;
Expand All @@ -693,8 +693,10 @@

/**
* @param ParametersAcceptor[] $acceptors
*
* @return ($acceptors is array<CallableParametersAcceptor> ? CallableParametersAcceptor : ExtendedParametersAcceptor)
*/
public static function combineAcceptors(array $acceptors): ExtendedParametersAcceptor

Check failure on line 699 in src/Reflection/ParametersAcceptorSelector.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.3, ubuntu-latest)

PHPDoc tag `@return` with type ($acceptors is array<PHPStan\Reflection\Callables\CallableParametersAcceptor> ? PHPStan\Reflection\Callables\CallableParametersAcceptor : PHPStan\Reflection\ExtendedParametersAcceptor) is not subtype of native type PHPStan\Reflection\ExtendedParametersAcceptor.

Check failure on line 699 in src/Reflection/ParametersAcceptorSelector.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.2, ubuntu-latest)

PHPDoc tag `@return` with type ($acceptors is array<PHPStan\Reflection\Callables\CallableParametersAcceptor> ? PHPStan\Reflection\Callables\CallableParametersAcceptor : PHPStan\Reflection\ExtendedParametersAcceptor) is not subtype of native type PHPStan\Reflection\ExtendedParametersAcceptor.

Check failure on line 699 in src/Reflection/ParametersAcceptorSelector.php

View workflow job for this annotation

GitHub Actions / PHPStan with result cache (8.2)

PHPDoc tag `@return` with type ($acceptors is array<PHPStan\Reflection\Callables\CallableParametersAcceptor> ? PHPStan\Reflection\Callables\CallableParametersAcceptor : PHPStan\Reflection\ExtendedParametersAcceptor) is not subtype of native type PHPStan\Reflection\ExtendedParametersAcceptor.

Check failure on line 699 in src/Reflection/ParametersAcceptorSelector.php

View workflow job for this annotation

GitHub Actions / PHPStan with result cache (8.5)

PHPDoc tag `@return` with type ($acceptors is array<PHPStan\Reflection\Callables\CallableParametersAcceptor> ? PHPStan\Reflection\Callables\CallableParametersAcceptor : PHPStan\Reflection\ExtendedParametersAcceptor) is not subtype of native type PHPStan\Reflection\ExtendedParametersAcceptor.

Check failure on line 699 in src/Reflection/ParametersAcceptorSelector.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.5, ubuntu-latest)

PHPDoc tag `@return` with type ($acceptors is array<PHPStan\Reflection\Callables\CallableParametersAcceptor> ? PHPStan\Reflection\Callables\CallableParametersAcceptor : PHPStan\Reflection\ExtendedParametersAcceptor) is not subtype of native type PHPStan\Reflection\ExtendedParametersAcceptor.

Check failure on line 699 in src/Reflection/ParametersAcceptorSelector.php

View workflow job for this annotation

GitHub Actions / PHPStan with result cache (8.3)

PHPDoc tag `@return` with type ($acceptors is array<PHPStan\Reflection\Callables\CallableParametersAcceptor> ? PHPStan\Reflection\Callables\CallableParametersAcceptor : PHPStan\Reflection\ExtendedParametersAcceptor) is not subtype of native type PHPStan\Reflection\ExtendedParametersAcceptor.

Check failure on line 699 in src/Reflection/ParametersAcceptorSelector.php

View workflow job for this annotation

GitHub Actions / PHPStan with result cache (8.4)

PHPDoc tag `@return` with type ($acceptors is array<PHPStan\Reflection\Callables\CallableParametersAcceptor> ? PHPStan\Reflection\Callables\CallableParametersAcceptor : PHPStan\Reflection\ExtendedParametersAcceptor) is not subtype of native type PHPStan\Reflection\ExtendedParametersAcceptor.

Check failure on line 699 in src/Reflection/ParametersAcceptorSelector.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.4, ubuntu-latest)

PHPDoc tag `@return` with type ($acceptors is array<PHPStan\Reflection\Callables\CallableParametersAcceptor> ? PHPStan\Reflection\Callables\CallableParametersAcceptor : PHPStan\Reflection\ExtendedParametersAcceptor) is not subtype of native type PHPStan\Reflection\ExtendedParametersAcceptor.

Check failure on line 699 in src/Reflection/ParametersAcceptorSelector.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.1, ubuntu-latest)

PHPDoc tag `@return` with type ($acceptors is array<PHPStan\Reflection\Callables\CallableParametersAcceptor> ? PHPStan\Reflection\Callables\CallableParametersAcceptor : PHPStan\Reflection\ExtendedParametersAcceptor) is not subtype of native type PHPStan\Reflection\ExtendedParametersAcceptor.

Check failure on line 699 in src/Reflection/ParametersAcceptorSelector.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.0, ubuntu-latest)

PHPDoc tag `@return` with type ($acceptors is array<PHPStan\Reflection\Callables\CallableParametersAcceptor> ? PHPStan\Reflection\Callables\CallableParametersAcceptor : PHPStan\Reflection\ExtendedParametersAcceptor) is not subtype of native type PHPStan\Reflection\ExtendedParametersAcceptor.

Check failure on line 699 in src/Reflection/ParametersAcceptorSelector.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.4, windows-latest)

PHPDoc tag `@return` with type ($acceptors is array<PHPStan\Reflection\Callables\CallableParametersAcceptor> ? PHPStan\Reflection\Callables\CallableParametersAcceptor : PHPStan\Reflection\ExtendedParametersAcceptor) is not subtype of native type PHPStan\Reflection\ExtendedParametersAcceptor.

Check failure on line 699 in src/Reflection/ParametersAcceptorSelector.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.2, windows-latest)

PHPDoc tag `@return` with type ($acceptors is array<PHPStan\Reflection\Callables\CallableParametersAcceptor> ? PHPStan\Reflection\Callables\CallableParametersAcceptor : PHPStan\Reflection\ExtendedParametersAcceptor) is not subtype of native type PHPStan\Reflection\ExtendedParametersAcceptor.

Check failure on line 699 in src/Reflection/ParametersAcceptorSelector.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.3, windows-latest)

PHPDoc tag `@return` with type ($acceptors is array<PHPStan\Reflection\Callables\CallableParametersAcceptor> ? PHPStan\Reflection\Callables\CallableParametersAcceptor : PHPStan\Reflection\ExtendedParametersAcceptor) is not subtype of native type PHPStan\Reflection\ExtendedParametersAcceptor.

Check failure on line 699 in src/Reflection/ParametersAcceptorSelector.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.5, windows-latest)

PHPDoc tag `@return` with type ($acceptors is array<PHPStan\Reflection\Callables\CallableParametersAcceptor> ? PHPStan\Reflection\Callables\CallableParametersAcceptor : PHPStan\Reflection\ExtendedParametersAcceptor) is not subtype of native type PHPStan\Reflection\ExtendedParametersAcceptor.

Check failure on line 699 in src/Reflection/ParametersAcceptorSelector.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.0, windows-latest)

PHPDoc tag `@return` with type ($acceptors is array<PHPStan\Reflection\Callables\CallableParametersAcceptor> ? PHPStan\Reflection\Callables\CallableParametersAcceptor : PHPStan\Reflection\ExtendedParametersAcceptor) is not subtype of native type PHPStan\Reflection\ExtendedParametersAcceptor.

Check failure on line 699 in src/Reflection/ParametersAcceptorSelector.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.1, windows-latest)

PHPDoc tag `@return` with type ($acceptors is array<PHPStan\Reflection\Callables\CallableParametersAcceptor> ? PHPStan\Reflection\Callables\CallableParametersAcceptor : PHPStan\Reflection\ExtendedParametersAcceptor) is not subtype of native type PHPStan\Reflection\ExtendedParametersAcceptor.
{
if (count($acceptors) === 0) {
throw new ShouldNotHappenException(
Expand Down
33 changes: 30 additions & 3 deletions src/Type/IntersectionType.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace PHPStan\Type;

use PHPStan\Internal\CombinationsHelper;
use PHPStan\Php\PhpVersion;
use PHPStan\PhpDocParser\Ast\Type\ArrayShapeNode;
use PHPStan\PhpDocParser\Ast\Type\GenericTypeNode;
Expand All @@ -16,7 +17,7 @@
use PHPStan\Reflection\MissingConstantFromReflectionException;
use PHPStan\Reflection\MissingMethodFromReflectionException;
use PHPStan\Reflection\MissingPropertyFromReflectionException;
use PHPStan\Reflection\TrivialParametersAcceptor;
use PHPStan\Reflection\ParametersAcceptorSelector;
use PHPStan\Reflection\Type\IntersectionTypeUnresolvedMethodPrototypeReflection;
use PHPStan\Reflection\Type\IntersectionTypeUnresolvedPropertyPrototypeReflection;
use PHPStan\Reflection\Type\UnresolvedMethodPrototypeReflection;
Expand Down Expand Up @@ -1124,16 +1125,42 @@

public function getCallableParametersAcceptors(ClassMemberAccessAnswerer $scope): array
{
if ($this->isCallable()->no()) {
$yesAcceptors = [];
$maybeAcceptors = [];

foreach ($this->types as $type) {
$isCallable = $type->isCallable();
if ($isCallable->no()) {
continue;
}

if ($isCallable->yes()) {
$yesAcceptors[] = $type->getCallableParametersAcceptors($scope);
} else {
$maybeAcceptors[] = $type->getCallableParametersAcceptors($scope);
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.

would it make sense to return early with return [new TrivialParametersAcceptor()]; on the first maybe-acceptor we find?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

That was the earlier test run which confirmed all 11656 tests passed. Everything is already committed and pushed.

}
}

if (count($yesAcceptors) > 0) {
$acceptors = $yesAcceptors;
} elseif (count($maybeAcceptors) > 0) {
$acceptors = $maybeAcceptors;
} else {
throw new ShouldNotHappenException();
}

return [new TrivialParametersAcceptor()];
$result = [];
$combinations = CombinationsHelper::combinations($acceptors);
foreach ($combinations as $combination) {
$result[] = ParametersAcceptorSelector::combineAcceptors($combination);
}

return $result;

Check failure on line 1158 in src/Type/IntersectionType.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.3, ubuntu-latest)

Method PHPStan\Type\IntersectionType::getCallableParametersAcceptors() should return list<PHPStan\Reflection\Callables\CallableParametersAcceptor> but returns list<PHPStan\Reflection\ExtendedParametersAcceptor>.

Check failure on line 1158 in src/Type/IntersectionType.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.2, ubuntu-latest)

Method PHPStan\Type\IntersectionType::getCallableParametersAcceptors() should return list<PHPStan\Reflection\Callables\CallableParametersAcceptor> but returns list<PHPStan\Reflection\ExtendedParametersAcceptor>.

Check failure on line 1158 in src/Type/IntersectionType.php

View workflow job for this annotation

GitHub Actions / PHPStan with result cache (8.2)

Method PHPStan\Type\IntersectionType::getCallableParametersAcceptors() should return list<PHPStan\Reflection\Callables\CallableParametersAcceptor> but returns list<PHPStan\Reflection\ExtendedParametersAcceptor>.

Check failure on line 1158 in src/Type/IntersectionType.php

View workflow job for this annotation

GitHub Actions / PHPStan with result cache (8.5)

Method PHPStan\Type\IntersectionType::getCallableParametersAcceptors() should return list<PHPStan\Reflection\Callables\CallableParametersAcceptor> but returns list<PHPStan\Reflection\ExtendedParametersAcceptor>.

Check failure on line 1158 in src/Type/IntersectionType.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.5, ubuntu-latest)

Method PHPStan\Type\IntersectionType::getCallableParametersAcceptors() should return list<PHPStan\Reflection\Callables\CallableParametersAcceptor> but returns list<PHPStan\Reflection\ExtendedParametersAcceptor>.

Check failure on line 1158 in src/Type/IntersectionType.php

View workflow job for this annotation

GitHub Actions / PHPStan with result cache (8.3)

Method PHPStan\Type\IntersectionType::getCallableParametersAcceptors() should return list<PHPStan\Reflection\Callables\CallableParametersAcceptor> but returns list<PHPStan\Reflection\ExtendedParametersAcceptor>.

Check failure on line 1158 in src/Type/IntersectionType.php

View workflow job for this annotation

GitHub Actions / PHPStan with result cache (8.4)

Method PHPStan\Type\IntersectionType::getCallableParametersAcceptors() should return list<PHPStan\Reflection\Callables\CallableParametersAcceptor> but returns list<PHPStan\Reflection\ExtendedParametersAcceptor>.

Check failure on line 1158 in src/Type/IntersectionType.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.4, ubuntu-latest)

Method PHPStan\Type\IntersectionType::getCallableParametersAcceptors() should return list<PHPStan\Reflection\Callables\CallableParametersAcceptor> but returns list<PHPStan\Reflection\ExtendedParametersAcceptor>.

Check failure on line 1158 in src/Type/IntersectionType.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.1, ubuntu-latest)

Method PHPStan\Type\IntersectionType::getCallableParametersAcceptors() should return list<PHPStan\Reflection\Callables\CallableParametersAcceptor> but returns list<PHPStan\Reflection\ExtendedParametersAcceptor>.

Check failure on line 1158 in src/Type/IntersectionType.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.0, ubuntu-latest)

Method PHPStan\Type\IntersectionType::getCallableParametersAcceptors() should return list<PHPStan\Reflection\Callables\CallableParametersAcceptor> but returns list<PHPStan\Reflection\ExtendedParametersAcceptor>.

Check failure on line 1158 in src/Type/IntersectionType.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.4, windows-latest)

Method PHPStan\Type\IntersectionType::getCallableParametersAcceptors() should return list<PHPStan\Reflection\Callables\CallableParametersAcceptor> but returns list<PHPStan\Reflection\ExtendedParametersAcceptor>.

Check failure on line 1158 in src/Type/IntersectionType.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.2, windows-latest)

Method PHPStan\Type\IntersectionType::getCallableParametersAcceptors() should return list<PHPStan\Reflection\Callables\CallableParametersAcceptor> but returns list<PHPStan\Reflection\ExtendedParametersAcceptor>.

Check failure on line 1158 in src/Type/IntersectionType.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.3, windows-latest)

Method PHPStan\Type\IntersectionType::getCallableParametersAcceptors() should return list<PHPStan\Reflection\Callables\CallableParametersAcceptor> but returns list<PHPStan\Reflection\ExtendedParametersAcceptor>.

Check failure on line 1158 in src/Type/IntersectionType.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.5, windows-latest)

Method PHPStan\Type\IntersectionType::getCallableParametersAcceptors() should return list<PHPStan\Reflection\Callables\CallableParametersAcceptor> but returns list<PHPStan\Reflection\ExtendedParametersAcceptor>.

Check failure on line 1158 in src/Type/IntersectionType.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.0, windows-latest)

Method PHPStan\Type\IntersectionType::getCallableParametersAcceptors() should return list<PHPStan\Reflection\Callables\CallableParametersAcceptor> but returns list<PHPStan\Reflection\ExtendedParametersAcceptor>.

Check failure on line 1158 in src/Type/IntersectionType.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.1, windows-latest)

Method PHPStan\Type\IntersectionType::getCallableParametersAcceptors() should return list<PHPStan\Reflection\Callables\CallableParametersAcceptor> but returns list<PHPStan\Reflection\ExtendedParametersAcceptor>.

Check failure on line 1158 in src/Type/IntersectionType.php

View workflow job for this annotation

GitHub Actions / Mutation Testing (8.4, ubuntu-latest)

Method PHPStan\

Check failure on line 1158 in src/Type/IntersectionType.php

View workflow job for this annotation

GitHub Actions / Mutation Testing (8.3, ubuntu-latest)

Method PHPStan\
}

public function isCloneable(): TrinaryLogic
{
return $this->intersectResults(static fn (Type $type): TrinaryLogic => $type->isCloneable());

Check failure on line 1163 in src/Type/IntersectionType.php

View workflow job for this annotation

GitHub Actions / PHPStan (7.4, ubuntu-latest)

Method PHPStan\Type\IntersectionType::getCallableParametersAcceptors() should return list<PHPStan\Reflection\Callables\CallableParametersAcceptor> but returns list<PHPStan\Reflection\ExtendedParametersAcceptor>.

Check failure on line 1163 in src/Type/IntersectionType.php

View workflow job for this annotation

GitHub Actions / PHPStan (7.4, windows-latest)

Method PHPStan\Type\IntersectionType::getCallableParametersAcceptors() should return list<PHPStan\Reflection\Callables\CallableParametersAcceptor> but returns list<PHPStan\Reflection\ExtendedParametersAcceptor>.
}

public function isSmallerThan(Type $otherType, PhpVersion $phpVersion): TrinaryLogic
Expand Down
84 changes: 84 additions & 0 deletions tests/PHPStan/Analyser/nsrt/bug-14362.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<?php // lint >= 8.1

declare(strict_types = 1);

namespace Bug14362;

use function PHPStan\Testing\assertType;

interface A
{
public function __invoke(B $b): int;
}

interface B
{

}

class C {
public static function u(): A&B {
Comment thread
staabm marked this conversation as resolved.
return new class() implements A, B {
public function __invoke(B $b): int {
return 1;
}
};
}
}

class D {
public static function u(): A {
return new class() implements A {
public function __invoke(B $b): int {
return 1;
}
};
}
}

interface E
{
public function __invoke(B $b, bool $option = true): int;
}

interface F
{

}

class G {
public static function u(): A&E {
return new class() implements A, E {
public function __invoke(B $b, bool $option = true): int {
return 1;
}
};
}
}

class H {
public static function u(): B&F {
return new class() implements B, F {
};
}
}

function doBar() : void {
assertType('Closure(Bug14362\B): int', C::u()(...));
assertType('Closure(Bug14362\B): int', D::u()(...));

// Intersection with two yes-callable compatible
assertType('Closure(Bug14362\B, bool=): int', G::u()(...));

// Intersection with only maybe-callable types (neither has __invoke)
assertType('Closure', H::u()(...));
}

function doFoo(string $c):void {
if (is_callable($c)) {
$a = $c;
} else {
$a = C::u()(...);
}
assertType('callable-string|(Closure(Bug14362\B): int)', $a);
}
Loading