Cycle detected when const checking? Yes! The cycle is on purpose!

I'm writing a compiler. I'm trying to represent the AST using Rust consts, where each node holds 'static references to all its descendent nodes. Since this is actually an abstract syntax graph and not a tree, there are cycles. I'm doing this on purpose, but Rust doesn't like it.

Simple reproducer:

struct Node {
    name: &'static str,
    next: Option<&'static Node>,
}

const A: Node = Node { name: "A", next: Some(&B) };
const B: Node = Node { name: "B", next: Some(&A) };

The entire error seen on the playground:

error[E0391]: cycle detected when const checking `A`
 --> src/lib.rs:6:47
  |
6 | const A: Node = Node { name: "A", next: Some(&B) };
  |                                               ^
  |
note: ...which requires const checking `B`...
 --> src/lib.rs:7:47
  |
7 | const B: Node = Node { name: "B", next: Some(&A) };
  |                                               ^
  = note: ...which again requires const checking `A`, completing the cycle
note: cycle used when processing `A`
 --> src/lib.rs:6:1
  |
6 | const A: Node = Node { name: "A", next: Some(&B) };
  | ^^^^^^^^^^^^^^^^^^^^

For more information about this error, try `rustc --explain E0391`.

I'm hoping there's some easy fix for this, but I'm not holding my breath. The nodes already have unique names, so it's trivial for me to use a HashMap or some such to break the cycle. I was just hoping I wouldn't have to.

Interestingly, rustc --explain E0391 isn't quite applicable to this situation:

A type dependency cycle has been encountered.

Erroneous code example:

trait FirstTrait : SecondTrait {

}

trait SecondTrait : FirstTrait {

}

The previous example contains a circular dependency between two traits: FirstTrait depends on SecondTrait which itself depends on FirstTrait.

The best way to think about const is that the value is inlined wherever it's used. So in a way, you just made a mutually recursive function. The way to avoid this is quite simple, thankfully! Use static instead of const, and then you're guaranteed to only have a single instance, which the compiler can handle without issue.

3 Likes

Oh, excellent. That does, indeed, work.

Thanks so much!

(Edit to add:) Ironically, the language I'm compiling has similar semantics for const, and would have encountered the same problem.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.