Stable Rust: Where is documented which argument strip_prefix or split_once accept?

Where can I find information on the allowed types of values that are passed as argument to strip_prefix or split_once on stable Rust? The corresponding Pattern trait is unstable yet.

Do I have to try-and-error using stable Rust?

Sorry if I misunderstood the complexity of your question, but aren't you just looking for the implementors of Pattern here?

If you look at the types implementing Pattern you will find that the following types are accepted:

  • char
  • &str
  • &String
  • &[char]
  • &&str
  • &[char; N
  • impl FnMut(char) -> bool
  • [char; N]

Yes, but those which are stabilized.

All trait implementations are stable. Rustc doesn't currently support unstable trait impls.


But the whole Pattern API is unstable.

Whatever happens to Pattern, the set of types that are documented as implementing it now is stable in the sense that those types are guaranteed to always be accepted by the relevant functions.

I think implementing Pattern for your own type is considered unstable, not the implementation of it in the standard library

Is that documented somewhere?

Well, kinda. In the tracking issue it says:

We have many APIs which support the ability to search with any number of patterns generically within a string (e.g. substrings, characters, closures, etc), but implementing your own pattern (e.g. a regex) is not stable. It would be nice if these implementations could indeed be stable!

It’s a direct consequence of Rust’s compatibility policy. Any change to a stable function cannot break existing code. Thus if a function accepts type T now, it must always do that, no matter how exactly it does that.

1 Like

It won't be a huge problem for me (in my current use case) if something breaks, but…

I don't see an explicit guarantee this applies to all implementations that might be added or removed while the unstable trait is moving towards stabilization.

For that being relevant for a user of the API, it would needed to be documented as stable in the first place, which is what I'm arguing about.

You mean like here where it says it's been stable since Rust 1.45.0?

1 Like

The method is stable, of course. But it's not documented which types I may pass as prefix, except in the unstable trait Pattern.

But if your users break your stable API with their own implementation of the unstable Pattern trait, aren't they at fault?

1 Like

I can only blame a 3rd party when I expose the (unstable) Pattern trait in my API.

What I meant in my OP is this:

fn main() {
    let x = "Hello World!";
    // Where is it documented that each of those is stable?
    let y = x.strip_suffix('!').unwrap();
    let z = x.strip_suffix("!").unwrap();


Apparently I just noticed that the (stable) documentation of strip_suffix does mention which types are supported:

The pattern can be a &str, char, a slice of chars, or a function or closure that determines if a character matches.

I overlooked that part, because I was checking out split_once first, and that section is missing there.

P.S.: I will just assume that it's the same in both cases, but maybe it would be good to add it to the documentation of split_once. (But perhaps I'm the only one who would even notice/care :sweat_smile:.)

But the point is that even though Pattern is unstable, it logically follows that the set of types implementing it must be a (non-strict) subset of the set of types accepted by the stable function strip_prefix. Anything else would break the compatibility contract of the stable function.

These types listed in Pattern's documentation must always be accepted by strip_prefix &co, even if the trait itself goes totally away. At least until Rust 2. Thus, you can think of the contract of these functions as "I accept any of the following types", it's just that the mechanism by which it does so is unstable.

Pattern type Match condition
&str is substring
char is contained in string
&[char] any char in slice is contained in string
F: FnMut(char) -> bool F returns true for a char in string
&&str is substring
&String is substring
1 Like

I think my disagreement is about what's documented to be stable (and can be relied upon). It's difficult (for me) to judge about which part of the documentation refers to something that is stable and which part refers to something that is not stable.

I naïvely assume(d) that anything that's under a :microscope: This is a nightly-only experimental API warning is unstable and might change.

But I think maybe I get your point now. Because split_once is stable all implementations of it must be stable too. Maybe that makes sense, but it's pretty much implicit and requires some assumptions in regard to what it means if a method is defined for types implementing an unstable trait.

1 Like

I don't know if there is a documentation defining how unstable APIs and features behave.[1]

But you'll never be surprised at ? and DST in daily use, both of which are unstable w.r.t their traits:

  1. I do know there is an official book The Unstable Book - The Rust Unstable Book listing all unstable functionalities in Rust. ↩︎

1 Like

From my perspective this is accurate. Pattern is in principle allowed to change the same way as any other unstable item, as long as stable functions which use it like strip_prefix are refactored when needed so that the change does not cause any breakage. Deleting an impl like impl Pattern for char is theoretically possible, but would require a new trait to take its place for strip_prefix and co. to use so that "abc".strip_prefix('a') still works after the change.

1 Like