Skip to content

Commit 1671b81

Browse files
authored
Preserve maybe in BitwiseFlagHelper for bitwise-or with dynamic operands (#6080)
1 parent cdce092 commit 1671b81

5 files changed

Lines changed: 76 additions & 2 deletions

File tree

src/Type/BitwiseFlagHelper.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ public function bitwiseOrContainsConstant(Expr $expr, Scope $scope, string $cons
4040
}
4141

4242
if ($expr instanceof BitwiseOr) {
43-
return TrinaryLogic::createFromBoolean($this->bitwiseOrContainsConstant($expr->left, $scope, $constName)->yes() ||
44-
$this->bitwiseOrContainsConstant($expr->right, $scope, $constName)->yes());
43+
return $this->bitwiseOrContainsConstant($expr->left, $scope, $constName)
44+
->or($this->bitwiseOrContainsConstant($expr->right, $scope, $constName));
4545
}
4646

4747
$fqcn = new FullyQualified($constName);

tests/PHPStan/Analyser/nsrt/preg_split.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ public function doWithVariables(string $pattern, string $subject, int $offset, i
5252
assertType('list<array{string, int<0, max>}>|false', preg_split($pattern, $subject, $offset, PREG_SPLIT_OFFSET_CAPTURE));
5353
assertType("list<string>|false", preg_split($pattern, $subject, $offset, PREG_SPLIT_DELIM_CAPTURE));
5454
assertType('list<array{string, int<0, max>}>|false', preg_split($pattern, $subject, $offset, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_OFFSET_CAPTURE));
55+
assertType('list<array{string, int<0, max>}|string>|false', preg_split($pattern, $subject, $offset, PREG_SPLIT_DELIM_CAPTURE | $flags));
56+
assertType('list<array{string, int<0, max>}|string>|false', preg_split($pattern, $subject, $offset, $flags | PREG_SPLIT_DELIM_CAPTURE));
5557
}
5658

5759
/**

tests/PHPStan/Rules/Exceptions/CatchWithUnthrownExceptionRuleTest.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,16 @@ public function testBug4814(): void
321321
]);
322322
}
323323

324+
public function testJsonMaybeThrowWithDynamicFlags(): void
325+
{
326+
$this->analyse([__DIR__ . '/data/json-maybe-throw-dynamic-flags.php'], [
327+
[
328+
'Dead catch - JsonException is never thrown in the try block.',
329+
35,
330+
],
331+
]);
332+
}
333+
324334
public function testBug9066(): void
325335
{
326336
$this->analyse([__DIR__ . '/data/bug-9066.php'], [
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
3+
namespace JsonMaybeThrowDynamicFlags;
4+
5+
function (string $s, int $flags): void {
6+
try {
7+
json_decode($s, true, 512, JSON_BIGINT_AS_STRING | $flags);
8+
} catch (\JsonException $e) {
9+
10+
}
11+
};
12+
13+
function (string $s, int $flags): void {
14+
try {
15+
json_decode($s, true, 512, $flags | JSON_BIGINT_AS_STRING);
16+
} catch (\JsonException $e) {
17+
18+
}
19+
};
20+
21+
/**
22+
* @param mixed $m
23+
*/
24+
function ($m, int $flags): void {
25+
try {
26+
json_encode($m, JSON_PRETTY_PRINT | $flags);
27+
} catch (\JsonException $e) {
28+
29+
}
30+
};
31+
32+
function (string $s): void {
33+
try {
34+
json_decode($s, true, 512, JSON_BIGINT_AS_STRING | JSON_INVALID_UTF8_IGNORE);
35+
} catch (\JsonException $e) {
36+
37+
}
38+
};

tests/PHPStan/Type/BitwiseFlagHelperTest.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,30 @@ public static function dataJsonExprContainsConst(): array
7979
'JSON_THROW_ON_ERROR',
8080
TrinaryLogic::createNo(),
8181
],
82+
[
83+
new BitwiseOr(
84+
new ConstFetch(new FullyQualified('JSON_NUMERIC_CHECK')),
85+
new Variable('integerVar'),
86+
),
87+
'JSON_THROW_ON_ERROR',
88+
TrinaryLogic::createMaybe(),
89+
],
90+
[
91+
new BitwiseOr(
92+
new Variable('integerVar'),
93+
new ConstFetch(new FullyQualified('JSON_THROW_ON_ERROR')),
94+
),
95+
'JSON_THROW_ON_ERROR',
96+
TrinaryLogic::createYes(),
97+
],
98+
[
99+
new BitwiseOr(
100+
new ConstFetch(new FullyQualified('JSON_NUMERIC_CHECK')),
101+
new Variable('stringVar'),
102+
),
103+
'JSON_THROW_ON_ERROR',
104+
TrinaryLogic::createNo(),
105+
],
82106
[
83107
new Variable('mixedVar'),
84108
'JSON_THROW_ON_ERROR',

0 commit comments

Comments
 (0)