Skip to content

Commit 62eb019

Browse files
bug symfony#61543 [TypeInfo] Prevent interfaces extending BackedEnum to be treated as BackedEnums (ettoredn)
This PR was merged into the 7.3 branch. Discussion ---------- [TypeInfo] Prevent interfaces extending BackedEnum to be treated as BackedEnums | Q | A | ------------- | --- | Branch? | 7.3 | Bug fix? | yes | New feature? | no | Deprecations? | no | Issues | | License | MIT Given ``` interface DummyBackedEnumInterface extends \BackedEnum { } ``` `TypeFactoryTrait.php::enum():249` throws exception `Class "DummyBackedEnumInterface" is not an enum` trying to get the backing type, which is not defined. ``` public static function enum(string $className, ?BuiltinType $backingType = null): EnumType { if (is_subclass_of($className, \BackedEnum::class)) { if (null === $backingType) { $reflectionBackingType = (new \ReflectionEnum($className))->getBackingType(); // <-- throws $typeIdentifier = TypeIdentifier::INT->value === (string) $reflectionBackingType ? TypeIdentifier::INT : TypeIdentifier::STRING; $backingType = new BuiltinType($typeIdentifier); } return new BackedEnumType($className, $backingType); } return new EnumType($className); } ``` This PR is meant as a fix. Upgrading to 7.3 broke my project because of this issue. The open problem is how TypeInfo should handle BackedEnums that have no backing type defined. Besides interfaces, I'm not aware of any other way this can happen. An alternative would be to extend `BackedEnumType` to support undefined backing type. Commits ------- fe49578 [TypeInfo] Prevent interfaces extending BackedEnum to be treated as BackedEnums
2 parents 854a592 + fe49578 commit 62eb019

File tree

4 files changed

+21
-1
lines changed

4 files changed

+21
-1
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\TypeInfo\Tests\Fixtures;
13+
14+
interface DummyBackedEnumInterface extends \BackedEnum
15+
{
16+
}

src/Symfony/Component/TypeInfo/Tests/Fixtures/ReflectionExtractableDummy.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ final class ReflectionExtractableDummy extends AbstractDummy
3737
public DummyBackedEnum $backedEnum;
3838
public ?DummyBackedEnum $nullableBackedEnum;
3939

40+
public DummyBackedEnumInterface $backedEnumInterface;
41+
4042
public int|string $union;
4143
public \Traversable&\Stringable $intersection;
4244

src/Symfony/Component/TypeInfo/Tests/TypeResolver/ReflectionTypeResolverTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use Symfony\Component\TypeInfo\Tests\Fixtures\AbstractDummy;
1818
use Symfony\Component\TypeInfo\Tests\Fixtures\Dummy;
1919
use Symfony\Component\TypeInfo\Tests\Fixtures\DummyBackedEnum;
20+
use Symfony\Component\TypeInfo\Tests\Fixtures\DummyBackedEnumInterface;
2021
use Symfony\Component\TypeInfo\Tests\Fixtures\DummyEnum;
2122
use Symfony\Component\TypeInfo\Tests\Fixtures\ReflectionExtractableDummy;
2223
use Symfony\Component\TypeInfo\Type;
@@ -67,6 +68,7 @@ public static function resolveDataProvider(): iterable
6768
yield [Type::nullable(Type::enum(DummyEnum::class)), $reflection->getProperty('nullableEnum')->getType()];
6869
yield [Type::enum(DummyBackedEnum::class), $reflection->getProperty('backedEnum')->getType()];
6970
yield [Type::nullable(Type::enum(DummyBackedEnum::class)), $reflection->getProperty('nullableBackedEnum')->getType()];
71+
yield [Type::object(DummyBackedEnumInterface::class), $reflection->getProperty('backedEnumInterface')->getType()];
7072
yield [Type::union(Type::int(), Type::string()), $reflection->getProperty('union')->getType()];
7173
yield [Type::intersection(Type::object(\Traversable::class), Type::object(\Stringable::class)), $reflection->getProperty('intersection')->getType()];
7274
}

src/Symfony/Component/TypeInfo/TypeResolver/ReflectionTypeResolver.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ public function resolve(mixed $subject, ?TypeContext $typeContext = null): Type
7676
default => $identifier,
7777
};
7878

79-
if (is_subclass_of($className, \UnitEnum::class)) {
79+
if (is_subclass_of($className, \UnitEnum::class) && !interface_exists($className)) {
8080
$type = Type::enum($className);
8181
} else {
8282
$type = Type::object($className);

0 commit comments

Comments
 (0)