it is not an implementation detail at all. The syntax and semantics are very different. Stackfull coroutines allow suspending more than one activation frame (i.e. a subset of the callstack) in one go. You can of course "emulate" it with stack less coroutines by converting each frame in the call stack to a coroutine, but it is a manual and intrusive process.
I think if your syntax and semantics imply the stack-ness of your coroutine implementation then you you have a language design problem. Coroutines are subroutines with two additional primitives (resume after call, and yield before return). Whether `yield`/`resume` imply stack swapping or a state transition between activation frames is just an implementation detail. Both have tradeoffs, to be sure.
> I think if your syntax and semantics imply the stack-ness of your coroutine implementation then you you have a language design problem
A lot of languages, including C#, python, C++, rust and many others specify the stackless-ness of coroutines. So it is not just an implementation detail. You could argue that specifying these semantics is a problem, and I would actually agree, but obviously it is not something many, if not most, language designers agree.