Skip to content

Commit ef31b4f

Browse files
authored
Check types when argument is passed by reference for userland functions
1 parent ea95907 commit ef31b4f

File tree

5 files changed

+80
-1
lines changed

5 files changed

+80
-1
lines changed

src/Rules/FunctionCallParametersCheck.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ public function check(
252252
if ($this->checkArgumentTypes) {
253253
$parameterType = TypeUtils::resolveLateResolvableTypes($parameter->getType());
254254

255-
if (!$parameter->passedByReference()->createsNewVariable()) {
255+
if (!$parameter->passedByReference()->createsNewVariable() || !$isBuiltin) {
256256
$accepts = $this->ruleLevelHelper->acceptsWithReason($parameterType, $argumentValueType, $scope->isDeclareStrictTypes());
257257

258258
if (!$accepts->result) {

tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,10 @@ public function testPassingNonVariableToParameterPassedByReference(): void
297297
'Parameter #1 $array of function reset expects array|object, null given.',
298298
39,
299299
],
300+
[
301+
'Parameter #1 $s of function PassedByReference\bar expects string, int given.',
302+
48,
303+
],
300304
]);
301305
}
302306

@@ -1623,4 +1627,18 @@ public function testDiscussion10454(): void
16231627
]);
16241628
}
16251629

1630+
public function testBug10626(): void
1631+
{
1632+
$this->analyse([__DIR__ . '/data/bug-10626.php'], [
1633+
[
1634+
'Parameter #1 $value of function Bug10626\intByValue expects int, string given.',
1635+
16,
1636+
],
1637+
[
1638+
'Parameter #1 $value of function Bug10626\intByReference expects int, string given.',
1639+
17,
1640+
],
1641+
]);
1642+
}
1643+
16261644
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
namespace Bug10626;
4+
5+
function intByValue(int $value): void
6+
{
7+
8+
}
9+
10+
function intByReference(int &$value): void
11+
{
12+
13+
}
14+
15+
$notAnInt = 'not-an-int';
16+
intByValue($notAnInt);
17+
intByReference($notAnInt);

tests/PHPStan/Rules/Methods/CallStaticMethodsRuleTest.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -629,6 +629,21 @@ public function testBug5781(): void
629629
]);
630630
}
631631

632+
public function testBug8296(): void
633+
{
634+
$this->checkThisOnly = false;
635+
$this->analyse([__DIR__ . '/data/bug-8296.php'], [
636+
[
637+
'Parameter #1 $objects of static method Bug8296\VerifyLoginTask::continueDump() expects array<string, object>, array<string, Bug8296\stdClass|true> given.',
638+
12,
639+
],
640+
[
641+
'Parameter #1 $string of static method Bug8296\VerifyLoginTask::stringByRef() expects string, int given.',
642+
15,
643+
],
644+
]);
645+
}
646+
632647
public function testRequireExtends(): void
633648
{
634649
$this->checkThisOnly = false;
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
namespace Bug8296;
4+
5+
class VerifyLoginTask{
6+
7+
public static function dumpMemory() : void{
8+
$dummy = [
9+
"a" => new stdClass(),
10+
"b" => true
11+
];
12+
self::continueDump($dummy);
13+
14+
$string = 12345;
15+
self::stringByRef($string);
16+
}
17+
18+
/**
19+
* @phpstan-param array<string, object> $objects
20+
* @phpstan-param-out array<string, object> $objects
21+
*/
22+
private static function continueDump(array &$objects) : void{
23+
24+
}
25+
26+
private static function stringByRef(string &$string) : void{
27+
28+
}
29+
}

0 commit comments

Comments
 (0)