Skip to content

Commit 06ea1e1

Browse files
phpstan-botVincentLangletclaude
authored
Fix phpstan/phpstan#3250: \settype() is not handled properly (#5404)
Co-authored-by: VincentLanglet <9052536+VincentLanglet@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 72b1bb5 commit 06ea1e1

File tree

3 files changed

+85
-4
lines changed

3 files changed

+85
-4
lines changed

src/Type/Php/SetTypeFunctionTypeSpecifyingExtension.php

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@
1010
use PHPStan\Analyser\TypeSpecifierContext;
1111
use PHPStan\DependencyInjection\AutowiredService;
1212
use PHPStan\Reflection\FunctionReflection;
13+
use PHPStan\Type\Constant\ConstantStringType;
1314
use PHPStan\Type\ErrorType;
1415
use PHPStan\Type\FunctionTypeSpecifyingExtension;
1516
use PHPStan\Type\NullType;
1617
use PHPStan\Type\ObjectType;
18+
use PHPStan\Type\ObjectWithoutClassType;
1719
use PHPStan\Type\TypeCombinator;
1820
use stdClass;
1921
use function count;
@@ -41,7 +43,15 @@ public function specifyTypes(FunctionReflection $functionReflection, FuncCall $n
4143

4244
$constantStrings = $castType->getConstantStrings();
4345
if (count($constantStrings) < 1) {
44-
return new SpecifiedTypes();
46+
$constantStrings = [
47+
new ConstantStringType('bool'),
48+
new ConstantStringType('int'),
49+
new ConstantStringType('float'),
50+
new ConstantStringType('string'),
51+
new ConstantStringType('array'),
52+
new ConstantStringType('object'),
53+
new ConstantStringType('null'),
54+
];
4555
}
4656

4757
$types = [];
@@ -67,7 +77,17 @@ public function specifyTypes(FunctionReflection $functionReflection, FuncCall $n
6777
$types[] = $valueType->toArray();
6878
break;
6979
case 'object':
70-
$types[] = new ObjectType(stdClass::class);
80+
$isObject = $valueType->isObject();
81+
if ($isObject->yes()) {
82+
$types[] = $valueType;
83+
} elseif ($isObject->no()) {
84+
$types[] = new ObjectType(stdClass::class);
85+
} else {
86+
$types[] = TypeCombinator::union(
87+
TypeCombinator::intersect($valueType, new ObjectWithoutClassType()),
88+
new ObjectType(stdClass::class),
89+
);
90+
}
7191
break;
7292
case 'null':
7393
$types[] = new NullType();
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Bug3250;
4+
5+
use DateTime;
6+
use stdClass;
7+
use function PHPStan\Testing\assertType;
8+
9+
function castTo(string $value, string $castTo): void
10+
{
11+
$newValue = $value;
12+
settype($newValue, $castTo);
13+
14+
assertType('array{string}|bool|float|int|stdClass|string|null', $newValue);
15+
}
16+
17+
function castToInt(string $value): void
18+
{
19+
$newValue = $value;
20+
settype($newValue, 'int');
21+
22+
assertType('int', $newValue);
23+
}
24+
25+
/**
26+
* @param 'int'|'float' $castTo
27+
*/
28+
function castToIntOrFloat(string $value, string $castTo): void
29+
{
30+
$newValue = $value;
31+
settype($newValue, $castTo);
32+
33+
assertType('float|int', $newValue);
34+
}
35+
36+
function castObjectToObject(DateTime $value): void
37+
{
38+
$newValue = $value;
39+
settype($newValue, 'object');
40+
41+
assertType('DateTime', $newValue);
42+
}
43+
44+
/**
45+
* @param DateTime|string $value
46+
*/
47+
function castMixedToObject($value): void
48+
{
49+
$newValue = $value;
50+
settype($newValue, 'object');
51+
52+
assertType('DateTime|stdClass', $newValue);
53+
}
54+
55+
function castStringToObject(string $value): void
56+
{
57+
$newValue = $value;
58+
settype($newValue, 'object');
59+
60+
assertType('stdClass', $newValue);
61+
}

tests/PHPStan/Analyser/nsrt/set-type-type-specifying.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ function doObject(string $s, int $i, float $f, array $a, object $o)
146146
assertType('stdClass', $a);
147147

148148
settype($o, 'object');
149-
assertType('stdClass', $o);
149+
assertType('object', $o);
150150
}
151151

152152
function doNull(string $s, int $i, float $f, array $a, object $o)
@@ -669,5 +669,5 @@ function setTypeSpecifying($value, string $castTo): void
669669

670670
// Mixed to non-constant.
671671
settype($value, $castTo);
672-
assertType("array|bool|float|int|stdClass|string|null", $value);
672+
assertType("array|bool|float|int|object|string|null", $value);
673673
}

0 commit comments

Comments
 (0)