Skip to content

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

Closed
@imbaczek

Description

@imbaczek

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.

Metadata

Metadata

Assignees

Labels

A-diagnosticsArea: Messages for errors, warnings, and lintsC-enhancementCategory: An issue proposing an enhancement or a PR with one.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions