you shouldn't add the async keyword to the function, doing that makes the future return a future.
BoxFuture is a future on it's own, and it can be awaited.
I can't see how it's true that your example async function should desugar to those two enums; Every call to recursive needs the full state. Which is recursive by definition. Break the recursion with indirection, which is what has been shown several times already.
The enum presented isn't actually meant to be for the programmer to write, It's just to show you what the compiler may emit.
enum FuncStates {
State1{ /* state data */ },
State2{ /* state data */ },
State3{ /* state data */ },
/* etc... */
}
You need to create a type that the compiler won't try to add to the imaginary enum (because if it does, it would be adding the enum to itself - which is not allowed).
enum States {
State1 {},
State2 { x: States }, // <- not allowed, compiler won't be able to find the size. It's infinite...
/* etc... */
}
It is possible to add indirection by adding an indirect type:
enum States {
State1 {},
State2 { x: Box<States> }, // this will compile, because a Box is a pointer.
}
Rust requires a Box for this to be possible, and tokio's executor's spawn function requires functions to be Pin & Send, this example complies with all these requirements:
I understood that it is not meant to be written by programmer !!
But I am asking why the indirection is not broken by generating proper enum as I show above ?
Because the states won't have a defined size. Every state would require it's previous states, that would require memory allocation.
Your previous example doesn't store previous states of calls to recursive, how would describe a recursive binary-tree search with an enum? I don't see how it's possible without either setting a limit (will utilize allot of unused memory), or dynamic allocation.
The compiler won't automatically box the recursive call for you because it prefers to make things influencing performance (e.g. allocation) explicit. A key part of zero cost abstractions (which Rust's async-await tries to be) is making sure you don't pay for the things you don't need.
If it tried to help out in simple examples like this then you wouldn't have enough control when you really need it.