{"id":13500974,"url":"https://github.com/teh-cmc/rust-async","last_synced_at":"2026-02-27T16:35:15.648Z","repository":{"id":80234624,"uuid":"220994572","full_name":"teh-cmc/rust-async","owner":"teh-cmc","description":"Demystifying Asynchronous Rust","archived":false,"fork":false,"pushed_at":"2020-01-23T09:44:19.000Z","size":742,"stargazers_count":205,"open_issues_count":1,"forks_count":11,"subscribers_count":16,"default_branch":"master","last_synced_at":"2025-11-12T06:05:11.815Z","etag":null,"topics":["async","book","rust"],"latest_commit_sha":null,"homepage":"https://teh-cmc.github.io/rust-async/html/","language":"Makefile","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/teh-cmc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2019-11-11T14:05:15.000Z","updated_at":"2025-10-04T17:40:45.000Z","dependencies_parsed_at":null,"dependency_job_id":"e5555f4a-c3e2-4d88-8682-c0f9f7b00d5e","html_url":"https://github.com/teh-cmc/rust-async","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/teh-cmc/rust-async","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/teh-cmc%2Frust-async","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/teh-cmc%2Frust-async/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/teh-cmc%2Frust-async/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/teh-cmc%2Frust-async/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/teh-cmc","download_url":"https://codeload.github.com/teh-cmc/rust-async/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/teh-cmc%2Frust-async/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29904506,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-27T14:46:13.553Z","status":"ssl_error","status_checked_at":"2026-02-27T14:46:10.522Z","response_time":57,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["async","book","rust"],"created_at":"2024-07-31T22:01:21.162Z","updated_at":"2026-02-27T16:35:15.624Z","avatar_url":"https://github.com/teh-cmc.png","language":"Makefile","funding_links":[],"categories":["Makefile"],"sub_categories":[],"readme":"# Demystifying Asynchronous Rust\n\n(You will find an mdBook version of this book [here](https://teh-cmc.github.io/rust-async/html/), if that's more your thing.)\n\n## Who is this book for?\n\nThis book is targeted towards experienced programmers that already feel somewhat comfortable with vanilla Rust (you definitely do not need to be an \"expert\" though, I certainly am not) and would like to dip their toes into its async ecosystem.\n\nAs the title indicates, this is not so much a book about _how to use async Rust_ as much as it is about trying to build a solid understanding of how it all works under the hood. From there, efficient usage should come naturally.  \nAs such, we'll try to answer the usual fundamental questions that arise from any piece of sufficiently complex technology:\n- How and why did we get to this?\n- What are the layers that make up the stack?\n- What are their respective roles?\n- How and why do they work the way they do?\n- How do they fit together?\n- What are the upsides \u0026 drawbacks of this approach?\n- What are the semantics of the overall execution model?\n- How is everything represented in memory?\n- Etc...\n\nOn our way to answering all of those, we will encounter lots and lots of abstractions that will look like complete magic at first.  \nWe won't hesitate to wander off the main road and take as long a detour as needed, until we've successfully suppressed every last bit of hidden magic.  \nDigression will be the norm here, not the exception.\n\nMy hope is that, after reading this book, one would be able to A) dig into any arbitrarily complex async codebase and B) decipher any error message that the compiler might throw at them.\n\n## Why this book when there already is \u003cinsert_name\u003e?\n\n[Asynchronous Programming in Rust](https://rust-lang.github.io/async-book/01_getting_started/01_chapter.html) \u0026 [Async programming in Rust with async-std](https://book.async.rs/) are two examples of great upcoming resources to learn about Rust's asynchronous stack, and I'd highly suggest that you read through them in addition to this book.\n\nThat being said, there are several reasons that have pushed me to write this material on top of what already exists:\n- First, I am learning myself, and writing these notes has helped me greatly in processing the ridiculous amount of information one has to digest to fully comprehend this stack. Might as well share them while I'm it.\n- Second, I feel like there definitely is value to be had, as a community, in having the same subject covered from different angles. The approach taken by this book should hopefully be unique enough to warrant its own text.\n- And last but not least, who doesn't want to be writing about Rust these days?\n\n## Can I help?\n\nYep, you sure can.\n\nI am not an async Rust expert by any means. I'm not even a Rust expert to begin with.  \nThere will be errors, misconceptions, inaccuracies and other awful, awful things in this book.  \nPlease report them via Github's issues.\n\n***\n\n1. [Towards less blocking pastures](#1-towards-less-blocking-pastures)  \n    1.1. [Iterators](#11-iterators)  \n    1.2. [Closures](#12-closures)  \n    1.3. [Iterators are closures are iterators](#13-iterators-are-closures-are-iterators)  \n    1.4. [The case for asynchronous Rust](#14-the-case-for-asynchronous-rust)  \n2. [Chapter II](#2-chapter-ii)  \n\n***\n\n# 1. Towards less blocking pastures\n\n```ignore\nlast-edited: 2019-11-11\nrustc-version: rustc 1.40.0-nightly (b520af6fd 2019-11-03)\n```\n\nSo what's the deal here? Why do we need asynchronous Rust in the first place?\n\nIn my experience, more often than not, the first answers to come up are along the lines of \"to workaround the limitations of synchronous I/O\".  \nI'm not a big fan of this answer; while async I/O is undoubtedly the poster child of all async applications, I reckon it is still just that: _an_ application, out of many.\n\nIn particular, async I/O is a very tricky beast that brings with it A) its own set of very specific problems and B) a gazillon of moving pieces that have nothing to do with Rust's async primitives per-se.  \nFor these reasons, I'd like to instead try and approach the matter from a different, and perhaps more familiar angle: start from the beginning with iterators and closures, and see where that takes us.  \nOf course, we'll cover async I/O when the time is right.\n\nNow I'm sure that opening a book about asynchronous Rust with a whole chapter dedicated to iterators and closures might seem like a dubious choice but, as we'll see, iterators, closures, streams \u0026 futures are all very much alike in more than one ways.  \nIn fact, I simply cannot fathom how we'd go about demystifying asynchronous Rust without first lifting all of the magic behind iterators and closures. That might just be me, though.\n\nHence in this first chapter, we'll do just that, demystify iterators and closures:\n- What they are and what they're not.\n- Their memory representation and execution model.\n- Their interesting similarities.\n- And last but not least: why would we need and/or want something else to begin with?\n\n## 1.1. Iterators\n\nAn iterator is a state-machine that you can move forward by calling its `.next` method.  \nDoing so will simultaneously yield its current value as well as mutate it towards its next state (hence `next(\u0026mut self)`).  \nIt's _that_ simple.\n\n```rust\npub trait Iterator {\n    type Item;\n\n    /// Advances the iterator and returns the next value.\n    ///\n    /// Returns None when iteration is finished. Individual iterator\n    /// implementations may choose to resume iteration, and so calling next()\n    /// again may or may not eventually start returning Some(Item) again at some\n    /// point.\n    fn next(\u0026mut self) -\u003e Option\u003cSelf::Item\u003e;\n}\n```\n\nHere's an implementation of a simple `Range` iterator that yields all the values between two `T`s:\n```rust\npub struct Range\u003cT\u003e {\n    cur: T,\n    end: T,\n    incr: T,\n}\n\nimpl\u003cT\u003e Range\u003cT\u003e {\n    pub fn new(start: T, end: T, incr: T) -\u003e Self {\n        Self {\n            cur: start,\n            end,\n            incr,\n        }\n    }\n}\n\nimpl\u003cT\u003e Iterator for Range\u003cT\u003e\nwhere\n    T: std::ops::AddAssign + PartialOrd + Clone,\n{\n    type Item = T;\n\n    fn next(\u0026mut self) -\u003e Option\u003cSelf::Item\u003e {\n        match \u0026self.cur {\n            v if *v \u003c self.end =\u003e {\n                let ret = self.cur.clone();\n                self.cur += self.incr.clone();\n                ret.into()\n            }\n            _ =\u003e None,\n        }\n    }\n}\n```\nIn action:\n```rust\nlet mut j = 1;\nfor i in Range::new(1usize, 4, 1) {\n    assert_eq!(j, i);\n    j += 1;\n}\n```\n\nStraighforward stuff. This does demonstrate a couple important characteristics of iterators, though.\n\n**Laziness**\n\nIterators are lazy, they don't do anything unless _polled_.  \nIn this case the for loop is doing the polling, as it desugars to something along these lines:\n```rust\nlet mut it = Range::new(10, 20, 1).into_iter();\nwhile let Some(i) = it.next() {\n    /* ... */\n}\n```\n\nAll the usual laziness-related goodies apply, e.g. in this specific case we never dynamically allocate anything: we can represent an arbitrarily large range of numbers without ever allocating a single byte of heap space.\n\nSimilarly, one can effectively _cancel_ the execution of an iterator at any time _between two yields_: you just stop polling it is all.\n\n**Zero magic, zero allocs**\n\nOur iterator is nothing more than a vanilla structure (its state) with a `.next` method defined on it.  \nIn this example, the iterator sits on `main`'s stack, and answers to the same rules as any other struct: ownership, lifetimes, marker traits, etc.\n\nThere really isn't any kind of magic going on here: no hidden allocations, no codegen, no nothing; it's as dull as it gets.\n\n### 1.1.a. Combinators\n\nIterators can be defined in terms of other iterators, making it possible to _combine_ (hence \"iterator combinators\") them into arbitrarily complex state-machines by wrapping iterators into iterators into iterators... and so on and so forth.\n\nHere's a `Bounds` combinator that makes sure our `Range` never yields results that are out of bounds:\n```rust,no_run\npub struct Bounds\u003cI, T\u003e {\n    inner: I,\n    min: T,\n    max: T,\n}\n\nimpl\u003cI, T\u003e Bounds\u003cI, T\u003e {\n    pub fn new(inner: I, min: T, max: T) -\u003e Self {\n        Self { inner, min, max }\n    }\n}\n\nimpl\u003cI\u003e Iterator for Bounds\u003cI, I::Item\u003e\nwhere\n    I: Iterator,\n    I::Item: PartialOrd,\n{\n    type Item = I::Item;\n\n    fn next(\u0026mut self) -\u003e Option\u003cSelf::Item\u003e {\n        loop {\n            match self.inner.next() {\n                Some(v) if v \u003e= self.min \u0026\u0026 v \u003c self.max =\u003e return v.into(),\n                Some(_) =\u003e {}\n                None =\u003e return None,\n            }\n        }\n    }\n}\n```\n\nIn action:\n```rust\nlet mut it = Bounds::new(Range::new(1usize, 20, 1), 5, 8);\nassert_eq!(Some(5), it.next());\nassert_eq!(Some(6), it.next());\nassert_eq!(Some(7), it.next());\nassert_eq!(None, it.next());\n```\n\nOnce again, no magic here.  \n`Bounds` simply takes ownership of a `Range`, and then the wrapper (`Bounds`) is free to delegate the polling to the wrappee (`Range`), injecting its own rules in the process (i.e. filtering values, in this case).\n\nFrom the programmer's point-of-view, nothing changes: we get a _something_ that implements the `Iterator` trait and we can poll it as needed.  \nThanks to monomorphization, everything is still sitting on the stack here; we just have a bigger, self-contained struct is all:\n```rust\nuse std::mem::size_of_val;\n\nlet it = Range::new(1usize, 20, 1).into_iter();\nassert_eq!(24, size_of_val(\u0026it));\n\nlet it = Bounds::new(Range::new(1usize, 20, 1), 5,8).into_iter();\nassert_eq!(40, size_of_val(\u0026it));\n```\n\nRandom tip: `-Zprint-size-types` is a great tool to know what monomorphization has been up to:\n```sh\n$ cargo rustc --lib -- --test -Zprint-type-sizes\n# [...]\n`Range\u003cusize\u003e`: 24 bytes, alignment: 8 bytes\n`Bounds\u003cRange\u003cusize\u003e, usize\u003e`: 40 bytes, alignment: 8 bytes\n```\n\n**What we have so far**\n\nWe can now build up complex state-machines by composing smaller, simpler parts.  \nWhile this is great in an of itself, one will quickly disenchant when trying to build a sufficiently complex combinator:\n```rust\nlet it = MyCombinator1::new(MyCombinator2::new(MyCombinator3::new(MyCombinator4::new(MyCombinator5::new(MyIterator::new())))));\n```\n\nYikes. Enter extensions.\n\n## 1.1.b. Extensions\n\nExtension traits allow us to define some behavior and implement it for both local and external types (provided you respect trait coherence rules... a topic for another day).  \nThey come in very handy in the case of iterator combinators, as they allow us to express our compound state-machines using something akin to the familiar builder pattern.\n\nHere we define a `BoundsExt` trait and provide a default implementation for everything that is an `Iterator` (provided that their `Item`s are `PartialOrd`, of course!):\n```rust\npub trait BoundsExt: Iterator\nwhere\n    Self: Sized,\n{\n    fn bounds\u003cT\u003e(self, min: T, max: T) -\u003e Bounds\u003cSelf, T\u003e {\n        Bounds::new(self, min, max)\n    }\n}\n\nimpl\u003cI: Iterator\u003e BoundsExt for I {}\n```\nAnd just like that, we're able to express our intent in a much more natural fashion:\n```rust\nlet mut it = Range::new(1usize, 20, 1).bounds(1, 20).bounds(3, 13).bounds(5, 8);\nassert_eq!(Some(5), it.next());\nassert_eq!(Some(6), it.next());\nassert_eq!(Some(7), it.next());\nassert_eq!(None, it.next());\n```\n\nAnd, again, no magic in sight. This is effectively just syntactic sugar.  \nIn fact, it's all so _not_ magic that the compiler did not even realize that our combinator chain is absolute non-sense and a complete waste of resources:\n```sh\n$ cargo rustc --lib -- --test -Zprint-type-sizes\n# [...]\n`Bounds\u003cBounds\u003cBounds\u003cRange\u003cusize\u003e, usize\u003e, usize\u003e, usize\u003e`: 72 bytes, alignment: 8 bytes\n```\nHow could it? It's just blindly monomorphizing structs inside of other structs, that's all there is to it!\n\n**What we have so far**\n\nWe can now build up complex state-machines by composing them from smaller, simpler parts... and what's more, we can even do it in an expressive, readable and maintainable way.\n\nStill, if we had to implement an iterator combinator from scratch everytime we wanted to achieve a slightly different behavior for our overall state-machine, things would get very tedious, very fast; which is why iterators are almost always used in tandem with their close friends, closures.\n\n## 1.2. Closures\n\nWhile iterators are pretty straightforward both from a usage and an implementation standpoint, closures are anything but.  \nIn fact, I'd argue they're one of the most complex pieces of \"standard\" synchronous Rust.  \nTheir very expressive nature, thanks to a lot of magical sugar exposed by the compiler, make them a prime tool to push the type system into very complex corners, whether voluntarily... or not.\n\nClosures also happen to be the cornerstone of any serious asynchronous codebase, where their incidental complexity tends to skyrocket as a multitude of issues specific to asynchronous \u0026 multi-threaded code join in on the party.\n\n### 1.2.a. A better `Bounds`\n\nWe'll kick off this section by turning our `Bounds` filter into a filter of... well, anything, really:\n```rust\npub struct Filter\u003cI, P\u003e {\n    inner: I,\n    predicate: P,\n}\n\nimpl\u003cI, P\u003e Filter\u003cI, P\u003e {\n    pub fn new(inner: I, predicate: P) -\u003e Self {\n        Self { inner, predicate }\n    }\n}\n\nimpl\u003cI, P\u003e Iterator for Filter\u003cI, P\u003e\nwhere\n    I: Iterator,\n    P: FnMut(\u0026I::Item) -\u003e bool,\n{\n    type Item = I::Item;\n\n    fn next(\u0026mut self) -\u003e Option\u003cSelf::Item\u003e {\n        loop {\n            match self.inner.next() {\n                Some(v) if (self.predicate)(\u0026v) =\u003e return v.into(),\n                Some(_) =\u003e {}\n                None =\u003e return None,\n            }\n        }\n    }\n}\n```\nMight as well provide an extension for it too:\n```rust\npub trait FilterExt: Iterator\nwhere\n    Self: Sized,\n{\n    fn filter_with\u003cP\u003e(self, predicate: P) -\u003e Filter\u003cSelf, P\u003e\n    where\n        P: FnMut(\u0026Self::Item) -\u003e bool,\n    {\n        Filter::new(self, predicate)\n    }\n}\n\nimpl\u003cI: Iterator\u003e FilterExt for I {}\n```\nLo and behold:\n```rust\nlet mut it = Range::new(1usize, 20, 1).filter_with(|\u0026v| v \u003e= 5 \u0026\u0026 v \u003c 8);\nassert_eq!(Some(5), it.next());\nassert_eq!(Some(6), it.next());\nassert_eq!(Some(7), it.next());\nassert_eq!(None, it.next());\n```\nYep, that does it.\n\nSo that's nice and all but... how does our final state-machine ends up being implemented?\n```sh\n$ cargo rustc --lib -- --test -Zprint-type-sizes\n# [...]\n`Filter\u003cRange\u003cusize\u003e, [closure]\u003e`: 24 bytes, alignment: 8 bytes\n`Range\u003cusize\u003e`: 24 bytes, alignment: 8 bytes\n```\nWait, wat? How come a monomorphized `Filter\u003cRange\u003cusize\u003e, \u003c[closure]\u003e\u003e` is the same size as a `Range\u003cusize\u003e`?\n\nThe only way this is possible is if storing our closure costs a whopping 0 byte which... doesn't seem plausible?  \nLet's take a minute to try and understand what's going on here.\n\n### 1.2.b. What's a closure, anyway?\n\nA closure is nothing but a structure (its captured environment) that implements one (or more) trait from the `Fn*` family of traits (`FnOnce`, `FnMut` and `Fn`):\n```rust\npub trait FnOnce\u003cArgs\u003e {\n    type Output;\n    extern \"rust-call\" fn call_once(self, args: Args) -\u003e Self::Output;\n}\n\npub trait FnMut\u003cArgs\u003e: FnOnce\u003cArgs\u003e {\n    extern \"rust-call\" fn call_mut(\u0026mut self, args: Args) -\u003e Self::Output;\n}\n\npub trait Fn\u003cArgs\u003e: FnMut\u003cArgs\u003e {\n    extern \"rust-call\" fn call(\u0026self, args: Args) -\u003e Self::Output;\n}\n```\nWhat that structure looks like will vary depending on the environment that the closure captures.  \nFor that reason, every closure has a different type (!), and every closure requires a proper structure declaration in order to carry its state.  \nObviously, having to manually declare a proper definition for your closure's captured state every time would be way too cumbersome, to the point of rendering closures completely useless.\n\nTo cope with that, the compiler automatically generates an appropriate anonymous structure every time you create a closure.  \nConsider e.g. the following code:\n```rust\nlet a = 42;\nlet b = 100;\nlet f = |v: i32| v + a + b;\n```\nBehind the scenes, the compiler will generate something along these lines to store the state of the closure:\n```rust\nstruct __anonymous_e3b0105\u003c'a\u003e {\n    a: \u0026'a i32,\n    b: \u0026'a i32,\n}\n```\n\nNow, if we instead had specified that we wanted to _move_ (i.e. take ownership of) the captured variables into the closure's state rather than just keep references to them, i.e. this:\n```rust\nlet a = 42;\nlet b = 100;\nlet f = move |v: i32| v + a + b;\n```\nwould then turn into this:\n```rust\nstruct __anonymous_e3b0105 {\n    a: i32,\n    b: i32,\n}\n```\nDon't take my word for it, ask the compiler:\n```sh\n$ cargo rustc --lib -- --test -Zprint-type-sizes\n# [...]\n`[closure\u003ca:\u0026i32, b:\u0026i32\u003e]`: 16 bytes ## let f = |v: i32| v + a + b;\n`[closure\u003ca:i32, b:i32\u003e]`: 8 bytes ## let f = move |v: i32| v + a + b;\n```\n\nAnd so that covers the issue of generating an appropriate structure to hold the state (or captured environment) of the closure.  \nWhat about implementing `FnOnce`/`FnMut`/`Fn` on that generated structure, though?\n\nSimilarly, manually providing the right `Fn*` trait(s) implementations for each and every closure would be unmanageable, and so, once again, the compiler got our backs and does it for us.  \nTo see what these implementations might look like, we could either A) have a look at the generated IR and/or assembly, or better yet, B) handcraft our own closure out of thin air.\n\nLet's go with option B.\n\n### 1.2.c. Handcrafted closures\n\nRemember we had this:\n```rust\nlet a = 42;\nlet b = 100;\nlet f = |v: i32| v + a + b;\n```\nNow what we'd like to do is to implement `f` without any help from the compiler.\n\nFirst, we need to store our state somewhere. In this case, the capture is made by reference and so our structure should reflect that:\n```rust\nstruct MyClosure\u003c'a\u003e {\n    a: \u0026'a i32,\n    b: \u0026'a i32,\n}\n```\nThen, we need to implement the right `Fn*` trait(s). This part is a bit trickier.\n\n---\n\n### Aside: The many, many faces of Closures\n\nWhen you create a closure, the compiler will always try to implement the most versatile of all the `Fn*` traits that it can, i.e. the trait that will allow you to use the closure in as many situations as possible.  \nWhether or not a `Fn*` trait can be implemented depends solely on how the closure interacts with its state.  \n\n**`FnOnce`**\n\nIf the closure moves anything out of its state, then its state (i.e. `self`) will have to be _consumed_ to perform the call, in which case the only trait that it can implement is `FnOnce`:\n```rust\nfn call_once(self, args: Args) -\u003e Self::Output // `self`\n```\n\n/!\\\\ A common misconception is that whether a closure is or isn't `FnOnce` has anything to do with the use of `move`. It does _**not**_.\n\nThis closure is `Fn`, as demonstrated by the multiple calls to it:\n```rust\nlet a = 42;\nlet b = 100;\nlet f: \u0026dyn Fn(i32) -\u003e i32 = \u0026|v: i32| v + a + b; // Compiles!\nassert_eq!(150, f(8)); // really `Fn::call(\u0026f, (8,))`\nassert_eq!(150, f(8)); // really `Fn::call(\u0026f, (8,))`\nassert_eq!(150, f(8)); // really `Fn::call(\u0026f, (8,))`\n```\nAnd so is this one:\n```rust\nlet a = 42;\nlet b = 100;\nlet f: \u0026dyn Fn(i32) -\u003e i32 = \u0026move |v: i32| v + a + b; // Compiles still!\nassert_eq!(150, f(8)); // really `Fn::call(\u0026f, (8,))`\nassert_eq!(150, f(8)); // really `Fn::call(\u0026f, (8,))`\nassert_eq!(150, f(8)); // really `Fn::call(\u0026f, (8,))`\n```\nIt doesn't matter that the second closure moves `a` \u0026 `b` into its state (well it certainly matters to the enclosing scope, which can't refer to these variables anymore, but that's besides the point).\n\nWhat matters is how the closure interacts with its state when it gets called.  \nIn the example above, that interaction is just a read through a reference, and so a shared reference to the state (i.e. `\u0026self`) is enough to perform the call: the compiler makes sure that this closure is `Fn`.\n\nNow if you were to do this on the other hand...:\n```rust\nstruct MyNonCopyType(i32);\nlet a = MyNonCopyType(42);\nlet b = MyNonCopyType(100);\nlet f = |v: i32| {\n    let ret = v + a.0 + b.0;\n    drop(a);\n    ret\n};\nassert_eq!(150, f(8)); // really `FnOnce::call_once(f, (8,))`\n// assert_eq!(150, f(8)); // Won't compile: value used after move\n```\nNow that's a big no-no. `drop(a)` moves `a` out of the closure's state, and so the only way to perform the call is to consume its state (i.e. `self`). The compiler makes sure that this closure is `FnOnce`, and thus uncommenting the second call won't compile.  \nNotice that we're even capturing `a` \u0026 `b` by reference in this case and it doesn't matter, because this has nothing to do with the use of `move`!\n\n**`FnMut`**\n\nIf the closure needs to modify its state during execution, but doesn't need to move anything out of it, then it's gonna need a mutable reference to `self` to perform the call; i.e. it implements `FnMut`:\n```rust\nfn call_mut(\u0026mut self, args: Args) -\u003e Self::Output // `\u0026mut self`\n```\nOf course, if our `FnMut` closure can be called N times, then it would certainly make sense that we should be able to call it only once. Indeed, `FnOnce` is a supertrait of `FnMut` (hence `FnMut\u003cArgs\u003e: FnOnce\u003cArgs\u003e`).  \nThis is easier to visualize with an example:\n```rust\nfn run_once\u003cF\u003e(f: F) -\u003e i32 // `f` isn't even marked as `mut`...\nwhere\n    F: FnOnce() -\u003e i32,\n{\n    f() // ...but `self` is really `\u0026mut self`, because tricks!\n}\n\nfn run_mut\u003cF\u003e(mut f: F) -\u003e i32\nwhere\n    F: FnMut() -\u003e i32,\n{\n    f()\n}\n\nlet mut a = 10;\nlet mut fmut = || {\n    a += 1;\n    a\n};\n\nassert_eq!(11, run_once(\u0026mut fmut));\nassert_eq!(12, run_once(\u0026mut fmut));\nassert_eq!(13, run_mut(\u0026mut fmut));\nassert_eq!(14, run_mut(\u0026mut fmut));\n```\nAnd the reason why this works is because of this little jewel in libcore:\n```rust\n#[stable(feature = \"rust1\", since = \"1.0.0\")]\nimpl\u003cA, F: ?Sized\u003e FnOnce\u003cA\u003e for \u0026mut F\nwhere\n    F: FnMut\u003cA\u003e,\n{\n    type Output = F::Output;\n    extern \"rust-call\" fn call_once(self, args: A) -\u003e F::Output {\n        (*self).call_mut(args)\n    }\n}\n```\n\n**`Fn`**\n\nFinally, if the closure just reads from its environment without ever modifying it, all it's gonna need to perform a call is a shared refence to `self`: it implements `Fn`.\n```rust\nfn call(\u0026self, args: Args) -\u003e Self::Output // `\u0026self`\n```\nOnce again, no reason why a `Fn` closure couldn't behave as a `FnMut`; if a closure can be executed N times while modifying its state, it certainly can be executed N times without modifying it (hence `Fn\u003cArgs\u003e: FnMut\u003cArgs\u003e`).  \nAnd, as we know, if a closure is `FnMut`, then it is `FnOnce` too:\n```rust\nfn run_once\u003cF\u003e(f: F, b: i32) -\u003e i32\nwhere\n    F: FnOnce(i32) -\u003e i32,\n{\n    f(b)\n}\n\nfn run_mut\u003cF\u003e(mut f: F, b: i32) -\u003e i32\nwhere\n    F: FnMut(i32) -\u003e i32,\n{\n    f(b)\n}\n\nfn run\u003cF\u003e(f: F, b: i32) -\u003e i32\nwhere\n    F: Fn(i32) -\u003e i32,\n{\n    f(b)\n}\n\nlet a = 10;\nlet f = |b: i32| a + b;\n\nassert_eq!(52, run_once(\u0026f, 42));\nassert_eq!(52, run_once(\u0026f, 42));\nassert_eq!(52, run_mut(\u0026f, 42));\nassert_eq!(52, run_mut(\u0026f, 42));\nassert_eq!(52, run(\u0026f, 42));\nassert_eq!(52, run(\u0026f, 42));\n```\nOnce again, we can thank libcore for this:\n```rust\n#[stable(feature = \"rust1\", since = \"1.0.0\")]\nimpl\u003cA, F: ?Sized\u003e FnOnce\u003cA\u003e for \u0026F\nwhere\n    F: Fn\u003cA\u003e,\n{\n    type Output = F::Output;\n\n    extern \"rust-call\" fn call_once(self, args: A) -\u003e F::Output {\n        (*self).call(args)\n    }\n}\n\n#[stable(feature = \"rust1\", since = \"1.0.0\")]\nimpl\u003cA, F: ?Sized\u003e FnMut\u003cA\u003e for \u0026F\nwhere\n    F: Fn\u003cA\u003e,\n{\n    extern \"rust-call\" fn call_mut(\u0026mut self, args: A) -\u003e F::Output {\n        (**self).call(args)\n    }\n}\n```\n\nAnd that concludes our aside regarding the `Fn*` family of traits.\n\n---\n\nBack to our original business.  \nWe were wondering how to implement the right `Fn*` traits for our closure's state:\n```rust\nstruct MyClosure\u003c'a\u003e {\n    a: \u0026'a i32,\n    b: \u0026'a i32,\n}\n```\nOur closure only references its environment: it never modifies it nor does it ever move it somewhere else, therefore the most versatile implementation that we can provide is `Fn`, which should allow it to be run pretty much anywhere.  \nAs we've seen, `FnOnce` is a supertrait of `FnMut` is a supertrait of `Fn`, and so we need to implement the entire family tree in this case:\n```rust\nimpl\u003c'a\u003e FnOnce\u003c(i32,)\u003e for MyClosure\u003c'a\u003e {\n    type Output = i32;\n\n    extern \"rust-call\" fn call_once(self, _args: (i32,)) -\u003e Self::Output {\n        unreachable!()\n    }\n}\n\nimpl\u003c'a\u003e FnMut\u003c(i32,)\u003e for MyClosure\u003c'a\u003e {\n    extern \"rust-call\" fn call_mut(\u0026mut self, _args: (i32,)) -\u003e Self::Output {\n        unreachable!()\n    }\n}\n\nimpl\u003c'a\u003e Fn\u003c(i32,)\u003e for MyClosure\u003c'a\u003e {\n    extern \"rust-call\" fn call(\u0026self, (v,): (i32,)) -\u003e Self::Output {\n        v + self.a + self.b\n    }\n}\n```\nLo and behold, we've got ourselves a closure:\n```rust\nlet a = 42;\nlet b = 100;\nlet f = MyClosure { a: \u0026a, b: \u0026b };\nassert_eq!(150, f(8)); // really `Fn::call(\u0026f, (8,))`\nassert_eq!(150, f(8)); // really `Fn::call(\u0026f, (8,))`\nassert_eq!(150, f(8)); // really `Fn::call(\u0026f, (8,))`\n```\n\nSo that's great and all, but it still doesn't explain why this:\n```rust\nlet mut it = Range::new(1usize, 20, 1).filter_with(|\u0026v| v \u003e= 5 \u0026\u0026 v \u003c 8);\nassert_eq!(Some(5), it.next());\nassert_eq!(Some(6), it.next());\nassert_eq!(Some(7), it.next());\nassert_eq!(None, it.next());\n```\nyields this:\n```\n`Filter\u003cRange\u003cusize\u003e, [closure]\u003e`: 24 bytes, alignment: 8 bytes\n`Range\u003cusize\u003e`: 24 bytes, alignment: 8 bytes\n```\nI.e. how a `Range\u003cusize\u003e` happens to be the same size as a `Filter\u003cRange\u003cusize\u003e`.\nThe first thing to take note of is that this closure never captures anything, and so it'd make sense that its state is 0-byte sized:\n```sh\n$ cargo rustc --lib -- --test -Zprint-type-sizes\n# [...]\n`[closure]`: 0 bytes, alignment: 1 bytes\n```\nIn fact, the compiler won't even bother generating an anonymous structure for it, and so our closure lives entirely in the code section of the executable: it has no associated data.  \nEffectively, it is just a plain function pointer:\n```rust\nlet _f: fn(usize) -\u003e bool = |v: usize| v \u003e= 5 \u0026\u0026 v \u003c 8; // compiles!\n```\n\nThat explains why our closure is 0 byte, but it certainly doesn't explain why a `Filter\u003cRange\u003cusize\u003e, [closure]\u003e` is the same size as a `Range\u003cusize\u003e`. Even if the closure itself is 0 byte, `Filter` still has has to hold a function pointer to the code portion of the closure, which is 8 bytes on a 64bit platform such as mine.  \nWhat are we missing?\n\nConsider the following code where we instantiate a `Filter` using an empty closure (i.e. an anonymous function):\n```rust\n#[cfg(feature = \"empty_closure\")]\nfn empty_closure() {\n    let range = Range::new(10usize, 20, 1).into_iter();\n    assert_eq!(24, size_of_val(\u0026range));\n\n    let mut filter = range.filter_with(|\u0026v| v \u003e= 7 \u0026\u0026 v \u003c 15);\n    assert_eq!(24, size_of_val(\u0026filter)); // 24 bytes!\n\n    let x = filter.next();\n    println!(\"{:?}\", x);\n}\n```\nTo understand what's actually going on here, we need to have a direct look at the assembly generated for our `Filter`'s `.next` method:\n```sh\n$ cargo asm --features empty_closure \\\n            --asm-style att \\\n            --build-type debug \\\n            '\u003cchapter_1::Filter\u003cI,P\u003e as core::iter::traits::iterator::Iterator\u003e::next'\n```\nWe'll specifically focus on the indirect call to the predicate (i.e. `(self.predicate)(\u0026v)`):\n```assembly\n;; (self.predicate)(\u0026v)\nleaq    64(%rsp), %rax\nmovq    %rax, 80(%rsp)\nmovq    32(%rsp), %rdi\nmovq    80(%rsp), %rax\nmovq    %rax, 88(%rsp)\nmovq    88(%rsp), %rsi\ncallq   closure_filters::empty_closure::{{closure}}\nmovb    %al, 31(%rsp)\n```\nDon't worry too much about all these `mov` instructions for now, the only relevant piece of information is in fact written in plain english: `callq closure_filters::empty_closure::{{closure}}`.  \nThe compiler has completely optimized out the indirect call through `self.predicate`: the address of the closure is hardcoded right there into the `.next` method!  \nWe have monomorphization to thank for that, it generated a `.next` function specialized for `I = Range\u003cusize\u003e` and `P = [closure]`, where `[closure]` denotes the unique, anonymous type of our closure (remember, _each and every_ closure gets its own anonymous type).  \nSince `self.predicate` is a `P`, and the compiler knows that `P` is nothing but a function pointer (i.e. `P: FnMut`), it therefore knows that it can eliminate the runtime dispatch in favor of what we're seeing here.\n\nWhat if our closure _did_ capture some state, then?\n```rust\n#[cfg(feature = \"capturing_closure\")]\nfn capturing_closure() {\n    let range = Range::new(10usize, 20, 1).into_iter();\n    assert_eq!(24, size_of_val(\u0026range));\n\n    let min = 7;\n    let max = 15;\n    let mut filter = range.filter_with(|\u0026v| v \u003e= min \u0026\u0026 v \u003c max);\n    assert_eq!(40, size_of_val(\u0026filter)); // 40 bytes!\n\n    let x = filter.next();\n    println!(\"{:?}\", x);\n}\n```\nWe can see here that we capture two references to `usize`, i.e. 16 bytes:\n```sh\n$ cargo rustc --bin closure_filters --features capturing_closure -- -Zprint-type-sizes\n# [...]\n`[closure\u003cmin:\u0026usize, max:\u0026usize\u003e]`: 16 bytes, alignment: 8 bytes\n```\nAnd so our `Filter\u003cRange\u003cusize\u003e, [closure\u003c\u0026usize,\u0026usize\u003e]` should be\n```sh\nsizeof(Range\u003cusize\u003e) + ## 24\nsizeof([closure\u003c\u0026usize,\u0026usize\u003e]) + ## 16\nsizeof(\u0026dyn FnMut(\u0026I::Item) -\u003e bool) ## 8\n```\ni.e. 50 bytes.  \nBut of course, the same optimization applies:\n```sh\n$ cargo rustc --bin closure_filters --features capturing_closure -- -Zprint-type-sizes\n# [...]\n`Filter\u003cRange\u003cusize\u003e, [closure\u003cmin:\u0026usize, max:\u0026usize\u003e]\u003e`: 40 bytes, alignment: 8 bytes\n```\nOnce again monomorphization has eliminated the extra indirection:\n```sh\n$ cargo asm --features capturing_closure \\\n            --asm-style att \\\n            --build-type debug \\\n            '\u003cchapter_1::Filter\u003cI,P\u003e as core::iter::traits::iterator::Iterator\u003e::next'\n```\n```assembly\n;; (self.predicate)(\u0026v)\nleaq    64(%rsp), %rax\nmovq    %rax, 80(%rsp)\nmovq    32(%rsp), %rax\naddq    $24, %rax       ;; 24 bytes offset from the start of `Filter\u003cI, P\u003e` is `self.predicate`,\n                        ;; i.e. the captured state, aka `self`.\nmovq    80(%rsp), %rcx\nmovq    %rcx, 88(%rsp)\nmovq    88(%rsp), %rsi\nmovq    %rax, %rdi\ncallq   closure_filters::capturing_closure::{{closure}}\nmovb    %al, 31(%rsp)\n```\nThe attentive reader shall notice the two extra instructions this time: the compiler is properly setting up the stack so that our closure can access its state (which is made to point to `self.predicate`, using a 24 bytes offset).\n\n### 1.2.c. Usual complications\n\nWhen working in single-threaded environments, closures are usually a breeze to work with. The compiler gets to do its magic and you rarely seem to get into trouble, if at all.  \nOnce we get into async code, though, some concepts that are usually mostly invisible will start becoming very apparent as Rust compile-time safeties start kicking in.\n\n**Higher Ranked Trait Bounds**\n\nThe first complication that I want to mention has nothing to do with neither multi-threading nor asynchronous code, but you're bound to face it at one point or another if you start digging into any closure-heavy codebase (which is true of any async codebase, so..), so I'd rather mention it in passing.\n\nTL;DR, you _will_ encounter this syntax at one point or another:\n```rust\n// Notice the `for\u003c'a\u003e` in that trait bound.\nfn my_func\u003cF: for\u003c'a\u003e Fn(\u0026'a str) -\u003e bool\u003e(f: F) -\u003e bool { /* ... */ }\n```\nwhich is meant to denote the higher-kindness of a lifetime trait bound, meaning that `\u0026str` cannot outlive `'a`, where `'a` is _any_ lifetime, i.e. it is left unconstrained.\n\nWhile I would love to talk about Generic Associated Types, Higher Ranked Types/Lifetimes and all that fun at some point, now is nor the time nor the place.  \nFor now, just keep in mind that this syntax exists, that you will most likely encouter it at some point, and that you'll find all the information you'll ever need in [the original RFC](https://rust-lang.github.io/rfcs/0387-higher-ranked-trait-bounds.html) as well as in [the corresponding nomicon entry](https://doc.rust-lang.org/nomicon/hrtb.html).\n\n**Auto marker traits and inferred lifetimes**\n\nAlways keep in mind that closures are just structures, and thus the usual rules regarding compound types and auto \u0026 marker traits as well as lifetimes apply.  \nI.e. the lifetime and intrinsic properties of a state-machine built up from the combination of iterators and closures will be a direct result of both its explicitly _and_ implicitly captured enviroments.\n\nConsider our `Filter` combinator, for example:\n```rust\nlet min = 5;\nlet max = 8;\nlet mut it = Range::new(1usize, 20, 1).filter_with(|\u0026v| v \u003e= min \u0026\u0026 v \u003c max);\nassert_eq!(Some(5), it.next());\nassert_eq!(Some(6), it.next());\nassert_eq!(Some(7), it.next());\nassert_eq!(None, it.next());\n```\n\nIn this case, the resulting state-machine's (`it`) lifetime is bounded by the lifetimes of `min` \u0026 `max`.  \nSimilarly, whether `it` can or cannot be moved between threads (i.e. `Send`) depends on whether `min` \u0026 `max` can be sent between threads.\n\nObviously, in a state-machine as simple as this one, this won't ever cause you any trouble.  \nIn a massive asynchronous state-machine, built-up from many many parts (that may even cross module boundaries), and that will be arbitrarily moved back and forth between threads by some executor that you might or might not control, on the other hand... Let's just say that it can be easy to lose track of who requires what and for how long.  \n\nBut, hey, that's precisely why we're using Rust in the first place!  \nCompiler errors for these hard cases have become insanely good too, if quite verbose.\n\n## 1.3. Iterators are closures are iterators\n\n_And now for the fun part._\n\nLet's recap the first two sections of this chapter, in as many sentences:\n- Iterators are state-machines that are implemented using a structure to keep their state and a `.next()` method that takes a mutable reference to said state (`\u0026mut self`) in order to move the machine forward.\n- Closures are state-machines that are implemented using a structure to hold their state (i.e. their captured environment) and a `call_once`/`call_mut`/`call` method that takes said state by move/mutable reference/shared reference (respectively) in order to drive the machine forward.\n\nIf you're thinking to yourself that these two sound similar, that's because they are.  \nIn this section we're going to have us a little fun by digressing into these similarities.\n\n### 1.3.a. Iterators as closures\n\nConsider our `Range` iterator from earlier:\n```rust\npub struct Range\u003cT\u003e {\n    cur: T,\n    end: T,\n    incr: T,\n}\n\nimpl\u003cT\u003e Range\u003cT\u003e {\n    pub fn new(start: T, end: T, incr: T) -\u003e Self {\n        Self {\n            cur: start,\n            end,\n            incr,\n        }\n    }\n}\n\nimpl\u003cT\u003e Iterator for Range\u003cT\u003e\nwhere\n    T: std::ops::AddAssign + PartialOrd + Clone,\n{\n    type Item = T;\n\n    fn next(\u0026mut self) -\u003e Option\u003cSelf::Item\u003e {\n        match \u0026self.cur {\n            v if *v \u003c self.end =\u003e {\n                let ret = self.cur.clone();\n                self.cur += self.incr.clone();\n                ret.into()\n            }\n            _ =\u003e None,\n        }\n    }\n}\n```\nthat we used like this:\n```rust\nlet mut j = 1;\nfor i in Range::new(1usize, 4, 1) {\n    assert_eq!(j, i);\n    j += 1;\n}\n```\n\nCould we express `Range` in terms of a closure instead?  \nWell of course we can, what's an iterator but a `FnMut() -\u003e Option\u003cT\u003e` closure, really?\n```rust\npub mod range_fn {\n    pub fn new\u003cT\u003e(mut start: T, end: T, incr: T) -\u003e impl FnMut() -\u003e Option\u003cT\u003e\n    where\n        T: std::ops::AddAssign + PartialOrd + Clone,\n    {\n        move || {\n            if start \u003c end {\n                let ret = start.clone();\n                start += incr.clone();\n                return ret.into();\n            }\n            None\n        }\n    }\n}\n```\nwhich we can basically use the same way as an iterator:\n```rust\nlet mut f = range_fn::new(1, 4, 1);\nassert_eq!(Some(1), f());\nassert_eq!(Some(2), f());\nassert_eq!(Some(3), f());\nassert_eq!(None, f());\n```\nBut what about combinators, you say?\n\n### 1.3.b. Closure combinators\n\nRemember our `Range` iterator could be combined with a `Bounds` iterator, allowing us to express something like the following:\n```rust\nlet mut it = Bounds::new(Range::new(1usize, 20, 1), 5, 8);\nassert_eq!(Some(5), it.next());\nassert_eq!(Some(6), it.next());\nassert_eq!(Some(7), it.next());\nassert_eq!(None, it.next());\n```\n\nWe can apply the same pattern to closures: by moving ownership of the wrappee inside the state of the wrapper, we can delegate the state-machinery from the wrapper and into the wrappee.\n```rust\npub mod bounds_fn {\n    pub fn new\u003cT, F\u003e(mut inner: F, min: T, max: T) -\u003e impl FnMut() -\u003e Option\u003cT\u003e\n    where\n        T: PartialOrd,\n        F: FnMut() -\u003e Option\u003cT\u003e,\n    {\n        move || loop {\n            match inner() {\n                Some(v) if v \u003e= min \u0026\u0026 v \u003c max =\u003e return v.into(),\n                Some(_) =\u003e {}\n                None =\u003e return None,\n            }\n        }\n    }\n}\n```\nAgain, using our closure combinator is pretty similar to using our iterator combinator:\n```rust\nlet mut f = bounds_fn::new(range_fn::new(1usize, 20, 1), 5, 8);\nassert_eq!(Some(5), f());\nassert_eq!(Some(6), f());\nassert_eq!(Some(7), f());\nassert_eq!(None, f());\n```\nAnd, as we'd expect based on everything we've learned so far, what gets generated here is pretty much the same thing, both from a memory representation and execution model standpoints, as what got generated for the equivalent iterator combinator.  \n```sh\n$ cargo rustc --lib -- --test -Zprint-type-sizes\n# [...]\n## Iterator combinator\n`Bounds\u003cRange\u003cusize\u003e, usize\u003e`: 40 bytes, alignment: 8 bytes\n## Closure combinator\n`[closure\u003cf:[closure\u003cstart:usize, end:usize, incr:usize\u003e], min:usize, max:usize\u003e]`: 40 bytes, alignment: 8 bytes\n```\nWhat about extensions, though? Those were _the_ true killer feature of iterator combinators!\n\n### 1.3.c. Closure extensions\n\nRemember how we were able to do this?\n```rust\nlet mut it = Range::new(1usize, 20, 1).bounds(1, 20).bounds(3, 13).bounds(5, 8);\nassert_eq!(Some(5), it.next());\nassert_eq!(Some(6), it.next());\nassert_eq!(Some(7), it.next());\nassert_eq!(None, it.next());\n```\n\nWell closures are a trait too, aren't they? Surely we can extend it!\n```rust\ntrait BoundsExtFn\u003c'a, T\u003e: FnMut() -\u003e Option\u003cT\u003e\nwhere\n    Self: 'a + Sized,\n    T: 'a + std::cmp::PartialOrd,\n{\n    fn bounds(self, min: T, max: T) -\u003e Box\u003cdyn FnMut() -\u003e Option\u003cT\u003e + 'a\u003e {\n        Box::new(bounds_fn::new(self, min, max))\n    }\n}\n\nimpl\u003c'a, F, T\u003e BoundsExtFn\u003c'a, T\u003e for F\nwhere\n    F: 'a + FnMut() -\u003e Option\u003cT\u003e,\n    T: 'a + std::cmp::PartialOrd,\n{\n}\n```\nTa-daaaa!\n```rust\nlet mut f = range_fn::new(1usize, 20, 1).bounds(1, 20).bounds(3, 13).bounds(5, 8);\nassert_eq!(Some(5), f());\nassert_eq!(Some(6), f());\nassert_eq!(Some(7), f());\nassert_eq!(None, f());\n```\nOk, that's not really \"ta-da\" worthy, actually. I lied.\n\nWhile what we've created here does indeed provide similar functional behavior as our hand-crafted combinator defined above, it has a _completely different_ memory representation and execution model (not to mention that the code itself looks way more complex).  \nAnd by different, I actually mean _worse in every way_.  \nWe've just brought heap allocations and pointer indirections upon ourselves. Oh noes.\n\n```sh\n$ cargo rustc --lib -- --test -Zprint-type-sizes\n# [...]\n`[closure\u003cf:Box\u003cdyn FnMut() -\u003e Option\u003cusize\u003e\u003e, min:usize, max:usize\u003e]`: 32 bytes, alignment: 8 bytes\n```\n\nAll of our issues stem from the use of a `Box` there (`Box\u003cdyn FnMut() -\u003e Option\u003cT\u003e + 'a\u003e`), which begs the question: why did we reach for a `Box` in the first place?\n\nThe reason is actually a limitation in Rust's type system, namely the lack of Generic Associated Types, which prevents us from expressing a trait method that returns a `impl FnMut() -\u003e Option\u003cT\u003e`, i.e. an unconstrained generic type (GATs are in fact a limited form of HKTs which, once again, are a topic for another day).\n\nBut wait a minute, why didn't we face this issue back when we implemented `BoundsExt` for iterators?\n```rust\npub trait BoundsExt: Iterator\nwhere\n    Self: Sized,\n{\n    fn bounds\u003cT\u003e(self, min: T, max: T) -\u003e Bounds\u003cSelf, T\u003e {\n        Bounds::new(self, min, max)\n    }\n}\n\nimpl\u003cI: Iterator\u003e BoundsExt for I {}\n```\nThat right here is the magical part: `Bounds\u003cSelf, T\u003e`.  \nI.e. we never had the problem before because we were actually capable of referring to a `Bounds\u003cSelf, T\u003e` by its name.\n\nUnfortunately, one of the first thing we've learned about closures is that we cannot name them; they're all different, and they're all anonymous. Thus we _have_ to return a generic type here, and it certainly cannot be constrained by the caller, since they couldn't possibly name the type of a closure that doesn't even yet exist!\n\nTherefore, what we're left to work with is an unconstrained generic type to return, and an unfortunate solution to the problem: boxing the return value into a trait object, which is exactly what we did there.  \nOf course, in doing so we've also sacrificed any chance at monomorphization and all the good things that can come out of it: inlining, code elimination, recursive optimizations, etc...\n\n### 1.3.d. Back and forth\n\nWe've shown that we can express iterators as closures and vice-versa, thus we should be able to freely turn one into the other and back again on the fly, shouldn't we?\n\nTurning an iterator into a closure is just a matter of implementing `FnMut` for `I: Iterator`, where the implementation does nothing but delegate the call to `Iterator::next`:\n```rust\npub fn iter_to_closure\u003cI: Iterator\u003e(inner: I) -\u003e impl FnMut() -\u003e Option\u003cI::Item\u003e {\n    // We cannot implement Fn* traits directly on `I: Iterator` because of\n    // coherence.\n    struct Iter\u003cI\u003e(I);\n\n    impl\u003cI\u003e FnOnce\u003c()\u003e for Iter\u003cI\u003e\n    where\n        I: Iterator,\n    {\n        type Output = Option\u003cI::Item\u003e;\n\n        extern \"rust-call\" fn call_once(mut self, _args: ()) -\u003e Self::Output {\n            Iterator::next(\u0026mut self.0)\n        }\n    }\n    impl\u003cI\u003e FnMut\u003c()\u003e for Iter\u003cI\u003e\n    where\n        I: Iterator,\n    {\n        extern \"rust-call\" fn call_mut(\u0026mut self, _args: ()) -\u003e Self::Output {\n            Iterator::next(\u0026mut self.0)\n        }\n    }\n\n    Iter(inner)\n}\n```\nGoing the other way is even more straightforward:\n```rust\npub fn closure_to_iter\u003cT, F: FnMut() -\u003e Option\u003cT\u003e\u003e(inner: F) -\u003e impl Iterator\u003cItem = T\u003e {\n    struct Iter\u003cF\u003e(F);\n\n    impl\u003cF, T\u003e Iterator for Iter\u003cF\u003e\n    where\n        F: FnMut() -\u003e Option\u003cT\u003e,\n    {\n        type Item = T;\n\n        fn next(\u0026mut self) -\u003e Option\u003cSelf::Item\u003e {\n            self.0()\n        }\n    }\n\n    Iter(inner)\n}\n```\nAnd in fact, it seems so natural to want to express an iterator as a closure that libcore provides the exact same code via [`core::iter::from_fn`](https://doc.rust-lang.org/core/iter/fn.from_fn.html).\n\nAnd, voila! From iterators to closures and back again.  \nNo magic tricks, no hidden allocs, no nothing.\n```rust\nlet mut it = Range::new(1usize, 20, 1).into_iter().bounds(5, 14);\nassert_eq!(Some(5), it.next());\nassert_eq!(Some(6), it.next());\nassert_eq!(Some(7), it.next());\n\nlet mut f = iter_to_closure(it);\nassert_eq!(Some(8), f());\nassert_eq!(Some(9), f());\nassert_eq!(Some(10), f());\n\nlet mut it = closure_to_iter(f);\nassert_eq!(Some(11), it.next());\nassert_eq!(Some(12), it.next());\nassert_eq!(Some(13), it.next());\n\nassert_eq!(None, it.next());\n```\n\n## 1.4. The case for asynchronous Rust\n\nAnd with that, our little demystifying tour of iterators and closures comes to an end.  \nSo, what was the point of all of this? What do iterators and closures have to do with anything?\n\nActually, beyond iterators and closures, what we've really looked at during this chapter are the various ways of expressing state-machines using Rust's native tools.  \nCoincidentally, a lot (most?) of idiomatic Rust code comes down to just that: building up complex state machines by combining iterators and closures, and then polling these state-machines at the edge of the software, where errors will be dealt with properly.  \n\nWhat's with asynchronous Rust, then? What can we express in async Rust that we couldn't convey with these tools? The answer is multiplexing... kind of.\n\n### 1.4.a. What are we trying to fix?\n\nA standard iterator will hold an entire OS thread from the time it's polled and until it yields its next value. Whether this iterator actually does something useful with that OS thread is irrelevant.  \nConsider this over-used example of an iterator that sends a packet to a station on Mars when it gets polled, and yields a welcoming message when an answer comes back from the network:\n```rust\npub struct PingMars;\n\nimpl Iterator for PingMars {\n    type Item = \u0026'static str;\n\n    fn next(\u0026mut self) -\u003e Option\u003cSelf::Item\u003e {\n        fn ping_mars() -\u003e \u0026'static str {\n            use std::{thread::sleep, time::Duration};\n            sleep(Duration::from_secs(2)); // simulating network\n            \"Hello from Mars!\"\n        }\n\n        ping_mars().into()\n    }\n}\n```\nOnce we start polling it, this iterator will keep hold of the underlying OS thread for as long as it takes for Mars to respond.  \nObviously, in this case, the overwhelming majority of the CPU time will be spent idling, waiting for data from the network.\n```rust\nlet mut mars_com = PingMars;\nfor msg in mars_com { // Blocking an entire OS thread :(\n    println!(\"received message from Mars: {}!\", msg);\n}\n```\n\nThat's the textbook case of synchronous/blocking I/O, which has been thrown around and around for the last decades.\n\nBut the issue isn't really confined to I/O, is it?  \nWhat about a program that has to sleep, e.g. to wait for an external piece of hardware to get ready?  \nWhat about a program that is stuck waiting for an intra-program signal, e.g. a channel or a mutex?\n\nIt seems that what we're getting at is that the issue isn't specific to I/O, but rather generalizes to any non-CPU intensive code.  \nActually, I'd argue that it encompasses even more than \"just\" non-CPU intensive code.\n\nWhat if we had a state-machine that needed to do some CPU-heavy computation on every poll, but we'd still very much like for it _not_ to hijack an entire OS thread until its next yield; i.e. we'd like to be able to pause the computation of a value at arbitrary points, so that another state-machine could make some progress of its own in the meanwhile.  \nHeck, what if we were running on some kind of embedded platform that doesn't provide OS threads in the first place?  \n\nConsider this (ridiculously bad) Fibonacci iterator:\n```rust\npub struct Fibonacci {\n    cur: usize,\n    until: usize,\n}\n\nimpl Fibonacci {\n    pub fn new(until: usize) -\u003e Self {\n        Self { cur: 0, until }\n    }\n}\n\nimpl Iterator for Fibonacci {\n    type Item = (usize, usize);\n\n    fn next(\u0026mut self) -\u003e Option\u003cSelf::Item\u003e {\n        if self.cur \u003e self.until {\n            return None;\n        }\n        let n = self.cur;\n        self.cur += 1;\n\n        fn fib(n: usize) -\u003e usize {\n            match n {\n                v if v == 0 =\u003e 0,\n                v if v == 1 =\u003e 1,\n                v =\u003e fib(v - 1) + fib(v - 2),\n            }\n        }\n        (n, fib(n)).into()\n    }\n}\n```\nFor big enough values of `n`, every poll is going to take so much CPU-time to compute, maybe we'd rather let some other state-machine progress from time to time, hm?  \n(Yes, Fibonacci is a very contrived example. Yes, memoization would be a much better solution in this case. Bear with me.)\n\nThe real issue here is neither blocking I/O, or non-CPU intensive code, or anything specific like that.  \nThe real issue simply is that we need a way to express _multiplexing_ as part of our state-machines, and more specifically as part of our polling mechanism.\n\nQuestion: _Haven't we fixed that issue already, though? Like decades ago?_  \nThat's exactly what OS threads are for, multiplexing N programs onto M physical threads, and we've had those for who-knows how long.  \nIn fact they work so well that you can spawn millions of them without breaking a sweat on modern hardware.\n\nAnswer: _Yes, there is in fact nothing that you could express with Futures/Streams that you wouldn't be able to convey with Closures/Iterators and a bunch of good ol' OS threads._  \nIn fact, both Rust's stdlib and ecosystem offer very powerful tools for working with OS threads ([`crossbeam`](https://github.com/crossbeam-rs/crossbeam)) and multi-threaded iterators ([`rayon`](https://github.com/rayon-rs/rayon)); these tools should most likely always be your first weapon of choice, unless you fall into either of those two categories:\n- You have hard performance constraints.  \nAsync code can achieve A) much better performance and B) more efficient CPU usage than OS threads thanks to the lack of context-switching overhead.  \nAt large enough scale, this will more than likely manifests itself as A) smoother tail latencies and B) much cheaper CPU bills.\n- You have hard environment constraints.  \nWhat if your platform simply doesn't provide OS threads? What if it does but you cannot use them for some reason (e.g. some determinism contraints)?\n\nOf course, those gains don't come for free.  \nAs we'll see in the rest of this book, asynchronous Rust ships with a metric ton of added complexity, a tradeoff that may or may not be worth it depending on your constraints.\n\n### 1.4.b. How'd we go about fixing it?\n\nLet's take a minute to think about how'd we go about fixing the lack of multiplexing capability of closures and iterators.  \n\nIn the case of the `PingMars` iterator, the solution is obvious: we would need to make use of non-blocking I/O so that we could give back control of the OS thread to the poller in case the underlying network device isn't ready yet.  \nSomehow, we'll also need to find a way to notify the poller when the underlying device finally turns ready again, otherwise how could they know when they should start polling again?\n\nFor the `Fibonacci` example, we'd need a way to give control of the thread back to the poller in case the current value is taking too long to compute (for an arbitrary definition of \"too long\").  \nInterestingly, we don't need to ever notify the poller in this case: they're free to start polling again whenever they want, the iterator only released the OS thread for the sake of politeness anyway; i.e. it's always ready.  \nWhat we're definitely going to need, though, is a way to know exactly where we stopped in the computation back when we released the OS thread, so that we can continue from that point on when the polling restarts.\n\nWe could go on and on, but already a pattern starts emerging here:\n- The state-machine must be able to give back control of the OS thread to the poller, even from the middle of a polling cycle.\n- The state-machine must have a way of notifying the poller when it's a good time to start polling again.\n- The state-machine must keep track of the progress made during the last polling cycle, so that it can start again from there.\n\nSay we were to take the definition of Iterator and encode those constraints in it, we'd probably end up with something like this:\n```rust\npub enum Poll\u003cT\u003e {\n    Ready(Option\u003cT\u003e),\n    NotReady,\n}\n\npub struct Notifier {/* ... */}\n\npub trait MultiplexedIterator {\n    type Item;\n\n    /// Advances the iterator and returns the next value as a `Poll::Ready(T)`\n    /// if it's ready to be yielded, otherwise returns `Poll::NotReady`.\n    /// The poller is responsible for polling again and again, until an actual\n    /// value can be returned.\n    ///\n    /// Returns `Poll::Ready(None)` when iteration is finished.\n    /// Individual iterator implementations must notify the poller when it can\n    /// poll again after having returned `Poll::NotReady`.\n    fn next(\u0026mut self, n: Notifier) -\u003e Poll\u003cSelf::Item\u003e;\n}\n```\nGuess what, we've essentially just reinvented `Stream` (..almost)!\n\nWhen you take Closures and Iterators, and engineer multiplexing-support into them, what you get back are Futures and Streams.  \n\n### 1.4.c. Conclusion\n\n**Asynchronous Rust is about expressing state-machines that can be multiplexed onto a single OS thread**.\n\nThe main reasons to do so are A) better overall performance and B) environment constraints, at the cost of a massive increase in complexity, both from a usage and implementation standpoints.\n\n`Future`s and `Stream`s are logical extensions to closures and iterators, giving them the ability to be multiplexed onto a single OS thread.  \nAs we'll see, the four of them all share many of the same properties and design principles, which is why we've spent this entire chapter covering every last details of closures and iterators in the first place.\n\nIterators and closures are, as I like to say, the gateway drugs to Futures and Streams.  \nIn fact, as we'll see later in this book, these four can (and will be) all be expressed in terms of the mother of all state-machines: Generators.\n\n***\n\n# 2. Chapter II\n\nTODO\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fteh-cmc%2Frust-async","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fteh-cmc%2Frust-async","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fteh-cmc%2Frust-async/lists"}