Skip to content

"error: illegal recursive type; insert an enum or struct in the cycle, if this is desired" not very helpful #17539

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

Closed
imbaczek opened this issue Sep 25, 2014 · 6 comments · Fixed by #88121
Assignees
Labels
A-diagnostics Area: Messages for errors, warnings, and lints C-enhancement Category: An issue proposing an enhancement or a PR with one. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@imbaczek
Copy link

imbaczek commented Sep 25, 2014

I've tried to write code that would work like this:

let mut f = some_fn;  // many other some_fns also exist

loop {
    f = f()
}

To make coding some_fn and its friends easier, I wanted to create a type:

type SomeFn = fn() -> SomeFn;

Unfortunately, this results in some type-theoretic error message that isn't really understandable by mere mortals:

<anon>:1:15: 1:29 error: illegal recursive type; insert an enum or struct in the cycle, if this is desired
<anon>:1 type SomeFn = fn() -> SomeFn;
                       ^~~~~~~~~~~~~~

It's not at all clear what 'the cycle' is and where to insert an enum or struct. Turns out that if you know what the compiler is talking about, the fix is simple:

struct SomeFn(fn() -> SomeFn);

// ergonomy suffers
fn fn1() -> SomeFn { println!("1"); SomeFn(fn2) }
fn fn2() -> SomeFn { println!("2"); SomeFn(fn1) }

fn main() {
    let mut f = SomeFn(fn1);
    f = { let SomeFn(ff) = f; ff() };
    f = { let SomeFn(ff) = f; ff() };
}

Output:

1
2

But I was very confused by the message and tried a contraption like this instead:

type SomeFn = fn() -> Option<SomeFn>;

A hint in the error message that points the programmer to the right direction would be very helpful. Ergonomy of the solution is also questionable, but at least it compiles.

@reem
Copy link
Contributor

reem commented Sep 26, 2014

Since the size of a fn does not depend on its output type, I doubt this is a necessary restriction in the type system.

@kmcallister kmcallister added the A-diagnostics Area: Messages for errors, warnings, and lints label Sep 27, 2014
@nham
Copy link
Contributor

nham commented May 13, 2015

Triage: The error message seems better, but perhaps is still not ideal. Compiling this code:

type SomeFn = fn() -> SomeFn;
fn main() {}

on a recent nightly (rustc 1.1.0-nightly (4b88e8f63 2015-05-11) (built 2015-05-12)) results in:

iss_17539.rs:1:23: 1:29 error: unsupported cyclic reference between types/traits detected
iss_17539.rs:1 type SomeFn = fn() -> SomeFn;
                                     ^~~~~~
note: the cycle begins when processing `SomeFn`...
note: ...which then again requires processing `SomeFn`, completing the cycle.
error: aborting due to previous error

The "processing" language sounds a bit strange to me. Could it maybe say something like "the definition of the type SomeFn depends on SomeFn"?

@steveklabnik
Copy link
Member

Triage: same as @nham reported. I agree that we could improve on 'processing'.

@steveklabnik steveklabnik added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Mar 9, 2017
@Mark-Simulacrum Mark-Simulacrum added the C-enhancement Category: An issue proposing an enhancement or a PR with one. label Jul 22, 2017
@estebank
Copy link
Contributor

Current output is same as above, with new style output:

error[E0391]: unsupported cyclic reference between types/traits detected
 --> src/main.rs:1:23
  |
1 | type SomeFn = fn() -> SomeFn;
  |                       ^^^^^^ cyclic reference
  |
note: the cycle begins when processing `SomeFn`...
 --> src/main.rs:1:1
  |
1 | type SomeFn = fn() -> SomeFn;
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  = note: ...which then again requires processing `SomeFn`, completing the cycle.

@estebank
Copy link
Contributor

estebank commented Nov 7, 2018

Current output:

error[E0391]: cycle detected when processing `SomeFn`
 --> src/main.rs:1:23
  |
1 | type SomeFn = fn() -> SomeFn;
  |                       ^^^^^^
  |
  = note: ...which again requires processing `SomeFn`, completing the cycle

@camelid
Copy link
Member

camelid commented Jul 5, 2021

I have an idea on how to improve this error. @rustbot claim

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints C-enhancement Category: An issue proposing an enhancement or a PR with one. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants