Wouldn't using a different trait name also be a breaking change unless both traits are implemented by the same types?
Afterall the trait name is part of the stable docs.
Wouldn't using a different trait name also be a breaking change unless both traits are implemented by the same types?
Afterall the trait name is part of the stable docs.
I don't think appearing in stable docs matters as far as Rust's stability guarantees go, you can't directly use it without opting in to unstable features so there's no stable code out there that directly relies on its existence or functionality. Appearing in stable docs does make it relevant for people writing stable code, and it would make replacing/renaming it potentially confusing and undesirable that way, but it could still be done without breaking anyone's code (unless they're using the unstable feature, of course).
I would consider that a reasonable thing to add to the documentation of any method/function relying on it.
Some chapter somewhere on how unstable features work generally would be nice. I found almost zero documentation.
The rule, as I understand it, is that if you can write some code with a stable compiler without any #![feature]
s, then it's covered by the API stability guarantees. (Unless it depends on something explicitly documented as unstable-even-in-stable-code like Debug
output.) Since all of these types can be used in stable code today, it is a stable property that they can all be passed to strip_prefix
, split_once
, etc.
I understand many of the assumptions, rules, etc. brought up in this thread and I feel safe enough to use these impl
s, but I also still feel like there is (too) much interpretation/reasoning/indirection required to really conclude what is stable and what is not.
Rust forbids leaking private types into public interfaces, but it leaks unstable traits into stable interfaces. I understand it's not the same, and I understand why this is done. But I do feel like it might deserve a bit more explicit documentation as it's not really unambiguously clear what a stable function with bounds using unstable items means. Maybe it is clear to people who work on std
, but I feel like it can be very confusing for a reader of the docs.
To give some more examples:
Is it guaranteed that the bound will be using this named trait? Or a different trait? Or is it just guaranteed to work with the current impl
s of that trait? Could the trait get a lifetime parameter added in the future? etc. etc.
I agree that "what does unstable / features mean" should have a chapter somewhere.
AFAIK you can't stably name the trait, so no.
Changing the parameters of the method is a breaking change (though TBH one I could see slipping through).
let _: fn(&'static str, char) -> _ = str::strip_prefix::<'_, char>;
But I don't see how it couldn't be a trait of some sort in this case, even if that gets broken. [1]
And the cases I can imagine where a trait wouldn't be needed today (e.g. only one stable implementer) seem unlikely.
An unstable trait shape itself could change, yes. But AFAIK that can't directly break you on stable, since you can't name it. Changes to the shape might break some inference somewhere.
OK I can imagine, but nothing likely or feasible to implement in the next decade+, so... ↩︎
Note that you can't name the trait since it's unstable, nor can you somehow extract a mention of the trait from just the split_once
function signature. If the trait were replaced with a different trait (or renamed), this cannot break any programs unless the set of impls changed.
I would not expect the stability guarantees to include anything about the trait itself, but that doesn't matter for the purposes of writing programs in stable Rust.
I had one more thought in regard to the idea of "if it runs on stable Rust, it will run on stable Rust in future too".
That is not true. There are a lot of things which work fine but are explicitly documented to not be relied upon. RwLock priorities, for example, but I'm sure there's other things.
The (trait of the) bound is explicitly unstable. So I really have a hard time to argue that due to compatibility policies any implementations of an unstable trait are to be relied upon.
I feel like this is more a case of "it's obvious we won't remove any impl
s because bad things would happen if we did", but it's not documented, I guess (i.e. ambiguous in my opinion). Perhaps I'm too strict though with my view.
That said: I don't think it's a big deal or big problem.
Do you know what sealed trait is?
Actually sealed traits are very common and works precisely like “unstable trait in a stable interface”.
Note that all these things are precisely and exactly the same in case of sealed traits.
If you are using Rust you are supposed to know about sealed traits and then unstable traits work using the exact same approach.
I can see the similarity to sealed traits.
This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.