Skip to content

Commit

Permalink
Fixed Scramble mutating return type if it has templates in it (#524)
Browse files Browse the repository at this point in the history
* fixed mutating method returns

* Fix styling

---------

Co-authored-by: romalytvynenko <[email protected]>
  • Loading branch information
romalytvynenko and romalytvynenko authored Sep 6, 2024
1 parent 8eb2672 commit 3bc745c
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 1 deletion.
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"require": {
"php": "^8.1",
"illuminate/contracts": "^10.0|^11.0",
"myclabs/deep-copy": "^1.12",
"nikic/php-parser": "^5.0",
"phpstan/phpdoc-parser": "^1.0",
"spatie/laravel-package-tools": "^1.9.2"
Expand Down
4 changes: 3 additions & 1 deletion src/Infer/Services/ReferenceTypeResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
use Illuminate\Support\Collection;
use Illuminate\Support\Str;

use function DeepCopy\deep_copy;

class ReferenceTypeResolver
{
public function __construct(
Expand Down Expand Up @@ -558,7 +560,7 @@ private function getFunctionCallResult(
$this->prepareArguments($callee, $arguments),
))->mapWithKeys(fn ($searchReplace) => [$searchReplace[0]->name => $searchReplace[1]])->toArray());

$returnType = (new TypeWalker)->replace($returnType, function (Type $t) use ($inferredTemplates) {
$returnType = (new TypeWalker)->replace(deep_copy($returnType), function (Type $t) use ($inferredTemplates) {
if (! $t instanceof TemplateType) {
return null;
}
Expand Down
19 changes: 19 additions & 0 deletions tests/Infer/ReferenceTypesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,25 @@ public function bar () {
->toBe('(): int(2)');
});

it('correctly replaces templates without modifying type', function () {
$type = analyzeFile(<<<'EOD'
<?php
class Foo {
public function foo ($a) {
return ['a' => $a];
}
}
EOD);

/*
* Previously this test would fail due to original return type being mutated.
*/
$type->getExpressionType('(new Foo)->foo(123)');

expect($type->getExpressionType('(new Foo)->foo(42)')->toString())
->toBe('array{a: int(42)}');
});

it('resolves a cyclic reference safely', function () {
$type = analyzeFile(<<<'EOD'
<?php
Expand Down

0 comments on commit 3bc745c

Please sign in to comment.