Skip to content

Traits can no longer be mutually dependent #23118

Closed
@apasel422

Description

@apasel422

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions