Closed
Description
Before #23026, it was possible to use where clauses to have traits that must be implemented together, like:
pub trait Map where Self: Lookup<Self::Key> {
type Key;
type Value;
fn insert(&mut self, key: Self::Key, value: Self::Value) -> Option<Self::Value>;
}
pub trait Lookup<Q: ?Sized> where Self: Map {
fn get(&self, key: &Q) -> Option<&Self::Value>;
}
The new version (using either the newly supported supertrait syntax or where clauses) now causes a cycle error:
src/lib.rs:1:1: 5:2 error: unsupported cyclic reference between types/traits detected
src/lib.rs:1 pub trait Map where Self: Lookup<<Self as Map>::Key> {
src/lib.rs:2 type Key;
src/lib.rs:3 type Value;
src/lib.rs:4 fn insert(&mut self, key: Self::Key, value: Self::Value) -> Option<Self::Value>;
src/lib.rs:5 }
note: the cycle begins when computing the supertraits of `Map`...
note: ...which then requires computing the supertraits of `Lookup`...
note: ...which then again requires computing the supertraits of `Map`, completing the cycle.
src/lib.rs:4:31: 4:40 error: unsupported cyclic reference between types/traits detected
src/lib.rs:4 fn insert(&mut self, key: Self::Key, value: Self::Value) -> Option<Self::Value>;
^~~~~~~~~
note: the cycle begins when computing the supertraits of `Lookup`...
note: ...which then requires computing the supertraits of `Map`...
note: ...which then again requires computing the supertraits of `Lookup`, completing the cycle.
src/lib.rs:4:49: 4:60 error: unsupported cyclic reference between types/traits detected
src/lib.rs:4 fn insert(&mut self, key: Self::Key, value: Self::Value) -> Option<Self::Value>;
^~~~~~~~~~~
note: the cycle begins when computing the supertraits of `Lookup`...
note: ...which then requires computing the supertraits of `Map`...
note: ...which then again requires computing the supertraits of `Lookup`, completing the cycle.
src/lib.rs:4:72: 4:83 error: unsupported cyclic reference between types/traits detected
src/lib.rs:4 fn insert(&mut self, key: Self::Key, value: Self::Value) -> Option<Self::Value>;
^~~~~~~~~~~
note: the cycle begins when computing the supertraits of `Lookup`...
note: ...which then requires computing the supertraits of `Map`...
note: ...which then again requires computing the supertraits of `Lookup`, completing the cycle.
src/lib.rs:7:1: 9:2 error: unsupported cyclic reference between types/traits detected
src/lib.rs:7 pub trait Lookup<Q: ?Sized> where Self: Map {
src/lib.rs:8 fn get(&self, key: &Q) -> Option<&Self::Value>;
src/lib.rs:9 }
note: the cycle begins when computing the supertraits of `Lookup`...
note: ...which then requires computing the supertraits of `Map`...
note: ...which then again requires computing the supertraits of `Lookup`, completing the cycle.
src/lib.rs:8:39: 8:50 error: unsupported cyclic reference between types/traits detected
src/lib.rs:8 fn get(&self, key: &Q) -> Option<&Self::Value>;
^~~~~~~~~~~
note: the cycle begins when computing the supertraits of `Map`...
note: ...which then requires computing the supertraits of `Lookup`...
note: ...which then again requires computing the supertraits of `Map`, completing the cycle.
This is expected, based on @nikomatsakis's comment in the PR:
This is technically a [breaking-change] because it affects the definition of a super-trait. Anything in a where clause that looks like where Self : Foo is now considered a supertrait. Because cycles are disallowed in supertraits, that could lead to some errors. This has not been observed in any existing code.
However, this seems like a useful pattern.