trait Bar {}
trait Foo {
fn func(self) -> Self
where Self: Bar;
..other items..
}
Right now, there is no way to implement Foo for a type that doesn't implement Bar without refining fn func to not have the bound, defeating its entire purpose. There are sometimes some work arounds, like you could do this:
struct SomeType<T> {...}
/// # Safety
/// just don't
unsafe trait NoImpl {}
impl<T: NoImpl > Bar for SomeType<T> {}
impl Foo for SomeType {
fn func(self) -> Self
where Self: Bar {
unimplemented!();
}
..other items..
}
(or implementing it for an empty enum/!)
but this requires a generic and Bar not to be something like Send or Sync which can often defeat the whole purpose, especially when using traits a impl blocks on foreign types. This also makes it appear that there may be some way to access fn func on SomeType even when its entirely inaccessible.
Removing the requirement to include the function would fix this problem. Done universally, this would cause a issue where new trait impl are now breaking changes, so instead it needs to have the following restraint: The trait in the where bound that is unsatisfiable must be defined in the same crate and doesn't have any auto-impl that could be satisfied for the type by the type gaining new foreign trait impls.
Simply having the type being local isn't enough because if the trait got a new auto-impl or loosened the restrictions on its auto-impl, it would be a breaking change.
You might be interested to learn that actually one can add the bound: For some reason, rustc doesnāt care so much anymore about āimpossibleā bounds if you add some higher-ranked lifetime to it. So e.g. while
impl Foo for SomeType {
fn func(self) -> Self
where
Self: Bar,
{
unreachable!()
}
}
is rejected, doing this instead is actually accepted:
impl Foo for SomeType {
fn func(self) -> Self
where
for<'a> Self: Bar,
{
unreachable!()
}
}
(equivalently: Self: for<'a> Bar. Also I somethimes would write this using for<'__> Self: Bar marking the name of the lifetime more clearly āirrelevantā, arguably.)
Also for Self: Sized as a bound, you are allowed to skip the method. This seems like deliberate design, so itās probably possible to find prior discussion somewhere, giving a clue on why that particular case is supported but more cases seem not to.
Refinement tracking issue, so you could write a method without the bounds when they aren't met, and actually make use of it
Trivial bounds tracking issue, so you could write a method with the trivially unmet bounds present without a compiler error
That has an issue, but is also a workaround for the lack of stable trivial bounds. (As is writing a method without bounds, but you can't currently call it.)
This is, I believe, an accidental stabilisation; the feature to allow trivial bounds is unstable (see the tracking issue linked earlier) but you can opt-in to it on stable Rust by adding a pointless higher-ranked lifetime, and lots of people seem to have figured that out (and even the people who don't figure it out on their own may see the "see issue #48214" in the error message, and the issue in question discusses the workaround).
It's unclear what to do about this; trivial bounds are already intended to be added to Rust at some point in the future, and although they're meant to be unstable at the time being (and posibly have bugs), there is a trivial workaround to make use of them anyway, so lots of people are. The only real way to resolve the situation would be to stabilise the feature, but I can imagine that that might be undesirable for a feature that might not be fully working/tested yetā¦