Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't relate two associated types – unsupported cyclic reference between types/traits #24092

Closed
stevenblenkinsop opened this issue Apr 5, 2015 · 8 comments
Labels
A-associated-items Area: Associated items (types, constants & functions) A-type-system Area: Type system

Comments

@stevenblenkinsop
Copy link

Trying to compile code with this kind of structure leads to an unsupported cyclic reference error:

trait Trait {
    type A;
    type B;
    fn id(self) -> Self { self }
}

struct S;
struct SA;
struct SB;
struct SAA;

impl Trait for S {
    type A = SA;
    type B = SB;
}

impl Trait for SA {
    type A = SAA;
    type B = SB;
}

fn test<T: Trait>() where T::A : Trait<B=T::B> {}

fn main() {}
<anon>:22:42: 22:46 error: unsupported cyclic reference between types/traits detected
<anon>:22 fn test<T: Trait>() where T::A : Trait<B=T::B> {}
                                                   ^~~~
note: the cycle begins when computing the bounds for type parameter `T`...
note: ...which then again requires computing the bounds for type parameter `T`, completing the cycle.
error: aborting due to previous error

This seems somewhat surprising, since, T is merely acting as the scope for T::A and T::B, which are distinct types. Also, it seems quite reasonable to want to assert a relationship between two associated types. Is there actually something inherently cyclic about this that I'm not seeing, or is it an artefact of how the implementation detects cycles? Also, is this kind of constraint likely to eventually be supported?

@stevenblenkinsop stevenblenkinsop changed the title Can't relate two associated types – unsupported cyclic reference between traits Can't relate two associated types – unsupported cyclic reference between types/traits Apr 5, 2015
@steveklabnik steveklabnik added the A-type-system Area: Type system label Apr 6, 2015
@steveklabnik
Copy link
Member

/cc @nikomatsakis

@stevenblenkinsop
Copy link
Author

Turns out the problem goes away when I use the explicit <T as Trait>::A notation: http://is.gd/3sJOba

Aside from the overall problem of it being somewhat inconsistent whether you need to use this syntax or not, this is a deeply misleading error. The fact that it shows up might indicate a problem with how the associated type syntax is seen by the compiler. If not, the error should probably be improved regardless.

@mitchmindtree
Copy link
Contributor

I'm running into this also on rustc 1.0.0-nightly (f207ecbe0 2015-04-03) (built 2015-04-03) @stevenblenkinsop thanks for posting this along with the hint for temporarily side-stepping it 👍

@nikomatsakis
Copy link
Contributor

Hmm, yes. I'm a bit surprised that we wind up with a cycle in that particular example, we may be able to tighten the code to avoid it.

@nikomatsakis nikomatsakis added the A-associated-items Area: Associated items (types, constants & functions) label Apr 8, 2015
@brendanzab
Copy link
Member

I came across this too.

This errors:

use std::ops::*;

trait VectorSpace {}

trait AffineSpace where
    Self: Add<Self::Diff, Output = Self>,
    Self: Sub<Self, Output = Self::Diff>,
{
    type Diff: VectorSpace;
}

playground

anon>:6:15: 6:25 error: unsupported cyclic reference between types/traits detected [E0391]
<anon>:6     Self: Add<Self::Diff, Output = Self>,
                       ^~~~~~~~~~
<anon>:6:15: 6:25 help: see the detailed explanation for E0391
note: the cycle begins when computing the bounds for type parameter `Self`...
note: ...which then again requires computing the bounds for type parameter `Self`, completing the cycle.
<anon>:7:30: 7:40 error: unsupported cyclic reference between types/traits detected [E0391]
<anon>:7     Self: Sub<Self, Output = Self::Diff>,
                                      ^~~~~~~~~~
<anon>:7:30: 7:40 help: see the detailed explanation for E0391
note: the cycle begins when computing the bounds for type parameter `Self`...
note: ...which then again requires computing the bounds for type parameter `Self`, completing the cycle.
<anon>:6:15: 6:25 error: unsupported cyclic reference between types/traits detected [E0391]
<anon>:6     Self: Add<Self::Diff, Output = Self>,
                       ^~~~~~~~~~
<anon>:6:15: 6:25 help: see the detailed explanation for E0391
note: the cycle begins when computing the supertraits of `AffineSpace`...
note: ...which then again requires computing the supertraits of `AffineSpace`, completing the cycle.
error: aborting due to 3 previous errors

Where as this compiles fine:

use std::ops::*;

trait VectorSpace {}

trait AffineSpace where
    Self: Add<<Self as AffineSpace>::Diff, Output = Self>,
    Self: Sub<Self, Output = <Self as AffineSpace>::Diff>,
{
    type Diff: VectorSpace;
}

playground

@mitchmindtree
Copy link
Contributor

I have also come across this same issue working on some generic DSP code (I'd post an example of the error however they look very much the same as the examples here by bjz and steveblenkinsop).

@Mark-Simulacrum
Copy link
Member

The original example compiles with an addition of Self: Sized, but the one here still doesn't. I suspect that this is related to #38864, but I'm uncertain... the error is different. Triage: Still a bug.

@Mark-Simulacrum
Copy link
Member

This is basically the same as #35237, closing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-associated-items Area: Associated items (types, constants & functions) A-type-system Area: Type system
Projects
None yet
Development

No branches or pull requests

6 participants