Skip to content

Commit 0710bc5

Browse files
Introduce __stringnotstringable
1 parent b05cb5e commit 0710bc5

File tree

5 files changed

+164
-3
lines changed

5 files changed

+164
-3
lines changed

resources/functionMap.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1650,7 +1650,7 @@
16501650
'DomXsltStylesheet::result_dump_mem' => ['string', 'xmldoc'=>'DOMDocument'],
16511651
'DOTNET::__construct' => ['void', 'assembly_name'=>'string', 'class_name'=>'string', 'codepage='=>'int'],
16521652
'dotnet_load' => ['int', 'assembly_name'=>'string', 'datatype_name='=>'string', 'codepage='=>'int'],
1653-
'doubleval' => ['float', 'var'=>'scalar|array|resource|null'],
1653+
'doubleval' => ['float', 'var'=>'int|float|__stringnotstringable|bool|array|resource|null'],
16541654
'Ds\Deque::__construct' => ['void', 'values='=>'mixed'],
16551655
'Ds\Deque::count' => ['0|positive-int'],
16561656
'Ds\Deque::jsonSerialize' => ['array'],
@@ -2448,7 +2448,7 @@
24482448
'finfo_file' => ['string|false', 'finfo'=>'resource', 'file_name'=>'string', 'options='=>'int', 'context='=>'resource'],
24492449
'finfo_open' => ['resource|false', 'options='=>'int', 'arg='=>'string'],
24502450
'finfo_set_flags' => ['bool', 'finfo'=>'resource', 'options'=>'int'],
2451-
'floatval' => ['float', 'var'=>'scalar|array|resource|null'],
2451+
'floatval' => ['float', 'var'=>'int|float|__stringnotstringable|bool|array|resource|null'],
24522452
'flock' => ['bool', 'fp'=>'resource', 'operation'=>'int-mask<LOCK_SH, LOCK_EX, LOCK_UN, LOCK_NB>', '&w_wouldblock='=>'0|1'],
24532453
'floor' => ['__benevolent<float|false>', 'number'=>'float'],
24542454
'flush' => ['void'],
@@ -5075,7 +5075,7 @@
50755075
'intltz_to_date_time_zone' => ['DateTimeZone|false', 'obj'=>''],
50765076
'intltz_use_daylight_time' => ['bool', 'obj'=>''],
50775077
'intlz_create_default' => ['IntlTimeZone'],
5078-
'intval' => ['int', 'var'=>'scalar|array|resource|null', 'base='=>'int'],
5078+
'intval' => ['int', 'var'=>'int|float|__stringnotstringable|bool|array|resource|null', 'base='=>'int'],
50795079
'InvalidArgumentException::__clone' => ['void'],
50805080
'InvalidArgumentException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'(?Throwable)|(?InvalidArgumentException)'],
50815081
'InvalidArgumentException::__toString' => ['string'],

src/PhpDoc/TypeNodeResolver.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@
9898
use PHPStan\Type\StaticType;
9999
use PHPStan\Type\StaticTypeFactory;
100100
use PHPStan\Type\StringAlwaysAcceptingObjectWithToStringType;
101+
use PHPStan\Type\StringNeverAcceptingObjectWithToStringType;
101102
use PHPStan\Type\StringType;
102103
use PHPStan\Type\ThisType;
103104
use PHPStan\Type\Type;
@@ -462,6 +463,8 @@ private function resolveIdentifierTypeNode(IdentifierTypeNode $typeNode, NameSco
462463
return StaticTypeFactory::falsey();
463464
case '__stringandstringable':
464465
return new StringAlwaysAcceptingObjectWithToStringType();
466+
case '__stringnotstringable':
467+
return new StringNeverAcceptingObjectWithToStringType();
465468
}
466469

467470
if ($nameScope->getClassName() !== null) {
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Type;
4+
5+
use PHPStan\Reflection\ReflectionProviderStaticAccessor;
6+
7+
class StringNeverAcceptingObjectWithToStringType extends StringType
8+
{
9+
10+
public function accepts(Type $type, bool $strictTypes): AcceptsResult
11+
{
12+
return parent::accepts($type, true);
13+
}
14+
15+
}

tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2397,6 +2397,51 @@ public function testArrayRand(): void
23972397
]);
23982398
}
23992399

