Skip to content

Commit

Permalink
fix: handle float type casting properly
Browse files Browse the repository at this point in the history
Regression fix for 0479532
  • Loading branch information
NanoSector committed Sep 16, 2024
1 parent b9c6add commit 8742b27
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 9 deletions.
24 changes: 15 additions & 9 deletions src/Mapper/Tree/Shell.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ public function withType(Type $newType): self
{
$clone = clone $this;
$clone->type = $newType;
$clone->value = self::castCompatibleValue($newType, $this->value);

return $clone;
}
Expand All @@ -91,17 +92,9 @@ public function type(): Type

public function withValue(mixed $value): self
{
// When the value is an integer and the type is a float, the value is
// cast to float, to follow the rule of PHP regarding acceptance of an
// integer value in a float type. Note that PHPStan/Psalm analysis
// applies the same rule.
if ($this->type instanceof FloatType && is_int($value)) {
$value = (float)$value;
}

$clone = clone $this;
$clone->hasValue = true;
$clone->value = $value;
$clone->value = self::castCompatibleValue($clone->type, $value);

return $clone;
}
Expand Down Expand Up @@ -173,4 +166,17 @@ public function path(): string

return implode('.', $path);
}

private static function castCompatibleValue(Type $type, mixed $value): mixed
{
// When the value is an integer and the type is a float, the value is
// cast to float, to follow the rule of PHP regarding acceptance of an
// integer value in a float type. Note that PHPStan/Psalm analysis
// applies the same rule.
if ($type instanceof FloatType && is_int($value)) {
return (float)$value;
}

return $value;
}
}
9 changes: 9 additions & 0 deletions tests/Integration/Mapping/UnionMappingTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,15 @@ public static function union_mapping_works_properly_data_provider(): iterable
'assertion' => fn (mixed $result) => self::assertNull($result),
];

yield 'nullable float with integer value' => [
'type' => 'float|null',
'source' => 42,
'assertion' => function (mixed $result) {
self::assertIsFloat($result);
self::assertEquals(42.0, $result);
},
];

yield 'string or list of string, with string' => [
'type' => 'string|list<string>',
'source' => 'foo',
Expand Down

0 comments on commit 8742b27

Please sign in to comment.