Change:
Cc Will fill the content later. Creating this so that can be merged and tracked.
The code generated by is really complicated and inefficient. Godbolt link: Should we add / method directly to or trait?
Oof that does indeed look pretty bad.
I whipped up that fix here: Not sure if it's actually the ideal fix, but figured it would be a good point to launch the discussion from.
Ok, the code should be far more optimized now. What remains to be done? The main issue description has yet to be filled in.
On , I'm seeing that is much faster than , at least for newlines only. Is this only because I'm stripping off a very small amount of text, or is this function more optimized than (assuming that I didn't screw something up)? See "Standard strip suffix" versus "Standard trim end", with "unix" having the input of and "win" being : !
Ah, yeah, looks the optimizations I made to stripprefix/stripsuffix in are optimizations that don't exist for : I wonder if could be reimplemented as a loop over ... By the way, since I'm here, (or anyone else on the Rust team), what remains to be done for this issue?
If you want to change the implementation this is a good time. Else, the thing left is stabilisation with the libs team approving it (if needed) but i'd wait for some time to check if there are any other issues.
The implementation is now faster than the existing similar stable functions and , so I think we're in a good spot implementation wise. Would you be able to add a note about the progress and when we expect to start the stabilization discussion in the issue description? (Or whatever normally goes in there?)
you can submit a stabilisation PR by following the instructions here:

Discussion:
/// # Examples /// /// ``` <del> /// #![feature(str_strip)] /// </del> /// assert_eq!("foo:bar".strip_prefix("foo:"), Some("bar")); /// assert_eq!("foo:bar".strip_prefix("bar"), None); /// assert_eq!("foofoo".strip_prefix("foo"), Some("foo")); /// ``` #[must_use = "this returns the remaining substring as a new slice,  without modifying the original"] <del> #[unstable(feature = "str_strip", reason = "newly added", issue = "67302")] </del> <ins> #[stable(feature = "str_strip", since = "1.45.0")] </ins> pub fn strip_prefix<'a, P: Pattern<'a>>(&'a self, prefix: P) -> Option<&'a str> { prefix.strip_prefix_of(self) }

/// # Examples /// /// ``` <del> /// #![feature(str_strip)] </del> /// assert_eq!("bar:foo".strip_suffix(":foo"), Some("bar")); /// assert_eq!("bar:foo".strip_suffix("bar"), None); /// assert_eq!("foofoo".strip_suffix("foo"), Some("foo")); /// ``` #[must_use = "this returns the remaining substring as a new slice,  without modifying the original"] <del> #[unstable(feature = "str_strip", reason = "newly added", issue = "67302")] </del> <ins> #[stable(feature = "str_strip", since = "1.45.0")] </ins> pub fn strip_suffix<'a, P>(&'a self, suffix: P) -> Option<&'a str> where P: Pattern<'a>,

#![feature(in_band_lifetimes)] #![feature(crate_visibility_modifier)] #![feature(or_patterns)] <del> #![feature(str_strip)] </del> #![feature(option_zip)] #![recursion_limit = "512"] // For rustdoc

#![cfg_attr(feature = "deny-warnings", deny(warnings))] #![feature(rustc_private)] <del> #![feature(str_strip)] </del> // FIXME: switch to something more ergonomic here, once available. // (Currently there is no way to opt into sysroot crates without `extern crate`.)