Skip to content

Commit

Permalink
Enfore optional parameters in callable types
Browse files Browse the repository at this point in the history
  • Loading branch information
Richard van Velzen authored and ondrejmirtes committed May 30, 2022
1 parent 4da16b3 commit 0910d70
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 4 deletions.
7 changes: 6 additions & 1 deletion src/Type/CallableType.php
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,12 @@ public function describe(VerbosityLevel $level): string
fn (): string => sprintf(
'callable(%s): %s',
implode(', ', array_map(
static fn (ParameterReflection $param): string => sprintf('%s%s', $param->isVariadic() ? '...' : '', $param->getType()->describe($level)),
static fn (ParameterReflection $param): string => sprintf(
'%s%s%s',
$param->isVariadic() ? '...' : '',
$param->getType()->describe($level),
$param->isOptional() && !$param->isVariadic() ? '=' : '',
),
$this->getParameters(),
)),
$this->returnType->describe($level),
Expand Down
5 changes: 5 additions & 0 deletions src/Type/CallableTypeHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ public static function isParametersAcceptorSuperTypeOf(

$ourParameter = $ourParameters[$i];
$ourParameterType = $ourParameter->getType();

if ($ourParameter->isOptional() && !$theirParameter->isOptional()) {
return TrinaryLogic::createNo();
}

if ($treatMixedAsAny) {
$isSuperType = $theirParameter->getType()->accepts($ourParameterType, true);
} else {
Expand Down
10 changes: 9 additions & 1 deletion src/Type/ClosureType.php
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,15 @@ public function describe(VerbosityLevel $level): string
static fn (): string => 'Closure',
fn (): string => sprintf(
'Closure(%s): %s',
implode(', ', array_map(static fn (ParameterReflection $parameter): string => sprintf('%s%s', $parameter->isVariadic() ? '...' : '', $parameter->getType()->describe($level)), $this->parameters)),
implode(', ', array_map(
static fn (ParameterReflection $param): string => sprintf(
'%s%s%s',
$param->isVariadic() ? '...' : '',
$param->getType()->describe($level),
$param->isOptional() && !$param->isVariadic() ? '=' : '',
),
$this->parameters,
)),
$this->returnType->describe($level),
),
);
Expand Down
12 changes: 10 additions & 2 deletions tests/PHPStan/Analyser/AnalyserIntegrationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -763,9 +763,9 @@ public function testDiscussion7124(): void

$errors = $this->runAnalyse(__DIR__ . '/data/discussion-7124.php');
$this->assertCount(4, $errors);
$this->assertSame('Parameter #2 $callback of function Discussion7124\filter expects callable(bool, int): bool, Closure(int, bool): bool given.', $errors[0]->getMessage());
$this->assertSame('Parameter #2 $callback of function Discussion7124\filter expects callable(bool, int=): bool, Closure(int, bool): bool given.', $errors[0]->getMessage());
$this->assertSame(38, $errors[0]->getLine());
$this->assertSame('Parameter #2 $callback of function Discussion7124\filter expects callable(bool, int): bool, Closure(int): bool given.', $errors[1]->getMessage());
$this->assertSame('Parameter #2 $callback of function Discussion7124\filter expects callable(bool, int=): bool, Closure(int): bool given.', $errors[1]->getMessage());
$this->assertSame(45, $errors[1]->getLine());
$this->assertSame('Parameter #2 $callback of function Discussion7124\filter expects callable(int): bool, Closure(bool): bool given.', $errors[2]->getMessage());
$this->assertSame(52, $errors[2]->getLine());
Expand Down Expand Up @@ -841,6 +841,14 @@ public function testBug7351(): void
$this->assertNoErrors($errors);
}

public function testBug7320(): void
{
$errors = $this->runAnalyse(__DIR__ . '/data/bug-7320.php');
$this->assertCount(1, $errors);
$this->assertSame('Parameter #1 $c of function Bug7320\foo expects callable(int=): void, Closure(int): void given.', $errors[0]->getMessage());
$this->assertSame(13, $errors[0]->getLine());
}

/**
* @param string[]|null $allAnalysedFiles
* @return Error[]
Expand Down
14 changes: 14 additions & 0 deletions tests/PHPStan/Analyser/data/bug-7320.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php declare(strict_types = 1);

namespace Bug7320;

/**
* @param callable(int=): void $c
*/
function foo(callable $c): void {
$c();
}

function () {
foo(function (int $a): void {});
};

0 comments on commit 0910d70

Please sign in to comment.