1
0
mirror of https://github.com/danog/psalm.git synced 2025-01-21 21:31:13 +01:00

Strict int/float comparison for conditional types, improve range return type (#5601)

This commit is contained in:
AndrolGenhald 2021-04-09 10:28:48 -05:00 committed by GitHub
parent 5f4a21190f
commit 518d0af895
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 72 additions and 5 deletions

View File

@ -229,7 +229,12 @@ class TemplateInferredTypeReplacer
if (UnionTypeComparator::isContainedBy(
$codebase,
new Type\Union([$candidate_atomic_type]),
$atomic_type->conditional_type
$atomic_type->conditional_type,
false,
false,
null,
false,
false
)
&& (!$candidate_atomic_type instanceof Type\Atomic\TInt
|| $atomic_type->conditional_type->getId() !== 'float')
@ -238,7 +243,12 @@ class TemplateInferredTypeReplacer
} elseif (!UnionTypeComparator::isContainedBy(
$codebase,
$atomic_type->conditional_type,
new Type\Union([$candidate_atomic_type])
new Type\Union([$candidate_atomic_type]),
false,
false,
null,
false,
false
)) {
$matching_else_types[] = $candidate_atomic_type;
}
@ -251,7 +261,12 @@ class TemplateInferredTypeReplacer
&& UnionTypeComparator::isContainedBy(
$codebase,
$if_candidate_type,
$atomic_type->conditional_type
$atomic_type->conditional_type,
false,
false,
null,
false,
false
)
) {
$if_template_type = clone $atomic_type->if_type;
@ -274,7 +289,12 @@ class TemplateInferredTypeReplacer
&& UnionTypeComparator::isContainedBy(
$codebase,
$else_candidate_type,
$atomic_type->as_type
$atomic_type->as_type,
false,
false,
null,
false,
false
)
) {
$else_template_type = clone $atomic_type->else_type;

View File

@ -430,7 +430,7 @@ function abs($number) {}
* @param TStep $step
* @return (
* T is int
* ? (TStep is int ? non-empty-list<int> : non-empty-list<int|float>)
* ? (TStep is int ? non-empty-list<int> : non-empty-list<float>)
* : (
* T is float
* ? non-empty-list<float>

View File

@ -851,6 +851,26 @@ class FunctionCallTest extends TestCase
foo($x);
}',
],
'rangeWithIntOrFloatStep' => [
'<?php
/** @var int|float */
$step = 1;
$a = range(1, 10, $step);
/** @var int */
$step = 1;
$b = range(1, 10, $step);
/** @var float */
$step = 1.;
$c = range(1, 10, $step);
',
'assertions' => [
'$a' => 'non-empty-list<float|int>',
'$b' => 'non-empty-list<int>',
'$c' => 'non-empty-list<float>',
],
],
'duplicateNamespacedFunction' => [
'<?php
namespace Bar;

View File

@ -2562,6 +2562,33 @@ class ConditionalTest extends \Psalm\Tests\TestCase
return "";
}'
],
'strictIntFloatComparison' => [
'<?php
/**
* @psalm-suppress InvalidReturnType
* @psalm-suppress MismatchingDocblockReturnType
* @return ($bar is int ? list<int> : list<float>)
*/
function foo($bar): string {}
/** @var int */
$baz = 1;
$a = foo($baz);
/** @var float */
$baz = 1.;
$b = foo($baz);
/** @var int|float */
$baz = 1;
$c = foo($baz);
',
'assertions' => [
'$a' => 'list<int>',
'$b' => 'list<float>',
'$c' => 'list<float|int>',
],
],
];
}