Skip to content

Commit 64da8f9

Browse files
committed
Fixed expression assignment throwing away native expression types for treatPhpDocTypesAsCertain: false
1 parent b01c6c9 commit 64da8f9

File tree

3 files changed

+61
-1
lines changed

3 files changed

+61
-1
lines changed

src/Analyser/MutatingScope.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3171,6 +3171,7 @@ public function invalidateExpression(Expr $expressionToInvalidate, bool $require
31713171
{
31723172
$exprStringToInvalidate = $this->getNodeKey($expressionToInvalidate);
31733173
$moreSpecificTypeHolders = $this->moreSpecificTypes;
3174+
$nativeExpressionTypes = $this->nativeExpressionTypes;
31743175
foreach (array_keys($moreSpecificTypeHolders) as $exprString) {
31753176
$exprString = (string) $exprString;
31763177
if (Strings::startsWith($exprString, $exprStringToInvalidate)) {
@@ -3180,6 +3181,7 @@ public function invalidateExpression(Expr $expressionToInvalidate, bool $require
31803181
$nextLetter = substr($exprString, strlen($exprStringToInvalidate), 1);
31813182
if (Strings::match($nextLetter, '#[a-zA-Z_0-9\x7f-\xff]#') === null) {
31823183
unset($moreSpecificTypeHolders[$exprString]);
3184+
unset($nativeExpressionTypes[$exprString]);
31833185
continue;
31843186
}
31853187
}
@@ -3195,6 +3197,7 @@ public function invalidateExpression(Expr $expressionToInvalidate, bool $require
31953197
}
31963198

31973199
unset($moreSpecificTypeHolders[$exprString]);
3200+
unset($nativeExpressionTypes[$exprString]);
31983201
}
31993202

32003203
return $this->scopeFactory->create(
@@ -3209,7 +3212,7 @@ public function invalidateExpression(Expr $expressionToInvalidate, bool $require
32093212
$this->anonymousFunctionReflection,
32103213
$this->inFirstLevelStatement,
32113214
$this->currentlyAssignedExpressions,
3212-
[],
3215+
$nativeExpressionTypes,
32133216
[],
32143217
$this->afterExtractCall,
32153218
$this->parentScope
@@ -3993,6 +3996,10 @@ public function debug(): array
39933996
$key = sprintf('const %s', $name);
39943997
$descriptions[$key] = $type->describe(VerbosityLevel::precise());
39953998
}
3999+
foreach ($this->nativeExpressionTypes as $exprString => $nativeType) {
4000+
$key = sprintf('native %s', $exprString);
4001+
$descriptions[$key] = $nativeType->describe(VerbosityLevel::precise());
4002+
}
39964003

39974004
return $descriptions;
39984005
}

tests/PHPStan/Analyser/NodeScopeResolverTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10352,6 +10352,11 @@ public function dataBug4099(): array
1035210352
return $this->gatherAssertTypes(__DIR__ . '/data/bug-4099.php');
1035310353
}
1035410354

10355+
public function dataBug3760(): array
10356+
{
10357+
return $this->gatherAssertTypes(__DIR__ . '/data/bug-3760.php');
10358+
}
10359+
1035510360
/**
1035610361
* @param string $file
1035710362
* @return array<string, mixed[]>
@@ -10535,6 +10540,7 @@ private function gatherAssertTypes(string $file): array
1053510540
* @dataProvider dataBug3880
1053610541
* @dataProvider dataIncDecInConditions
1053710542
* @dataProvider dataBug4099
10543+
* @dataProvider dataBug3760
1053810544
* @param string $assertType
1053910545
* @param string $file
1054010546
* @param mixed ...$args
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Bug3760;
4+
5+
use function PHPStan\Analyser\assertNativeType;
6+
use function PHPStan\Analyser\assertType;
7+
8+
class HelloWorld
9+
{
10+
/**
11+
* Whether the type allows covariant matches
12+
*
13+
* @var bool
14+
*/
15+
public $allowsCovariance;
16+
17+
/**
18+
* Whether the type allows contravariant matches
19+
*
20+
* @var bool
21+
*/
22+
public $allowsContravariance;
23+
24+
/**
25+
* @param bool $allowsCovariance
26+
* @param bool $allowsContravariance
27+
*/
28+
protected function __construct($allowsCovariance, $allowsContravariance)
29+
{
30+
assertType('bool', $allowsCovariance);
31+
assertNativeType('mixed', $allowsCovariance);
32+
assertType('bool', $allowsContravariance);
33+
assertNativeType('mixed', $allowsContravariance);
34+
$this->allowsCovariance = (bool)$allowsCovariance;
35+
36+
assertType('bool', $allowsCovariance);
37+
assertNativeType('mixed', $allowsCovariance);
38+
assertType('bool', $allowsContravariance);
39+
assertNativeType('mixed', $allowsContravariance);
40+
$this->allowsContravariance = (bool)$allowsContravariance;
41+
42+
assertType('bool', $allowsCovariance);
43+
assertNativeType('mixed', $allowsCovariance);
44+
assertType('bool', $allowsContravariance);
45+
assertNativeType('mixed', $allowsContravariance);
46+
}
47+
}

0 commit comments

Comments
 (0)