1010use PHPStan \Type \Constant \ConstantIntegerType ;
1111use PHPStan \Type \Constant \ConstantStringType ;
1212use PHPStan \Type \FloatType ;
13+ use PHPStan \Type \IntegerRangeType ;
1314use PHPStan \Type \IntegerType ;
1415use PHPStan \Type \IntersectionType ;
1516use PHPStan \Type \IterableType ;
@@ -39,14 +40,17 @@ public static function create(TemplateTypeScope $scope, string $name, ?Type $bou
3940 }
4041
4142 $ boundClass = get_class ($ bound );
42- if ($ bound instanceof ObjectType && ($ boundClass === ObjectType::class || $ bound instanceof TemplateType)) {
43- return new TemplateObjectType ($ scope , $ strategy , $ variance , $ name , $ bound , $ default );
44- }
45-
4643 if ($ bound instanceof GenericObjectType && ($ boundClass === GenericObjectType::class || $ bound instanceof TemplateType)) {
4744 return new TemplateGenericObjectType ($ scope , $ strategy , $ variance , $ name , $ bound , $ default );
4845 }
4946
47+ // Catches plain ObjectType and any other object subtype without a dedicated
48+ // Template* class (e.g. enum-case object types), preserving the precise bound
49+ // instead of widening it to TemplateMixedType.
50+ if ($ bound instanceof ObjectType) {
51+ return new TemplateObjectType ($ scope , $ strategy , $ variance , $ name , $ bound , $ default );
52+ }
53+
5054 if ($ bound instanceof ObjectWithoutClassType && ($ boundClass === ObjectWithoutClassType::class || $ bound instanceof TemplateType)) {
5155 return new TemplateObjectWithoutClassType ($ scope , $ strategy , $ variance , $ name , $ bound , $ default );
5256 }
@@ -71,7 +75,7 @@ public static function create(TemplateTypeScope $scope, string $name, ?Type $bou
7175 return new TemplateConstantStringType ($ scope , $ strategy , $ variance , $ name , $ bound , $ default );
7276 }
7377
74- if ($ bound instanceof IntegerType && ($ boundClass === IntegerType::class || $ bound instanceof TemplateType)) {
78+ if ($ bound instanceof IntegerType && ($ boundClass === IntegerType::class || $ bound instanceof IntegerRangeType || $ bound instanceof TemplateType)) {
7579 return new TemplateIntegerType ($ scope , $ strategy , $ variance , $ name , $ bound , $ default );
7680 }
7781
@@ -83,7 +87,7 @@ public static function create(TemplateTypeScope $scope, string $name, ?Type $bou
8387 return new TemplateFloatType ($ scope , $ strategy , $ variance , $ name , $ bound , $ default );
8488 }
8589
86- if ($ bound instanceof BooleanType && ($ boundClass === BooleanType::class || $ bound instanceof TemplateType)) {
90+ if ($ bound instanceof BooleanType && ($ boundClass === BooleanType::class || $ bound-> isTrue ()-> yes () || $ bound -> isFalse ()-> yes () || $ bound instanceof TemplateType)) {
8791 return new TemplateBooleanType ($ scope , $ strategy , $ variance , $ name , $ bound , $ default );
8892 }
8993
0 commit comments