I know this would be a breaking change so I am not suggesting it but rather trying to understand the reasoning behind the str::replace return type.
Why doesn't it return a Cow<'s, str>? To me it seems reasonable that you could check if there are any pattern matches before allocating a new String. Of course this is just my assumption and I am sure there is a solid reason why this isn't the case.
I believe the main justification for this was that it is reasonable to expect replacement to actually occur, and most users of the function will approach it that way. If the function did return Cow, the vast majority of the time you're going to be converting it to String anyway, because you'll need to uniformly tolerate the replacing case.
The downside of this is as you noted: replace is less efficient if you're expecting it to be a no-op most of the time. In practice, this is not the common case, and where it is, there may be better ways to detect it an avoid calling replace in those cases to start with.
This sounds reasonable to me and am willing to bet that this was other people's idea as well. I guess I was just thinking along the lines of unknown input and having the potential for no replacements. Thanks for your answer.