No. We prefer a more traditional style with event-driven I/O, e.g. via unix::poll. This should be more familiar to C programmers than to those coming from higher-level languages with async/await constructs.
FWIW, frequently I've wished that languages had a version of https://www.chiark.greenend.org.uk/~sgtatham/coroutines.html built-in for implementing iterators, like Python generators, or somewhat similar to async/await. Porting the macros to C++ suffers because switches can't jump past declaring local variables with required constructors, and my hacks around this issue were ugly and error-prone. I haven't learned C++ coroutines yet, but they seem confusing.
We do not have first-class iterators, but we do have an iterator pattern which is common throughout the Hare standard library. As an example, here's how you can enumerate the nodes in a directory:
let iter = os::iter("/")!;
for (true) {
const entry = match (fs::next(&iter)) {
case let ent: fs::dirent =>
yield ent;
case void =>
break;
};
fs::println(entry.name)!;
};
I understand not having first-class iterators; Rust traits encourage using option/iterator combinator methods rather than imperative code, which I find unclear in nearly all cases (though iterator reduce() is better at finding the min/max of a sequence, since you don't have to initialize the counter to a sentinel value). I was discussing the use of coroutines for building iterators, for example implementing the next function for a recursive filesystem glob or B-tree map iterator or database table join, which I find miserable and bug-prone to write by hand.