diff --git a/src/Type/TypeCombinator.php b/src/Type/TypeCombinator.php index 03ddffd988..cd776efa5f 100644 --- a/src/Type/TypeCombinator.php +++ b/src/Type/TypeCombinator.php @@ -3,8 +3,10 @@ namespace PHPStan\Type; use PHPStan\Type\Accessory\AccessoryArrayListType; +use PHPStan\Type\Accessory\AccessoryLowercaseStringType; use PHPStan\Type\Accessory\AccessoryNonEmptyStringType; use PHPStan\Type\Accessory\AccessoryType; +use PHPStan\Type\Accessory\AccessoryUppercaseStringType; use PHPStan\Type\Accessory\HasOffsetType; use PHPStan\Type\Accessory\HasOffsetValueType; use PHPStan\Type\Accessory\HasPropertyType; @@ -452,7 +454,10 @@ private static function compareTypesInUnion(Type $a, Type $b): ?array && ($b->describe(VerbosityLevel::value()) === 'non-empty-string' || $b->describe(VerbosityLevel::value()) === 'non-falsy-string') ) { - return [null, new StringType()]; + return [null, self::intersect( + new StringType(), + ...self::getAccessoryCaseStringTypes($b), + )]; } if ( @@ -461,7 +466,10 @@ private static function compareTypesInUnion(Type $a, Type $b): ?array && ($a->describe(VerbosityLevel::value()) === 'non-empty-string' || $a->describe(VerbosityLevel::value()) === 'non-falsy-string') ) { - return [new StringType(), null]; + return [self::intersect( + new StringType(), + ...self::getAccessoryCaseStringTypes($a), + ), null]; } if ( @@ -469,10 +477,11 @@ private static function compareTypesInUnion(Type $a, Type $b): ?array && $a->getValue() === '0' && $b->describe(VerbosityLevel::value()) === 'non-falsy-string' ) { - return [null, new IntersectionType([ + return [null, self::intersect( new StringType(), new AccessoryNonEmptyStringType(), - ])]; + ...self::getAccessoryCaseStringTypes($b), + )]; } if ( @@ -480,15 +489,32 @@ private static function compareTypesInUnion(Type $a, Type $b): ?array && $b->getValue() === '0' && $a->describe(VerbosityLevel::value()) === 'non-falsy-string' ) { - return [new IntersectionType([ + return [self::intersect( new StringType(), new AccessoryNonEmptyStringType(), - ]), null]; + ...self::getAccessoryCaseStringTypes($a), + ), null]; } return null; } + /** + * @return array + */ + private static function getAccessoryCaseStringTypes(Type $type): array + { + $accessory = []; + if ($type->isLowercaseString()->yes()) { + $accessory[] = new AccessoryLowercaseStringType(); + } + if ($type->isUppercaseString()->yes()) { + $accessory[] = new AccessoryUppercaseStringType(); + } + + return $accessory; + } + private static function unionWithSubtractedType( Type $type, ?Type $subtractedType, diff --git a/tests/PHPStan/Analyser/nsrt/bug-12312.php b/tests/PHPStan/Analyser/nsrt/bug-12312.php new file mode 100644 index 0000000000..f67d1aa3cb --- /dev/null +++ b/tests/PHPStan/Analyser/nsrt/bug-12312.php @@ -0,0 +1,140 @@ +