Skip to content

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

Closed
@stevenblenkinsop

Description

@stevenblenkinsop

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?

Activity

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[/+] on Apr 5, 2015
steveklabnik

steveklabnik commented on Apr 6, 2015

@steveklabnik
Member
stevenblenkinsop

stevenblenkinsop commented on Apr 7, 2015

@stevenblenkinsop
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

mitchmindtree commented on Apr 7, 2015

@mitchmindtree
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

nikomatsakis commented on Apr 8, 2015

@nikomatsakis
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.

brendanzab

brendanzab commented on Oct 29, 2015

@brendanzab
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

mitchmindtree commented on Mar 11, 2016

@mitchmindtree
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

Mark-Simulacrum commented on May 1, 2017

@Mark-Simulacrum
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

Mark-Simulacrum commented on May 10, 2017

@Mark-Simulacrum
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

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-associated-itemsArea: Associated items (types, constants & functions)A-type-systemArea: Type system

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @steveklabnik@nikomatsakis@brendanzab@stevenblenkinsop@mitchmindtree

        Issue actions

          Can't relate two associated types – unsupported cyclic reference between types/traits · Issue #24092 · rust-lang/rust