There's a discussion how to stabilize trait methods which clash with 3rd-party crates. A recent example is Iterator::intersperse
, which can't be stabilized because it clashes with itertools::Itertools::intersperse
, therefore stabilizing it would break a lot of crates.
My idea is to add a #[lower_priority]
attribute for decreasing the "priority" with which trait items are resolved:
pub trait Iterator {
#[lower_priority]
fn intersperse() {...}
}
When a method name is ambiguous, Rust chooses the method with the highest priority. Currently, trait methods have a lower priority than inherent methods. With the proposed #[lower_priority]
attribute, the priority can be decreased even further. This attribute can be added either to a trait method or to a trait as a whole.
With this attribute, standard library traits can be extended without having to worry about breaking third-party crates -- unless third-party crates also use the #[lower_priority]
attribute. This can be prevented by making the attribute perma-unstable, effectively allowing it only in the standard library and on Nightly. Another solution might be to allow assigning a priority as an integer:
#[priority(0)] // default priority of trait methods
#[priority(-1)] // lower priority
#[priority(-2)] // even lower priority
...
I would however recommend to disallow positive values: If people were able to increase their traits' priority, they might be tempted to do so proactively on all traits to prevent breakage in the future. I don't want to encourage this. (This reminds me of !important
in CSS (which is strongly discouraged) (though it's not a perfect analogy since CSS attributes have inheritance))
Another partial solution is the supertrait item shadowing RFC, but that RFC seems to only address the use cases with generic bounds:
use itertools::Itertools;
fn foo<I: Itertools<Item = i32>>(iter: I) {
for _ in iter.intersperse(0) {}
}
but not the use cases without generics:
use itertools::Itertools;
fn foo() {
for _ in (1..5).intersperse(0) {}
}
To be clear what I hope to achieve with this proposal: I want all additions to standard library traits to be 100% backwards compatible.