Substrings in older versions of Java used to reuse the character array of the original string instead making a copy. The flip side is that the original string must be retained in memory until all the substrings have “become garbage”. So there is a trade-off.
The Rust version has that same tradeoff; the string can't be deallocated until all the tokens' lifetimes have ended. (In this particular use case, that's not really a cost, since you probably need to keep the string available the whole time anyway.)
Go, which is garbage-collected, also does the slice-by-reference trick (but fails criterion #1 because it doesn't really have iterators).
Yeah. But there's also a bigger tradeoff which is having garbage collection in the first place. Rust lets you depend on immutability without having garbage collection to clean up the values for you, which is a really special thing.