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

Improve accuracy of optional example

This commit is contained in:
Matt Brown 2020-12-10 01:12:58 -05:00
parent e6dad6e65f
commit 37659445f0
2 changed files with 41 additions and 14 deletions

View File

@ -229,7 +229,8 @@ class TemplateInferredTypeReplacer
? clone $inferred_upper_bounds[$atomic_type->param_name][$atomic_type->defining_class]->type ? clone $inferred_upper_bounds[$atomic_type->param_name][$atomic_type->defining_class]->type
: null; : null;
$class_template_type = null; $if_template_type = null;
$else_template_type = null;
$atomic_type = clone $atomic_type; $atomic_type = clone $atomic_type;
@ -270,37 +271,53 @@ class TemplateInferredTypeReplacer
$else_candidate_type = $matching_else_types ? new Type\Union($matching_else_types) : null; $else_candidate_type = $matching_else_types ? new Type\Union($matching_else_types) : null;
if ($if_candidate_type if ($if_candidate_type
&& !$else_candidate_type
&& UnionTypeComparator::isContainedBy( && UnionTypeComparator::isContainedBy(
$codebase, $codebase,
$if_candidate_type, $if_candidate_type,
$atomic_type->conditional_type $atomic_type->conditional_type
) )
) { ) {
$class_template_type = clone $atomic_type->if_type; $if_template_type = clone $atomic_type->if_type;
$refined_template_result = clone $template_result;
$refined_template_result->upper_bounds[$atomic_type->param_name][$atomic_type->defining_class]
= new \Psalm\Internal\Type\TemplateBound(
$if_candidate_type
);
self::replace( self::replace(
$class_template_type, $if_template_type,
$template_result, $refined_template_result,
$codebase $codebase
); );
} elseif (!$if_candidate_type }
&& $else_candidate_type
if ($else_candidate_type
&& UnionTypeComparator::isContainedBy( && UnionTypeComparator::isContainedBy(
$codebase, $codebase,
$else_candidate_type, $else_candidate_type,
$atomic_type->as_type $atomic_type->as_type
) )
) { ) {
$class_template_type = clone $atomic_type->else_type; $else_template_type = clone $atomic_type->else_type;
$refined_template_result = clone $template_result;
$refined_template_result->upper_bounds[$atomic_type->param_name][$atomic_type->defining_class]
= new \Psalm\Internal\Type\TemplateBound(
$else_candidate_type
);
self::replace( self::replace(
$class_template_type, $else_template_type,
$template_result, $refined_template_result,
$codebase $codebase
); );
} }
} }
if (!$class_template_type) { if (!$if_template_type && !$else_template_type) {
self::replace( self::replace(
$atomic_type->if_type, $atomic_type->if_type,
$template_result, $template_result,
@ -318,6 +335,16 @@ class TemplateInferredTypeReplacer
$atomic_type->else_type, $atomic_type->else_type,
$codebase $codebase
); );
} elseif ($if_template_type && !$else_template_type) {
$class_template_type = $if_template_type;
} elseif (!$if_template_type) {
$class_template_type = $else_template_type;
} else {
$class_template_type = Type::combineUnionTypes(
$if_template_type,
$else_template_type,
$codebase
);
} }
$keys_to_unset[] = $key; $keys_to_unset[] = $key;

View File

@ -674,9 +674,9 @@ class ConditionalReturnTypeTest extends TestCase
public string $name = "Dave"; public string $name = "Dave";
} }
function takesNullableUser(?User $user) : void { /** @return User|NullObject */
$name = optional($user); function takesNullableUser(?User $user) {
if ($name instanceof NullObject) {} return optional($user);
} }
class NullObject { class NullObject {