Skip to content

Commit f29c855

Browse files
committed
Merge remote-tracking branch 'origin/1.12.x' into 2.1.x
2 parents 843be53 + cc6c200 commit f29c855

File tree

6 files changed

+187
-3
lines changed

6 files changed

+187
-3
lines changed
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<?php // lint >= 8.1
2+
3+
declare(strict_types = 1);
4+
5+
namespace Bug11861;
6+
7+
use function PHPStan\Testing\assertType;
8+
9+
/**
10+
* @template T
11+
* @template K of array-key
12+
* @template R
13+
*
14+
* @param array<K, T> $source
15+
* @param callable(T, K): R $mappingFunction
16+
* @return array<K, R>
17+
*/
18+
function mapArray(array $source, callable $mappingFunction): array
19+
{
20+
$result = [];
21+
22+
foreach ($source as $key => $value) {
23+
$result[$key] = $mappingFunction($value, $key);
24+
}
25+
26+
return $result;
27+
}
28+
29+
/**
30+
* @template K
31+
* @template T
32+
*
33+
* @param array<K, null|T> $source
34+
* @return array<K, T>
35+
*/
36+
function filterArrayNotNull(array $source): array
37+
{
38+
return array_filter(
39+
$source,
40+
fn($item) => $item !== null,
41+
ARRAY_FILTER_USE_BOTH
42+
);
43+
}
44+
45+
/** @var list<array<string, null|int>> $a */
46+
$a = [];
47+
48+
$mappedA = mapArray(
49+
$a,
50+
static fn(array $entry) => filterArrayNotNull($entry)
51+
);
52+
53+
$mappedAWithFirstClassSyntax = mapArray(
54+
$a,
55+
filterArrayNotNull(...)
56+
);
57+
58+
assertType('array<int<0, max>, array<int|string, mixed>>', $mappedA);
59+
assertType('array<int<0, max>, array<int|string, mixed>>', $mappedAWithFirstClassSyntax);

tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1960,21 +1960,31 @@ public function testBug12051(): void
19601960
}
19611961

19621962
public function testBug8046(): void
1963+
{
1964+
$this->analyse([__DIR__ . '/data/bug-8046.php'], []);
1965+
}
1966+
1967+
public function testBug11942(): void
19631968
{
19641969
if (PHP_VERSION_ID < 80100) {
19651970
$this->markTestSkipped('Test requires PHP 8.1.');
19661971
}
19671972

1968-
$this->analyse([__DIR__ . '/data/bug-8046.php'], []);
1973+
$this->analyse([__DIR__ . '/data/bug-11942.php'], []);
19691974
}
19701975

19711976
public function testBug11418(): void
1977+
{
1978+
$this->analyse([__DIR__ . '/data/bug-11418.php'], []);
1979+
}
1980+
1981+
public function testBug9167(): void
19721982
{
19731983
if (PHP_VERSION_ID < 80100) {
19741984
$this->markTestSkipped('Test requires PHP 8.1.');
19751985
}
19761986

1977-
$this->analyse([__DIR__ . '/data/bug-11418.php'], []);
1987+
$this->analyse([__DIR__ . '/data/bug-9167.php'], []);
19781988
}
19791989

19801990
public function testBug3107(): void
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
namespace Bug11942;
4+
5+
/**
6+
* @template A
7+
* @param A $a
8+
* @return A
9+
*/
10+
function identity(mixed $a): mixed
11+
{
12+
return $a;
13+
}
14+
15+
/**
16+
* @param callable(int): int $fn
17+
*/
18+
function simple(callable $fn): int
19+
{
20+
return $fn(42);
21+
}
22+
23+
simple(identity(...));
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
namespace Bug9167;
4+
5+
use Closure;
6+
7+
class A {
8+
/**
9+
* @template TRet
10+
* @param Closure(int):TRet $next
11+
* @return TRet
12+
*/
13+
public function __invoke(Closure $next) {
14+
return $next(12);
15+
}
16+
}
17+
18+
/**
19+
* @template T
20+
* @param T $in
21+
* @return T
22+
*/
23+
function value(mixed $in): mixed {
24+
return $in;
25+
}
26+
27+
function want_int(int $in): void {}
28+
29+
function pass_b(): void {
30+
$a = new A();
31+
want_int($a(value(...)));
32+
}

tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3539,8 +3539,17 @@ public function testBug12422(): void
35393539
$this->checkNullables = true;
35403540
$this->checkUnionTypes = true;
35413541
$this->checkExplicitMixed = true;
3542-
35433542
$this->analyse([__DIR__ . '/data/bug-12422.php'], []);
35443543
}
35453544

3545+
public function testBug6828(): void
3546+
{
3547+
$this->checkThisOnly = false;
3548+
$this->checkNullables = true;
3549+
$this->checkUnionTypes = true;
3550+
$this->checkExplicitMixed = true;
3551+
3552+
$this->analyse([__DIR__ . '/data/bug-6828.php'], []);
3553+
}
3554+
35463555
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php // lint >= 8.1
2+
3+
declare(strict_types=1);
4+
5+
namespace Bug6828;
6+
7+
/** @template T */
8+
interface Option
9+
{
10+
/**
11+
* @template U
12+
* @param \Closure(T):U $c
13+
* @return Option<U>
14+
*/
15+
function map(\Closure $c);
16+
}
17+
18+
/**
19+
* @template T
20+
* @template E
21+
*/
22+
abstract class Result
23+
{
24+
/** @return T */
25+
function unwrap()
26+
{
27+
28+
}
29+
30+
/**
31+
* @template U
32+
* @param U $v
33+
* @return Result<U, mixed>
34+
*/
35+
static function ok($v)
36+
{
37+
38+
}
39+
}
40+
41+
/**
42+
* @template U
43+
* @template F
44+
* @param Result<Option<U>, F> $result
45+
* @return Option<Result<U, F>>
46+
*/
47+
function f(Result $result): Option
48+
{
49+
/** @var Option<Result<U, F>> */
50+
return $result->unwrap()->map(Result::ok(...));
51+
}

0 commit comments

Comments
 (0)