diff --git a/src/Type/Pest/HigherOrderExpectationTypeExtension.php b/src/Type/Pest/HigherOrderExpectationTypeExtension.php index 2f72220..22cafb5 100644 --- a/src/Type/Pest/HigherOrderExpectationTypeExtension.php +++ b/src/Type/Pest/HigherOrderExpectationTypeExtension.php @@ -20,6 +20,7 @@ use PHPStan\Type\ExpressionTypeResolverExtension; use PHPStan\Type\Generic\GenericObjectType; use PHPStan\Type\MixedType; +use PHPStan\Type\NeverType; use PHPStan\Type\NullType; use PHPStan\Type\ObjectType; use PHPStan\Type\Type; @@ -35,6 +36,11 @@ public function __construct( public function getType(Expr $expr, Scope $scope): ?Type { + if (($expr instanceof PropertyFetch || $expr instanceof MethodCall) + && (new NeverType)->isSuperTypeOf($scope->getType($expr->var))->yes()) { + return null; + } + if ($expr instanceof PropertyFetch) { return $this->resolvePropertyFetch($expr, $scope); } diff --git a/tests/Type/ExpectTypeTest.php b/tests/Type/ExpectTypeTest.php index 583c1a7..ccb4808 100644 --- a/tests/Type/ExpectTypeTest.php +++ b/tests/Type/ExpectTypeTest.php @@ -86,6 +86,12 @@ yield from TestCase::gatherAssertTypes(__DIR__.'/data/higher-order-exhaustive.php'); }); +test('never receiver is not an expectation', function (string $assertType, string $file, mixed ...$args): void { + $this->assertFileAsserts($assertType, $file, ...$args); +})->with(function (): Iterator { + yield from TestCase::gatherAssertTypes(__DIR__.'/data/never-receiver.php'); +}); + test('exhaustive test call types', function (string $assertType, string $file, mixed ...$args): void { $this->assertFileAsserts($assertType, $file, ...$args); })->with(function (): Iterator { diff --git a/tests/Type/data/never-receiver.php b/tests/Type/data/never-receiver.php new file mode 100644 index 0000000..35721db --- /dev/null +++ b/tests/Type/data/never-receiver.php @@ -0,0 +1,31 @@ +title); +} + +/** + * @param never $value + */ +function testMethodCallOnNever(mixed $value): void +{ + assertType('*ERROR*', $value->getTitle()); +} + +function testRealExpectationIsUnaffected(): void +{ + $post = new Post; + assertType('Pest\Expectations\HigherOrderExpectation, string>', expect($post)->title); +}