2400+
public function testBug6560(): void
2401+
{
2402+
$this->checkExplicitMixed = true;
2403+
$this->checkImplicitMixed = true;
2404+
2405+
$this->analyse([__DIR__ . '/data/bug-6560.php'], [
2406+
[
2407+
'Parameter #1 $value of function strval expects bool|float|int|resource|string|null, array given.',
2408+
20,
2409+
],
2410+
[
2411+
'Parameter #1 $value of function strval expects bool|float|int|resource|string|null, stdClass given.',
2412+
74,
2413+
],
2414+
[
2415+
'Parameter #1 $value of function intval expects array|bool|float|int|resource|string|null, stdClass given.',
2416+
77,
2417+
],
2418+
[
2419+
'Parameter #1 $value of function floatval expects array|bool|float|int|resource|string|null, stdClass given.',
2420+
80,
2421+
],
2422+
[
2423+
'Parameter #1 $value of function intval expects array|bool|float|int|resource|string|null, Stringable@anonymous/tests/PHPStan/Rules/Functions/data/bug-6560.php:10 given.',
2424+
86,
2425+
],
2426+
[
2427+
'Parameter #1 $value of function floatval expects array|bool|float|int|resource|string|null, Stringable@anonymous/tests/PHPStan/Rules/Functions/data/bug-6560.php:10 given.',
2428+
89,
2429+
],
2430+
[
2431+
'Parameter #1 $value of function strval expects bool|float|int|resource|string|null, mixed given.',
2432+
92,
2433+
],
2434+
[
2435+
'Parameter #1 $value of function intval expects array|bool|float|int|resource|string|null, mixed given.',
2436+
95,
2437+
],
2438+
[
2439+
'Parameter #1 $value of function floatval expects array|bool|float|int|resource|string|null, mixed given.',
2440+
98,
2441+
],
2442+
]);
2443+
}
2444+
24002445
#[RequiresPhp('< 8.0')]
24012446
public function testArrayRandPhp7(): void
24022447
{
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
<?php
2+
$array = [];
3+
$string = '';
4+
$int = 1;
5+
$float = .1;
6+
$resource = fopen('./.env', 'r'); // Cannot cast resource to float. But works
7+
\assert(false !== $resource);
8+
$bool = true;
9+
$object = new stdClass();
10+
$stringable = new class() {
11+
public function __toString(): string {
12+
return '';
13+
}
14+
};
15+
$null = null;
16+
/** @var mixed $mixed */
17+
$mixed = null;
18+
19+
echo (string) $array . PHP_EOL;
20+
echo strval($array) . PHP_EOL;
21+
22+
echo (int) $array . PHP_EOL;
23+
echo intval($array) . PHP_EOL;
24+
25+
echo (float) $array . PHP_EOL;
26+
echo floatval($array) . PHP_EOL;
27+
28+
echo (string) $string . PHP_EOL;
29+
echo strval($string) . PHP_EOL;
30+
31+
echo (int) $string . PHP_EOL;
32+
echo intval($string) . PHP_EOL;
33+
34+
echo (float) $string . PHP_EOL;
35+
echo floatval($string) . PHP_EOL;
36+
37+
echo (string) $int . PHP_EOL;
38+
echo strval($int) . PHP_EOL;
39+
40+
echo (int) $int . PHP_EOL;
41+
echo intval($int) . PHP_EOL;
42+
43+
echo (float) $int . PHP_EOL;
44+
echo floatval($int) . PHP_EOL;
45+
46+
echo (string) $float . PHP_EOL;
47+
echo strval($float) . PHP_EOL;
48+
49+
echo (int) $float . PHP_EOL;
50+
echo intval($float) . PHP_EOL;
51+
52+
echo (float) $float . PHP_EOL;
53+
echo floatval($float) . PHP_EOL;
54+
55+
echo (string) $resource . PHP_EOL;
56+
echo strval($resource) . PHP_EOL;
57+
58+
echo (int) $resource . PHP_EOL;
59+
echo intval($resource) . PHP_EOL;
60+
61+
echo (float) $resource . PHP_EOL;
62+
echo floatval($resource) . PHP_EOL;
63+
64+
echo (string) $bool . PHP_EOL;
65+
echo strval($bool) . PHP_EOL;
66+
67+
echo (int) $bool . PHP_EOL;
68+
echo intval($bool) . PHP_EOL;
69+
70+
echo (float) $bool . PHP_EOL;
71+
echo floatval($bool) . PHP_EOL;
72+
73+
echo (string) $object . PHP_EOL;
74+
echo strval($object) . PHP_EOL;
75+
76+
echo (int) $object . PHP_EOL;
77+
echo intval($object) . PHP_EOL;
78+
79+
echo (float) $object . PHP_EOL;
80+
echo floatval($object) . PHP_EOL;
81+
82+
echo (string) $stringable . PHP_EOL;
83+
echo strval($stringable) . PHP_EOL;
84+
85+
echo (int) $stringable . PHP_EOL;
86+
echo intval($stringable) . PHP_EOL;
87+
88+
echo (float) $stringable . PHP_EOL;
89+
echo floatval($stringable) . PHP_EOL;
90+
91+
echo (string) $mixed . PHP_EOL;
92+
echo strval($mixed) . PHP_EOL;
93+
94+
echo (int) $mixed . PHP_EOL;
95+
echo intval($mixed) . PHP_EOL;
96+
97+
echo (float) $mixed . PHP_EOL;
98+
echo floatval($mixed) . PHP_EOL;

0 commit comments

Comments
 (0)