for example:
let f = || {
let x1 = [42u8; 50000];
let x2 = [42u8; 50000];
let x3 = [42u8; 50000];
let x4 = [42u8; 50000];
let x5 = [42u8; 50000];
let x6 = [42u8; 50000];
};
red zone means that when the stack free space reaches this value, the function is allocated to the heap space。When the remaining space has this value, it indicates that the area is a red line and cannot exceed the reserved space
First to note that It is likely this is an XY problem.
You cannot solve the problem, because the problem is equivalent to the halting problem in general. But there are possible approaches under some assumptions.
Green threads are much easier to write concurrently than something like Tokio. Like Golang. Unlike Golang, Rust does not allow stack migration, but it may be possible to allocate to the heap using a scheme like Stacker
I am looking for whether there is a feasible plan, set a pre-allocated stack space (space allocation when judging function need enough, if enough direct execution, if not assigned to the heap) it is hard to solve the problem is that we don't know Fn need to how much space, can only be used for current has much space
I think you could just allocate a buffer of some large fixed size.
In typical environment, physical memory is not used until the memory is actually accessed, so the total number of allocations can be large.
There are some other issues with stackful coroutines in Rust, though.
An existing implementation of stackful coroutine is https://github.com/Xudong-Huang/may.
Some of the reasons that predicting stack usage is complicated is dynamic dispatch and recursion. With dynamic dispatch, you are calling functions that you don't know about up front, so there's no way to know their stack usage, and with recursion, you also can't predict it without knowing how many times it will recursively call itself, which can also be hard to predict.
Interestingly, with async/await, the future object itself, which stores all variables that are held alive across a yield point, does have a specific, known-in-advance type, which Rust can do because async/await is compiled entirely differently. Hence, Tokio can allocate exactly the amount of memory needed to store the future object. Still, this might not be enough because anything that happens between yield points still uses the ordinary stack, and cannot be predicted.
Suppose the fixed allocation of space is 2KB (the same as the initial golang value), but when the user starts the first green thread and applies for a 4KB stack or more (we only know that there is 2KB left), panic occurs instead of normal execution
What I suggested is using a larger stack limit, comparable to the typical thread default stack size (or use that value).
Yes stack overflow can still occur, but stack overflow also occurs in the default stack (normal execution), so it is fine for most programs.
Knowing the exact stack space size the function needs without actual execution, is isomorphic to the halting problem. You can translate all the loops in the function with recursions - which uses finite stack space iff it halts.