diff --git a/src/Type/Php/StrPadFunctionReturnTypeExtension.php b/src/Type/Php/StrPadFunctionReturnTypeExtension.php index fd98d36ae4..92b0ec286d 100644 --- a/src/Type/Php/StrPadFunctionReturnTypeExtension.php +++ b/src/Type/Php/StrPadFunctionReturnTypeExtension.php @@ -6,6 +6,7 @@ use PHPStan\Analyser\Scope; use PHPStan\Reflection\FunctionReflection; use PHPStan\Type\Accessory\AccessoryLiteralStringType; +use PHPStan\Type\Accessory\AccessoryLowercaseStringType; use PHPStan\Type\Accessory\AccessoryNonEmptyStringType; use PHPStan\Type\Accessory\AccessoryNonFalsyStringType; use PHPStan\Type\DynamicFunctionReturnTypeExtension; @@ -44,15 +45,17 @@ public function getTypeFromFunctionCall( $accessoryTypes[] = new AccessoryNonEmptyStringType(); } - if ($inputType->isLiteralString()->yes()) { - if (count($args) < 3) { - $accessoryTypes[] = new AccessoryLiteralStringType(); - } else { - $padStringType = $scope->getType($args[2]->value); - if ($padStringType->isLiteralString()->yes()) { - $accessoryTypes[] = new AccessoryLiteralStringType(); - } - } + if (count($args) < 3) { + $padStringType = null; + } else { + $padStringType = $scope->getType($args[2]->value); + } + + if ($inputType->isLiteralString()->yes() && ($padStringType === null || $padStringType->isLiteralString()->yes())) { + $accessoryTypes[] = new AccessoryLiteralStringType(); + } + if ($inputType->isLowercaseString()->yes() && ($padStringType === null || $padStringType->isLowercaseString()->yes())) { + $accessoryTypes[] = new AccessoryLowercaseStringType(); } if (count($accessoryTypes) > 0) { diff --git a/src/Type/Php/StrRepeatFunctionReturnTypeExtension.php b/src/Type/Php/StrRepeatFunctionReturnTypeExtension.php index 22c9714168..632fea85f0 100644 --- a/src/Type/Php/StrRepeatFunctionReturnTypeExtension.php +++ b/src/Type/Php/StrRepeatFunctionReturnTypeExtension.php @@ -7,6 +7,7 @@ use PHPStan\Analyser\Scope; use PHPStan\Reflection\FunctionReflection; use PHPStan\Type\Accessory\AccessoryLiteralStringType; +use PHPStan\Type\Accessory\AccessoryLowercaseStringType; use PHPStan\Type\Accessory\AccessoryNonEmptyStringType; use PHPStan\Type\Accessory\AccessoryNonFalsyStringType; use PHPStan\Type\Accessory\AccessoryNumericStringType; @@ -93,6 +94,10 @@ public function getTypeFromFunctionCall( } } + if ($inputType->isLowercaseString()->yes()) { + $accessoryTypes[] = new AccessoryLowercaseStringType(); + } + if (count($accessoryTypes) > 0) { $accessoryTypes[] = new StringType(); return new IntersectionType($accessoryTypes); diff --git a/tests/PHPStan/Analyser/nsrt/literal-string.php b/tests/PHPStan/Analyser/nsrt/literal-string.php index ff63036d9b..93bf8949d9 100644 --- a/tests/PHPStan/Analyser/nsrt/literal-string.php +++ b/tests/PHPStan/Analyser/nsrt/literal-string.php @@ -36,9 +36,9 @@ public function doFoo($literalString, string $string, $numericString) "'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'", str_repeat('a', 99) ); - assertType('literal-string&non-falsy-string', str_repeat('a', 100)); - assertType('literal-string&non-empty-string&numeric-string', str_repeat('0', 100)); // could be non-falsy-string - assertType('literal-string&non-falsy-string&numeric-string', str_repeat('1', 100)); + assertType('literal-string&lowercase-string&non-falsy-string', str_repeat('a', 100)); + assertType('literal-string&lowercase-string&non-empty-string&numeric-string', str_repeat('0', 100)); // could be non-falsy-string + assertType('literal-string&lowercase-string&non-falsy-string&numeric-string', str_repeat('1', 100)); // Repeating a numeric type multiple times can lead to a non-numeric type: 3v4l.org/aRBdZ assertType('non-empty-string', str_repeat($numericString, 100)); @@ -51,13 +51,13 @@ public function doFoo($literalString, string $string, $numericString) assertType("non-empty-string", str_repeat($numericString, 2)); assertType("literal-string", str_repeat($literalString, 1)); $x = rand(1,2); - assertType("literal-string&non-falsy-string", str_repeat(' 1 ', $x)); - assertType("literal-string&non-falsy-string", str_repeat('+1', $x)); - assertType("literal-string&non-falsy-string", str_repeat('1e9', $x)); - assertType("literal-string&non-falsy-string&numeric-string", str_repeat('19', $x)); + assertType("literal-string&lowercase-string&non-falsy-string", str_repeat(' 1 ', $x)); + assertType("literal-string&lowercase-string&non-falsy-string", str_repeat('+1', $x)); + assertType("literal-string&lowercase-string&non-falsy-string", str_repeat('1e9', $x)); + assertType("literal-string&lowercase-string&non-falsy-string&numeric-string", str_repeat('19', $x)); $x = rand(0,2); - assertType("literal-string", str_repeat('19', $x)); + assertType("literal-string&lowercase-string", str_repeat('19', $x)); $x = rand(-10,-1); assertType("*NEVER*", str_repeat('19', $x)); diff --git a/tests/PHPStan/Analyser/nsrt/lowercase-string-pad.php b/tests/PHPStan/Analyser/nsrt/lowercase-string-pad.php new file mode 100644 index 0000000000..79633d7538 --- /dev/null +++ b/tests/PHPStan/Analyser/nsrt/lowercase-string-pad.php @@ -0,0 +1,23 @@ +