Skip to content

Commit 59a67bf

Browse files
committed
Narrow l/r/trim() arg on comparison to ''
1 parent 398622a commit 59a67bf

File tree

3 files changed

+95
-0
lines changed

3 files changed

+95
-0
lines changed

src/Analyser/TypeSpecifier.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1303,6 +1303,26 @@ 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), ['trim', 'ltrim', 'rtrim'], true)
1311+
&& isset($exprNode->getArgs()[0])
1312+
&& $constantStringValue === ''
1313+
) {
1314+
$argType = $scope->getType($exprNode->getArgs()[0]->value);
1315+
1316+
if ($argType->isString()->yes()) {
1317+
return $this->create(
1318+
$exprNode->getArgs()[0]->value,
1319+
new AccessoryNonEmptyStringType(),
1320+
$context->negate(),
1321+
$scope,
1322+
)->setRootExpr($rootExpr);
1323+
}
1324+
}
1325+
13061326
return null;
13071327
}
13081328

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
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 trimTypes(string $value): void
20+
{
21+
if (trim($value) === '') {
22+
assertType('string', $value);
23+
} else {
24+
assertType('non-empty-string', $value);
25+
}
26+
assertType('string', $value);
27+
28+
if (trim($value) !== '') {
29+
assertType('non-empty-string', $value);
30+
} else {
31+
assertType('string', $value);
32+
}
33+
assertType('string', $value);
34+
}
35+
36+
function ltrimTypes(string $value): void
37+
{
38+
if (ltrim($value) === '') {
39+
assertType('string', $value);
40+
} else {
41+
assertType('non-empty-string', $value);
42+
}
43+
assertType('string', $value);
44+
45+
if (ltrim($value) !== '') {
46+
assertType('non-empty-string', $value);
47+
} else {
48+
assertType('string', $value);
49+
}
50+
assertType('string', $value);
51+
}
52+
53+
function rtrimTypes(string $value): void
54+
{
55+
if (rtrim($value) === '') {
56+
assertType('string', $value);
57+
} else {
58+
assertType('non-empty-string', $value);
59+
}
60+
assertType('string', $value);
61+
62+
if (rtrim($value) !== '') {
63+
assertType('non-empty-string', $value);
64+
} else {
65+
assertType('string', $value);
66+
}
67+
assertType('string', $value);
68+
}

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)