Of course at the lowest level it's "explicit" as in you see the API used to implement it.
But in practice there's nothing explicit about it, because any function can yield and you don't have to explicitly know it did.
Lua is heavily used to script games, and you can see scripts like this there:
walkTo(desk)
pause(3);
turn(180);
say("I changed my mind, can I come with you?")
response = promptPlayer("OK, come", "No, stay");
...
...
Notice that every single one of those commands is not instant. It takes some time for it to happen, there's animation, user prompts, and so on.
All of this is happening async. But you don't have to do anything about it. You're writing a function, and the API for it yields where it has to. For you, all that's implicit.
It's literally identical to yours in practice, but it doesn't return promises. It yields natively.