Skip to content

Commit a44d54e

Browse files
authored
Add more foreach with by-ref $value tests (#4934)
1 parent 4de1cdc commit a44d54e

File tree

6 files changed

+164
-0
lines changed

6 files changed

+164
-0
lines changed

tests/PHPStan/Analyser/nsrt/bug-13809.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,37 @@ function bar(array $list): void
2828
assertType("list<'foo'>", $list);
2929
}
3030

31+
/**
32+
* @param list<mixed> $list
33+
*/
34+
function bar2(array $list): void
35+
{
36+
foreach ($list as $key => &$value) {
37+
if (rand(0, 1)) {
38+
$value = 'foo';
39+
}
40+
$key = 'bar';
41+
}
42+
43+
assertType("list<mixed>", $list);
44+
}
45+
46+
/**
47+
* @param list<mixed> $list
48+
*/
49+
function bar3(array $list): void
50+
{
51+
foreach ($list as &$value) {
52+
if (rand(0, 1)) {
53+
$value = 'foo';
54+
} else {
55+
$value = 'maybe';
56+
}
57+
}
58+
59+
assertType("list<mixed>", $list); // could be list<'foo'|'maybe'>
60+
}
61+
3162
/**
3263
* @param list<string> $list
3364
*/
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace Bug13851;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
class Transaction
8+
{
9+
public function __construct(public int $value)
10+
{
11+
}
12+
13+
public function withValue(int $value): self
14+
{
15+
return new self($value);
16+
}
17+
}
18+
19+
/**
20+
* @return array<string, non-empty-list<Transaction>>
21+
*/
22+
function getPositions(): array
23+
{
24+
return ['AAPL' => [new Transaction(50)], 'TSLA' => [new Transaction(50), new Transaction(100)]];
25+
}
26+
27+
$positions = getPositions();
28+
29+
foreach ($positions as $symbol => &$transactions) {
30+
foreach ($transactions as &$transaction) {
31+
$transaction = $transaction->withValue(60);
32+
}
33+
}
34+
35+
assertType('array<string, non-empty-list<Bug13851\Transaction>>', $positions);
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Bug14083;
6+
7+
use function PHPStan\Testing\assertType;
8+
9+
/**
10+
* @param list<string> $convert
11+
*/
12+
function example(array $convert): void {
13+
foreach ($convert as &$item) {
14+
$item = strtoupper($item);
15+
}
16+
assertType('list<string>', $convert);
17+
}
18+
19+
/**
20+
* @param list<string> $convert
21+
*/
22+
function example2(array $convert): void {
23+
foreach ($convert as $key => $item) {
24+
$convert[$key] = strtoupper($item);
25+
}
26+
assertType('list<uppercase-string>', $convert);
27+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Bug14084;
6+
7+
use function PHPStan\Testing\assertType;
8+
9+
/**
10+
* @param array<string, list<string>> $convert
11+
*/
12+
function example(array $convert): void
13+
{
14+
foreach ($convert as &$inner) {
15+
foreach ($inner as &$val) {
16+
$val = strtoupper($val); // https://github.com/phpstan/phpstan/issues/14083
17+
}
18+
}
19+
assertType('array<string, list<string>>', $convert);
20+
}
21+
22+
/**
23+
* @param array<string, list<string>> $convert
24+
*/
25+
function example2(array $convert): void
26+
{
27+
foreach ($convert as &$inner) {
28+
foreach ($inner as $key => $val) {
29+
$inner[$key] = strtoupper($val);
30+
}
31+
}
32+
assertType('array<string, list<string>>', $convert);
33+
}
34+
35+
/**
36+
* @param array<string, list<string>> $convert
37+
*/
38+
function example3(array &$convert): void
39+
{
40+
foreach ($convert as $outerKey => $inner) {
41+
foreach ($inner as $key => $val) {
42+
$convert[$outerKey][$key] = strtoupper($val);
43+
}
44+
}
45+
assertType('array<string, list<string>>', $convert);
46+
}

tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1305,4 +1305,9 @@ public function testBug5946(): void
13051305
]);
13061306
}
13071307

1308+
public function testBug9669(): void
1309+
{
1310+
$this->analyse([__DIR__ . '/data/bug-9669.php'], []);
1311+
}
1312+
13081313
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
namespace Bug9669;
4+
5+
class HelloWorld
6+
{
7+
/**
8+
* @param array<int, array{a: string}> $sets
9+
*
10+
* @return array<int, array{a: string, b: bool}>
11+
*/
12+
public function sayHello(array $sets): array
13+
{
14+
foreach ($sets as &$set) {
15+
$set['b'] = false;
16+
}
17+
18+
return $sets;
19+
}
20+
}

0 commit comments

Comments
 (0)