There's a handful of event loop methods that are currently documented as coroutines, but in reality they return asyncio.Future:
These methods need to become proper coroutines beacause:
loop.create_task(loop.sock_recv(..)) fails with a cryptic error.
It's harder for us to refactor the code keeping these functions as regular functions returning Futures. Once asyncio was broken because of the bug in loop.sock_connect() because of a complex refactoring. After we converted it to a coroutine in 3.6, we received 0 complaints, but the code became simpler.
It's easier to read the source code of asyncio, when all methods that are documented as coroutines are actually coroutines.
This downgrades the role of 'asyncio.ensure_future()' function. Basically, when a user needs a task, they can now use create_task() (which won't fail on some "coroutines" sometimes). asyncio users will be advised to design APIs in their programs and libraries around async/await and not Future objects.