1
0
mirror of https://github.com/danog/psalm.git synced 2025-01-22 05:41:20 +01:00

Fix mixed type hole when sending Foo<string> to Foo<mixed> (#8481)

* Fix mixed type hole when sending Foo<string> to Foo<mixed>

* Fix ifThisIs test

* Suppress bugs highlighted with fix

* Fix PHPDoc parsing
This commit is contained in:
Matthew Brown 2022-09-13 13:13:06 -04:00 committed by GitHub
parent afe85fad86
commit d957ff2015
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 28 additions and 12 deletions

View File

@ -52,6 +52,7 @@
"phpunit/phpunit": "^9.5", "phpunit/phpunit": "^9.5",
"psalm/plugin-phpunit": "^0.16", "psalm/plugin-phpunit": "^0.16",
"slevomat/coding-standard": "^7.0", "slevomat/coding-standard": "^7.0",
"phpstan/phpdoc-parser": "1.6.4",
"squizlabs/php_codesniffer": "^3.6", "squizlabs/php_codesniffer": "^3.6",
"symfony/process": "^4.3 || ^5.0 || ^6.0" "symfony/process": "^4.3 || ^5.0 || ^6.0"
}, },

View File

@ -38,6 +38,7 @@
<file name="vendor/felixfbecker/advanced-json-rpc/lib/Dispatcher.php" /> <file name="vendor/felixfbecker/advanced-json-rpc/lib/Dispatcher.php" />
<directory name="vendor/netresearch/jsonmapper" /> <directory name="vendor/netresearch/jsonmapper" />
<directory name="vendor/phpunit" /> <directory name="vendor/phpunit" />
<file name="vendor/nikic/php-parser/lib/PhpParser/Node/UnionType.php" />
</ignoreFiles> </ignoreFiles>
</projectFiles> </projectFiles>

View File

@ -57,6 +57,8 @@ class TextDocument
* @param TextDocumentIdentifier $textDocument The document to get the content for * @param TextDocumentIdentifier $textDocument The document to get the content for
* *
* @return Promise<TextDocumentItem> The document's current content * @return Promise<TextDocumentItem> The document's current content
*
* @psalm-suppress MixedReturnTypeCoercion due to Psalm bug
*/ */
public function xcontent(TextDocumentIdentifier $textDocument): Promise public function xcontent(TextDocumentIdentifier $textDocument): Promise
{ {

View File

@ -167,13 +167,7 @@ class GenericTypeComparator
) { ) {
// do nothing // do nothing
} else { } else {
if ($container_param->hasMixed() || $container_param->isArrayKey()) { $all_types_contain = false;
if ($atomic_comparison_result) {
$atomic_comparison_result->type_coerced_from_mixed = true;
}
} else {
$all_types_contain = false;
}
if ($atomic_comparison_result) { if ($atomic_comparison_result) {
$atomic_comparison_result->type_coerced = false; $atomic_comparison_result->type_coerced = false;

View File

@ -219,7 +219,7 @@ class IfThisIsTest extends TestCase
'ifThisIsResolveTemplateParams' => [ 'ifThisIsResolveTemplateParams' => [
'code' => '<?php 'code' => '<?php
/** /**
* @template T * @template-covariant T
*/ */
final class Option final class Option
{ {
@ -228,8 +228,8 @@ class IfThisIsTest extends TestCase
} }
/** /**
* @template L * @template-covariant L
* @template R * @template-covariant R
*/ */
final class Either final class Either
{ {

View File

@ -987,15 +987,16 @@ class ClassTemplateExtendsTest extends TestCase
} }
} }
/** @var SplObjectStorage<\stdClass, string> */ /** @var SplObjectStorage<\stdClass, mixed> */
$storage = new SplObjectStorage(); $storage = new SplObjectStorage();
new SomeService($storage); new SomeService($storage);
$c = new \stdClass(); $c = new \stdClass();
$storage[$c] = "hello"; $storage[$c] = "hello";
/** @psalm-suppress MixedAssignment */
$b = $storage->offsetGet($c);', $b = $storage->offsetGet($c);',
'assertions' => [ 'assertions' => [
'$b' => 'string', '$b' => 'mixed',
], ],
], ],
'extendsArrayIterator' => [ 'extendsArrayIterator' => [

View File

@ -4600,6 +4600,23 @@ class ClassTemplateTest extends TestCase
final class Three {}', final class Three {}',
'error_message' => 'InvalidReturnStatement - src' . DIRECTORY_SEPARATOR . 'somefile.php:12:40 - The inferred type \'T:A as One|Two\' ', 'error_message' => 'InvalidReturnStatement - src' . DIRECTORY_SEPARATOR . 'somefile.php:12:40 - The inferred type \'T:A as One|Two\' ',
], ],
'preventMixedNestedCoercion' => [
'code' => '<?php
/** @template T */
class MyCollection {
/** @param array<T> $members */
public function __construct(public array $members) {}
}
/**
* @param MyCollection<string> $c
* @return MyCollection<mixed>
*/
function getMixedCollection(MyCollection $c): MyCollection {
return $c;
}',
'error_message' => 'InvalidReturnStatement',
],
]; ];
} }
} }