Skip to content

Commit 0626464

Browse files
authored
Narrow l/r/trim() arg on comparison to ''
1 parent 17c4fe5 commit 0626464

File tree

4 files changed

+137
-0
lines changed

4 files changed

+137
-0
lines changed

src/Analyser/TypeSpecifier.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1303,6 +1303,28 @@ private function specifyTypesForConstantStringBinaryExpression(
13031303
)->setRootExpr($rootExpr);
13041304
}
13051305

1306+
if (
1307+
$context->false()
1308+
&& $exprNode instanceof FuncCall
1309+
&& $exprNode->name instanceof Name
1310+
&& in_array(strtolower((string) $exprNode->name), [
1311+
'trim', 'ltrim', 'rtrim',
1312+
'mb_trim', 'mb_ltrim', 'mb_rtrim',
1313+
], true)
1314+
&& isset($exprNode->getArgs()[0])
1315+
&& $constantStringValue === ''
1316+
) {
1317+
return $this->create(
1318+
$exprNode->getArgs()[0]->value,
1319+
TypeCombinator::intersect(
1320+
new StringType(),
1321+
new AccessoryNonEmptyStringType(),
1322+
),
1323+
$context->negate(),
1324+
$scope,
1325+
)->setRootExpr($rootExpr);
1326+
}
1327+
13061328
return null;
13071329
}
13081330

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php // lint >= 8.4
2+
3+
namespace Bug12973Php84;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
function mbtrim($value): void
8+
{
9+
if (mb_trim($value) === '') {
10+
assertType('mixed', $value);
11+
} else {
12+
assertType('non-empty-string', $value);
13+
}
14+
assertType('mixed', $value);
15+
16+
if (mb_ltrim($value) === '') {
17+
assertType('mixed', $value);
18+
} else {
19+
assertType('non-empty-string', $value);
20+
}
21+
assertType('mixed', $value);
22+
23+
if (mb_rtrim($value) === '') {
24+
assertType('mixed', $value);
25+
} else {
26+
assertType('non-empty-string', $value);
27+
}
28+
assertType('mixed', $value);
29+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<?php
2+
3+
namespace Bug12973;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
/**
8+
* @return non-empty-string|null
9+
*/
10+
function nullIfBlank(?string $value): ?string
11+
{
12+
if ($value !== null) {
13+
return \trim($value) === '' ? null : $value;
14+
}
15+
16+
return null;
17+
}
18+
19+
function trimMixed($value): void
20+
{
21+
if (trim($value) === '') {
22+
assertType('mixed', $value);
23+
} else {
24+
assertType('non-empty-string', $value);
25+
}
26+
assertType('mixed', $value);
27+
28+
}
29+
30+
function trimTypes(string $value): void
31+
{
32+
if (trim($value) === '') {
33+
assertType('string', $value);
34+
} else {
35+
assertType('non-empty-string', $value);
36+
}
37+
assertType('string', $value);
38+
39+
if (trim($value) !== '') {
40+
assertType('non-empty-string', $value);
41+
} else {
42+
assertType('string', $value);
43+
}
44+
assertType('string', $value);
45+
}
46+
47+
function ltrimTypes(string $value): void
48+
{
49+
if (ltrim($value) === '') {
50+
assertType('string', $value);
51+
} else {
52+
assertType('non-empty-string', $value);
53+
}
54+
assertType('string', $value);
55+
56+
if (ltrim($value) !== '') {
57+
assertType('non-empty-string', $value);
58+
} else {
59+
assertType('string', $value);
60+
}
61+
assertType('string', $value);
62+
}
63+
64+
function rtrimTypes(string $value): void
65+
{
66+
if (rtrim($value) === '') {
67+
assertType('string', $value);
68+
} else {
69+
assertType('non-empty-string', $value);
70+
}
71+
assertType('string', $value);
72+
73+
if (rtrim($value) !== '') {
74+
assertType('non-empty-string', $value);
75+
} else {
76+
assertType('string', $value);
77+
}
78+
assertType('string', $value);
79+
}

tests/PHPStan/Rules/Functions/ReturnTypeRuleTest.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,4 +378,11 @@ public function testBug9401(): void
378378
]);
379379
}
380380

381+
public function testBug12973(): void
382+
{
383+
$this->checkNullables = true;
384+
$this->checkExplicitMixed = true;
385+
$this->analyse([__DIR__ . '/../../Analyser/nsrt/bug-12973.php'], []);
386+
}
387+
381388
}

0 commit comments

Comments
 (0)