diff --git a/src/Psalm/Internal/Provider/ReturnTypeProvider/StrReplaceReturnTypeProvider.php b/src/Psalm/Internal/Provider/ReturnTypeProvider/StrReplaceReturnTypeProvider.php index 2dfa3681691..6b5270e40d5 100644 --- a/src/Psalm/Internal/Provider/ReturnTypeProvider/StrReplaceReturnTypeProvider.php +++ b/src/Psalm/Internal/Provider/ReturnTypeProvider/StrReplaceReturnTypeProvider.php @@ -10,6 +10,7 @@ use Psalm\Type\Atomic\TString; use Psalm\Type\Union; +use function call_user_func; use function count; use function in_array; @@ -50,7 +51,24 @@ public static function getFunctionReturnType(FunctionReturnTypeProviderEvent $ev $return_type = Type::getString(); - if (in_array($function_id, ['preg_replace', 'preg_replace_callback'], true)) { + if (in_array($function_id, ['str_replace', 'str_ireplace'], true) + && $subject_type->isSingleStringLiteral() + ) { + $first_arg = $statements_source->node_data->getType($call_args[0]->value); + $second_arg = $statements_source->node_data->getType($call_args[1]->value); + if ($first_arg && $second_arg && $first_arg->isSingleStringLiteral() && $second_arg->isSingleStringLiteral()) { + /** + * @var string $replaced_string + */ + $replaced_string = call_user_func( + $function_id, + $first_arg->getSingleStringLiteral()->value, + $second_arg->getSingleStringLiteral()->value, + $subject_type->getSingleStringLiteral()->value + ); + $return_type = Type::getString($replaced_string); + } + } elseif (in_array($function_id, ['preg_replace', 'preg_replace_callback'], true)) { $return_type = new Union([new TString, new TNull()]); $codebase = $statements_source->getCodebase();