For example; if you run this on top of Copas, and a Trio task would call a Copas socket function (read/write/connect) it would do a Copas yield to the Trio scheduler (meaning it would pass the Copas socket and request (read/write) to Trio, which
would not be expecting those.
For structured concurrency to work, it needs to be honored all the way down the stack. And for the full API, it's not only about keeping child coroutines in the scope of the parent, but also about having a consistent and flexible cancellation scheme. But everything in the program performing blocking I/O needs to cooperate.
The Python ecosystem faces this problem too. Python has async/await syntax, but, like Lua, it's very flexible about plugging in your own scheduler and ways to deal with parallel tasks (async/await says nothing about how to spawn a task). So there is standard asyncio (which isn't that great, and predates async/await and learnings from trio), twisted, curio, trio, ... each having incompatible event loops, and using a different yield protocol.
"Sans I/O" libraries have emerged as a solution. Such a library provides a synchronous (and hopefully, high quality) API, suitable for integration with any event loop (or none at all), effectively separating concerns between protocol logic and I/O.
> h11 contains no IO code whatsoever. This means you can hook h11 up to your favorite network API, and that could be anything you want: synchronous, threaded, asynchronous, [...] Compare this to the current state of the art, where every time a new network API comes along then someone gets to start over reimplementing the entire HTTP protocol from scratch.