mirror of
https://github.com/danog/psalm.git
synced 2024-11-27 04:45:20 +01:00
Fix #4943
Prevent input types becoming part of the inferred generic params when a match is found
This commit is contained in:
parent
c1a710999c
commit
6ef0f2e63e
@ -18,6 +18,11 @@ class TemplateStandinTypeReplacer
|
||||
{
|
||||
/**
|
||||
* This replaces template types in unions with standins (normally the template as type)
|
||||
*
|
||||
* $input_type here is normally the argument passed to a templated function or method.
|
||||
*
|
||||
* This method fills in the values in $template_result based on how the various atomic types
|
||||
* of $union_type match up to the types inside $input_type
|
||||
*/
|
||||
public static function replace(
|
||||
Union $union_type,
|
||||
@ -36,6 +41,23 @@ class TemplateStandinTypeReplacer
|
||||
|
||||
$original_atomic_types = $union_type->getAtomicTypes();
|
||||
|
||||
// here we want to subtract atomic types from the input type
|
||||
// when they're also in the union type, so those shared atomic
|
||||
// types will never be inferred as part of the generic type
|
||||
if ($input_type && !$input_type->isSingle()) {
|
||||
$new_input_type = clone $input_type;
|
||||
|
||||
foreach ($original_atomic_types as $key => $_) {
|
||||
if ($new_input_type->hasType($key)) {
|
||||
$new_input_type->removeType($key);
|
||||
}
|
||||
}
|
||||
|
||||
if ($new_input_type->getAtomicTypes()) {
|
||||
$input_type = $new_input_type;
|
||||
}
|
||||
}
|
||||
|
||||
$had_template = false;
|
||||
|
||||
foreach ($original_atomic_types as $key => $atomic_type) {
|
||||
|
@ -1444,6 +1444,47 @@ class FunctionTemplateTest extends TestCase
|
||||
|
||||
$value = takesClosure(function(Foo $foo) : void {})(new Foo());'
|
||||
],
|
||||
'subtractTemplatedNull' => [
|
||||
'<?php
|
||||
/**
|
||||
* @template T
|
||||
* @param T|null $var
|
||||
* @return T
|
||||
*/
|
||||
function notNull($var) {
|
||||
if ($var === null) {
|
||||
throw new \InvalidArgumentException("");
|
||||
}
|
||||
|
||||
return $var;
|
||||
}
|
||||
|
||||
function takesNullableString(?string $s) : string {
|
||||
return notNull($s);
|
||||
}'
|
||||
],
|
||||
'subtractTemplatedInt' => [
|
||||
'<?php
|
||||
/**
|
||||
* @template T
|
||||
* @param T|int $var
|
||||
* @return T
|
||||
*/
|
||||
function notNull($var) {
|
||||
if (\is_int($var)) {
|
||||
throw new \InvalidArgumentException("");
|
||||
}
|
||||
|
||||
return $var;
|
||||
}
|
||||
|
||||
function takesNullableString(string|int $s) : string {
|
||||
return notNull($s);
|
||||
}',
|
||||
[],
|
||||
[],
|
||||
'8.0'
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user