[
  {
    "path": ".gitignore",
    "content": ".DS_Store\nwip"
  },
  {
    "path": "assets/main.rs",
    "content": "fn main() {\n    println!(\"hopefully github detects this file and categorizes my repo as a Rust repo\");\n}\n"
  },
  {
    "path": "license-apache",
    "content": "                              Apache License\n                        Version 2.0, January 2004\n                     http://www.apache.org/licenses/\n\nTERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n1. Definitions.\n\n   \"License\" shall mean the terms and conditions for use, reproduction,\n   and distribution as defined by Sections 1 through 9 of this document.\n\n   \"Licensor\" shall mean the copyright owner or entity authorized by\n   the copyright owner that is granting the License.\n\n   \"Legal Entity\" shall mean the union of the acting entity and all\n   other entities that control, are controlled by, or are under common\n   control with that entity. For the purposes of this definition,\n   \"control\" means (i) the power, direct or indirect, to cause the\n   direction or management of such entity, whether by contract or\n   otherwise, or (ii) ownership of fifty percent (50%) or more of the\n   outstanding shares, or (iii) beneficial ownership of such entity.\n\n   \"You\" (or \"Your\") shall mean an individual or Legal Entity\n   exercising permissions granted by this License.\n\n   \"Source\" form shall mean the preferred form for making modifications,\n   including but not limited to software source code, documentation\n   source, and configuration files.\n\n   \"Object\" form shall mean any form resulting from mechanical\n   transformation or translation of a Source form, including but\n   not limited to compiled object code, generated documentation,\n   and conversions to other media types.\n\n   \"Work\" shall mean the work of authorship, whether in Source or\n   Object form, made available under the License, as indicated by a\n   copyright notice that is included in or attached to the work\n   (an example is provided in the Appendix below).\n\n   \"Derivative Works\" shall mean any work, whether in Source or Object\n   form, that is based on (or derived from) the Work and for which the\n   editorial revisions, annotations, elaborations, or other modifications\n   represent, as a whole, an original work of authorship. For the purposes\n   of this License, Derivative Works shall not include works that remain\n   separable from, or merely link (or bind by name) to the interfaces of,\n   the Work and Derivative Works thereof.\n\n   \"Contribution\" shall mean any work of authorship, including\n   the original version of the Work and any modifications or additions\n   to that Work or Derivative Works thereof, that is intentionally\n   submitted to Licensor for inclusion in the Work by the copyright owner\n   or by an individual or Legal Entity authorized to submit on behalf of\n   the copyright owner. For the purposes of this definition, \"submitted\"\n   means any form of electronic, verbal, or written communication sent\n   to the Licensor or its representatives, including but not limited to\n   communication on electronic mailing lists, source code control systems,\n   and issue tracking systems that are managed by, or on behalf of, the\n   Licensor for the purpose of discussing and improving the Work, but\n   excluding communication that is conspicuously marked or otherwise\n   designated in writing by the copyright owner as \"Not a Contribution.\"\n\n   \"Contributor\" shall mean Licensor and any individual or Legal Entity\n   on behalf of whom a Contribution has been received by Licensor and\n   subsequently incorporated within the Work.\n\n2. Grant of Copyright License. Subject to the terms and conditions of\n   this License, each Contributor hereby grants to You a perpetual,\n   worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n   copyright license to reproduce, prepare Derivative Works of,\n   publicly display, publicly perform, sublicense, and distribute the\n   Work and such Derivative Works in Source or Object form.\n\n3. Grant of Patent License. Subject to the terms and conditions of\n   this License, each Contributor hereby grants to You a perpetual,\n   worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n   (except as stated in this section) patent license to make, have made,\n   use, offer to sell, sell, import, and otherwise transfer the Work,\n   where such license applies only to those patent claims licensable\n   by such Contributor that are necessarily infringed by their\n   Contribution(s) alone or by combination of their Contribution(s)\n   with the Work to which such Contribution(s) was submitted. If You\n   institute patent litigation against any entity (including a\n   cross-claim or counterclaim in a lawsuit) alleging that the Work\n   or a Contribution incorporated within the Work constitutes direct\n   or contributory patent infringement, then any patent licenses\n   granted to You under this License for that Work shall terminate\n   as of the date such litigation is filed.\n\n4. Redistribution. You may reproduce and distribute copies of the\n   Work or Derivative Works thereof in any medium, with or without\n   modifications, and in Source or Object form, provided that You\n   meet the following conditions:\n\n   (a) You must give any other recipients of the Work or\n       Derivative Works a copy of this License; and\n\n   (b) You must cause any modified files to carry prominent notices\n       stating that You changed the files; and\n\n   (c) You must retain, in the Source form of any Derivative Works\n       that You distribute, all copyright, patent, trademark, and\n       attribution notices from the Source form of the Work,\n       excluding those notices that do not pertain to any part of\n       the Derivative Works; and\n\n   (d) If the Work includes a \"NOTICE\" text file as part of its\n       distribution, then any Derivative Works that You distribute must\n       include a readable copy of the attribution notices contained\n       within such NOTICE file, excluding those notices that do not\n       pertain to any part of the Derivative Works, in at least one\n       of the following places: within a NOTICE text file distributed\n       as part of the Derivative Works; within the Source form or\n       documentation, if provided along with the Derivative Works; or,\n       within a display generated by the Derivative Works, if and\n       wherever such third-party notices normally appear. The contents\n       of the NOTICE file are for informational purposes only and\n       do not modify the License. You may add Your own attribution\n       notices within Derivative Works that You distribute, alongside\n       or as an addendum to the NOTICE text from the Work, provided\n       that such additional attribution notices cannot be construed\n       as modifying the License.\n\n   You may add Your own copyright statement to Your modifications and\n   may provide additional or different license terms and conditions\n   for use, reproduction, or distribution of Your modifications, or\n   for any such Derivative Works as a whole, provided Your use,\n   reproduction, and distribution of the Work otherwise complies with\n   the conditions stated in this License.\n\n5. Submission of Contributions. Unless You explicitly state otherwise,\n   any Contribution intentionally submitted for inclusion in the Work\n   by You to the Licensor shall be under the terms and conditions of\n   this License, without any additional terms or conditions.\n   Notwithstanding the above, nothing herein shall supersede or modify\n   the terms of any separate license agreement you may have executed\n   with Licensor regarding such Contributions.\n\n6. Trademarks. This License does not grant permission to use the trade\n   names, trademarks, service marks, or product names of the Licensor,\n   except as required for reasonable and customary use in describing the\n   origin of the Work and reproducing the content of the NOTICE file.\n\n7. Disclaimer of Warranty. Unless required by applicable law or\n   agreed to in writing, Licensor provides the Work (and each\n   Contributor provides its Contributions) on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n   implied, including, without limitation, any warranties or conditions\n   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n   PARTICULAR PURPOSE. You are solely responsible for determining the\n   appropriateness of using or redistributing the Work and assume any\n   risks associated with Your exercise of permissions under this License.\n\n8. Limitation of Liability. In no event and under no legal theory,\n   whether in tort (including negligence), contract, or otherwise,\n   unless required by applicable law (such as deliberate and grossly\n   negligent acts) or agreed to in writing, shall any Contributor be\n   liable to You for damages, including any direct, indirect, special,\n   incidental, or consequential damages of any character arising as a\n   result of this License or out of the use or inability to use the\n   Work (including but not limited to damages for loss of goodwill,\n   work stoppage, computer failure or malfunction, or any and all\n   other commercial damages or losses), even if such Contributor\n   has been advised of the possibility of such damages.\n\n9. Accepting Warranty or Additional Liability. While redistributing\n   the Work or Derivative Works thereof, You may choose to offer,\n   and charge a fee for, acceptance of support, warranty, indemnity,\n   or other liability obligations and/or rights consistent with this\n   License. However, in accepting such obligations, You may act only\n   on Your own behalf and on Your sole responsibility, not on behalf\n   of any other Contributor, and only if You agree to indemnify,\n   defend, and hold each Contributor harmless for any liability\n   incurred by, or claims asserted against, such Contributor by reason\n   of your accepting any such warranty or additional liability.\n\nEND OF TERMS AND CONDITIONS\n"
  },
  {
    "path": "license-mit",
    "content": "Permission is hereby granted, free of charge, to any\nperson obtaining a copy of this software and associated\ndocumentation files (the \"Software\"), to deal in the\nSoftware without restriction, including without\nlimitation the rights to use, copy, modify, merge,\npublish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software\nis furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice\nshall be included in all copies or substantial portions\nof the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF\nANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED\nTO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A\nPARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT\nSHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR\nIN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\nDEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "posts/chat-server.md",
    "content": "# Beginner's Guide to Concurrent Programming: Coding a Multithreaded Chat Server using Tokio\n\n_04 May 2024 · #rust · #async · #concurrency · #tokio_\n\n![chat server demo](../assets/chat-server-demo.gif)\n\n<details>\n<summary><b>Table of contents</b></summary>\n\n[Introduction](#introduction)<br>\n[01\\) Simplest possible echo server](#01-simplest-possible-echo-server)<br>\n[02\\) Handling multiple connections serially](#02-handling-multiple-connections-serially)<br>\n[03\\) Modifying messages](#03-modifying-messages)<br>\n[04\\) Parsing a stream of bytes as lines](#04-parsing-a-stream-of-bytes-as-lines)<br>\n[05\\) Adding `/help` & `/quit` server commands](#05-adding-help--quit-server-commands)<br>\n[06\\) Handling multiple connections concurrently](#06-handling-multiple-connections-concurrently)<br>\n[07\\) Letting users kinda chat](#07-letting-users-kinda-chat)<br>\n[08\\) Letting users actually chat](#08-letting-users-actually-chat)<br>\n[09\\) Assigning names to users](#09-assigning-names-to-users)<br>\n[10\\) Letting users edit their names with `/name`](#10-letting-users-edit-their-names-with-name)<br>\n[11\\) Freeing user's name if they disconnect](#11-freeing-users-name-if-they-disconnect)<br>\n[12\\) Adding a main room](#12-adding-a-main-room)<br>\n[13\\) Letting users join or create rooms with `/join`](#13-letting-users-join-or-create-rooms-with-join)<br>\n[14\\) Listing all rooms with `/rooms`](#14-listing-all-rooms-with-rooms)<br>\n[15\\) Removing empty rooms](#15-removing-empty-rooms)<br>\n[16\\) Listing users in the room with `/users`](#16-listing-users-in-the-room-with-users)<br>\n[17\\) Optimizing performance](#17-optimizing-performance)<br>\n[18\\) Finishing touches](#18-finishing-touches)<br>\n[Conclusion](#conclusion)<br>\n[Discuss](#discuss)<br>\n[Further reading](#further-reading)<br>\n[Notifications](#notifications)<br>\n\n</details>\n\n## Introduction\n\nI recently finished coding a multithreaded chat server using Tokio and I'm pretty happy with it. I'd like to share what I learned in this easy-to-follow step-by-step tutorial-style article. Let's get into it.\n\n> [!NOTE]\n> The full source code for every step can be found in [the examples directory](https://github.com/pretzelhammer/chat-server/tree/main/examples) of [this repository](https://github.com/pretzelhammer/chat-server).\n\n## 01\\) Simplest possible echo server\n\nLet's start by writing the simplest possible echo server.\n\n```rust\nuse tokio::{io::{AsyncReadExt, AsyncWriteExt}, net::TcpListener};\n\n#[tokio::main]\nasync fn main() -> anyhow::Result<()> {\n    let server = TcpListener::bind(\"127.0.0.1:42069\").await?;\n    let (mut tcp, _) = server.accept().await?;\n    let mut buffer = [0u8; 16];\n    loop {\n        let n = tcp.read(&mut buffer).await?;\n        if n == 0 {\n            break;\n        }\n        let _ = tcp.write(&buffer[..n]).await?;\n    }\n    Ok(())\n}\n```\n\n`#[tokio::main]` is a procedural macro that removes some of the boilerplate of building a tokio runtime, and turns this:\n\n```rust\n#[tokio::main]\nasync fn my_async_fn() {\n    todo!()\n}\n```\n\nRoughly into this:\n\n```rust\nfn main() {\n    tokio::runtime::Builder::new_multi_thread()\n        .enable_all()\n        .build()\n        .unwrap()\n        .block_on(my_async_fn)\n}\n\nasync fn my_async_fn() {\n    todo!()\n}\n```\n\nAnd as a quick refresher if we have an async function like this:\n\n```rust\nasync fn my_async_fn<T>(t: T) -> T {\n    todo!()\n}\n```\n\nIt roughly desugars into:\n\n```rust\nfn my_async_fn<T>(t: T) -> impl Future<Output = T> {\n    todo!()\n}\n```\n\nAnd a `Future` represents some form of asynchronous computation that we can `await` to get the result.\n\nLet's also use the `anyhow` crate for carefree error propagation. Any place where we might want to return `Result<T, Box<dyn std::err::Error>>` we can substitute it with `anyhow::Result<T>` and get the same behavior.\n\nIn this line we're binding a TCP listener:\n\n```rust\nlet server = TcpListener::bind(\"127.0.0.1:42069\").await?;\n```\n\n> [!IMPORTANT]\n> This is `tokio::net::TcpListener` and not `std::net::TcpListener`. The former is async and the latter is sync. Also calling `bind` returns a `Future` which we **must** `await` for anything to happen because futures are lazy in Rust!\n\nAs a general rule of thumb, if there's a type that handles IO by the same name in both `tokio` and `std` we want to use the one in `tokio`.\n\nThe rest of the code should hopefully be straight-forward:\n\n```rust\nlet (mut tcp, _) = server.accept().await?;\nlet mut buffer = [0u8; 16];\nloop {\n    let n = tcp.read(&mut buffer).await?;\n    if n == 0 {\n        break;\n    }\n    let _ = tcp.write(&buffer[..n]).await?;\n}\n```\n\nWe accept a connection, create a buffer, and then we read bytes from the connection into the buffer and write those bytes back to the connection in a loop until the connection closes.\n\nWe can connect to this server using a tool like `telnet` to see that it does in fact echo everything back to us:\n\n```console\n$ telnet 127.0.0.1 42069\n> my first e c h o server!\nmy first e c h o server!\n> hooray!\nhooray!\n```\n\n> [!TIP]\n> To quit `telnet` type `^]` (control + right square bracket) to enter command mode and type \"quit\" + ENTER.\n\nIf you'd like to mess around with the code yourself just `git clone` [this repository](https://github.com/pretzelhammer/chat-server) and you'll be able to quickly run any example with `just example {number}`. Then you can tinker with the source code at `examples/server-{number}.rs` to your heart's content. Once an example is running you can interact with it by running `just telnet`.\n\n## 02\\) Handling multiple connections serially\n\nThere's an annoying bug in our server: it quits after handling just one connection! If we try to `just telnet` more than once we get `telnet: Unable to connect to remote host: Connection refused` at which point we have to manually restart the server with `just example 01` again. 🤦\n\nHere's how we would fix it:\n\n```rust\nuse tokio::{io::{AsyncReadExt, AsyncWriteExt}, net::TcpListener};\n\n#[tokio::main]\nasync fn main() -> anyhow::Result<()> {\n    let server = TcpListener::bind(\"127.0.0.1:42069\").await?;\n    loop {\n        let (mut tcp, _) = server.accept().await?;\n        let mut buffer = [0u8; 16];\n        loop {\n            let n = tcp.read(&mut buffer).await?;\n            if n == 0 {\n                break;\n            }\n            let _ = tcp.write(&buffer[..n]).await?;\n        }\n    }\n}\n```\n\nWe just had to add another `loop` around our `server.accept()` line! Pretty easy, now we can run the updated example with `just example 02` and the server stays up regardless of how many times we run `just telnet` in a row.\n\n## 03\\) Modifying messages\n\nAs exciting as an echo server is, it would be even more exciting if it modified messages somehow. So how about we try adding a ❤️ emoji at the end of every echoed line? Here's what that would look like:\n\n```rust\nuse tokio::{io::{AsyncReadExt, AsyncWriteExt}, net::TcpListener};\n\n#[tokio::main]\nasync fn main() -> anyhow::Result<()> {\n    let server = TcpListener::bind(\"127.0.0.1:42069\").await?;\n    loop {\n        let (mut tcp, _) = server.accept().await?;\n        let mut buffer = [0u8; 16];\n        loop {\n            let n = tcp.read(&mut buffer).await?;\n            if n == 0 {\n                break;\n            }\n            // convert byte slice to a String\n            let mut line = String::from_utf8(buffer[..n].to_vec())?;\n            // remove line terminating chars added by telnet\n            line.pop(); // remove \\n char\n            line.pop(); // remove \\r char\n            // add our own line terminator :)\n            line.push_str(\" ❤️\\n\");\n            let _ = tcp.write(line.as_bytes()).await?;\n        }\n    }\n}\n```\n\nDemo of our hearty echo server:\n\n```console\n$ just telnet\n> hello\nhello ❤️\n> it works!\nit works! ❤️\n```\n\nHowever if we write a message that's a little too long we'll see this bug:\n\n```console\n> this is the best day ever!\nthis is the be ❤️\n day ever ❤️\n```\n\nWelp! Nobody said this was gonna be easy. We can increase the fixed size of our buffer but by how much? We can use a growable buffer like a `Vec` but what if the client sends a _really, really long line_? We could solve these problems ourselves, but they're pretty common, so we can also offload them to someone else too.\n\n## 04\\) Parsing a stream of bytes as lines\n\nTokio offers a convenient and robust solution to our line problem in the `tokio-util` crate. Here's how we can use it:\n\n```rust\nuse futures::{SinkExt, StreamExt};\nuse tokio::net::TcpListener;\nuse tokio_util::codec::{FramedRead, FramedWrite, LinesCodec};\n\n#[tokio::main]\nasync fn main() -> anyhow::Result<()> {\n    let server = TcpListener::bind(\"127.0.0.1:42069\").await?;\n    loop {\n        let (mut tcp, _) = server.accept().await?;\n        let (reader, writer) = tcp.split();\n        let mut stream = FramedRead::new(reader, LinesCodec::new());\n        let mut sink = FramedWrite::new(writer, LinesCodec::new());\n        while let Some(Ok(mut msg)) = stream.next().await {\n            msg.push_str(\" ❤️\");\n            sink.send(msg).await?;\n        }\n    }\n}\n```\n\nThere's a lot of new stuff in this example so let's go over it. The `split` method splits a `TcpStream` into a `ReadHalf` and `WriteHalf`. This is useful if we want to add these halves to different structs, or send them to different threads, or read and write to the same `TcpStream` concurrently (which we'll be doing later).\n\n`ReadHalf` implements `AsyncRead` and `WriteHalf` implements `AsyncWrite`, however as mentioned previously, these can be tedious and error-prone to work with directly, which why we bring in `LinesCodec`, `FramedRead`, and `FramedWrite`.\n\n`LinesCodec` handles the low-level details of converting a stream of bytes into a stream of UTF-8 strings delimited by newlines, and using it together with `FramedRead` we can wrap a `ReadHalf` to get an implementation of `Stream<Item = Result<String, _>>`, which is much easier to work with than an `AsyncRead`. A `Stream` is like the async version of an `Iterator`. For example, if we had a sync function like this:\n\n```rust\nfn iterate<T>(items: impl Iterator<Item = T>) {\n    for item in items {\n        todo!()\n    }\n}\n```\n\nThe refactored async version would be:\n\n```rust\nuse futures::{Stream, StreamExt};\n\nasync fn iterate<T>(mut items: impl Stream<Item = T> + Unpin) {\n    while let Some(item) = items.next().await {\n        todo!()\n    }\n}\n```\n\nWe also use `LinesCodec` together with `FramedWrite` to wrap a `WriteHalf` to get an implementation of `Sink<String, Error = _>`, which is much easier to work with than an `AsyncWrite`. As you've probably guessed, a `Sink` is the opposite of a `Stream`, it consumes values instead of producing values.\n\nThe rest of the code is straight-forward:\n\n```rust\nwhile let Some(Ok(mut msg)) = stream.next().await {\n    msg.push_str(\" ❤️\");\n    sink.send(msg).await?;\n}\n```\n\nWe get message from the stream, add a heart to it, and then send it to the sink. If we wanted to be fancy we could have also mapped the stream and forward it to the sink like this:\n\n```rust\nstream.map(|msg| {\n    let mut msg = msg?;\n    msg.push_str(\" ❤️\");\n    Ok(msg)\n}).forward(sink).await?\n```\n\n`forward` returns a `Future` that completes when the `Stream` has been fully processed into the `Sink` and the `Sink` has been closed and flushed.\n\nNow our server correctly appends the heart regardless of message length:\n\n```console\n$ just telnet\n> this is a really really really long message kinda\nthis is a really really really long message kinda ❤️\n```\n\n## 05\\) Adding `/help` & `/quit` server commands\n\nTelnet is annoying to quit. The usual tricks of `esc`, `^C`, and `^D` don't work. We have to type `^]` to enter command mode and then type `quit` + ENTER. 🤦\n\nWe can make our server more user-friendly by implementing our own commands, so let's start with `/help` and `/quit`. `/help` will print out a list and description of all the commands our server supports and `/quit` will cause the server to close the connection (which will also cause telnet to quit).\n\nSo that these commands are discoverable lets send them immediately to every client that connects. Here's what everything put together looks like:\n\n```rust\nuse futures::{SinkExt, StreamExt};\nuse tokio::net::TcpListener;\nuse tokio_util::codec::{FramedRead, FramedWrite, LinesCodec};\n\nconst HELP_MSG: &str = include_str!(\"help.txt\");\n\n#[tokio::main]\nasync fn main() -> anyhow::Result<()> {\n    let server = TcpListener::bind(\"127.0.0.1:42069\").await?;\n    loop {\n        let (mut tcp, _) = server.accept().await?;\n        let (reader, writer) = tcp.split();\n        let mut stream = FramedRead::new(reader, LinesCodec::new());\n        let mut sink = FramedWrite::new(writer, LinesCodec::new());\n        // send list of server commands to\n        // the user as soon as they connect\n        sink.send(HELP_MSG).await?;\n        while let Some(Ok(mut msg)) = stream.next().await {\n            // handle new /help command\n            if msg.starts_with(\"/help\") {\n                sink.send(HELP_MSG).await?;\n            // handle new /quit command\n            } else if msg.starts_with(\"/quit\") {\n                break;\n            // handle regular message\n            } else {\n                msg.push_str(\" ❤️\");\n                sink.send(msg).await?;\n            }\n        }\n    }\n}\n```\n\nLet's give it a spin:\n\n```console\n$ just telnet\nServer commands\n  /help - prints this message\n  /quit - quits server\n> /help # new command\nServer commands\n  /help - prints this message\n  /quit - quits server\n> woohoo it works\nwoohoo it works ❤️\n> /quit # new command\nConnection closed by foreign host.\n```\n\n## 06\\) Handling multiple connections concurrently\n\nThe biggest downside of our server is that it only handles one connection at a time! If we run `just telnet` in two separate terminals we'll notice our server will only respond to the first connection, and won't start responding to the second connection until the first quits. Although we've been using a lot of async APIs our current implementation behaves no differently than a sync single-threaded server. Let's change that:\n\n```rust\nuse futures::{SinkExt, StreamExt};\nuse tokio::net::{TcpListener, TcpStream};\nuse tokio_util::codec::{FramedRead, FramedWrite, LinesCodec};\n\nconst HELP_MSG: &str = include_str!(\"help.txt\");\n\n#[tokio::main]\nasync fn main() -> anyhow::Result<()> {\n    let server = TcpListener::bind(\"127.0.0.1:42069\").await?;\n    loop {\n        let (tcp, _) = server.accept().await?;\n        // spawn a separate task for\n        // to handle every connection\n        tokio::spawn(handle_user(tcp));\n    }\n}\n\nasync fn handle_user(mut tcp: TcpStream) -> anyhow::Result<()> {\n    let (reader, writer) = tcp.split();\n    let mut stream = FramedRead::new(reader, LinesCodec::new());\n    let mut sink = FramedWrite::new(writer, LinesCodec::new());\n    sink.send(HELP_MSG).await?;\n    while let Some(Ok(mut msg)) = stream.next().await {\n        if msg.starts_with(\"/help\") {\n            sink.send(HELP_MSG).await?;\n        } else if msg.starts_with(\"/quit\") {\n            break;\n        } else {\n            msg.push_str(\" ❤️\");\n            sink.send(msg).await?;\n        }\n    }\n    Ok(())\n}\n```\n\n`tokio::spawn` takes a `Future` and spawns an asynchronous \"task\" to complete it. The execution begins immediately so we don't have to `await` the returned join handle like we would a future. A \"task\" is like a native thread except instead of being managed by the OS it's managed by Tokio. You're probably already familiar with this concept by some of these other names: lightweight threads, green threads, user-space threads.\n\n## 07\\) Letting users kinda chat\n\nTo really get the party started we need to upgrade our echo server to a chat server that lets separate concurrent connections communicate with each other:\n\n> [!NOTE]\n> The code is starting to get long and difficult to read. All following examples will be presented as a heavily abbreviated diff highlighting the key changes, but you can still find the full source code for any example in [the examples directory](https://github.com/pretzelhammer/chat-server/tree/main/examples) of [this repository](https://github.com/pretzelhammer/chat-server). You can see a diff between any two examples by running `just diff {number} {number}`. For instance, to see the diff between this example and the previous example you would run `just diff 06 07`.\n\n```rust\n// ...\nasync fn main() -> anyhow::Result<()> {\n    // ...\n    // create broadcast channel\n    let (tx, _) = broadcast::channel::<String>(32);\n    // ...\n    // clone it for every connected client\n    tokio::spawn(handle_user(tcp, tx.clone()));\n}\n\nasync fn handle_user(\n    mut tcp: TcpStream,\n    tx: Sender<String>\n) -> anyhow::Result<()> {\n    // ...\n    // get a receiver from the sender\n    let mut rx = tx.subscribe();\n    // ...\n    while let Some(Ok(mut user_msg)) = stream.next().await {\n        // ...\n        // send all messages to the channel\n        tx.send(user_msg)?;\n        // ...\n        // receive all of our and others'\n        // messages from the channel\n        let peer_msg = rx.recv().await?;\n        sink.send(peer_msg).await?;\n    }\n    // ...\n}\n```\n\nWe communicate between different clients using a broadcast channel. After creating the channel we get a `Sender` and a `Receiver` which we can `clone` any number of times and send to different threads. Each value sent via a `Sender` gets received by every `Receiver`, so the value type must implement `Clone`.\n\nBefore we would get a message from the client's stream and immediately echo it out to the client's sink. Now when we get a message from the client's stream we pass it through the broadcast channel before we get it back and then send it to the client's sink. Every client will receive their own and others' messages from the shared channel.\n\nLet's try out our new code by connecting with two clients at once:\n\n```console\n$ just telnet # concurrent client 1\n> 1: hello # msg 1\n1: hello ❤️\n> 1: anybody there? # msg 2\n1: anybody there? ❤️\n\n$ just telnet # concurrent client 2\n> 2: hey there # msg 3\n1: hello ❤️\n> 2: how are you # msg 4\n1: anybody there? ❤️\n> 2: i am right here # msg 5\n2: hey there ❤️\n> 2: wtf # msg 6\n2: how are you ❤️\n```\n\nEach client is seeing each other's messages but they seem kinda delayed and staggered for some reason. Something just isn't quite right here.\n\nThe bug in our code is here:\n\n```rust\n// the client must first send a message\nwhile let Some(Ok(mut user_msg)) = stream.next().await {\n    // in order to receive a message\n    let peer_msg = rx.recv().await?;\n    // and these two things always alternate\n}\n```\n\nIn order to receive a message from a peer, we must first send a message. What if we want to be a lurker? Or what if our conversation partner is much more chatty than us? On the other hand, if we're the chatty one then we'll barely see any messages from our partner since we'll mostly see our own echoed output.\n\nTo solve this problem we need to be able to `await` two futures at once. In this case those futures are the ones created by `stream.next()`, which gets the next message from the client, and `rx.recv()`, which gets the next message from the channel.\n\n## 08\\) Letting users actually chat\n\n`tokio::select!` allows us to poll multiple futures at once:\n\n```rust\nasync fn handle_user(\n    mut tcp: TcpStream,\n    tx: Sender<String>\n) -> anyhow::Result<()> {\n    // ...\n    loop {\n        tokio::select! {\n            user_msg = stream.next() => {\n                // ...\n            },\n            peer_msg = rx.recv() => {\n                // ...\n            },\n        }\n    }\n    // ...\n}\n```\n\nWe execute the match arm of whatever future completes first. The other future is dropped.\n\nNow if we try our server:\n\n```console\n$ just telnet # concurrent client 1\n> 1: hello # msg 1\n1: hello ❤️\n> 1: anybody there? # msg 2\n1: anybody there? ❤️\n2: i am right here ❤️\n2: how are you ❤️\n> 1: i am doing great # msg 5\n\n$ just telnet # concurrent client 2\n1: hello ❤️\n1: anybody there? ❤️\n> 2: i am right here # msg 3\n2: i am right here ❤️\n> 2: how are you? # msg 4\n2: how are you ❤️\n1: i am doing great ❤️\n```\n\nIt works! Anyway, celebrations aside, we need to talk about cancel safety. As mentioned before, Rust futures are lazy, and they only make progress while being polled. Polling is a little bit different than awaiting. To await a future means to poll it to completion. To poll a future means to ask it to make some progress, but it may not necessarily complete.\n\nOn one hand, this is great, because if we start polling a future and later decide we don't need its result anymore, we can stop polling it and we won't waste anymore CPU on doing useless work. On the other hand, this may not be so great if the future we're cancelling is in the middle of an important operation that if not completed may drop important data or may leave data in a corrupt state.\n\nLet's look at an example of \"cancelling\" a future. Cancelling is in quotes because it's not an explicit operation, it just means we started to poll a future but then stopped polling it before it completed.\n\n```rust\nuse tokio::time::sleep;\nuse std::time::Duration;\n\nasync fn count_to(num: u8) {\n    for i in 1..=num {\n        sleep(Duration::from_millis(100)).await;\n        println!(\"{i}\");\n    }\n}\n\n#[tokio::main]\nasync fn main() {\n    println!(\"start counting\");\n    // the select! macro polls each\n    // future until one of them completes,\n    // and then we execute the match arm\n    // of the completed future and drop\n    // all of the other futures\n    tokio::select! {\n        _ = count_to(3) => {\n            println!(\"counted to 3\");\n        },\n        _ = count_to(10) => {\n            println!(\"counted to 10\");\n        },\n    };\n    println!(\"stop counting\");\n    // this sleep is here to demonstrate\n    // that the count_to(10) doesn't make\n    // any progress after we stop polling\n    // it, even if we go to sleep and do\n    // nothing else for a while\n    sleep(Duration::from_millis(1000)).await;\n}\n```\n\nThis program outputs:\n\n```\nstart counting\n1\n1\n2\n2\n3\n3\ncounted to 3\nstop counting\n```\n\nWe \"cancelled\" the `count_to(10)` future. In this simple toy example we don't care if the count completes or not so this future is cancel-safe in that sense, but if finishing the count was critical to our application then cancelling this future would be a problem. To make sure the future completes we can `await` it after the `tokio::select!`:\n\n```rust\n// ...\nasync fn main() {\n    println!(\"start counting\");\n    let count_to_10 = count_to(10);\n    tokio::select! {\n        _ = count_to(3) => {\n            println!(\"counted to 3\");\n        },\n        _ = count_to_10 => { // ❌\n            println!(\"counted to 10\");\n        },\n    };\n    println!(\"stop counting\");\n    println!(\"jk, keep counting\");\n    count_to_10.await; // ❌\n    println!(\"finished counting to 10\");\n}\n```\n\nThrows:\n\n```\nerror[E0382]: use of moved value: count_to_10\n```\n\nOh duh, we made the simplest mistake in the book, trying to use a value after we moved it. Let's pass a mutable reference instead:\n\n```rust\n// ...\nasync fn main() {\n    println!(\"start counting\");\n    let count_to_10 = count_to(10);\n    tokio::select! {\n        _ = count_to(3) => {\n            println!(\"counted to 3\");\n        },\n        _ = &mut count_to_10 => { // ❌\n            println!(\"counted to 10\");\n        },\n    };\n    println!(\"stop counting\");\n    println!(\"jk, keep counting\");\n    count_to_10.await;\n    println!(\"counted to 10\");\n}\n```\n\nNow throws:\n\n```\nerror[E0277]: {async fn body@src/main.rs:23:28: 28:2}\n              cannot be unpinned\n   -> src/main.rs:34:5\n   |\n23 |   async fn count_to(num: u8) {\n   |   ----------------- within this impl futures::Future<Output = ()>\n...\n34 | /     tokio::select! {\n35 | |         _ = count_to(3) => {\n36 | |             println!(\"counted to 3\");\n37 | |         },\n...  \n41 | |     };\n   | |     ^\n   | |     |\n   | |_____within impl futures::Future<Output = ()>,\n   |       the trait Unpin is not implemented for\n   |       {async fn body@src/main.rs:23:28: 28:2},\n   |       which is required by &mut impl\n   |       futures::Future<Output = ()>: futures::Future\n   |       required by a bound introduced by this call\n   |\n   = note: consider using the pin! macro\n           consider using Box::pin if you need to access\n           the pinned value outside of the current scope\n```\n\nWe need to \"pin\" our future. Okay, let's do what the compiler suggested:\n\n```rust\n#[tokio::main]\nasync fn main() {\n    println!(\"start counting\");\n    let count_to_10 = count_to(10);\n    tokio::pin!(count_to_10); // ✔️\n    tokio::select! {\n        _ = count_to(3) => {\n            println!(\"counted to 3\");\n        },\n        _ = &mut count_to_10 => {\n            println!(\"counted to 10\");\n        },\n    };\n    println!(\"stop counting\");\n    println!(\"jk, keep counting\");\n    count_to_10.await;\n    println!(\"finished counting to 10\");\n}\n```\n\nCompiles and outputs:\n\n```\nstart counting\n1\n1\n2\n2\n3\n3\ncounted to 3\nstop counting\njk, keep counting\n4\n5\n6\n7\n8\n9\n10\nfinished counting to 10\n```\n\nTo pin something in Rust means to pin its location in memory. Once it is pinned it cannot be moved. The reason some futures need to be pinned before being polled is because under-the-hood they can contain self-referential pointers that would be invalidated if the future was ever moved.\n\nIf that last part flew over your head don't worry, I don't fully get it either. But fear not, here's a general algorithm we can follow to solve these kinds of problems when they arise:\n\n**1\\)** If we're writing generic code that takes a future or something that produces futures we can add `+ Unpin` to the trait bounds. So for example this doesn't compile:\n\n```rust\nuse futures::{Stream, StreamExt};\n\nasync fn iterate<T>(\n    mut items: impl Stream<Item = T>\n) {\n    while let Some(item) = items.next().await { // ❌\n        todo!()\n    }\n}\n```\n\nThrows:\n\n```\nerror[E0277]: impl Stream<Item = T> cannot be unpinned\n```\n\nBut if we sprinkle `Unpin` into the function signature it works:\n\n```rust\nasync fn iterate<T>(\n    mut items: impl Stream<Item = T> + Unpin // ✔️\n) {\n    while let Some(item) = items.next().await {\n        todo!()\n    }\n}\n```\n\n**2\\)** However, let's say that causes compile errors elsewhere in our code, because we are passing a stream to this function isn't `Unpin`. We can remove the `Unpin` from the function signature and use the `pin!` macro to pin the stream within the function:\n\n```rust\nasync fn iterate<T>(\n    mut items: impl Stream<Item = T>\n) {\n    tokio::pin!(items); // ✔️\n    while let Some(item) = items.next().await {\n        todo!()\n    }\n}\n```\n\nThis pins it to the stack, so it cannot escape the current scope.\n\n**3\\)** If the pinned object needs to escape the current scope there's `Box::pin` to pin it in the heap:\n\n```rust\nasync fn iterate<T>(\n    mut items: impl Stream<Item = T>\n) {\n    let mut items = Box::pin(items); // ✔️\n    while let Some(item) = items.next().await {\n        todo!()\n    }\n}\n```\n\n**4\\)** Or we can ask the caller to figure out this detail for us:\n\n```rust\nasync fn iterate<T, S: Stream<Item = T> + ?Sized>(\n    mut items: Pin<&mut S>\n) {\n    while let Some(item) = items.next().await {\n        todo!()\n    }\n}\n```\n\nHowever in this case the caller is also us, so this doesn't help that much over solutions 2 & 3.\n\n> [!IMPORTANT]\n> In summary: we need to be mindful which futures are and aren't cancel-safe when we pass them to code that may not poll them to completion, e.g. `tokio::select!`. If you're writing a Rust library that polls futures you need to document if your library will poll the futures to completion or not. If you're writing a Rust library that produces futures you need to document which of the futures are and aren't cancel-safe. If you're using a Rust library that either polls or returns futures you need to carefully read its docs.\n\n## 09\\) Assigning names to users\n\nIn the current iteration of our chat server it's hard to follow who said what. We could prepend each connection's socket address to their message to disambiguate them, and if we did it would look something like this:\n\n```console\n$ just telnet\n> hello\n127.0.0.1:51270: hello\n```\n\nHowever that is both ugly and boring. Let's generate random names by combining an adjective with an animal and assign them to users when they join:\n\n```rust\npub static ADJECTIVES: [&str; 628] = [\n    \"Mushy\",\n    \"Starry\",\n    \"Peaceful\",\n    \"Phony\",\n    \"Amazing\",\n    \"Queasy\",\n    // ...\n];\n\npub static ANIMALS: [&str; 243] = [\n    \"Owl\",\n    \"Mantis\",\n    \"Gopher\",\n    \"Robin\",\n    \"Vulture\",\n    \"Prawn\",\n    // ...\n];\n\npub fn random_name() -> String {\n    let adjective = fastrand::choice(ADJECTIVES).unwrap();\n    let animal = fastrand::choice(ANIMALS).unwrap();\n    format!(\"{adjective}{animal}\")\n}\n```\n\nHere's a sampling of some of the names this creates:\n\n```\nHushedLlama\nDimpledDinosaur\nUrbanMongoose\nYawningMinotaur\nRomanticRhino\nDapperPeacock\nPlasticCentaur\nBubblyChicken\nAnxiousGriffin\nSpicyAlpaca\nMindlessOctopus\nWealthyPelican\nCruelCapybara\nRegalFrog\nPinkPoodle\nQuirkyGazelle\nPoshGopher\nCarelessBobcat\nSomberWeasel\nZenMammoth\nDazzlingSquid\n```\n\nTo keep our main file clean and concise, let's put this functionality into our lib file and import it:\n\n```rust\nuse chat_server::random_name;\n\n// ...\n\nasync fn handle_user(\n    mut tcp: TcpStream,\n    tx: Sender<String>\n) -> anyhow::Result<()> {\n    // ...\n    // generate random name\n    let name = random_name();\n    // ...\n    // tell user their name\n    sink.send(format!(\"You are {name}\")).await?;\n    // ...\n    user_msg = stream.next() => {\n        // ...\n        // prepend user's name to their messages\n        tx.send(format!(\"{name}: {user_msg}\"))?;\n    },\n    // ...\n}\n```\n\nLet's give it a try:\n\n```console\n$ just chat\nYou are MeatyPuma\n> hello\nMeatyPuma: hello\nPeacefulGibbon: howdy\n```\n\nExcellent.\n\n> [!NOTE]\n> I switched from using `just telnet` to `just chat` because I got tired of using telnet and built a TUI chat client that's easier to use and looks nicer, which is what `just chat` runs.\n\n## 10\\) Letting users edit their names with `/name`\n\nWe'd like names to be unique across the server. We can enforce this by maintaining the names in a `HashSet<String>`. However, since we'd also like to let users edit their names using the `/name` command we need to share this set between users running in different threads.\n\n> [!TIP]\n> To share mutable data across many threads we can wrap it with `Arc<Mutex<T>>`, which is like the thread-safe version of `Rc<RefCell<T>>` if you've ever used that before.\n\nLet's wrap our `Arc<Mutex<HashSet<T>>>` in a new type to make using it more ergonomic:\n\n```rust\n// ...\n\n#[derive(Clone)]\nstruct Names(Arc<Mutex<HashSet<String>>>);\n\nimpl Names {\n    fn new() -> Self {\n        Self(Arc::new(Mutex::new(HashSet::new())))\n    }\n    // returns true if name was inserted,\n    // i.e. the name is unique\n    fn insert(&self, name: String) -> bool {\n        self.0.lock().unwrap().insert(name)\n    }\n    // returns unique name\n    fn get_unique(&self) -> String {\n        let mut name = random_name();\n        let mut guard = self.0.lock().unwrap();\n        while !guard.insert(name.clone()) {\n            name = random_name();\n        }\n        name\n    }\n}\n\n#[tokio::main]\nasync fn main() -> anyhow::Result<()> {\n    // ...\n    let names = Names::new();\n    // ...\n    tokio::spawn(handle_user(tcp, tx.clone(), names.clone()));\n}\n\nasync fn handle_user(\n    mut tcp: TcpStream,\n    tx: Sender<String>,\n    names: Names,\n) -> anyhow::Result<()> {\n    // ...\n    // get a unique name for new user\n    let mut name = names.get_unique();\n    // ...\n    // tell them their name\n    sink.send(format!(\"You are {name}\")).await?;\n    // ...\n    user_msg = stream.next() => {\n        // ...\n        // handle new /name command\n        if user_msg.starts_with(\"/name\") {\n            let new_name = user_msg\n                .split_ascii_whitespace()\n                .nth(1)\n                .unwrap()\n                .to_owned();\n            // check if name is unique\n            let changed_name = names.insert(new_name.clone());\n            if changed_name {\n                // notify everyone that user\n                // changed their name\n                tx.send(format!(\"{name} is now {new_name}\"))?;\n                // remove previous name\n                names.remove(&name);\n                // set new name\n                name = new_name;\n            } else {\n                // tell user that name is\n                // already taken\n                sink.send(\n                    format!(\"{new_name} is already taken\")\n                ).await?;\n            }\n        }\n        // ...\n    },\n    // ...\n}\n```\n\nLet's try it out:\n\n```console\n$ just chat\nServer commands\n  /help - prints this message\n  /name {name} - change name\n  /quit - quits server\nYou are FancyYak\n> hello\nFancyYak: hello\n> /name pretzelhammer # new command\nFancyYak is now pretzelhammer\n> 🦀🦀🦀\npretzelhammer: 🦀🦀🦀\n```\n\n> [!CAUTION]\n> Rust promises that compiling safe programs are free of memory vulnerabilities, but it makes no promises that they will be free of deadlocks. When we add locks to our program we need to be careful to avoid creating deadlock scenarios.\n\nHere's some tips for avoiding deadlocks:\n\n**1\\)** Don't hold locks across await points\n\nAn `await` point is anywhere in an async function where `await` is called. When we call `await` we yield control back to the Tokio scheduler. If our yielded future holds a lock that means any executing futures won't be able to acquire it, in which case they will block forever while waiting on it, and the yielded lock-holding future won't get an opportunity to run again, and so we have a deadlock.\n\nThat was a bit abstract so let's run through a concrete example. Imagine we have a single-threaded Tokio runtime, with three futures ready to be polled:\n\n```\nTokio scheduler, future queue:\n+---------+---------+---------+\n|  fut A  |  fut B  |  fut C  |\n+---------+---------+---------+\n```\n\nSince this is a single-threaded runtime we can only execute one future at a time. Tokio polls the first future, future A, which runs code that looks like this:\n\n```rust\nasync do_stuff<T: Debug>(mutex: Mutex<T>) {\n    // acquires lock\n    let guard = mutex.lock().unwrap();\n    // hits await point, i.e. yields to scheduler\n    other_async_fn().await?;\n    // releases lock\n    dbg!(guard);\n}\n```\n\nWhen it hits the `await` point, the future goes back to the end of the queue:\n\n```\nTokio scheduler, future queue:\n+---------+---------+---------+\n|  fut B  |  fut C  |  fut A* |\n+---------+---------+---------+\n* holding lock\n```\n\nThen Tokio tries to poll the next future, future B, and that future runs through the same code path, trying to acquire a lock to the same mutex that future A is currently holding! It will block forever! Future B cannot make progress until future A releases the lock, but future A cannot release the lock until future B yields back to the scheduler. We have a deadlock.\n\n_\"But what if we use an async mutex instead of a sync mutex?\"_\n\nIt is true that tip 1 applies to sync mutexes, like `std::sync::Mutex`, but not to async mutexes, like `tokio::sync::Mutex`. For mutexes designed to be used in an async context, we can hold their locks across `await` points, however they are slower. To quote the Tokio docs:\n\n> Contrary to popular belief, it is ok and often preferred to use the ordinary Mutex from the standard library in asynchronous code.\n>\n> The feature that the async mutex offers over the blocking mutex is the ability to keep it locked across an await point. This makes the async mutex more expensive than the blocking mutex, so the blocking mutex should be preferred in the cases where it can be used. The primary use case for the async mutex is to provide shared mutable access to IO resources such as a database connection. If the value behind the mutex is just data, it's usually appropriate to use a blocking mutex such as the one in the standard library.\n\nGenerally speaking, if we can structure our code to never to hold a lock across an `await` point it's better to use a sync mutex, and if we absolutely have to hold a lock across an `await` point then we would switch to an async mutex.\n\n**2\\)** Don't reaquire the same lock multiple times\n\nTrivial example:\n\n```rust\nfn main() {\n   let mut mutex = Mutex::new(5);\n   // acquire lock\n   let g = mutex.lock().unwrap();\n   // try to acquire lock again\n   mutex.lock().unwrap(); // deadlocks\n}\n```\n\nAlthough the mistake is super obvious in the example above when it happens in Real Code<sup>TM</sup> it's much harder to spot and debug.\n\n_\"I won't have to worry about this if I'm using a read-write lock, right? Since those are suppose to be able to give out many read locks to concurrent threads.\"_\n\nSurprisingly no, even reacquiring a read lock on a read-write lock twice in the same thread can produce a deadlock. To borrow a diagram from the standard library `RwLock` docs:\n\n```\n// Thread 1             |  // Thread 2\nlet _rg = lock.read();  |\n                        |  // will block\n                        |  let _wg = lock.write();\n// may deadlock         |\nlet _rg = lock.read();  |\n```\n\nAnd to quote the `RwLock` docs from the `parking_lot` crate:\n\n> This lock uses a task-fair locking policy which avoids both reader and writer starvation. This means that readers trying to acquire the lock will block even if the lock is unlocked when there are writers waiting to acquire the lock. Because of this, attempts to recursively acquire a read lock within a single thread may result in a deadlock.\n\nI guess we just have to be really careful 🤷\n\n**3\\)** Acquire locks in the same order everywhere\n\nIf we need to acquire multiple locks to safely perform some operation, we need to always acquire those locks in the same order, otherwise deadlocks can trivially occur, like here:\n\n```\n// Thread 1         |  // Thread 2\nlet _a = a.lock();  |  let _b = b.lock();\n// ...              |  // ...\nlet _b = b.lock();  |  let _a = a.lock();\n```\n\n_\"My head is spinning from all of these gotchas. Surely there has to be an easier or better way to do all of this locking stuff?\"_\n\n**4\\)** Use lockfree data structures\n\nDoing this allows you to disregard tips 1-3, since lockfree data structures cannot deadlock. However, in general, lockfree data structures are slower than most of their lock-based counterparts.\n\n**5\\)** Use channels for everything\n\nDoing this also allows you to disregard tips 1-3, since channels cannot deadlock. I'm not well-read enough on this subject to comment on whether using channels for everything can degrade or improve the performance of a concurrent program vs using locks. I imagine the answer, like the answer to most computer science questions, is _\"it depends.\"_\n\nThis approach is also sometimes called the \"actor pattern\" and if you search for \"actor\" on cargo you'll find a lot of actor framework crates that supposedly help with structuring your program to follow this pattern.\n\nAnyway, that was long detour. Let's get back to our chat server.\n\n## 11\\) Freeing user's name if they disconnect\n\nWe have a bug in our code. Names are not removed from the set when a user disconnects, so after a name is taken it can never be used again, not until we restart the server. Unfortunately there's a tricky obstacle we have to overcome before we can fix this.\n\nThe obstacle is the user may disconnect due to an error, and we're using `?` everywhere in our `handle_user` function, which propagates the error up to `main`, but it shouldn't be `main`'s responsibility to clean up names, that's a detail that should remain within `handle_user`. We can get rid of `?` and pattern match on `Result`s everywhere but that's verbose and ugly. So what do we do when we have to get rid of a bunch of repetitive, ugly, verbose code? We use macros.\n\nAs a quick recap, remember that all blocks in Rust are expressions, and we can `break` out of a block with a value. A couple examples:\n\n```rust\nfn main() {\n    // breaking from loop with value\n    let value = loop {\n        break \"value\";\n    };\n    assert_eq!(value, \"value\");\n\n    // to break from a non-loop block\n    // it needs to be labelled\n    let value = 'label: {\n        break 'label \"value\";\n    };\n    assert_eq!(value, \"value\");\n}\n```\n\nAlso, the `?` operator is not magic and can be implemented as a macro:\n\n```rust\nmacro_rules! question_mark {\n    ($result:expr) => {\n        match $result {\n            Ok(ok) => ok,\n            Err(err) => return Err(err.into()),\n        }\n    }\n}\n```\n\nWhich is everything we want, except the `return` should be a `break`, since we'd like to handle the errors within our function and not propagate them to the caller. So let's write a new macro and call it `b!` which is short for `break`:\n\n```rust\nmacro_rules! b {\n    ($result:expr) => {\n        match $result {\n            Ok(ok) => ok,\n            Err(err) => break Err(err.into()),\n        }\n    }\n}\n```\n\nAnd then we can refactor a function that propagates errors to its caller like this:\n\n```rust\nfn some_function() -> anyhow::Result<()> {\n    // initialize state here\n    loop {\n        fallible_statement_1?;\n        fallible_statement_2?;\n        // etc\n    }\n    // clean up state here, but\n    // this may never be reached\n    // because the ? returns from\n    // the function instead of\n    // breaking from the loop\n    Ok(())\n}\n```\n\nInto a function which catches and handles its own errors:\n\n```rust\nfn some_function() {\n    // initialize state here\n    let result = loop {\n        b!(fallible_statement_1);\n        b!(fallible_statement_2);\n        // etc\n    };\n    // clean up state here, always reached\n    if let Err(err) = result {\n        // handle errors if necessary\n    }\n    // nothing to return anymore since\n    // we take care of everything within\n    // the function :)\n}\n```\n\nSo with all of that context out of the way, here's the updated code:\n\n```rust\n// ...\n\nasync fn handle_user(\n    mut tcp: TcpStream,\n    tx: Sender<String>,\n    names: Names,\n) -> anyhow::Result<()> {\n    // ...\n    // we now catch errors here\n    let result: anyhow::Result<()> = loop {\n        // all fallible statements\n        // from before are now wrapped\n        // with our b!() macro\n    };\n    // the line below is always reached\n    // and the user's name is always freed,\n    // regardless if they quit normally or\n    // abruptly disconnected due to an error\n    names.remove(&name);\n    // return result to caller if they want\n    // to do anything extra\n    result\n}\n```\n\nNow if a user disconnects for any reason we will always reclaim their name.\n\n## 12\\) Adding a main room\n\nRight now all users are dumped into the same room and have nowhere else to go. It will be difficult to keep the conversation on one topic and hard to follow the discussion if multiple side-conversations start happening concurrently. We should add the ability to create and join different rooms within our server. As a first step let's refactor our current code to add everyone who joins the server into a default room, called `main`. The updated code:\n\n```rust\n// ...\n\nstruct Room {\n    tx: Sender<String>,\n}\n\nimpl Room {\n    fn new() -> Self {\n        let (tx, _) = broadcast::channel(32);\n        Self {\n            tx,\n        }\n    }\n}\n\nconst MAIN: &str = \"main\";\n\n#[derive(Clone)]\nstruct Rooms(Arc<RwLock<HashMap<String, Room>>>);\n\nimpl Rooms {\n    fn new() -> Self {\n        Self(Arc::new(RwLock::new(HashMap::new())))\n    }\n    fn join(&self, room_name: &str) -> Sender<String> {\n        // get read access\n        let read_guard = self.0.read().unwrap();\n        // check if room already exists\n        if let Some(room) = read_guard.get(room_name) {\n            return room.tx.clone();\n        }\n        // must drop read before acquiring write\n        drop(read_guard);\n        // create room if it doesn't yet exist\n        // get write access\n        let mut write_guard = self.0.write().unwrap();\n        let room = write_guard\n            .entry(room_name.to_owned())\n            .or_insert(Room::new());\n        room.tx.clone()\n    }\n}\n\n#[tokio::main]\nasync fn main() -> anyhow::Result<()> {\n    // ...\n    let rooms = Rooms::new();\n    // ...\n    tokio::spawn(handle_user(tcp, names.clone(), rooms.clone()));\n}\n\nasync fn handle_user(\n    mut tcp: TcpStream,\n    names: Names,\n    rooms: Rooms,\n) -> anyhow::Result<()> {\n    // ...\n    // when user connects to server\n    // automatically put them in\n    // the main room\n    let room_name = MAIN.to_owned();\n    let room_tx = rooms.join(&room_name);\n    let mut room_rx = room_tx.subscribe();\n    // notify everyone in room that\n    // a new user has joined\n    let _ = room_tx.send(format!(\"{name} joined {room_name}\"));\n    // ...\n    tokio::select! {\n        user_msg = stream.next() => {\n            // ...\n            // send messages to the room\n            // we're currently in\n            b!(room_tx.send(format!(\"{name}: {user_msg}\")));\n        },\n        // receive messages from the\n        // room we're currently in\n        peer_msg = room_rx.recv() => {\n            // ...\n        },\n    }\n    // ...\n    // notify everyone in room that\n    // we have left\n    let _ = room_tx.send(format!(\"{name} left {room_name}\"));\n    // ...\n}\n```\n\nA `Room` is a wrapper around a `broadcast::Sender<String>`, and `Rooms` is a wrapper around an `Arc<RwLock<HashMap<String, Room>>>` because we need to maintain a map of room names to broadcast channels and we'd like to share and modify this map across many threads.\n\nWe also added notification messages for when a user joins and leaves a room. Let's see what it looks like altogether:\n\n```console\n$ just chat\nYou are AwesomeVulture\nAwesomeVulture joined main\nJealousHornet joined main\nJealousHornet: we are at the main room!\n> can we create other rooms?\nAwesomeVulture: can we create other rooms?\nJealousHornet: not yet, back to work we go\nJealousHornet left main\n```\n\n## 13\\) Letting users join or create rooms with `/join`\n\nSince we implemented the `join` method earlier this will be pretty easy:\n\n```rust\n// ...\nasync fn handle_user(\n    mut tcp: TcpStream,\n    names: Names,\n    rooms: Rooms,\n) -> anyhow::Result<()> {\n    // ...\n    // automatically join main room\n    // on connect, as before\n    let mut room_name = MAIN.to_owned();\n    let mut room_tx = rooms.join(&room_name);\n    let mut room_rx = room_tx.subscribe();\n    // ...\n    if user_msg.starts_with(\"/join\") {\n        let new_room = user_msg\n            .split_ascii_whitespace()\n            .nth(1)\n            .unwrap()\n            .to_owned();\n        // check if user is already in the room\n        // they're trying to join\n        if new_room == room_name {\n            b!(sink.send(format!(\"You are in {room_name}\")).await);\n            continue;\n        }\n        // notify current room that we've left\n        b!(room_tx.send(format!(\"{name} left {room_name}\")));\n        // join new room, this creates\n        // the room if it doesn't\n        // already exist\n        room_tx = rooms.join(&new_room);\n        room_rx = room_tx.subscribe();\n        room_name = new_room;\n        // notify new room that we have joined\n        b!(room_tx.send(format!(\"{name} joined {room_name}\")));\n    }\n    // ...\n    // notify our current room that we've left\n    // on disconnect, as before\n    let _ = room_tx.send(format!(\"{name} left {room_name}\"));\n    // ...\n}\n```\n\nNow we can start pizza parties:\n\n```console\n$ just chat\nServer commands\n  /help - prints this message\n  /name {name} - change name\n  /join {room} - joins room\n  /quit - quits server\nYou are ElasticBonobo\nElasticBonobo joined main\nBlondCyclops joined main\n> /join pizza # new command\nElasticBonobo joined pizza\nBlondCyclops joined pizza\n> let's have a pizza party\nElasticBonobo: let's have a pizza party\nBlondCyclops: 🍕🥳\n```\n\n## 14\\) Listing all rooms with `/rooms`\n\nRight now pizza parties on the server are not very discoverable. If a user lands in the `main` room there's no way for them to know all the other users on the server are in `pizza`. Let's add a `/rooms` command that will list all of the rooms on server:\n\n```rust\n// ...\n\n#[derive(Clone)]\nstruct Rooms(Arc<RwLock<HashMap<String, Room>>>);\n\nimpl Rooms {\n    fn list(&self) -> Vec<(String, usize)> {\n        // iterate over rooms map\n        let mut list: Vec<_> = self\n            .0\n            .read()\n            .unwrap()\n            .iter()\n            // receiver_count tells us\n            // the # of users in the room\n            .map(|(name, room)| (\n                name.to_owned(),\n                room.tx.receiver_count(),\n            ))\n            .collect();\n        list.sort_by(|a, b| {\n            use std::cmp::Ordering::*;\n            // sort rooms by # of users first\n            match b.1.cmp(&a.1) {\n                // and by alphabetical order second\n                Equal => a.0.cmp(&b.0),\n                ordering => ordering,\n            }\n        });\n        list\n    }\n}\n\n// ...\n\nasync fn handle_user(\n    mut tcp: TcpStream,\n    names: Names,\n    rooms: Rooms,\n) -> anyhow::Result<()> {\n    // ...\n    // handle new /rooms command\n    if user_msg.starts_with(\"/rooms\") {\n        let rooms_list = rooms.list();\n        let rooms_list = rooms_list\n            .into_iter()\n            .map(|(name, count)| format!(\"{name} ({count})\"))\n            .collect::<Vec<_>>()\n            .join(\", \");\n        b!(sink.send(format!(\"Rooms - {rooms_list}\")).await);\n    }\n    // ...\n}\n```\n\nNow everyone is invited to our pizza parties:\n\n```console\n$ just chat\nServer commands\n  /help - prints this message\n  /name {name} - change name\n  /rooms - list rooms\n  /join {room} - joins room\n  /quit - quits server\nYou are SilentYeti\nSilentYeti joined main\n> /rooms # new command\nRooms - pizza (2), main (1)\n> /join pizza\nSilentYeti joined pizza\n> can i be part of this pizza party? 🥺\nSilentYeti: can i be part of this pizza party? 🥺\nBulkyApe: of course ❤️\nAmazingDragon: 🔥🔥🔥\n```\n\n## 15\\) Removing empty rooms\n\nWe have a bug, after a room is created it's never deleted, even after it becomes empty. After a while our server rooms list will look like this:\n\n```console\n> /rooms\nRooms - a (0), bunch (0), of (0), abandoned (0), rooms (0)\n```\n\nLet's fix that:\n\n```rust\n// ...\n\n#[derive(Clone)]\nstruct Rooms(Arc<RwLock<HashMap<String, Room>>>);\n\nimpl Rooms {\n    // ...\n    fn leave(&self, room_name: &str) {\n        let read_guard = self.0.read().unwrap();\n        let mut delete_room = false;\n        if let Some(room) = read_guard.get(room_name) {\n            // if the receiver count is 1 then\n            // we're the last person in the room\n            // and can remove it\n            delete_room = room.tx.receiver_count() <= 1;\n        }\n        drop(read_guard);\n        if delete_room {\n            let mut write_guard = self.0.write().unwrap();\n            write_guard.remove(room_name);\n        }\n    }\n    fn change(\n        &self,\n        prev_room: &str,\n        next_room: &str\n    ) -> Sender<String> {\n        self.leave(prev_room);\n        self.join(next_room)\n    }\n    // ...\n}\n\nasync fn handle_user(\n    mut tcp: TcpStream,\n    names: Names,\n    rooms: Rooms,\n) -> anyhow::Result<()> {\n    // ...\n    if user_msg.starts_with(\"/join\") {\n        // ...\n        // now correctly deletes the room\n        // we're leaving if it becomes empty\n        room_tx = rooms.change(&room_name, &new_room);\n        // ...\n    }\n    // ...\n    // when we disconnect we also\n    // need to leave and delete the\n    // room if it's empty\n    rooms.leave(&room_name);\n    // ...\n}\n```\n\n## 16\\) Listing users in the room with `/users`\n\nUsers within a room are not discoverable. Let's add a `/users` command that will list the users in the current room. To do that we'll have to add a `HashSet<String>` to the `Room` struct and update many of the `Rooms` methods to also take a user name when joining, changing, or leaving a room:\n\n```rust\n// ...\n\nstruct Room {\n    // ...\n    // keep track of the names\n    // of the users in the room\n    users: HashSet<String>,\n}\n\nimpl Room {\n    fn new() -> Self {\n        // ...\n        let users = HashSet::new();\n        Self {\n            // ...\n            users,\n        }\n    }\n}\n\n#[derive(Clone)]\nstruct Rooms(Arc<RwLock<HashMap<String, Room>>>);\n\nimpl Rooms {\n    // ...\n    fn join(&self, room_name: &str, user_name: &str) -> Sender<String> {\n        // ...\n        room.users.insert(user_name.to_owned());\n        // ...\n    }\n    fn leave(&self, room_name: &str, user_name: &str) {\n        // ...\n        room.users.remove(user_name);\n        // ...\n    }\n    // update user's name in room if they\n    // changed it using the /name command\n    fn change_name(\n        &self,\n        room_name: &str,\n        prev_name: &str,\n        new_name: &str\n    ) {\n        let mut write_guard = self.0.write().unwrap();\n        if let Some(room) = write_guard.get_mut(room_name) {\n            room.users.remove(prev_name);\n            room.users.insert(new_name.to_owned());\n        }\n    }\n    // returns list of users' names in the room\n    fn list_users(&self, room_name: &str) -> Option<Vec<String>> {\n        self\n            .0\n            .read()\n            .unwrap()\n            .get(room_name)\n            .map(|room| {\n                // get users in room\n                let mut users = room\n                    .users\n                    .iter()\n                    .cloned()\n                    .collect::<Vec<_>>();\n                // alphabetically sort\n                // users by names\n                users.sort();\n                users\n            })\n    }\n}\n\n// ...\n\nasync fn handle_user(\n    mut tcp: TcpStream,\n    names: Names,\n    rooms: Rooms,\n) -> anyhow::Result<()> {\n    // ...\n    // send our name when joining a room\n    room_tx = rooms.join(&room_name, &name);\n    // ...\n    if user_msg.starts_with(\"/name\") {\n        // ...\n        if changed_name {\n            // let room know we changed our name\n            rooms.change_name(&room_name, &name, &new_name);\n            // ...\n        }\n        // ...\n    } else if user_msg.starts_with(\"/join\") {\n        // ...\n        // send our name when changing rooms\n        room_tx = rooms.change(&room_name, &new_room, &name);\n        // ...\n    // handle new /users command\n    } else if user_msg.starts_with(\"/users\") {\n        let users_list = rooms\n            .list_users(&room_name)\n            .unwrap()\n            .join(\", \");\n        b!(sink.send(format!(\"Users - {users_list}\")).await);\n    }\n    // ...\n    rooms.leave(&room_name, &name);\n    // ...\n}\n```\n\nNow we can find our friends within rooms:\n\n```console\n$ just chat\nServer commands\n  /help - prints this message\n  /name {name} - change name\n  /rooms - list rooms\n  /join {room} - joins room\n  /users - lists users in current room\n  /quit - quits server\nYou are StarryDolphin\nStarryDolphin joined main\n> /users # new command\nUsers - ColorfulSheep, PaleHedgehog, StarryDolphin\n> hey colorful sheep! 👋\nStarryDolphin: hey colorful sheep! 👋\nColorfulSheep: good to see you again starry dolphin! 🙌\n```\n\n## 17\\) Optimizing performance\n\nWe're gonna bucket our performance optimizations into three categories: reducing heap allocations, reducing lock contention, and compiling for speed.\n\nThere's other categories, but I think these are the most relevant for our particular program.\n\n### Reducing heap allocations\n\nThe fastest code is the code that never runs. If we don't have to allocate something on the heap then we don't have to call the allocator.\n\n#### `String` -> `CompactString`\n\nWe have a lot of short strings. We can have thousands of users and hundreds of rooms on the server and user names and room names are both almost always shorter than 24 characters. Instead of storing them as `String`s we can store them as `CompactString`s. `String`s always store their data on the heap, but `CompactString`s will store strings shorter than 24 bytes on the stack, and will only heap allocate the string if it's longer than 24 bytes. If we enforce a maximum length of 24 ASCII characters for user and room names then we can guarantee we'll never have to perform any heap allocations for them.\n\n#### `Sender<String>` -> `Sender<Arc<str>>`\n\nAs you may remember, when we `send` something to a broadcast channel every call to `recv` clones that data. That means if a user sends a `String` message that is five paragraphs long in a room with 1000 other users we're going to have to clone that message 1000 times which means doing 1000 heap allocations. We know that after a message is sent it's immutable, so we don't need to send a `String`, we can convert the `String` to an `Arc<str>` instead and send that, because cloning an `Arc<str>` is very cheap since all it does is increment an atomic counter.\n\n#### Miscellaneous micro optimizations\n\nAfter combing through the code I found a couple places where we were carelessly allocating unnecessary `Vec`s and `String`s, mostly for the `/rooms` and `/users` commands, and made them both only allocate a single `String` when generating a response.\n\n### Reducing lock contention\n\nHigh lock contention increases how long threads need to wait for a lock to be free. Reducing lock contention reduces thread waiting time and increases program throughput.\n\n#### `Mutex<HashSet<String>>` -> `DashSet<CompactString>`\n\nWe store names in a `Mutex<HashSet<String>>`. That's one lock for potentially thousands of keys. Instead of putting a lock around the entire set, what if we could put a lock around every individual key in the set? A `DashSet` doesn't necessarily go that far, but it does split the data into several shards internally and each shard gets its own lock. Some ASCII diagrams to help explain:\n\n```\n+-------------------------------+\n| Mutex                         |\n| +---------------------------+ |\n| | HashSet                   | |\n| | +-----+-----+-----+-----+ | |\n| | | key | key | key | key | | |\n| | +-----+-----+-----+-----+ | |\n| +---------------------------+ |\n+-------------------------------+\n\n+-----------------------------------+\n| DashSet                           |\n| +---------------+---------------+ |\n| | RwLock        | RwLock        | |\n| | +-----+-----+ | +-----+-----+ | |\n| | | key | key | | | key | key | | |\n| | +-----+-----+ | +-----+-----+ | |\n| +-------------------+-----------+ |\n+-----------------------------------+\n```\n\nIn this case guarding the same amount of data but with more locks means each lock will get less contention between threads.\n\n#### `RwLock<HashMap<String, Room>>` -> `DashMap<CompactString, Room>`\n\nWe store rooms in a `RwLock<HashMap<String, Room>>` but for the same reasons mentioned above we can use a `DashMap` to reduce lock contention.\n\n#### Better random name generation\n\nThere's a big issue in our random name generation. It's a [Birthday Problem](https://en.wikipedia.org/wiki/Birthday_problem) just in different clothes. Even if we have 600 unique adjectives and 250 unique animals and we can generate 150k unique names using those, we'd expect the probability of a collision in the first 1k generated names to be very low, right? Unfortunately no, after generating just 460 names there's already a >50% chance that there will be a collision, and after generating just 1k names the probability of a collision is >96%. More collisions means more time threads will spend fighting to find a unique name for every user that joins the server as the number of active users on the server climbs.\n\nI refactored the name generation to iterate through all possible name combinations in a pseudo-random fashion, so the generated names still appear random but now we can guarantee that for 600 unique adjectives and 250 unique animals that we will generate 150k unique names in a row without any collisions.\n\n#### System allocator -> jemalloc\n\njemalloc is suppose to be faster for multithreaded programs because it uses per-thread arenas which reduces contention for memory allocation. That sounds good to me, so let's change our allocator to jemalloc.\n\n### Compiling for speed\n\nThe default cargo `build` command is configured to quickly compile slow programs. Instead, we would like to slowly compile a fast program. In order to do that we need to add this to our Cargo.toml:\n\n```toml\n[profile.release]\ncodegen-units = 1\nlto = \"fat\"\n```\n\nAnd then execute the `build` command with these flags:\n\n```console\n$ RUSTFLAGS=\"-C target-cpu=native\" cargo build --release\n```\n\nAnyway, this section was a lot. You can see the full source code [here](https://github.com/pretzelhammer/chat-server/blob/main/examples/server-17.rs), and you can see a diff between the non-optimized and optimized versions by running `just diff 16 17`.\n\n## 18\\) Finishing touches\n\nWe've neglected logging, parsing command line arguments, and error handling thus far because they're boring and most people don't like reading about them. Let's speed through them.\n\nHere's how we can setup `tracing` to log to `stdout`:\n\n```rust\nuse std::io;\nuse tracing_subscriber::{fmt, EnvFilter, layer::SubscriberExt};\n\nfn setup_logging() {\n    let subscriber = tracing_subscriber::registry()\n        .with(EnvFilter::from_default_env())\n        .with(fmt::Layer::new()\n            .without_time()\n            .compact()\n            .with_ansi(true)\n            .with_writer(io::stdout)\n        );\n    tracing::subscriber::set_global_default(subscriber)\n            .expect(\"Unable to set a global subscriber\");\n}\n```\n\nAnd then after running `setup_logging` somewhere early in our main function we can call the `trace!`, `debug!`, `info!`, `warn!`, and `error!` macros from `tracing`, which all function similarly to `println!`. We also can customize the logging level via the environment, using the `RUST_LOG` environment variable.\n\nRight now our server always runs at `127.0.0.1` on port `42069`. We should let server admins be able to customize this without having to recompile our code. We can accept these parameters as command line arguments and parse them using the `clap` crate:\n\n```rust\nuse std::net::{IpAddr, SocketAddr, Ipv4Addr};\nuse clap::Parser;\n\nconst DEFAULT_IP: IpAddr = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1));\nconst DEFAULT_PORT: u16 = 42069;\n\n#[derive(Parser)]\n#[command(long_about = None)]\nstruct Cli {\n    #[arg(short, long, default_value_t = DEFAULT_IP)]\n    ip: IpAddr,\n\n    #[arg(short, long, default_value_t = DEFAULT_PORT)]\n    port: u16,\n}\n\nfn parse_socket_addr() -> SocketAddr {\n    let cli = Cli::parse();\n    SocketAddr::new(cli.ip, cli.port)\n}\n```\n\nFor error handling there's a bunch of little mundane things that we neglected, none of which are particularly interesting to write about.\n\nYou can see the full source code with all logging and error handling [here](https://github.com/pretzelhammer/chat-server/blob/main/examples/server-18.rs). To see a diff against the previous version of the code run `just diff 17 18`.\n\n## Conclusion\n\nWe learned a lot! The final full code for the server is [here](https://github.com/pretzelhammer/chat-server/blob/main/src/bin/chat-server.rs). You can run it with `just server`. To chat run `just chat`. And if it gets lonely run `just bots`.\n\n## Discuss\n\nDiscuss this article on\n- [Github](https://github.com/pretzelhammer/rust-blog/discussions/75)\n- [official Rust users forum](https://users.rust-lang.org/t/beginners-guide-to-concurrent-programming-coding-a-multithreaded-chat-server-using-tokio/110976)\n- [learnrust subreddit](https://www.reddit.com/r/learnrust/comments/1cmebbo/beginners_guide_to_concurrent_programming_coding/)\n- [rust subreddit](https://www.reddit.com/r/rust/comments/1cnz9p9/beginners_guide_to_concurrent_programming_coding/)\n\n## Further reading\n\n- [Common Rust Lifetime Misconceptions](./common-rust-lifetime-misconceptions.md)\n- [Tour of Rust's Standard Library Traits](./tour-of-rusts-standard-library-traits.md)\n- [Learning Rust in 2024](./learning-rust-in-2024.md)\n- [Using Rust in Non-Rust Servers to Improve Performance](./rust-in-non-rust-servers.md)\n- [Sizedness in Rust](./sizedness-in-rust.md)\n- [RESTful API in Sync & Async Rust](./restful-api-in-sync-and-async-rust.md)\n- [Learn Assembly with Entirely Too Many Brainfuck Compilers](./too-many-brainfuck-compilers.md)\n\n\n\n## Notifications\n\nGet notified when a new blog post gets published by\n- Subscribing to this repo's [releases RSS feed](https://github.com/pretzelhammer/rust-blog/releases.atom) or\n- Watching this repo's releases (click `Watch` → click `Custom` → select `Releases` → click `Apply`)\n"
  },
  {
    "path": "posts/common-rust-lifetime-misconceptions.md",
    "content": "# Common Rust Lifetime Misconceptions\n\n_19 May 2020 · #rust · #lifetimes_\n\n**Table of Contents**\n- [Intro](#intro)\n- [The Misconceptions](#the-misconceptions)\n    - [1) `T` only contains owned types](#1-t-only-contains-owned-types)\n    - [2) if `T: 'static` then `T` must be valid for the entire program](#2-if-t-static-then-t-must-be-valid-for-the-entire-program)\n    - [3) `&'a T` and `T: 'a` are the same thing](#3-a-t-and-t-a-are-the-same-thing)\n    - [4) my code isn't generic and doesn't have lifetimes](#4-my-code-isnt-generic-and-doesnt-have-lifetimes)\n    - [5) if it compiles then my lifetime annotations are correct](#5-if-it-compiles-then-my-lifetime-annotations-are-correct)\n    - [6) boxed trait objects don't have lifetimes](#6-boxed-trait-objects-dont-have-lifetimes)\n    - [7) compiler error messages will tell me how to fix my program](#7-compiler-error-messages-will-tell-me-how-to-fix-my-program)\n    - [8) lifetimes can grow and shrink at run-time](#8-lifetimes-can-grow-and-shrink-at-run-time)\n    - [9) downgrading mut refs to shared refs is safe](#9-downgrading-mut-refs-to-shared-refs-is-safe)\n    - [10) closures follow the same lifetime elision rules as functions](#10-closures-follow-the-same-lifetime-elision-rules-as-functions)\n- [Conclusion](#conclusion)\n- [Discuss](#discuss)\n- [Further Reading](#further-reading)\n- [Notifications](#notifications)\n\n\n\n## Intro\n\nI've held all of these misconceptions at some point and I see many beginners struggle with these misconceptions today. Some of my terminology might be non-standard, so here's a table of shorthand phrases I use and what I intend for them to mean.\n\n| Phrase | Shorthand for |\n|-|-|\n| `T` | 1) a set containing all possible types _or_<br>2) some type within that set |\n| owned type | some non-reference type, e.g. `i32`, `String`, `Vec`, etc |\n| 1) borrowed type _or_<br>2) ref type | some reference type regardless of mutability, e.g. `&i32`, `&mut i32`, etc |\n| 1) mut ref _or_<br>2) exclusive ref | exclusive mutable reference, i.e. `&mut T` |\n| 1) immut ref _or_<br>2) shared ref | shared immutable reference, i.e. `&T` |\n\n\n\n## The Misconceptions\n\nIn a nutshell: A variable's lifetime is how long the data it points to can be statically verified by the compiler to be valid at its current memory address. I'll now spend the next ~6500 words going into more detail about where people commonly get confused.\n\n\n\n### 1) `T` only contains owned types\n\nThis misconception is more about generics than lifetimes but generics and lifetimes are tightly intertwined in Rust so it's not possible to talk about one without also talking about the other. Anyway:\n\nWhen I first started learning Rust I understood that `i32`, `&i32`, and `&mut i32` are different types. I also understood that some generic type variable `T` represents a set which contains all possible types. However, despite understanding both of these things separately, I wasn't able to understand them together. In my newbie Rust mind this is how I thought generics worked:\n\n| | | | |\n|-|-|-|-|\n| **Type Variable** | `T` | `&T` | `&mut T` |\n| **Examples** | `i32` | `&i32` | `&mut i32` |\n\n`T` contains all owned types. `&T` contains all immutably borrowed types. `&mut T` contains all mutably borrowed types. `T`, `&T`, and `&mut T` are disjoint finite sets. Nice, simple, clean, easy, intuitive, and completely totally wrong. This is how generics actually work in Rust:\n\n| | | | |\n|-|-|-|-|\n| **Type Variable** | `T` | `&T` | `&mut T` |\n| **Examples** | `i32`, `&i32`, `&mut i32`, `&&i32`, `&mut &mut i32`, ... | `&i32`, `&&i32`, `&&mut i32`, ... | `&mut i32`, `&mut &mut i32`, `&mut &i32`, ... |\n\n`T`, `&T`, and `&mut T` are all infinite sets, since it's possible to borrow a type ad-infinitum. `T` is a superset of both `&T` and `&mut T`. `&T` and `&mut T` are disjoint sets. Here's a couple examples which validate these concepts:\n\n```rust\ntrait Trait {}\nimpl<T> Trait for T {}\nimpl<T> Trait for &T {} // ❌\nimpl<T> Trait for &mut T {} // ❌\n```\n\nThe above program doesn't compile as expected:\n\n```none\nerror[E0119]: conflicting implementations of trait `Trait` for type `&_`\n --> src/lib.rs:3:1\n  |\n2 | impl<T> Trait for T {}\n  | ------------------- first implementation here\n3 | impl<T> Trait for &T {}\n  | ^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_`\n\nerror[E0119]: conflicting implementations of trait `Trait` for type `&mut _`\n --> src/lib.rs:4:1\n  |\n2 | impl<T> Trait for T {}\n  | ------------------- first implementation here\n3 | impl<T> Trait for &T {}\n4 | impl<T> Trait for &mut T {}\n  | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&mut _`\n```\n\nThe compiler doesn't allow us to define an implementation of `Trait` for `&T` and `&mut T` since it would conflict with the implementation of `Trait` for `T` which already includes all of `&T` and `&mut T`. The program below compiles as expected, since `&T` and `&mut T` are disjoint:\n\n```rust\ntrait Trait {}\nimpl<T> Trait for &T {} // ✅\nimpl<T> Trait for &mut T {} // ✅\n```\n\nAlthough it could probably go without saying, but for the sake of making sure nobody erroneously extrapolates the last couple examples, implementations for concrete types cannot overlap and this compiles just fine:\n\n```rust\ntrait Trait {}\nstruct Struct;\nimpl Trait for Struct {} // ✅\nimpl Trait for &Struct {} // ✅\nimpl Trait for &mut Struct {} // ✅\n```\n\n**Key Takeaways**\n- `T` is a superset of both `&T` and `&mut T`\n- `&T` and `&mut T` are disjoint sets\n\n\n### 2) if `T: 'static` then `T` must be valid for the entire program\n\n**Misconception Corollaries**\n- `T: 'static` should be read as _\"`T` has a `'static` lifetime\"_\n- `&'static T` and `T: 'static` are the same thing\n- if `T: 'static` then `T` must be immutable\n- if `T: 'static` then `T` can only be created at compile time\n\nMost Rust beginners get introduced to the `'static` lifetime for the first time in a code example that looks something like this:\n\n```rust\nfn main() {\n    let str_literal: &'static str = \"str literal\";\n}\n```\n\nThey get told that `\"str literal\"` is hardcoded into the compiled binary and is loaded into read-only memory at run-time so it's immutable and valid for the entire program and that's what makes it `'static`. These concepts are further reinforced by the rules surrounding defining `static` variables using the `static` keyword.\n\n```rust\n// Note: This example is purely for illustrative purposes.\n// Never use `static mut`. It's a footgun. There are\n// safe patterns for global mutable singletons in Rust but\n// those are outside the scope of this article.\n\nstatic BYTES: [u8; 3] = [1, 2, 3];\nstatic mut MUT_BYTES: [u8; 3] = [1, 2, 3];\n\nfn main() {\n   MUT_BYTES[0] = 99; // ❌ - mutating static is unsafe\n\n    unsafe {\n        MUT_BYTES[0] = 99;\n        assert_eq!(99, MUT_BYTES[0]);\n    }\n}\n```\n\nRegarding `static` variables\n- they can only be created at compile-time\n- they should be immutable, mutating them is unsafe\n- they're valid for the entire program\n\nThe `'static` lifetime was probably named after the default lifetime of `static` variables, right? So it makes sense that the `'static` lifetime has to follow all the same rules, right?\n\nWell yes, but a type _with_ a `'static` lifetime is different from a type _bounded by_ a `'static` lifetime. The latter can be dynamically allocated at run-time, can be safely and freely mutated, can be dropped, and can live for arbitrary durations.\n\nIt's important at this point to distinguish `&'static T` from `T: 'static`.\n\n`&'static T` is an immutable reference to some `T` that can be safely held indefinitely long, including up until the end of the program. This is only possible if `T` itself is immutable and does not move _after the reference was created_. `T` does not need to be created at compile-time. It's possible to generate random dynamically allocated data at run-time and return `'static` references to it via a memory leak, e.g.\n\n```rust\nuse rand;\n\n// generate random 'static str refs at run-time\nfn rand_str_generator() -> &'static str {\n    let rand_string = rand::random::<u64>().to_string();\n    Box::leak(rand_string.into_boxed_str())\n}\n```\n\n`T: 'static` is some `T` that can be safely held indefinitely long, including up until the end of the program. `T: 'static` includes all `&'static T` however it also includes all owned types, like `String`, `Vec`, etc. The owner of some data is guaranteed that data will never get invalidated as long as the owner holds onto it, therefore the owner can safely hold onto the data indefinitely long, including up until the end of the program. `T: 'static` should be read as _\"`T` can live at least as long as a `'static` lifetime\"_ not _\"`T` has a `'static` lifetime\"_. A program to help illustrate these concepts:\n\n```rust\nuse rand;\n\nfn drop_static<T: 'static>(t: T) {\n    std::mem::drop(t);\n}\n\nfn main() {\n    let mut strings: Vec<String> = Vec::new();\n    for _ in 0..10 {\n        if rand::random() {\n            // all the strings are randomly generated\n            // and dynamically allocated at run-time\n            let string = rand::random::<u64>().to_string();\n            strings.push(string);\n        }\n    }\n\n    // strings are owned types so they can\n    // live at least as long as 'static\n    for mut string in strings {\n        // all the strings are mutable\n        string.push_str(\"a mutation\");\n        // all the strings are droppable\n        drop_static(string); // ✅\n    }\n\n    // all the strings have been invalidated before the end of the program\n    println!(\"I am the end of the program\");\n}\n```\n\n**Key Takeaways**\n- `T: 'static` should be read as _\"`T` can live at least as long as a `'static` lifetime\"_\n- if `T: 'static` then `T` can be a borrowed type with a `'static` lifetime _or_ an owned type\n- since `T: 'static` includes owned types that means `T`\n    - can be dynamically allocated at run-time\n    - does not have to be valid for the entire program\n    - can be safely and freely mutated\n    - can be dynamically dropped at run-time\n    - can have lifetimes of different durations\n\n\n\n### 3) `&'a T` and `T: 'a` are the same thing\n\nThis misconception is a generalized version of the one above.\n\n`&'a T` requires and implies `T: 'a` since a reference to `T` of lifetime `'a` cannot be valid for `'a` if `T` itself is not valid for `'a`. For example, the Rust compiler will never allow the construction of the type `&'static Ref<'a, T>` because if `Ref` is only valid for `'a` we can't make a `'static` reference to it.\n\n`T: 'a` includes all `&'a T` but the reverse is not true.\n\n```rust\n// only takes ref types that can outlive 'a\nfn t_ref<'a, T: 'a>(t: &'a T) {}\n\n// takes any types that can outlive 'a\nfn t_bound<'a, T: 'a>(t: T) {}\n\n// owned type which contains a reference\nstruct Ref<'a, T: 'a>(&'a T);\n\nfn main() {\n    let string = String::from(\"string\");\n\n    t_bound(&string); // ✅\n    t_bound(Ref(&string)); // ✅\n    t_bound(&Ref(&string)); // ✅\n\n    t_ref(&string); // ✅\n    t_ref(Ref(&string)); // ❌ - expected ref, found struct\n    t_ref(&Ref(&string)); // ✅\n\n    // string can outlive 'static which is longer than 'a\n    t_bound(string); // ✅\n}\n```\n\n**Key Takeaways**\n- `T: 'a` is more general and more flexible than `&'a T`\n- `T: 'a` accepts owned types, owned types which contain references, and references\n- `&'a T` only accepts references\n- if `T: 'static` then `T: 'a` since `'static` >= `'a` for all `'a`\n\n\n\n### 4) my code isn't generic and doesn't have lifetimes\n\n**Misconception Corollaries**\n- it's possible to avoid using generics and lifetimes\n\nThis comforting misconception is kept alive thanks to Rust's lifetime elision rules, which allow you to omit lifetime annotations in functions because the Rust borrow checker will infer them following these rules:\n- every input ref to a function gets a distinct lifetime\n- if there's exactly one input lifetime it gets applied to all output refs\n- if there's multiple input lifetimes but one of them is `&self` or `&mut self` then the lifetime of `self` is applied to all output refs\n- otherwise output lifetimes have to be made explicit\n\nThat's a lot to take in so let's look at some examples:\n\n```rust\n// elided\nfn print(s: &str);\n\n// expanded\nfn print<'a>(s: &'a str);\n\n// elided\nfn trim(s: &str) -> &str;\n\n// expanded\nfn trim<'a>(s: &'a str) -> &'a str;\n\n// illegal, can't determine output lifetime, no inputs\nfn get_str() -> &str;\n\n// explicit options include\nfn get_str<'a>() -> &'a str; // generic version\nfn get_str() -> &'static str; // 'static version\n\n// illegal, can't determine output lifetime, multiple inputs\nfn overlap(s: &str, t: &str) -> &str;\n\n// explicit (but still partially elided) options include\nfn overlap<'a>(s: &'a str, t: &str) -> &'a str; // output can't outlive s\nfn overlap<'a>(s: &str, t: &'a str) -> &'a str; // output can't outlive t\nfn overlap<'a>(s: &'a str, t: &'a str) -> &'a str; // output can't outlive s & t\nfn overlap(s: &str, t: &str) -> &'static str; // output can outlive s & t\nfn overlap<'a>(s: &str, t: &str) -> &'a str; // no relationship between input & output lifetimes\n\n// expanded\nfn overlap<'a, 'b>(s: &'a str, t: &'b str) -> &'a str;\nfn overlap<'a, 'b>(s: &'a str, t: &'b str) -> &'b str;\nfn overlap<'a>(s: &'a str, t: &'a str) -> &'a str;\nfn overlap<'a, 'b>(s: &'a str, t: &'b str) -> &'static str;\nfn overlap<'a, 'b, 'c>(s: &'a str, t: &'b str) -> &'c str;\n\n// elided\nfn compare(&self, s: &str) -> &str;\n\n// expanded\nfn compare<'a, 'b>(&'a self, &'b str) -> &'a str;\n```\n\nIf you've ever written\n- a function which takes or returns references\n- a struct method which takes or returns references\n- a generic function\n- a trait object (more on this later)\n- a closure (more on this later)\n\nthen your code has generic elided lifetime annotations all over it.\n\n**Key Takeaways**\n- almost all Rust code is generic code and there's elided lifetime annotations everywhere\n\n\n\n### 5) if it compiles then my lifetime annotations are correct\n\n**Misconception Corollaries**\n- Rust's lifetime elision rules for functions are always right\n- Rust's borrow checker is always right, technically _and semantically_\n- Rust knows more about the semantics of my program than I do\n\nIt's possible for a Rust program to be technically compilable but still semantically wrong. Take this for example:\n\n```rust\nstruct ByteIter<'a> {\n    remainder: &'a [u8]\n}\n\nimpl<'a> ByteIter<'a> {\n    fn next(&mut self) -> Option<&u8> {\n        if self.remainder.is_empty() {\n            None\n        } else {\n            let byte = &self.remainder[0];\n            self.remainder = &self.remainder[1..];\n            Some(byte)\n        }\n    }\n}\n\nfn main() {\n    let mut bytes = ByteIter { remainder: b\"1\" };\n    assert_eq!(Some(&b'1'), bytes.next());\n    assert_eq!(None, bytes.next());\n}\n```\n\n`ByteIter` is an iterator that iterates over a slice of bytes. We're skipping the `Iterator` trait implementation for conciseness. It seems to work fine, but what if we want to check a couple bytes at a time?\n\n```rust\nfn main() {\n    let mut bytes = ByteIter { remainder: b\"1123\" };\n    let byte_1 = bytes.next();\n    let byte_2 = bytes.next();\n    if byte_1 == byte_2 { // ❌\n        // do something\n    }\n}\n```\n\nUh oh! Compile error:\n\n```none\nerror[E0499]: cannot borrow `bytes` as mutable more than once at a time\n  --> src/main.rs:20:18\n   |\n19 |     let byte_1 = bytes.next();\n   |                  ----- first mutable borrow occurs here\n20 |     let byte_2 = bytes.next();\n   |                  ^^^^^ second mutable borrow occurs here\n21 |     if byte_1 == byte_2 {\n   |        ------ first borrow later used here\n```\n\nI guess we can copy each byte. Copying is okay when we're working with bytes but if we turned `ByteIter` into a generic slice iterator that can iterate over any `&'a [T]` then we might want to use it in the future with types that may be very expensive or impossible to copy and clone. Oh well, I guess there's nothing we can do about that, the code compiles so the lifetime annotations must be right, right?\n\nNope, the current lifetime annotations are actually the source of the bug! It's particularly hard to spot because the buggy lifetime annotations are elided. Let's expand the elided lifetimes to get a clearer look at the problem:\n\n```rust\nstruct ByteIter<'a> {\n    remainder: &'a [u8]\n}\n\nimpl<'a> ByteIter<'a> {\n    fn next<'b>(&'b mut self) -> Option<&'b u8> {\n        if self.remainder.is_empty() {\n            None\n        } else {\n            let byte = &self.remainder[0];\n            self.remainder = &self.remainder[1..];\n            Some(byte)\n        }\n    }\n}\n```\n\nThat didn't help at all. I'm still confused. Here's a hot tip that only Rust pros know: give your lifetime annotations descriptive names. Let's try again:\n\n```rust\nstruct ByteIter<'remainder> {\n    remainder: &'remainder [u8]\n}\n\nimpl<'remainder> ByteIter<'remainder> {\n    fn next<'mut_self>(&'mut_self mut self) -> Option<&'mut_self u8> {\n        if self.remainder.is_empty() {\n            None\n        } else {\n            let byte = &self.remainder[0];\n            self.remainder = &self.remainder[1..];\n            Some(byte)\n        }\n    }\n}\n```\n\nEach returned byte is annotated with `'mut_self` but the bytes are clearly coming from `'remainder`! Let's fix it.\n\n```rust\nstruct ByteIter<'remainder> {\n    remainder: &'remainder [u8]\n}\n\nimpl<'remainder> ByteIter<'remainder> {\n    fn next(&mut self) -> Option<&'remainder u8> {\n        if self.remainder.is_empty() {\n            None\n        } else {\n            let byte = &self.remainder[0];\n            self.remainder = &self.remainder[1..];\n            Some(byte)\n        }\n    }\n}\n\nfn main() {\n    let mut bytes = ByteIter { remainder: b\"1123\" };\n    let byte_1 = bytes.next();\n    let byte_2 = bytes.next();\n    std::mem::drop(bytes); // we can even drop the iterator now!\n    if byte_1 == byte_2 { // ✅\n        // do something\n    }\n}\n```\n\nNow that we look back on the previous version of our program it was obviously wrong, so why did Rust compile it? The answer is simple: it was memory safe.\n\nThe Rust borrow checker only cares about the lifetime annotations in a program to the extent it can use them to statically verify the memory safety of the program. Rust will happily compile programs even if the lifetime annotations have semantic errors, and the consequence of this is that the program becomes unnecessarily restrictive.\n\nHere's a quick example that's the opposite of the previous example: Rust's lifetime elision rules happen to be semantically correct in this instance but we unintentionally write a very restrictive method with our own unnecessary explicit lifetime annotations.\n\n```rust\n#[derive(Debug)]\nstruct NumRef<'a>(&'a i32);\n\nimpl<'a> NumRef<'a> {\n    // my struct is generic over 'a so that means I need to annotate\n    // my self parameters with 'a too, right? (answer: no, not right)\n    fn some_method(&'a mut self) {}\n}\n\nfn main() {\n    let mut num_ref = NumRef(&5);\n    num_ref.some_method(); // mutably borrows num_ref for the rest of its lifetime\n    num_ref.some_method(); // ❌\n    println!(\"{:?}\", num_ref); // ❌\n}\n```\n\nIf we have some struct generic over `'a` we almost never want to write a method with a `&'a mut self` receiver. What we're communicating to Rust is _\"this method will mutably borrow the struct for the entirety of the struct's lifetime\"_. In practice this means Rust's borrow checker will only allow at most one call to `some_method` before the struct becomes permanently mutably borrowed and thus unusable. The use-cases for this are extremely rare but the code above is very easy for confused beginners to write and it compiles. The fix is to not add unnecessary explicit lifetime annotations and let Rust's lifetime elision rules handle it:\n\n```rust\n#[derive(Debug)]\nstruct NumRef<'a>(&'a i32);\n\nimpl<'a> NumRef<'a> {\n    // no more 'a on mut self\n    fn some_method(&mut self) {}\n\n    // above line desugars to\n    fn some_method_desugared<'b>(&'b mut self){}\n}\n\nfn main() {\n    let mut num_ref = NumRef(&5);\n    num_ref.some_method();\n    num_ref.some_method(); // ✅\n    println!(\"{:?}\", num_ref); // ✅\n}\n```\n\n**Key Takeaways**\n- Rust's lifetime elision rules for functions are not always right for every situation\n- Rust does not know more about the semantics of your program than you do\n- give your lifetime annotations descriptive names\n- try to be mindful of where you place explicit lifetime annotations and why\n\n\n\n### 6) boxed trait objects don't have lifetimes\n\nEarlier we discussed Rust's lifetime elision rules _for functions_. Rust also has lifetime elision rules for trait objects, which are:\n- if a trait object is used as a type argument to a generic type then its lifetime bound is inferred from the containing type\n    - if there's a unique bound from the containing then that's used\n    - if there's more than one bound from the containing type then an explicit bound must be specified\n- if the above doesn't apply then\n    - if the trait is defined with a single lifetime bound then that bound is used\n    - if `'static` is used for any lifetime bound then `'static` is used\n    - if the trait has no lifetime bounds then its lifetime is inferred in expressions and is `'static` outside of expressions\n\nAll of that sounds super complicated but can be simply summarized as _\"a trait object's lifetime bound is inferred from context.\"_ After looking at a handful of examples we'll see the lifetime bound inferences are pretty intuitive so we don't have to memorize the formal rules:\n\n```rust\nuse std::cell::Ref;\n\ntrait Trait {}\n\n// elided\ntype T1 = Box<dyn Trait>;\n// expanded, Box<T> has no lifetime bound on T, so inferred as 'static\ntype T2 = Box<dyn Trait + 'static>;\n\n// elided\nimpl dyn Trait {}\n// expanded\nimpl dyn Trait + 'static {}\n\n// elided\ntype T3<'a> = &'a dyn Trait;\n// expanded, &'a T requires T: 'a, so inferred as 'a\ntype T4<'a> = &'a (dyn Trait + 'a);\n\n// elided\ntype T5<'a> = Ref<'a, dyn Trait>;\n// expanded, Ref<'a, T> requires T: 'a, so inferred as 'a\ntype T6<'a> = Ref<'a, dyn Trait + 'a>;\n\ntrait GenericTrait<'a>: 'a {}\n\n// elided\ntype T7<'a> = Box<dyn GenericTrait<'a>>;\n// expanded\ntype T8<'a> = Box<dyn GenericTrait<'a> + 'a>;\n\n// elided\nimpl<'a> dyn GenericTrait<'a> {}\n// expanded\nimpl<'a> dyn GenericTrait<'a> + 'a {}\n```\n\nConcrete types which implement traits can have references and thus they also have lifetime bounds, and so their corresponding trait objects have lifetime bounds. Also you can implement traits directly for references which obviously have lifetime bounds:\n\n```rust\ntrait Trait {}\n\nstruct Struct {}\nstruct Ref<'a, T>(&'a T);\n\nimpl Trait for Struct {}\nimpl Trait for &Struct {} // impl Trait directly on a ref type\nimpl<'a, T> Trait for Ref<'a, T> {} // impl Trait on a type containing refs\n```\n\nAnyway, this is worth going over because it often confuses beginners when they refactor a function from using trait objects to generics or vice versa. Take this program for example:\n\n```rust\nuse std::fmt::Display;\n\nfn dynamic_thread_print(t: Box<dyn Display + Send>) {\n    std::thread::spawn(move || {\n        println!(\"{}\", t);\n    }).join();\n}\n\nfn static_thread_print<T: Display + Send>(t: T) { // ❌\n    std::thread::spawn(move || {\n        println!(\"{}\", t);\n    }).join();\n}\n```\n\nIt throws this compile error:\n\n```none\nerror[E0310]: the parameter type `T` may not live long enough\n  --> src/lib.rs:10:5\n   |\n9  | fn static_thread_print<T: Display + Send>(t: T) {\n   |                        -- help: consider adding an explicit lifetime bound...: `T: 'static +`\n10 |     std::thread::spawn(move || {\n   |     ^^^^^^^^^^^^^^^^^^\n   |\nnote: ...so that the type `[closure@src/lib.rs:10:24: 12:6 t:T]` will meet its required lifetime bounds\n  --> src/lib.rs:10:5\n   |\n10 |     std::thread::spawn(move || {\n   |     ^^^^^^^^^^^^^^^^^^\n```\n\nOkay great, the compiler tells us how to fix the issue so let's fix the issue.\n\n```rust\nuse std::fmt::Display;\n\nfn dynamic_thread_print(t: Box<dyn Display + Send>) {\n    std::thread::spawn(move || {\n        println!(\"{}\", t);\n    }).join();\n}\n\nfn static_thread_print<T: Display + Send + 'static>(t: T) { // ✅\n    std::thread::spawn(move || {\n        println!(\"{}\", t);\n    }).join();\n}\n```\n\nIt compiles now but these two functions look awkward next to each other, why does the second function require a `'static` bound on `T` where the first function doesn't? That's a trick question. Using the lifetime elision rules Rust automatically infers a `'static` bound in the first function so both actually have `'static` bounds. This is what the Rust compiler sees:\n\n```rust\nuse std::fmt::Display;\n\nfn dynamic_thread_print(t: Box<dyn Display + Send + 'static>) {\n    std::thread::spawn(move || {\n        println!(\"{}\", t);\n    }).join();\n}\n\nfn static_thread_print<T: Display + Send + 'static>(t: T) {\n    std::thread::spawn(move || {\n        println!(\"{}\", t);\n    }).join();\n}\n```\n\n**Key Takeaways**\n- all trait objects have some inferred default lifetime bounds\n\n\n\n### 7) compiler error messages will tell me how to fix my program\n\n**Misconception Corollaries**\n- Rust's lifetime elision rules for trait objects are always right\n- Rust knows more about the semantics of my program than I do\n\nThis misconception is the previous two misconceptions combined into one example:\n\n```rust\nuse std::fmt::Display;\n\nfn box_displayable<T: Display>(t: T) -> Box<dyn Display> { // ❌\n    Box::new(t)\n}\n```\n\nThrows this error:\n\n```none\nerror[E0310]: the parameter type `T` may not live long enough\n --> src/lib.rs:4:5\n  |\n3 | fn box_displayable<T: Display>(t: T) -> Box<dyn Display> {\n  |                    -- help: consider adding an explicit lifetime bound...: `T: 'static +`\n4 |     Box::new(t)\n  |     ^^^^^^^^^^^\n  |\nnote: ...so that the type `T` will meet its required lifetime bounds\n --> src/lib.rs:4:5\n  |\n4 |     Box::new(t)\n  |     ^^^^^^^^^^^\n```\n\nOkay, let's fix it how the compiler is telling us to fix it, nevermind the fact that it's automatically inferring a `'static` lifetime bound for our boxed trait object without telling us and its recommended fix is based on that unstated fact:\n\n```rust\nuse std::fmt::Display;\n\nfn box_displayable<T: Display + 'static>(t: T) -> Box<dyn Display> { // ✅\n    Box::new(t)\n}\n```\n\nSo the program compiles now... but is this what we actually want? Probably, but maybe not. The compiler didn't mention any other fixes but this would have also been appropriate:\n\n```rust\nuse std::fmt::Display;\n\nfn box_displayable<'a, T: Display + 'a>(t: T) -> Box<dyn Display + 'a> { // ✅\n    Box::new(t)\n}\n```\n\nThis function accepts all the same arguments as the previous version plus a lot more! Does that make it better? Not necessarily, it depends on the requirements and constraints of our program. This example is a bit abstract so let's take a look at a simpler and more obvious case:\n\n```rust\nfn return_first(a: &str, b: &str) -> &str { // ❌\n    a\n}\n```\n\nThrows:\n\n```none\nerror[E0106]: missing lifetime specifier\n --> src/lib.rs:1:38\n  |\n1 | fn return_first(a: &str, b: &str) -> &str {\n  |                    ----     ----     ^ expected named lifetime parameter\n  |\n  = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `a` or `b`\nhelp: consider introducing a named lifetime parameter\n  |\n1 | fn return_first<'a>(a: &'a str, b: &'a str) -> &'a str {\n  |                ^^^^    ^^^^^^^     ^^^^^^^     ^^^\n```\n\nThe error message recommends annotating both inputs and the output with the same lifetime. If we did this our program would compile but this function would overly-constrain the return type. What we actually want is this:\n\n```rust\nfn return_first<'a>(a: &'a str, b: &str) -> &'a str { // ✅\n    a\n}\n```\n\n**Key Takeaways**\n- Rust's lifetime elision rules for trait objects are not always right for every situation\n- Rust does not know more about the semantics of your program than you do\n- Rust compiler error messages suggest fixes which will make your program compile which is not that same as fixes which will make you program compile _and_ best suit the requirements of your program\n\n\n\n### 8) lifetimes can grow and shrink at run-time\n\n**Misconception Corollaries**\n- container types can swap references at run-time to change their lifetime\n- Rust borrow checker does advanced control flow analysis\n\nThis does not compile:\n\n```rust\nstruct Has<'lifetime> {\n    lifetime: &'lifetime str,\n}\n\nfn main() {\n    let long = String::from(\"long\");\n    let mut has = Has { lifetime: &long };\n    assert_eq!(has.lifetime, \"long\");\n\n    {\n        let short = String::from(\"short\");\n        // \"switch\" to short lifetime\n        has.lifetime = &short;\n        assert_eq!(has.lifetime, \"short\");\n\n        // \"switch back\" to long lifetime (but not really)\n        has.lifetime = &long;\n        assert_eq!(has.lifetime, \"long\");\n        // `short` dropped here\n    }\n\n    assert_eq!(has.lifetime, \"long\"); // ❌ - `short` still \"borrowed\" after drop\n}\n```\n\nIt throws:\n\n```none\nerror[E0597]: `short` does not live long enough\n  --> src/main.rs:11:24\n   |\n11 |         has.lifetime = &short;\n   |                        ^^^^^^ borrowed value does not live long enough\n...\n15 |     }\n   |     - `short` dropped here while still borrowed\n16 |     assert_eq!(has.lifetime, \"long\");\n   |     --------------------------------- borrow later used here\n```\n\nThis also does not compile, throws the exact same error as above:\n\n```rust\nstruct Has<'lifetime> {\n    lifetime: &'lifetime str,\n}\n\nfn main() {\n    let long = String::from(\"long\");\n    let mut has = Has { lifetime: &long };\n    assert_eq!(has.lifetime, \"long\");\n\n    // this block will never run\n    if false {\n        let short = String::from(\"short\");\n        // \"switch\" to short lifetime\n        has.lifetime = &short;\n        assert_eq!(has.lifetime, \"short\");\n\n        // \"switch back\" to long lifetime (but not really)\n        has.lifetime = &long;\n        assert_eq!(has.lifetime, \"long\");\n        // `short` dropped here\n    }\n\n    assert_eq!(has.lifetime, \"long\"); // ❌ - `short` still \"borrowed\" after drop\n}\n```\n\nLifetimes have to be statically verified at compile-time and the Rust borrow checker only does very basic control flow analysis, so it assumes every block in an `if-else` statement and every match arm in a `match` statement can be taken and then chooses the shortest possible lifetime for the variable. Once a variable is bounded by a lifetime it is bounded by that lifetime _forever_. The lifetime of a variable can only shrink, and all the shrinkage is determined at compile-time.\n\n**Key Takeaways**\n- lifetimes are statically verified at compile-time\n- lifetimes cannot grow or shrink or change in any way at run-time\n- Rust borrow checker will always choose the shortest possible lifetime for a variable assuming all code paths can be taken\n\n\n\n### 9) downgrading mut refs to shared refs is safe\n\n**Misconception Corollaries**\n- re-borrowing a reference ends its lifetime and starts a new one\n\nYou can pass a mut ref to a function expecting a shared ref because Rust will implicitly re-borrow the mut ref as immutable:\n\n```rust\nfn takes_shared_ref(n: &i32) {}\n\nfn main() {\n    let mut a = 10;\n    takes_shared_ref(&mut a); // ✅\n    takes_shared_ref(&*(&mut a)); // above line desugared\n}\n```\n\nIntuitively this makes sense, since there's no harm in re-borrowing a mut ref as immutable, right? Surprisingly no, as the program below does not compile:\n\n```rust\nfn main() {\n    let mut a = 10;\n    let b: &i32 = &*(&mut a); // re-borrowed as immutable\n    let c: &i32 = &a;\n    dbg!(b, c); // ❌\n}\n```\n\nThrows this error:\n\n```none\nerror[E0502]: cannot borrow `a` as immutable because it is also borrowed as mutable\n --> src/main.rs:4:19\n  |\n3 |     let b: &i32 = &*(&mut a);\n  |                     -------- mutable borrow occurs here\n4 |     let c: &i32 = &a;\n  |                   ^^ immutable borrow occurs here\n5 |     dbg!(b, c);\n  |          - mutable borrow later used here\n```\n\nA mutable borrow does occur, but it's immediately and unconditionally re-borrowed as immutable and then dropped. Why is Rust treating the immutable re-borrow as if it still has the mut ref's exclusive lifetime? While there's no issue in the particular example above, allowing the ability to downgrade mut refs to shared refs does indeed introduce potential memory safety issues:\n\n```rust\nuse std::sync::Mutex;\n\nstruct Struct {\n    mutex: Mutex<String>\n}\n\nimpl Struct {\n    // downgrades mut self to shared str\n    fn get_string(&mut self) -> &str {\n        self.mutex.get_mut().unwrap()\n    }\n    fn mutate_string(&self) {\n        // if Rust allowed downgrading mut refs to shared refs\n        // then the following line would invalidate any shared\n        // refs returned from the get_string method\n        *self.mutex.lock().unwrap() = \"surprise!\".to_owned();\n    }\n}\n\nfn main() {\n    let mut s = Struct {\n        mutex: Mutex::new(\"string\".to_owned())\n    };\n    let str_ref = s.get_string(); // mut ref downgraded to shared ref\n    s.mutate_string(); // str_ref invalidated, now a dangling pointer\n    dbg!(str_ref); // ❌ - as expected!\n}\n```\n\nThe point here is that when you re-borrow a mut ref as a shared ref you don't get that shared ref without a big gotcha: it extends the mut ref's lifetime for the duration of the re-borrow even if the mut ref itself is dropped. Using the re-borrowed shared ref is very difficult because it's immutable but it can't overlap with any other shared refs. The re-borrowed shared ref has all the cons of a mut ref and all the cons of a shared ref and has the pros of neither. I believe re-borrowing a mut ref as a shared ref should be considered a Rust anti-pattern. Being aware of this anti-pattern is important so that you can easily spot it when you see code like this:\n\n```rust\n// downgrades mut T to shared T\nfn some_function<T>(some_arg: &mut T) -> &T;\n\nstruct Struct;\n\nimpl Struct {\n    // downgrades mut self to shared self\n    fn some_method(&mut self) -> &Self;\n\n    // downgrades mut self to shared T\n    fn other_method(&mut self) -> &T;\n}\n```\n\nEven if you avoid re-borrows in function and method signatures Rust still does automatic implicit re-borrows so it's easy to bump into this problem without realizing it like so:\n\n```rust\nuse std::collections::HashMap;\n\ntype PlayerID = i32;\n\n#[derive(Debug, Default)]\nstruct Player {\n    score: i32,\n}\n\nfn start_game(player_a: PlayerID, player_b: PlayerID, server: &mut HashMap<PlayerID, Player>) {\n    // get players from server or create & insert new players if they don't yet exist\n    let player_a: &Player = server.entry(player_a).or_default();\n    let player_b: &Player = server.entry(player_b).or_default();\n\n    // do something with players\n    dbg!(player_a, player_b); // ❌\n}\n```\n\nThe above fails to compile. `or_default()` returns a `&mut Player` which we're implicitly re-borrowing as `&Player` because of our explicit type annotations. To do what we want we have to:\n\n```rust\nuse std::collections::HashMap;\n\ntype PlayerID = i32;\n\n#[derive(Debug, Default)]\nstruct Player {\n    score: i32,\n}\n\nfn start_game(player_a: PlayerID, player_b: PlayerID, server: &mut HashMap<PlayerID, Player>) {\n    // drop the returned mut Player refs since we can't use them together anyway\n    server.entry(player_a).or_default();\n    server.entry(player_b).or_default();\n\n    // fetch the players again, getting them immutably this time, without any implicit re-borrows\n    let player_a = server.get(&player_a);\n    let player_b = server.get(&player_b);\n\n    // do something with players\n    dbg!(player_a, player_b); // ✅\n}\n```\n\nKinda awkward and clunky but this is the sacrifice we make at the Altar of Memory Safety.\n\n**Key Takeaways**\n- try not to re-borrow mut refs as shared refs, or you're gonna have a bad time\n- re-borrowing a mut ref doesn't end its lifetime, even if the ref is dropped\n\n\n\n### 10) closures follow the same lifetime elision rules as functions\n\nThis is more of a Rust Gotcha than a misconception.\n\nClosures, despite being functions, do not follow the same lifetime elision rules as functions.\n\n```rust\nfn function(x: &i32) -> &i32 {\n    x\n}\n\nfn main() {\n    let closure = |x: &i32| x; // ❌\n}\n```\n\nThrows:\n\n```none\nerror: lifetime may not live long enough\n --> src/main.rs:6:29\n  |\n6 |     let closure = |x: &i32| x;\n  |                       -   - ^ returning this value requires that `'1` must outlive `'2`\n  |                       |   |\n  |                       |   return type of closure is &'2 i32\n  |                       let's call the lifetime of this reference `'1`\n```\n\nAfter desugaring we get:\n\n```rust\n// input lifetime gets applied to output\nfn function<'a>(x: &'a i32) -> &'a i32 {\n    x\n}\n\nfn main() {\n    // input and output each get their own distinct lifetimes\n    let closure = for<'a, 'b> |x: &'a i32| -> &'b i32 { x };\n    // note: the above line is not valid syntax, but we need it for illustrative purposes\n}\n```\n\nThere's no good reason for this discrepancy. Closures were first implemented with different type inference semantics than functions and now we're stuck with it forever because to unify them at this point would be a breaking change. So how can we explicitly annotate a closure's type? Our options include:\n\n```rust\nfn main() {\n    // cast to trait object, becomes unsized, oops, compile error\n    let identity: dyn Fn(&i32) -> &i32 = |x: &i32| x;\n\n    // can allocate it on the heap as a workaround but feels clunky\n    let identity: Box<dyn Fn(&i32) -> &i32> = Box::new(|x: &i32| x);\n\n    // can skip the allocation and just create a static reference\n    let identity: &dyn Fn(&i32) -> &i32 = &|x: &i32| x;\n\n    // previous line desugared :)\n    let identity: &'static (dyn for<'a> Fn(&'a i32) -> &'a i32 + 'static) = &|x: &i32| -> &i32 { x };\n\n    // this would be ideal but it's invalid syntax\n    let identity: impl Fn(&i32) -> &i32 = |x: &i32| x;\n\n    // this would also be nice but it's also invalid syntax\n    let identity = for<'a> |x: &'a i32| -> &'a i32 { x };\n\n    // since \"impl trait\" works in the function return position\n    fn return_identity() -> impl Fn(&i32) -> &i32 {\n        |x| x\n    }\n    let identity = return_identity();\n\n    // more generic version of the previous solution\n    fn annotate<T, F>(f: F) -> F where F: Fn(&T) -> &T {\n        f\n    }\n    let identity = annotate(|x: &i32| x);\n}\n```\n\nAs I'm sure you've already noticed from the examples above, when closure types are used as trait bounds they do follow the usual function lifetime elision rules.\n\nThere's no real lesson or insight to be had here, it just is what it is.\n\n**Key Takeaways**\n- every language has gotchas 🤷\n\n\n\n## Conclusion\n\n- `T` is a superset of both `&T` and `&mut T`\n- `&T` and `&mut T` are disjoint sets\n- `T: 'static` should be read as _\"`T` can live at least as long as a `'static` lifetime\"_\n- if `T: 'static` then `T` can be a borrowed type with a `'static` lifetime _or_ an owned type\n- since `T: 'static` includes owned types that means `T`\n    - can be dynamically allocated at run-time\n    - does not have to be valid for the entire program\n    - can be safely and freely mutated\n    - can be dynamically dropped at run-time\n    - can have lifetimes of different durations\n- `T: 'a` is more general and more flexible than `&'a T`\n- `T: 'a` accepts owned types, owned types which contain references, and references\n- `&'a T` only accepts references\n- if `T: 'static` then `T: 'a` since `'static` >= `'a` for all `'a`\n- almost all Rust code is generic code and there's elided lifetime annotations everywhere\n- Rust's lifetime elision rules are not always right for every situation\n- Rust does not know more about the semantics of your program than you do\n- give your lifetime annotations descriptive names\n- try to be mindful of where you place explicit lifetime annotations and why\n- all trait objects have some inferred default lifetime bounds\n- Rust compiler error messages suggest fixes which will make your program compile which is not that same as fixes which will make you program compile _and_ best suit the requirements of your program\n- lifetimes are statically verified at compile-time\n- lifetimes cannot grow or shrink or change in any way at run-time\n- Rust borrow checker will always choose the shortest possible lifetime for a variable assuming all code paths can be taken\n- try not to re-borrow mut refs as shared refs, or you're gonna have a bad time\n- re-borrowing a mut ref doesn't end its lifetime, even if the ref is dropped\n- every language has gotchas 🤷\n\n\n\n## Discuss\n\nDiscuss this article on\n- [learnrust subreddit](https://www.reddit.com/r/learnrust/comments/gmrcrq/common_rust_lifetime_misconceptions/)\n- [official Rust users forum](https://users.rust-lang.org/t/blog-post-common-rust-lifetime-misconceptions/42950)\n- [rust subreddit](https://www.reddit.com/r/rust/comments/golrsx/common_rust_lifetime_misconceptions/)\n- [Hackernews](https://news.ycombinator.com/item?id=23279731)\n- [Github](https://github.com/pretzelhammer/rust-blog/discussions)\n\n\n## Further Reading\n\n- [Tour of Rust's Standard Library Traits](./tour-of-rusts-standard-library-traits.md)\n- [Beginner's Guide to Concurrent Programming: Coding a Multithreaded Chat Server using Tokio](./chat-server.md)\n- [Learning Rust in 2024](./learning-rust-in-2024.md)\n- [Using Rust in Non-Rust Servers to Improve Performance](./rust-in-non-rust-servers.md)\n- [Sizedness in Rust](./sizedness-in-rust.md)\n- [RESTful API in Sync & Async Rust](./restful-api-in-sync-and-async-rust.md)\n- [Learn Assembly with Entirely Too Many Brainfuck Compilers](./too-many-brainfuck-compilers.md)\n\n\n\n## Notifications\n\nGet notified when a new blog post gets published by\n- Subscribing to this repo's [releases RSS feed](https://github.com/pretzelhammer/rust-blog/releases.atom) or\n- Watching this repo's releases (click `Watch` → click `Custom` → select `Releases` → click `Apply`)\n"
  },
  {
    "path": "posts/learning-rust-in-2020.md",
    "content": "# Learning Rust in 2020\n\n_09 May 2020 · #rust · #programming · #exercises_\n\n**Table of Contents**\n- [Intro](#intro)\n- [TL;DR](#tldr)\n- [Practical Rust Resource Reviews](#practical-rust-resource-reviews)\n    - [HackerRank](#hackerrank)\n    - [Project Euler](#project-euler)\n    - [LeetCode](#leetcode)\n    - [Codewars](#codewars)\n    - [Advent of Code](#advent-of-code)\n    - [Rustlings](#rustlings)\n    - [Exercism](#exercism)\n- [Conclusion](#conclusion)\n- [Discuss](#discuss)\n- [Further Reading](#further-reading)\n- [Notifications](#notifications)\n\n\n\n## Intro\n\nWhen I started learning Rust I made the mistake of following the advice to read [The Book](https://doc.rust-lang.org/book/title-page.html) first. While it's a great resource, it's pretty overwhelming for a beginner to get told _\"If you'd like to learn this programming language the best way to start is to read this 20 chapter book!\"_ Most people give up before they even get started when they get advice like this. Nobody ever told someone to read a 20 chapter book just to get started with Javascript or Python. Rust's learning curve is no joke but you gotta give the people what they want, and they want to program, not read about programming. Programming is fun and reading about programming is not as fun.\n\nThe first 10% of this article is gonna be me giving you advice on how to learn Rust in 2020 following a _practical hands-on coding_ approach. This is the good part of the article. You can safely exit after this part (I'll tell you when). The remaining 90% of this article is me ranting about how most online coding challenge sites have poor support for Rust.\n\n\n\n## TL;DR\n\nIf you're a total Rust newbie and want to learn as much as possible in just one day you should read fasterthanlime's excellent [A half-hour to learn Rust](https://fasterthanli.me/blog/2020/a-half-hour-to-learn-rust/) and then checkout the awesome [Rustlings](https://github.com/rust-lang/rustlings) repo and complete the exercises.\n\nIf you're a Rust beginner you should get started on [Exercism's Rust Track](https://exercism.io/tracks/rust). If you get stuck you should ask your friends Google and StackOverflow for help. I recommend taking the time to get comfortable reading and navigating the [Rust Standard Library Docs](https://doc.rust-lang.org/std/) which is amazing and has simple practical examples for how to use everything inside of it. [Rust by Example](https://doc.rust-lang.org/rust-by-example/) is also a really good high-level reference that you can use to quickly learn Rust syntax and features. If you want to gain a deeper understanding of a certain Rust concept only then do I recommend finding the appropriate chapter in [The Book](https://doc.rust-lang.org/book/title-page.html) to read. The best part of completing an exercise on Exercism is that you get access to all the solutions by other members which you can sort by most-starred to see particularly idiomatic or clever solutions. This is a great way to learn!\n\nAt this point you're probably an advanced beginner and can find your own path. If you need more guidance and would like to continue working on small simple programs I recommend doing the exercises from the [Advent of Code 2018 Calendar](https://adventofcode.com/2018). The reason why I specifically recommended the 2018 calendar is because once you're finished with an exercise you can compare your solution to [BurntSushi's Advent of Code 2018 Rust solutions](https://github.com/BurntSushi/advent-of-code). BurntSushi writes really clean, readable, idiomatic Rust code. Reading the code of an experienced Rustacean will teach you as much as the exercises themselves.\n\nExit now, the good part of the article is over.\n\n\n\n## Practical Rust Resource Reviews\n\n_Alternative title: Reviews of Free Online Resources a Rust Beginner can use to Practice Writing Small Simple Rust Programs_\n\nMost of these resources weren't specifically created for the purpose of teaching Rust, however they can all be used to learn and practice Rust and many of them explicitly support Rust submissions and provide Rust-specific versions of problems.\n\nThe resources are ordered from worst to best.\n\n\n\n### [HackerRank](https://www.hackerrank.com)\n\nRust is a supported language on HackerRank except you aren't allowed to submit Rust solutions to most of the problems on their site. I tried to upload my solution directly and they refused it:\n\n![hackerrank more like failrank](../assets/hackerrank-more-like-failrank.png)\n\nThis is really strange because I was able to browse Rust solutions for the problem above submitted by other HackerRank users, so it's possible to submit a Rust solution somehow. I tried Googling this issue but Google didn't return any useful results. There's no way for me to evaluate HackerRank other than to tell you not to waste your time with it like I did.\n\n\n\n### [Project Euler](https://projecteuler.net/archives)\n\nWhen I first started to learn programming back in 2012 I commonly heard _\"If you wanna get up to speed quickly in a new programming language solve some Project Euler problems with it!\"_ which was okay advice at the time since there were not many other alternatives but in my opinion Project Euler has very little to do with programming. Project Euler problems are more math problems than they are programming problems. Their challenge lies almost entirely in the mathematical reasoning required to reach the solution as the programming required is usually trivial. I would not recommend solving Project Euler problems as a way to learn Rust unless you're very mathematically inclined and have some nostalgia for the site.\n\n\n\n### [LeetCode](https://leetcode.com/problemset/all/)\n\nRust is a supported language on LeetCode. For every problem on LeetCode you get a solution template which usually contains a single unimplemented function which you then have to implement and submit in order to solve the problem. For more involved problems the solution template might include a `struct` and an `impl` block with several unimplemented methods. Unfortunately, these solution templates are not created by humans, they are automatically generated, which results in a lot of really awkward and unidiomatic Rust code. Examples:\n\n| LeetCode generated Rust | Idiomatic Rust |\n|-|-|\n| tree problems represent links as `Option<Rc<RefCell<Node>>>` | `Option<Rc<RefCell<Node>>>` is overkill for tree links and `Option<Box<Node>>` works just as well and is much easier to work with |\n| methods which obviously mutate self still borrow it immutably, e.g. `fn insert(&self, val: i32)` | methods that mutate self need to borrow it mutably, e.g. `fn insert(&mut self, val: i32)` |\n| signed 32-bit integers are used for all numbers, even if the problem is undefined for negative integers, e.g. `fn nth_fib(n: i32) -> i32` | problems which are undefined for negative integers should use unsigned integers, e.g. `fn nth_fib(n: u32) -> u32` |\n| functions always take ownership of their arguments, even if it's unnecessary, e.g. `fn sum(nums: Vec<i32>) -> i32` | if you don't need ownership then borrow `fn sum(nums: &[i32]) -> i32` |\n| functions sometimes ignore basic error cases, e.g. for `fn get_max(nums: Vec<i32>) -> i32` what `i32` should be returned if `nums` is empty? | if a result might be undefined the return type should be wrapped in an `Option`, e.g. `fn get_max(nums: &[i32]) -> Option<i32>` |\n\nOther LeetCode issues, specific to Rust:\n- LeetCode doesn't allow you to pull in 3rd-party dependencies in solutions. Normally I think this is okay for most languages but Rust in particular has a pretty slim standard library which doesn't even include regex support so a lot of the more complex string parsing problems on LeetCode are pointlessly difficult to solve in Rust but have otherwise trivial solutions in other languages which have regex support in their standard libraries.\n- None of the problems in the `concurrency` category accept solutions in Rust. What? Fearless concurrency is one of Rust's major selling points!\n- After solving a problem you can go to the problem's comments section to see other user's solutions (as many users like to publish their solutions there) but because Rust isn't very popular on LeetCode sometimes you won't find any Rust solutions ;(\n\nGeneral LeetCode issues:\n- LeetCode has a surprising amount of very low quality problems. Problems can be liked and disliked by users but problems are never removed even if they hit very high dislike ratios. I've seen lots of problems with 100+ votes and 80%+ dislike ratios and I don't understand why they are kept on the site.\n- Problem difficulty ratings are kinda off. Problems are rated as Easy, Medium, or Hard but there are many Easy problems with lower solve rates than many Hard problems.\n- Not all problems accept solutions in all languages, and you can't filter problems by which languages they accept. None of the graph problems on LeetCode accept Rust solutions, for example.\n- LeetCode blocks \"premium\" problems behind a steep monthly paywall but doesn't offer any kind of premium free-trial so there's no telling if the quality is actually any better than the free problems.\n\nThings LeetCode does right:\n- Solutions to problems are tested against a suite of secret unit tests, but if you fail a particular test case they show you the failed case.\n- All of the generated Rust code at least follows rustfmt conventions.\n\n\n\n### [Codewars](https://www.codewars.com/join?language=rust)\n\nCodewars is a misleading name. There's no war going on at Codewars. There's no time limit to solve problems and your solutions aren't judged on their speed of execution or memory usage. You aren't in competition with anyone else. This isn't a bad thing, just worth pointing out.\n\nRust is a supported language on Codewars. For every problem on Codewars you get a solution template which usually contains a single unimplemented function which you then have to implement and submit in order to solve the problem. These solution templates are created by humans, including humans who aren't familiar with Rust, so you occasionally get some awkward and unidiomatic Rust. Examples:\n\n| Codewars' Rust Problems | Idiomatic Rust |\n|-|-|\n| sometimes don't follow rustfmt conventions, e.g. `fn makeUppercase(s:&str)->String` | always follows rustfmt conventions, e.g. `fn make_uppercase(s: &str) -> String` |\n| sometimes takes signed integer arguments for problems that aren't defined for negative integers, e.g. `fn nth_fib(n: i32) -> i32` | if a problem isn't defined for negative integers use unsigned integer arguments, e.g. `fn nth_fib(n: u32) -> u32` |\n| sometimes a problem asks you to return `-1` for the null case, e.g. `fn get_index(needle: i32, haystack: &[i32]) -> i32` | if a result can be null the return type should be wrapped in an `Option`, e.g. `fn get_index(needle: i32, haystack: &[i32]) -> Option<usize>` |\n| sometimes don't take advantage of deref coercion, e.g. `fn do_stuff(s: &String, list: &Vec<i32>)` | takes advantage of deref coercion, e.g. `fn do_stuff(s: &str, list: &[i32])` |\n\nAll of the issues above only happen sometimes since there are Rustaceans of various skill-levels on Codewars translating problems to Rust. This is a huge step up from LeetCode where all of the generated Rust problem code is consistently unidiomatic. However, the Rust community on Codewars as a whole might lean towards the inexperienced side since I've seen some highly upvoted \"idiomatic\" solutions that were also a bit on the awkward side. Examples:\n\n| Codewars' highest upvoted Rust solutions | Idiomatic Rust |\n|-|-|\n| sometimes use an explicit return at the end of a function block, e.g. `return result;` | blocks are evaluated as expressions and implicitly return their last item, an explicit return at the end of a function block is unnecessary, e.g. `result` |\n| often use compact formatting to make the solution look more concise | should follow rustfmt conventions |\n| sometimes make unnecessary allocations, e.g. `str_slice.to_string().chars()` | if you don't need to allocate then don't, e.g. `str_slice.chars()` |\n| often try to solve the problem using nothing but iterators at the cost of everything else | iterators are expressive and idiomatic, but if you have to chain 15 of them in a row and there are multiple levels of nested iterators in-between then perhaps you should consider refactoring to use some helper functions, intermediate variables, and maybe even a for-loop |\n\nAgain, the issues above only happen sometimes. An experienced Rustacean can spot them easily but there are a lot of Rust newbies on these sites who have no clue they are learning anti-patterns.\n\nOther Codewars issues, specific to Rust:\n- Rust doesn't seem that popular on Codewars, the site has 9000 exercises but only 300 of them have been translated to Rust ;(\n\nOther general Codewars issues:\n- Your solution is tested against a suite of secret unit tests, if you fail one of the secret unit tests you aren't shown the failed test case. This is especially annoying if the test case tests for an edge case that wasn't clearly communicated in the problem description.\n\nThings Codewars does right:\n- There's a small whitelist of 3rd-party dependencies you can use to help solve problems with Rust. This whitelist includes: rand, chrono, regex, serde, itertools, and lazy_static which helps round out Rust's standard library and puts it more on par with other languages.\n- You can filter problems by language.\n- Submitting a solution to a problem also automatically publishes the solution. You can view and upvote other members' solutions. You can sort solutions by most upvotes to see particularly concise and clever solutions, which sometimes will also be very idiomatic (but sometimes not, as explained above).\n- Problem difficulty grading is pretty good! Instead of grading problems as Easy, Medium, or Hard like LeetCode, Codewars chooses to grade problems from easiest to hardest as: 8 kyu, 7 kyu, 6 kyu, 5 kyu, 4 kyu, 3 kyu, 2 kyu, 1 kyu. I completed 60 problems in the 8 kyu - 4 kyu range and every level felt a little more difficult than the last, which aligned with my expectations.\n\n\n\n### [Advent of Code](https://adventofcode.com/)\n\nAdvent of Code is totally language-agnostic. This would seem like a minus at first but seeing how horribly HackerRank, LeetCode, and Codewars handle their support for Rust on their sites it's actually a plus. Advent of Code also gets placed above the previously mentioned sites because AoC's exercises are really interesting, diverse, and high quality in my opinion.\n\nGeneral AoC issues:\n- After you finish an exercise there's no way to see other people's Rust solutions unless you search from them on Google, and even after you find some there's no telling how good or idiomatic they are.\n\nTo solve the above issue I recommend going through the 2018 Calendar problems and comparing your solutions to [BurntSushi's AoC 2018 Rust solutions](https://github.com/BurntSushi/advent-of-code). BurntSushi writes really clean, readable, idiomatic Rust code. If you want to go through the 2019 Calendar then I recommend comparing your solutions to [bcmyers' AoC 2019 Rust solutions](https://github.com/bcmyers/aoc2019). The reason I specifically suggest bcmyers' is because he made a [youtube playlist of him coding up the solutions](https://www.youtube.com/playlist?list=PLQXBtq4j4Ozkx3r4eoMstdkkOG98qpBfg) and he does a great job of explaining his thought process and why he's doing what he's doing while he's coding.\n\nThings AoC got right:\n- High quality, interesting, curated exercises that are tied together with a narrative.\n- Language agnostic, so while it doesn't teach you any Rust patterns it at least doesn't teach you any Rust anti-patterns either.\n\n\n\n### [Rustlings](https://github.com/rust-lang/rustlings)\n\nRustlings is sooo good. All Rustlings exercises are hand-crafted for Rust with love and it's a wonderful breath of fresh air. Finally, a set of exercises that really teach you idiomatic Rust!\n\nIf you're a total Rust newbie you should absolutely checkout [Rustlings](https://github.com/rust-lang/rustlings) and get started on the exercises. I highly recommend reading fasterthanlime's [A half-hour to learn Rust](https://fasterthanli.me/blog/2020/a-half-hour-to-learn-rust/) first as it'll get you up to speed on a lot of Rust syntax and concepts super quickly.\n\nI have only 1 tiny Rustlings criticism: there are some sudden difficulty spikes in the \"error-handling\" and \"conversions\" exercises that I could see some users getting overwhelmed by. I assume most probably make it through, or at least I hope.\n\nI also have 1 tiny non-criticism: it's too short. This is a non-criticism because it's one of Rustlings design goals to be a quick and gentle introduction to Rust but it's so good that of course I wish it was somehow longer.\n\n\n\n### [Exercism](https://exercism.io/tracks/rust)\n\nExercism has a Rust track, which is a collection of exercises roughly ordered by subject and difficulty. The Rust track shares a lot of exercises in common with other tracks, but all of the exercises were translated to Rust by experienced Rustaceans and don't suffer from any of the awkward unidiomatic Rust issues that are common on LeetCode and Codewars. There are about a dozen Rust-specific problems that require you to implement a standard library trait, or write a macro, or write a parallel solution using multiple threads, or write unsafe Rust code. These exercises are by far the highlights of the track and I wish there were more of them. Exercism is second only to Rustlings as a resource for learning Rust. The only reason I placed it above Rustlings is Rustlings can be completed in an evening and Exercism's Rust track will take at least a month to complete so it just has a lot more content.\n\nExercism issues, specific to the Rust track:\n- \"Mentored mode\" is useless, as most of the Rust mentors on the site are inactive, and the students heavily outnumber them, so it's much better to go through a track in \"practice mode\".\n- There are 92 exercises but a good chunk of them don't really teach you anything new so they kinda feel like busywork. They could probably cut ~20 exercises from the track to make it feel a lot tighter.\n\nThings Exercism does right:\n- All problems are translated to Rust or written for Rust by experienced Rustaceans.\n- There are problems which specifically teach Rust's idioms, design patterns, and unique features.\n- Problem difficulties are fairly graded, easy problems are easy, medium problems are medium, hard problems are hard.\n- You can include whatever 3rd-party dependencies that you want in your solutions.\n- All unit tests are public, if you're failing a test you know exactly why.\n- After you submit a solution you can browse other user's solutions, and you can sort solutions by which received the most stars.\n\n\n\n## Conclusion\n\nSame as the [TL;DR](#tldr) :)\n\n\n\n## Discuss\n\nDiscuss this article on\n- [learnrust subreddit](https://www.reddit.com/r/learnrust/comments/ggj8tf/learning_rust_in_2020/)\n- [official Rust users forum](https://users.rust-lang.org/t/blog-post-learning-rust-in-2020/42373)\n- [rust subreddit](https://www.reddit.com/r/rust/comments/gie64f/learning_rust_in_2020/)\n- [Hackernews](https://news.ycombinator.com/item?id=23160975)\n- [Github](https://github.com/pretzelhammer/rust-blog/discussions)\n\n\n## Further Reading\n\n- [Common Rust Lifetime Misconceptions](./common-rust-lifetime-misconceptions.md)\n- [Tour of Rust's Standard Library Traits](./tour-of-rusts-standard-library-traits.md)\n- [Beginner's Guide to Concurrent Programming: Coding a Multithreaded Chat Server using Tokio](./chat-server.md)\n- [Learning Rust in 2024](./learning-rust-in-2024.md)\n- [Using Rust in Non-Rust Servers to Improve Performance](./rust-in-non-rust-servers.md)\n- [Sizedness in Rust](./sizedness-in-rust.md)\n- [RESTful API in Sync & Async Rust](./restful-api-in-sync-and-async-rust.md)\n- [Learn Assembly with Entirely Too Many Brainfuck Compilers](./too-many-brainfuck-compilers.md)\n\n\n\n## Notifications\n\nGet notified when a new blog post gets published by\n- Subscribing to this repo's [releases RSS feed](https://github.com/pretzelhammer/rust-blog/releases.atom) or\n- Watching this repo's releases (click `Watch` → click `Custom` → select `Releases` → click `Apply`)\n"
  },
  {
    "path": "posts/learning-rust-in-2024.md",
    "content": "# Learning Rust in 2024\n\n_21 September 2024 · #rust · #coding · #exercises_\n\n**Table of contents**\n- [TL;DR](#tldr)\n- [0\\) Reference material](#0-reference-material)\n- [1\\) Read A half hour to learn Rust](#1-read-a-half-hour-to-learn-rust)\n- [2\\) Complete rustlings](#2-complete-rustlings)\n- [3\\) Spend 10 hours coding in Rust](#3-spend-10-hours-coding-in-rust)\n  - [100 Exercises to Learn Rust](#100-exercises-to-learn-rust)\n  - [The Rust track on Exercism](#the-rust-track-on-exercism)\n  - [Advent of Code](#advent-of-code)\n  - [Tutorials](#tutorials)\n- [4\\) Read Common Rust Lifetime Misconceptions](#4-read-common-rust-lifetime-misconceptions)\n- [5\\) Spend another 10 hours coding in Rust](#5-spend-another-10-hours-coding-in-rust)\n- [6\\) Read Tour of Rust's Standard Library Traits](#6-read-tour-of-rusts-standard-library-traits)\n- [What's next?](#whats-next)\n- [Honorable mentions](#honorable-mentions)\n- [Discuss](#discuss)\n- [Further Reading](#further-reading)\n- [Notifications](#notifications)\n\nThis is my opinionated guide on how to go from knowing nothing about Rust to being kinda okay at Rust quickly as possible. This is what I would tell myself if I was starting today.\n\n\n\n## TL;DR\n\n1. Read [A half hour to learn Rust](https://fasterthanli.me/articles/a-half-hour-to-learn-rust) (30 - 60 mins)\n2. Complete [rustlings](https://github.com/rust-lang/rustlings) (2 - 3 hours)\n3. Spend 10 hours coding in Rust (8 - 12 hours)\n4. Read [Common Rust Lifetime Misconceptions](./common-rust-lifetime-misconceptions.md) (30 - 60 mins)\n5. Spend another 10 hours coding in Rust (8 - 12 hours)\n6. Read [Tour of Rust's Standard Library Traits](./tour-of-rusts-standard-library-traits.md) (2 - 4 hours)\n\nAnd that's it, after a short 19 to 30 hours you'll go from being a Rust beginner to a Rust advanced beginner 😎\n\n\n\n## 0\\) Reference material\n\nWhile learning Rust it's useful to have [Rust by Example](https://doc.rust-lang.org/rust-by-example/index.html) and the [Rust Standard Library docs](https://doc.rust-lang.org/std/) open in a couple browser tabs. If you get stuck on something you can probably find the answer by searching in either of those two resources, as both have a search bar at the top if you need to quickly find something.\n\nOther good alternatives are StackOverflow and ChatGPT (or whatever LLM you prefer). Almost every Rust beginner question has been asked and answered on StackOverflow and is indexed on Google. As for ChatGPT, it may get the answer wrong like half the time, but it will at least point you in the general direction of where you should search next to find a good answer.\n\nIf you've tried all of those things but still cannot get unstuck, then here are some beginner-friendly online Rust communities where you can ask questions: the [/r/rust](https://www.reddit.com/r/rust/) subreddit, the [/r/learnrust](https://www.reddit.com/r/learnrust/) subreddit, and the [official Rust users forum](https://users.rust-lang.org/).\n\nAlso it's a good idea to have [Rust Playground](https://play.rust-lang.org/) open in a browser tab. It's an online code editor and compiler for Rust code. It's great for tinkering with small examples to reinforce what you're learning while reading.\n\n\n\n## 1\\) Read [A half hour to learn Rust](https://fasterthanli.me/articles/a-half-hour-to-learn-rust)\n\nI recommend [A half hour to learn Rust](https://fasterthanli.me/articles/a-half-hour-to-learn-rust) above all other resources similar to it because it introduces Rust syntax and concepts in a very systematic and ground-up approach. It starts with the simplest possible example and then incrementally adds a little bit more complexity in every following example. The sequencing is very logical and easy to follow.\n\n\n\n## 2\\) Complete [rustlings](https://github.com/rust-lang/rustlings)\n\n[Rustlings](https://github.com/rust-lang/rustlings) is an ordered collection of tiny Rust programming exercises. Each exercise is a tiny Rust program that doesn't compile or is failing its unit tests. Your job for every exercise is to fix the program so it compiles and passes its unit tests.\n\nBefore starting rustlings you need to have Rust installed. I recommend using [rustup](https://rustup.rs/) to manage Rust installations. Once you have `rustup` you just have to run `rustup update` to update Rust on your machine any time.\n\nWhen coding Rust, you can use whatever code editor you want, but I recommend using one that supports [rust-analyzer](https://rust-analyzer.github.io/). I use [VS Code](https://code.visualstudio.com/) with [this extension](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer) to enable rust-analyzer.\n\nGetting started with rustlings is very easy because we can install it using `cargo`. Cargo is Rust's dependency manager and build tool, and comes with all Rust installations. If you installed Rust using `rustup` then you already have it.\n\nRun `cargo install rustlings`. By default, it will put the rustlings binary in `$HOME/.cargo/bin`, so you should add that path to your `$PATH` variable if it's not in there already, e.g.\n\n```sh\nexport PATH=\"$HOME/.cargo/bin:$PATH\"\n```\n\nNow run `rustlings`, which will create a `rustlings/` directory for you with all of the exercises in it. Open that directory in a code editor and then run the `rustlings` command within the directory and follow its instructions. It will tell you which exercise to work on. Complete the exercise and then the command will tell which exercise to work on next. Rinse and repeat until you're done.\n\n\n\n## 3\\) Spend 10 hours coding in Rust\n\nThis can be whatever you want, but for your first 10 hours I would suggest sticking to single-threaded sync Rust. There's enough novel and challenging Rust concepts\\* to learn within those parameters to easily keep you busy for at least 10 hours, and many people take much longer to fully wrap their heads around them. Multithreaded async Rust adds a bunch of additional complex concepts\\*\\*, so starting with it before you have the basics down will likely be overwhelming.\n\n\\*: ownership, borrowing, lifetimes, lifetime elision, mutable vs immutable references, sizedness, deref coercion, traits, trait objects, generics, const generics, static vs dynamic dispatch, error handling, iterators, modules, declarative macros, procedural macros, just to name a few.\n\n\\*\\*: futures, pinning, polling, awaiting, send, sync, cancellation, streams, sinks, locks, atomics, channels, actors, just to name a few.\n\nIf you have no ideas on what to code then I have a few suggestions.\n\n\n\n### [100 Exercises to Learn Rust](https://rust-exercises.com/100-exercises/)\n\nIf you enjoyed the difficulty and pacing of rustlings then you will enjoy 100 Exercises to Learn Rust (100ELR). Although made by different authors, 100ELR feels like a natural extension of rustlings and clearly drew a lot of inspiration from it.\n\nTo get started clone the [mainmatter/100-exercises-to-learn-rust](https://github.com/mainmatter/100-exercises-to-learn-rust) repo to your machine. Install their test suite runner using `cargo install --locked workshop-runner`. Then start reading the [accompanying book](https://rust-exercises.com/100-exercises/). It has 100 chapters and at the end of each chapter it tells you what exercise to do in the repo. Once you complete an exercise run `wr` in the project root to check that your solution passes the unit tests, and if it does continue on to the next chapter. Rinse and repeat until you're done.\n\nAlthough 100 chapters sounds like a lot they're all quite short so you'll get through them faster than you think. Completing the entire book likely take most people about 15 to 25 hours.\n\nHowever, if you found rustlings too easy or too slow and would like to try something more challenging, then you may want to skip 100ELR.\n\n\n\n### The [Rust track](https://exercism.org/tracks/rust) on Exercism\n\nThe [Rust track](https://exercism.org/tracks/rust) on Exercism is the best collection of small Rust exercises on the internet aside from rustlings and 100ELR. What makes it so good is that many of the exercises were crafted by Rustaceans, and are meant to teach you the aspects of Rust that make it unique and interesting compared to other programming languages. There's an exercise where you have to write a declarative macro! There's even exercise where you have to write unsafe code!\n\nTo get started you have to make an account on Exercism and enroll in the Rust track (both are free). You can then complete the exercises online using Exercism's online code editor or by downloading the exercises to your machine, completing them using your code editor, and submitting your solutions to Exercism using the `exercism` cli tool.\n\nI recommend using the `exercism` cli tool. There are many advantages. First, your code editor has rust-analyzer and Exercism's online code editor doesn't. Second, you can use dark mode in your editor but you can't use dark mode on Exercism unless you pay (it's a premium feature). Third, you can track your solutions using git. Fourth, you can choose which unit tests to run while you're developing your solution, instead of running the full test suite every time. The official Exercism instructions on how to do the exercises locally on your machine are [here](https://exercism.org/docs/using/solving-exercises/working-locally).\n\nEach track on Exercism has a \"learning mode\" and a \"practice mode.\" At the moment the Rust track's \"learning mode\" is disabled while the Exercism team reworks it. Regardless, I think the \"practice mode\" is better because it lets you do the exercises in whatever order you want. So while you may not have the option right now, if the option between a \"learning mode\" and a \"practice mode\" comes back to the Rust track in the future I'd recommend picking practice mode.\n\nWhile the exercises in the Rust track are ordered, the order is arbitrary and following it isn't important. With the exception of the [Luhn](https://exercism.org/tracks/rust/exercises/luhn), [Luhn From](https://exercism.org/tracks/rust/exercises/luhn-from), and [Luhn Trait](https://exercism.org/tracks/rust/exercises/luhn-trait) exercises, all of the other exercises are totally unrelated to each other and can be done in whatever order.\n\nThe best part of completing an exercise is that it gives you the ability to see and star other people's solutions. After completing an exercise I recommend checking these out, especially the most starred solutions, as they can teach you elegant and idiomatic parts of Rust that you may have not discovered on your own.\n\nFurthermore, the exercises are rated by difficulty: easy, medium, or hard. Currently there's 99 total exercises in the Rust track and I would say that about 30 are really good and the other 59 are just generic exercises that were copy & pasted from other tracks. Less than 0.1% of people complete the entire track. I wouldn't be surprised if less than 1% of people even complete half of the track. I have done all of the exercises so I'll recommend which ones I think are the best, since you're likely not going to do all of them anyway.\n\nYou should start with the easy exercises. Difficulty-wise they're slightly more challenging than what you'd find in rustlings or 100ELR. Quality-wise all of them are okay. None of them will take you longer than 20 minutes to complete. Also, if completing the easy exercises stops being rewarding then move on to the medium exercises, don't push yourself to complete all the easy ones if you don't feel like you're getting anything out of them anymore.\n\nAnyway, as for the medium exercises, these are the best ones in my opinion (in no particular order):\n- [PaaS I/O](https://exercism.org/tracks/rust/exercises/paasio)\n- [Simple Linked List](https://exercism.org/tracks/rust/exercises/simple-linked-list)\n- [Fizzy](https://exercism.org/tracks/rust/exercises/fizzy)\n- [Robot Name](https://exercism.org/tracks/rust/exercises/robot-name)\n- [Triangle](https://exercism.org/tracks/rust/exercises/triangle)\n- [Robot Simulator](https://exercism.org/tracks/rust/exercises/robot-simulator)\n- [Accumulate](https://exercism.org/tracks/rust/exercises/accumulate)\n- [Word Count](https://exercism.org/tracks/rust/exercises/word-count)\n- [Grep](https://exercism.org/tracks/rust/exercises/grep)\n- [Luhn](https://exercism.org/tracks/rust/exercises/luhn)\n- [Luhn From](https://exercism.org/tracks/rust/exercises/luhn-from)\n- [Luhn Trait](https://exercism.org/tracks/rust/exercises/luhn-trait)\n- [Clock](https://exercism.org/tracks/rust/exercises/clock)\n- [Space Age](https://exercism.org/tracks/rust/exercises/space-age)\n- [Sublist](https://exercism.org/tracks/rust/exercises/sublist)\n- [Binary Search](https://exercism.org/tracks/rust/exercises/binary-search)\n- [ETL](https://exercism.org/tracks/rust/exercises/etl)\n- [Grade School](https://exercism.org/tracks/rust/exercises/grade-school)\n- [Hamming](https://exercism.org/tracks/rust/exercises/hamming)\n- [Isogram](https://exercism.org/tracks/rust/exercises/isogram)\n- [Nucleotide Count](https://exercism.org/tracks/rust/exercises/nucleotide-count)\n\nDepending on which ones you do they can take you anywhere from 10 to 45 minutes.\n\nOnce you're ready to bump up the difficulty again, these are the best hard exercises in my opinion (in no particular order):\n- [Macros](https://exercism.org/tracks/rust/exercises/macros)\n- [Parallel Letter Frequency](https://exercism.org/tracks/rust/exercises/parallel-letter-frequency)\n- [Xorcism](https://exercism.org/tracks/rust/exercises/xorcism)\n- [React](https://exercism.org/tracks/rust/exercises/react)\n- [Circular Buffer](https://exercism.org/tracks/rust/exercises/circular-buffer)\n- [Forth](https://exercism.org/tracks/rust/exercises/forth)\n- [Doubly Linked List](https://exercism.org/tracks/rust/exercises/doubly-linked-list)\n\nDepending on which ones you do they can take anywhere from 30 to 90 minutes.\n\nIf you do a bunch of easy exercises, plus the medium and hard ones I recommend, it will probably take you around 20 hours. I think completing the entire track will probably be double that, at around 40 hours. With that said don't push yourself to finish the entire track if you feel yourself starting to lose interest, it'd be better to change gears and continue your Rust coding journey trying something else next, because the most important thing is that you keep having fun while learning.\n\n\n\n### [Advent of Code](https://adventofcode.com/)\n\n[Advent of Code](https://adventofcode.com/) (AoC) is a collection of programming puzzles. Every year since 2015 a new puzzle has been released every day from December 1st to 25th. Each puzzle has 2 parts. The first 10-15 puzzles of each year are usually easy to medium difficulty, and the last 10-15 puzzles of each year are usually hard. The puzzles are designed to be language agnostic, meaning you can solve them using any programming language. So if your goal is to learn Rust then just doing the puzzles is not going to help you very much, but if you complete a puzzle and then review an experienced Rustacean's solution that could help teach you a lot of Rust.\n\nThe experienced Rustacean in this case would be fasterthanlime. On top of publishing his solutions for the 2020 and 2022 AoC puzzles he also wrote beginner-friendly blog posts explaining his thought process while solving each one. If you're going to do AoC to learn Rust then you should start with the 2020 puzzles and after completing each one read the corresponding fasterthanlime blog post on it. I wouldn't recommend going far past puzzle 10 for any given year because they can start to get really challenging and you'll be spending most of your time busting your brain trying to figure out how to solve the puzzle instead of learning Rust.\n\n\n\n#### Setting up\n\nFirst, create an account on [AoC](https://adventofcode.com/). Second, since AoC is language agnostic you have to set up your own cargo project with your own scaffolding in order to solve the puzzles. Doing this can be very educational but it's also pretty boring. I'd suggest skipping that and using this Github template instead: [fspoettel/advent-of-code-rust](https://github.com/fspoettel/advent-of-code-rust). Click on `Use this template` -> `Create a new repository`, then `git clone` the created repository to your machine. In `.cargo/config.toml` set `AOC_YEAR` to `2020`.\n\nAlso you can install the `aoc-cli` tool to fetch all instructions and inputs from your AoC account to your machine. To do that run `cargo install aoc-cli --version 0.12.0`, then create the file `$HOME/.adventofcode.session` and paste your AoC session cookie into it. To get your session cookie, press `F12` while anywhere on the AoC website to open your browser's developer tools, then look for `Cookies` under the `Application` or `Storage` tabs and copy the `session` cookie value.\n\nOnce all of that is done you can run `cargo download {day}` within your project directory to generate the scaffolding and download the puzzle for that day. Once you think you've solved it you can run `cargo solve {day}` and then submit your final result via the AoC website to verify. For day 1 the commands would be `cargo download 1` and `cargo solve 1`.\n\n\n\n#### Year 2020\n\nAs mentioned before, make sure to set `AOC_YEAR` to `2020` in `.cargo/config.toml`. After completing a puzzle read fasterthanlime's solution on his blog, here's direct links to his solutions to the first 10 puzzles:\n\n1. [AoC 2020 Day 1](https://fasterthanli.me/series/advent-of-code-2020/part-1)\n1. [AoC 2020 Day 2](https://fasterthanli.me/series/advent-of-code-2020/part-2)\n1. [AoC 2020 Day 3](https://fasterthanli.me/series/advent-of-code-2020/part-3)\n1. [Aoc 2020 Day 4](https://fasterthanli.me/series/advent-of-code-2020/part-4)\n1. [AoC 2020 Day 5](https://fasterthanli.me/series/advent-of-code-2020/part-5)\n1. [AoC 2020 Day 6](https://fasterthanli.me/series/advent-of-code-2020/part-6)\n1. [AoC 2020 Day 7](https://fasterthanli.me/series/advent-of-code-2020/part-7)\n1. [AoC 2020 Day 8](https://fasterthanli.me/series/advent-of-code-2020/part-8)\n1. [AoC 2020 Day 9](https://fasterthanli.me/series/advent-of-code-2020/part-9)\n1. [AoC 2020 Day 10](https://fasterthanli.me/series/advent-of-code-2020/part-10)\n\n\n\n#### Year 2022\n\nIf you completed at least 10 of the 2020 puzzles then year 2022 is the next best year to do. Clone another copy of [fspoettel/advent-of-code-rust](https://github.com/fspoettel/advent-of-code-rust) and set `AOC_YEAR` to `2022` in `.cargo/config.toml` in the project directory. Then here's direct links to fasterthanlime's 2022 solutions:\n\n1. [AoC 2022 Day 1](https://fasterthanli.me/series/advent-of-code-2022/part-1)\n1. [AoC 2022 Day 2](https://fasterthanli.me/series/advent-of-code-2022/part-2)\n1. [AoC 2022 Day 3](https://fasterthanli.me/series/advent-of-code-2022/part-3)\n1. [AoC 2022 Day 4](https://fasterthanli.me/series/advent-of-code-2022/part-4)\n1. [AoC 2022 Day 5](https://fasterthanli.me/series/advent-of-code-2022/part-5)\n1. [AoC 2022 Day 6](https://fasterthanli.me/series/advent-of-code-2022/part-6)\n1. [AoC 2022 Day 7](https://fasterthanli.me/series/advent-of-code-2022/part-7)\n1. [AoC 2022 Day 8](https://fasterthanli.me/series/advent-of-code-2022/part-8)\n1. [AoC 2022 Day 9](https://fasterthanli.me/series/advent-of-code-2022/part-9)\n1. [AoC 2022 Day 10](https://fasterthanli.me/series/advent-of-code-2022/part-10)\n\n\n\n### Tutorials\n\nThe goal of most Rust tutorials is to show you how some piece of software could be implemented in Rust, not to necessarily to teach you Rust, and so many tutorial authors assume their audience will already be somewhat competent with the language and will omit a bunch of beginner explanations for the sake of keeping the tutorial focused and concise.\n\nWith that said, writing a non-trivial piece of software can be a lot more fun and rewarding than completing a bunch of small exercises, so this approach can be preferable for keeping your motivations high, especially if you're building something you're genuinely interested and excited about.\n\nI wish I could recommend some tutorials here but there's so many of them out there that it would be hard for me to go through all of them and rank them by their quality. The quality probably isn't that important though, what's important is that you're writing Rust code and enjoying your time, so pick any tutorial that looks fun and follow along without sweating the details.\n\nI will give a shoutout to [Codecrafters](https://codecrafters.io) though. Their tutorials are clearly very high quality and they have Rust starter templates for all of them. In every step of every tutorial they give you instructions and hints on how to implement the next part of the program, and once you're done you submit your code and it runs against a test suite to check if everything was implemented correctly.\n\nA big downside of Codecrafters is that it costs $40/month. They occasionally run promotions where a tutorial will be free for a month, so depending on when you check their site you may get lucky and a tutorial that catches your eye will be free. However, their pricing suggests they target software companies looking to train their engineers, and not individual engineers themselves. If you're employed at such a company, check if your company provides you a discretionary training allowance for courses like Codecrafters, which you could use to cover the cost.\n\n\n\n## 4\\) Read [Common Rust Lifetime Misconceptions](./common-rust-lifetime-misconceptions.md)\n\nDisclaimer: I wrote this.\n\nReading [Common Rust Lifetime Misconceptions](./common-rust-lifetime-misconceptions.md) will help you understand why half of the stuff you tried in your last 10 hours of Rust coding didn't work 🙂\n\nJokes aside, understanding lifetimes is probably the biggest stumbling block that many beginners struggle to get over when learning Rust, and this article dispels all of the most common misconceptions that people have about lifetimes that cause them confusion and frustration.\n\nThe reason I recommend it after at least 10 hours of practical Rust coding experience is because I think it might be too much technical information too soon for absolute beginners, who may find it more overwhelming than helpful.\n\n\n\n## 5\\) Spend another 10 hours coding in Rust\n\nAs before if you're not sure what to code my suggestions remain the same: [100 Exercises to Learn Rust](https://rust-exercises.com/100-exercises/), the [Rust track](https://exercism.org/tracks/rust) on Exercism, [Advent of Code](https://adventofcode.com/), or tutorials.\n\nAlso since you now have some Rust experience under your belt feel free to try coding something in multithreaded async Rust if you're feeling adventurous.\n\n\n\n## 6\\) Read [Tour of Rust's Standard Library Traits](./tour-of-rusts-standard-library-traits.md)\n\nDisclaimer: I wrote this.\n\nTraits are the main way to write polymorphic code in Rust, so they're used everywhere, especially the ones from the standard library. [Tour of Rust's Standard Library Traits](./tour-of-rusts-standard-library-traits.md) gives a guided tour of the most popular standard library traits, their methods, how to use them, and when to implement them for your own types. It's pretty thorough, and shares a ton of useful tips. And although the article is lengthy you don't have to read the entire thing to get value out of it, so don't let its size daunt you.\n\n\n\n## What's next?\n\nCongrats. You made it. You definitely know enough Rust to forge your own path forward. Good luck and have fun.\n\n\n\n## Honorable mentions\n\nThese are other Rust beginner resources that I really like but wasn't able to find a spot for them in my Rust learning guide.\n\n\n\n### [Tour of Rust](https://tourofrust.com/)\n\nIt's really good. However, it covers a lot of the same ground that other resources in the guide already cover, so it was omitted for the sake of keeping the guide streamlined.\n\n\n\n### [Comprehensive Rust](https://google.github.io/comprehensive-rust/)\n\nThis is a Rust course developed by the Android team at Google. It's a collection of slides which are meant to be presented by a speaker experienced with Rust, but the book version has the speaker notes at the bottom of each page so that it can be learned from as a standalone resource.\n\nIt's very concise and fast-paced, and also has sections covering parts of Rust that are typically omitted from other beginner resources, such as [bare metal Rust](https://google.github.io/comprehensive-rust/bare-metal.html) and [concurrency in Rust](https://google.github.io/comprehensive-rust/concurrency/welcome.html). However, since it's better presented by a speaker it didn't make sense to put it into my guide for self-learners.\n\n\n\n### [Clear explanation of Rust's module system](https://www.sheshbabu.com/posts/rust-module-system/)\n\nThis is a great article. I wasn't sure where to put it in the guide because it could go anywhere, but ideally it comes right when the learner starts breaking their Rust code across multiple files, which comes at a different point for every person in their Rust coding journey. Anyway, whenever that point comes for you, read this article then.\n\n\n\n## Discuss\n\nDiscuss this article on\n- [Github](https://github.com/pretzelhammer/rust-blog/discussions/84)\n- [official Rust users forum](https://users.rust-lang.org/t/learning-rust-in-2024)\n- [learnrust subreddit](https://www.reddit.com/r/learnrust/comments/1fnlvd8/learning_rust_in_2024/)\n- [rust subreddit](https://www.reddit.com/r/rust/comments/1fod8u9/learning_rust_in_2024/)\n\n\n## Further reading\n\n- [Common Rust Lifetime Misconceptions](./common-rust-lifetime-misconceptions.md)\n- [Tour of Rust's Standard Library Traits](./tour-of-rusts-standard-library-traits.md)\n- [Beginner's Guide to Concurrent Programming: Coding a Multithreaded Chat Server using Tokio](./chat-server.md)\n- [Using Rust in Non-Rust Servers to Improve Performance](./rust-in-non-rust-servers.md)\n- [Sizedness in Rust](./sizedness-in-rust.md)\n- [RESTful API in Sync & Async Rust](./restful-api-in-sync-and-async-rust.md)\n- [Learn Assembly with Entirely Too Many Brainfuck Compilers](./too-many-brainfuck-compilers.md)\n\n\n\n## Notifications\n\nGet notified when a new blog post gets published by\n- Subscribing to this repo's [releases RSS feed](https://github.com/pretzelhammer/rust-blog/releases.atom) or\n- Watching this repo's releases (click `Watch` → click `Custom` → select `Releases` → click `Apply`)\n"
  },
  {
    "path": "posts/restful-api-in-sync-and-async-rust.md",
    "content": "\n# RESTful API in Sync & Async Rust\n\n_11 May 2021 · #rust · #diesel · #rocket · #sqlx · #actix-web_\n\n**Table of Contents**\n\n- [Intro](#intro)\n- [General](#general)\n    - [Project Setup](#project-setup)\n    - [Loading Environment Variables w/dotenv](#loading-environment-variables-wdotenv)\n    - [Handling Dates & Times w/chrono](#handling-dates--times-wchrono)\n    - [Logging w/fern](#logging-wfern)\n    - [JSON Serialization w/serde](#json-serialization-wserde)\n    - [Domain Modeling](#domain-modeling)\n- [Sync Implementation](#sync-implementation)\n    - [SQL Schema Migrations w/diesel-cli](#sql-schema-migrations-wdiesel-cli)\n    - [Executing SQL Queries w/Diesel](#executing-sql-queries-wdiesel)\n        - [Mapping DB Enums to Rust Enums](#mapping-db-enums-to-rust-enums)\n        - [Fetching Data](#fetching-data)\n        - [Inserting Data](#inserting-data)\n        - [Updating Data](#updating-data)\n        - [Deleting Data](#deleting-data)\n        - [Using a Connection Pool w/r2d2](#using-a-connection-pool-wr2d2)\n        - [Refactoring DB Operations Into a Module](#refactoring-db-operations-into-a-module)\n    - [HTTP Routing w/Rocket](#http-routing-wrocket)\n        - [Routing Basics](#routing-basics)\n        - [GET Requests](#get-requests)\n        - [POST & PATCH Requests](#post--patch-requests)\n        - [DELETE Requests](#delete-requests)\n        - [Refactoring API Routes Into a Module](#refactoring-api-routes-into-a-module)\n        - [Authentication](#authentication)\n- [Async Implementation](#async-implementation)\n    - [SQL Schema Migrations w/sqlx-cli](#sql-schema-migrations-wsqlx-cli)\n    - [Executing SQL Queries w/sqlx](#executing-sql-queries-wsqlx)\n        - [Fetching Data](#fetching-data-1)\n        - [Inserting Data](#inserting-data-1)\n        - [Updating Data](#updating-data-1)\n        - [Deleting Data](#deleting-data-1)\n        - [Compile-Time Verification of SQL Queries](#compile-time-verification-of-sql-queries)\n        - [Using a Connection Pool w/sqlx](#using-a-connection-pool-wsqlx)\n        - [Refactoring DB Operations Into a Module](#refactoring-db-operations-into-a-module-1)\n    - [HTTP Routing w/actix-web](#http-routing-wactix-web)\n        - [Routing Basics](#routing-basics-1)\n        - [GET Requests](#get-requests-1)\n        - [POST & PATCH Requests](#post--patch-requests-1)\n        - [DELETE Requests](#delete-requests-1)\n        - [Refactoring API Routes Into a Module](#refactoring-api-routes-into-a-module-1)\n        - [Authentication](#authentication-1)\n- [Benchmarks](#benchmarks)\n    - [Servers](#servers)\n    - [Methodology](#methodology)\n    - [Measuring Resource Usage](#measuring-resource-usage)\n    - [Results](#results)\n        - [Read-Only Workload](#read-only-workload)\n        - [Reads + Writes Workload](#reads--writes-workload)\n- [Concluding Thoughts](#concluding-thoughts)\n    - [Diesel vs sqlx](#diesel-vs-sqlx)\n    - [Rocket vs actix-web](#rocket-vs-actix-web)\n    - [Sync Rust vs Async Rust](#sync-rust-vs-async-rust)\n    - [Rust vs JS](#rust-vs-js)\n    - [In Summary](#in-summary)\n- [Discuss](#discuss)\n- [Further Reading](#further-reading)\n- [Notifications](#notifications)\n\n\n\n## Intro\n\nLet's implement a RESTful API server in Rust for an imaginary Kanban-style project management app. A popular real-world example of such an app is Trello:\n\n![trello board](../assets/trello-board.png)\n\nOn its surface Kanban is pretty simple: there's a board and cards. The board represents a project. The cards represent tasks. The position of the cards on the board represents the state and progress of the tasks. The simplest boards have 3 columns for tasks which are: queued (to do), in progress (doing), and done (done).\n\nDespite being simple on its surface, Kanban, and all kinds of project management software in general, is a literal bottomless pit of complexity. There's a million things we could implement, and after we finish the first million things there would be a million more. However, since I'm trying to write a single article and not an entire book series let's keep the feature scope tiny.\n\nThe server should support the ability to:\n- Create boards\n    - Boards have names\n- Get a list of all boards\n- Delete boards\n- Create cards\n    - Can associate cards with boards\n    - Cards have descriptions and statuses\n- Get a list of all the cards on a board\n- Get a board summary: count of all the cards on the board grouped by their status\n- Update cards\n- Delete cards\n\nAnd that's it! To make this project slightly more interesting let's also include token-based authentication for all of the server's endpoints, but let's keep it simple: as long as a request contains a valid token it has access to all of the boards and cards.\n\nFurthermore, to satisfy my own curiosity, and to maximize the educationalness of this article, we're going to write two implementations together: one using sync Rust and the other using async Rust. The first implementation will use r2d2, Diesel, and Rocket. The second implementation will use sqlx, and actix-web. Here's a quick preview of the crates we'll be using for this project:\n\nGeneral crates\n- dotenv (loading environment variables)\n- log + fern (logging)\n- chrono (date & time handling)\n- serde + serde_json (JSON de/serialization)\n\nSync crates\n- diesel-cli (DB schema migrations)\n- diesel + diesel-derive-enum (ORM / building SQL queries)\n- r2d2 (DB connection pool)\n- rocket + rocket_contrib (HTTP routing)\n\nAsync crates\n- sqlx-cli (DB schema migrations)\n- sqlx (executing SQL queries & DB connection pool)\n- actix-web (HTTP routing)\n- futures (general future-related utilities)\n\nAfter finishing both sync and async implementations we'll run some benchmarks to see which has better performance, because everyone loves benchmarks.\n\n\n\n## General\n\n\n\n### Project Setup\n\nAll of the boring instructions for setting this project up, like installing Docker and running  locally, are in the [companion code repository](https://github.com/pretzelhammer/kanban). For this article let's focus entirely on the fun part: the Rust!\n\nAfter the initial setup we have this empty `Cargo.toml` file:\n\n```toml\n# Cargo.toml\n\n[package]\nname = \"kanban\"\nversion = \"0.1.0\"\nedition = \"2018\"\n```\n\nAnd this empty main file:\n\n```rust\n// src/main.rs\n\nfn main() {\n    println!(\"Hello, world!\");\n}\n```\n\n\n### Loading Environment Variables w/dotenv\n\ncrates\n- dotenv\n\n```diff\n# Cargo.toml\n\n[package]\nname = \"kanban\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n+[dependencies]\n+dotenv = \"0.15\"\n```\n\nThis crate does one small simple job: it loads variables from an `.env` in the current working directory and adds them to the program's environment variables. Here's the general `.env` file we'll be using:\n\n```bash\n# .env\n\nLOG_LEVEL=INFO\nLOG_FILE=server.log\nDATABASE_URL=postgres://postgres@localhost:5432/postgres \n```\n\nUpdated main file which uses `dotenv`:\n\n```rust\n// src/main.rs\n\ntype StdErr = Box<dyn std::error::Error>;\n\nfn main() -> Result<(), StdErr> {\n    // loads env variables from .env\n    dotenv::dotenv()?;\n\n    // example\n    assert_eq!(\"INFO\", std::env::var(\"LOG_LEVEL\").unwrap());\n\n    Ok(())\n}\n```\n\n\n\n### Handling Dates & Times w/chrono\n\ncrates\n- chrono\n\n```diff\n# Cargo.toml\n\n[package]\nname = \"kanban\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n[dependencies]\ndotenv = \"0.15\"\n+chrono = \"0.4\"\n```\n\nRust's go-to library for handling dates & times is chrono. We're not using the dependency in our project _just yet_ but will very soon after we add a few more dependencies.\n\n\n\n### Logging w/fern\n\ncrates\n- log\n- fern\n\n```diff\n# Cargo.toml\n\n[package]\nname = \"kanban\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n[dependencies]\ndotenv = \"0.15\"\nchrono = \"0.4\"\n+log = \"0.4\"\n+fern = \"0.6\"\n```\n\nLog is Rust's logging facade library. It provides the high-level logging API but we still need to pick an implementation, and the implementation we're going to use is the fern crate. Fern allows us to easily customize the logging format and also chain multiple outputs so we can log to stderr and a file if we wanted to. After adding log and fern let's encapsulate all of the logging configuration and initialization into its own module:\n\n```rust\n// src/logger.rs\n\nuse std::env;\nuse std::fs;\nuse log::{debug, error, info, trace, warn};\n\npub fn init() -> Result<(), fern::InitError> {\n    // pull log level from env\n    let log_level = env::var(\"LOG_LEVEL\").unwrap_or(\"INFO\".into());\n    let log_level = log_level\n        .parse::<log::LevelFilter>()\n        .unwrap_or(log::LevelFilter::Info);\n\n    let mut builder = fern::Dispatch::new()\n        .format(|out, message, record| {\n            out.finish(format_args!(\n                \"[{}][{}][{}] {}\",\n                chrono::Local::now().format(\"%H:%M:%S\"),\n                record.target(),\n                record.level(),\n                message\n            ))\n        })\n        .level(log_level)\n        // log to stderr\n        .chain(std::io::stderr());\n\n    // also log to file if one is provided via env\n    if let Ok(log_file) = env::var(\"LOG_FILE\") {\n        let log_file = fs::File::create(log_file)?;\n        builder = builder.chain(log_file);\n    }\n\n    // globally apply logger\n    builder.apply()?;\n\n    trace!(\"TRACE output enabled\");\n    debug!(\"DEBUG output enabled\");\n    info!(\"INFO output enabled\");\n    warn!(\"WARN output enabled\");\n    error!(\"ERROR output enabled\");\n\n    Ok(())\n}\n```\n\nAnd then add that module to our main file:\n\n```diff\n// src/main.rs\n\n+mod logger;\n\ntype StdErr = Box<dyn std::error::Error>;\n\nfn main() -> Result<(), StdErr> {\n    dotenv::dotenv()?;\n+   logger::init()?;\n\n    Ok(())\n}\n```\n\nIf we run the program now, since `INFO` is the default logging level, here's what we'd see:\n\n```bash\n$ cargo run\n[08:36:30][kanban::logger][INFO] INFO output enabled\n[08:36:30][kanban::logger][WARN] WARN output enabled\n[08:36:30][kanban::logger][ERROR] ERROR output enabled\n```\n\n\n### JSON Serialization w/serde\n\ncrates\n- serde\n- serde_json\n\n```diff\n# Cargo.toml\n\n[package]\nname = \"kanban\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n[dependencies]\ndotenv = \"0.15\"\n- chrono = \"0.4\"\n+ chrono = { version = \"0.4\", features = [\"serde\"] }\nlog = \"0.4\"\nfern = \"0.6\"\n+ serde = { version = \"1.0\", features = [\"derive\"] }\n+ serde_json = \"1.0\"\n```\n\nPro-tip: when adding a new dependency to a project it's good to look through existing dependencies to see if they have the new dependency as a feature flag. In this case chrono has serde as a feature flag, which if enabled, adds `serde::Serialize` and `serde::Deserialize` impls to all of chrono's types. This will allow us to use chrono types in our own structs later which we will also derive `serde::Serialize` and `serde::Deserialize` impls for.\n\n\n\n### Domain Modeling\n\nOkay, let's start modeling our domain. We know we will have boards so:\n\n```rust\n#[derive(serde::Serialize)]\n#[serde(rename_all = \"camelCase\")]\npub struct Board {\n    pub id: i64,\n    pub name: String,\n    pub created_at: chrono::DateTime<chrono::Utc>,\n}\n```\n\nUnpacking the new stuff:\n- `#[derive(serde::Serialize)]` derives a `serde::Serialize` impl for `Board` which will allow us to serialize it to JSON using the `serde_json` crate.\n- `#[serde(rename_all = \"camelCase\")]` renames all of the snake_case member identifiers to camelCase when serializing (or vice versa when deserializing). This is because it's a convention to use snake_case names in Rust but JSON is often produced and consumed by JS code and the JS convention is to use camelCase for member identifiers.\n- Making `id` an `i64` instead of an `u64` might seem like an odd choice but since we're using PostgreSQL as our DB we have to do this because PostgreSQL only supports signed integer types.\n- A `created_at` member is always useful to have, if for no other reason than to be able to sort entities by chronological order when no better sort order is available.\n\nOkay, let's add cards and statuses:\n\n```rust\n#[derive(serde::Serialize)]\n#[serde(rename_all = \"camelCase\")]\npub struct Card {\n    pub id: i64,\n    pub board_id: i64,\n    pub description: String,\n    pub status: Status,\n    pub created_at: chrono::DateTime<chrono::Utc>,\n}\n\n#[derive(serde::Serialize, serde::Deserialize)]\n#[serde(rename_all = \"camelCase\")]\npub enum Status {\n    Todo,\n    Doing,\n    Done,\n}\n```\n\nSince we'd also like to support returning a \"board summary\" which contains the count of all of the cards on a board grouped by their status here's the model for that:\n\n```rust\n#[derive(serde::Serialize)]\npub struct BoardSummary {\n    pub todo: i64,\n    pub doing: i64,\n    pub done: i64,\n}\n```\n\nWhen using the API to create a new board users can provide the board name but not its id, since that will be set by the DB, so we need a model for that as well:\n\n```rust\n#[derive(serde::Deserialize)]\npub struct CreateBoard {\n    pub name: String,\n}\n```\n\nLikewise users can also create cards. When creating a card let's assume we only want users to provide the new card's description and what board it should be associated with. The new card will get the default todo status and will get its id set by the DB:\n\n```rust\n#[derive(serde::Deserialize)]\n#[serde(rename_all = \"camelCase\")]\npub struct CreateCard {\n    pub board_id: i64,\n    pub description: String,\n}\n```\n\nWhen updating a card let's assume we want users to only be able to update the description or the status. It would be pretty weird if we allowed them to move cards between boards which is a pretty unusual feature in most project management apps:\n\n```rust\n#[derive(serde::Deserialize)]\npub struct UpdateCard {\n    pub description: String,\n    pub status: Status,\n}\n```\n\nThrow all of those into their own module and we get:\n\n```rust\n// src/models.rs\n\n// for GET requests\n\n#[derive(serde::Serialize)]\n#[serde(rename_all = \"camelCase\")]\npub struct Board {\n    pub id: i64,\n    pub name: String,\n    pub created_at: chrono::DateTime<chrono::Utc>,\n}\n\n#[derive(serde::Serialize)]\n#[serde(rename_all = \"camelCase\")]\npub struct Card {\n    pub id: i64,\n    pub board_id: i64,\n    pub description: String,\n    pub status: Status,\n    pub created_at: chrono::DateTime<chrono::Utc>,\n}\n\n#[derive(serde::Serialize, serde::Deserialize)]\n#[serde(rename_all = \"camelCase\")]\npub enum Status {\n    Todo,\n    Doing,\n    Done,\n}\n\n#[derive(serde::Serialize)]\npub struct BoardSummary {\n    pub todo: i64,\n    pub doing: i64,\n    pub done: i64,\n}\n\n// for POST requests\n\n#[derive(serde::Deserialize)]\npub struct CreateBoard {\n    pub name: String,\n}\n\n#[derive(serde::Deserialize)]\n#[serde(rename_all = \"camelCase\")]\npub struct CreateCard {\n    pub board_id: i64,\n    pub description: String,\n}\n\n// for PATCH requests\n\n#[derive(serde::Deserialize)]\npub struct UpdateCard {\n    pub description: String,\n    pub status: Status,\n}\n```\n\nAnd the updated main file:\n\n```diff\n// src/main.rs\n\nmod logger;\n+mod models;\n\ntype StdErr = Box<dyn std::error::Error>;\n\nfn main() -> Result<(), StdErr> {\n    dotenv::dotenv()?;\n    logger::init()?;\n\n    Ok(())\n}\n```\n\n\n## Sync Implementation\n\n\n\n### SQL Schema Migrations w/diesel-cli\n\ncrates\n- diesel-cli\n\n```bash\ncargo install diesel_cli\n```\n\nIf the above command doesn't work at first, it's likely because we don't have all the development libraries for all of diesel-cli's supported databases. Since we're just using PostgreSQL, we can make sure the development libraries are installed with these commands:\n\n```bash\n# macOS\nbrew install postgresql\n\n# ubuntu\napt-get install postgresql libpq-dev\n```\n\nAnd then we can tell cargo to only install diesel-cli with support for PostgreSQL:\n\n```bash\ncargo install diesel_cli --no-default-features --features postgres\n```\n\nOnce we have diesel-cli installed we can use it to create new migrations and execute pending migrations. diesel-cli figures out which DB to connect to by checking the `DATABASE_URL` environment variable, which it will also load from an `.env` file if one exists in the current working directory.\n\nAssuming the DB is currently running and a `DATABASE_URL` environment variable is present, here's the first diesel-cli command we'd run to bootstrap our project:\n\n```bash\ndiesel setup\n```\n\nWith this diesel-cli creates a `migrations` directory where we can generate and write our DB schema migrations. Let's generate our first migration:\n\n```bash\ndiesel migration generate create_boards\n```\n\nThis will create a new directory, e.g. `migrations/<year>-<month>-<day>-<time>_create_boards`, with an `up.sql` and `down.sql` which is where we'll write our SQL queries. The \"up\" query is for creating or modifying our DB schema, in this case creating a boards table:\n\n```sql\n-- create_boards up.sql\nCREATE TABLE IF NOT EXISTS boards (\n    id BIGSERIAL PRIMARY KEY,\n    name TEXT NOT NULL,\n    created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT (CURRENT_TIMESTAMP AT TIME ZONE 'utc')\n);\n\n-- seed db with some test data for local dev\nINSERT INTO boards\n(name)\nVALUES\n('Test board 1'),\n('Test board 2'),\n('Test board 3');\n```\n\nAnd the \"down\" query is for reverting the schema changes made in the \"up\" query, in this case dropping the created boards table:\n\n```sql\n-- create_boards down.sql\nDROP TABLE IF EXISTS boards;\n```\n\nWe will also need to store some cards:\n\n```bash\ndiesel migration generate create_cards\n```\n\nThe up query for cards:\n\n```sql\n-- create_cards up.sql\nCREATE TYPE STATUS_ENUM AS ENUM ('todo', 'doing', 'done');\n\nCREATE TABLE IF NOT EXISTS cards (\n    id BIGSERIAL PRIMARY KEY,\n    board_id BIGINT NOT NULL,\n    description TEXT NOT NULL,\n    status STATUS_ENUM NOT NULL DEFAULT 'todo',\n    created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT (CURRENT_TIMESTAMP AT TIME ZONE 'utc'),\n    CONSTRAINT board_fk\n        FOREIGN KEY (board_id)\n        REFERENCES boards(id)\n        ON DELETE CASCADE\n);\n\n-- seed db with some test data for local dev\nINSERT INTO cards\n(board_id, description, status)\nVALUES\n(1, 'Test card 1', 'todo'),\n(1, 'Test card 2', 'doing'),\n(1, 'Test card 3', 'done'),\n(2, 'Test card 4', 'todo'),\n(2, 'Test card 5', 'todo'),\n(3, 'Test card 6', 'done'),\n(3, 'Test card 7', 'done');\n```\n\nAnd the down query for cards:\n\n```sql\n-- create_cards down.sql\nDROP TABLE IF EXISTS cards;\n```\n\nAfter writing our migrations we can run them with this command:\n\n```bash\ndiesel migration run\n```\n\nThis executes the migrations in chronological order and also writes a Diesel schema file which should look like something like this at this point:\n\n```rust\n// src/schema.rs\n\ntable! {\n    boards (id) {\n        id -> Int8,\n        name -> Text,\n        created_at -> Timestamptz,\n    }\n}\n\ntable! {\n    cards (id) {\n        id -> Int8,\n        board_id -> Int8,\n        description -> Text,\n        status -> Status_enum,\n        created_at -> Timestamptz,\n    }\n}\n\njoinable!(cards -> boards (board_id));\n\nallow_tables_to_appear_in_same_query!(\n    boards,\n    cards,\n);\n```\n\nThe above file will always be generated by diesel-cli and is not something we should ever try to edit by hand, however the `diesel setup` command from earlier also generates a `diesel.toml` configuration file which we can edit if we need to configure or modify how the Diesel schema is generated:\n\n```toml\n# diesel.toml\n\n[print_schema]\nfile = \"src/schema.rs\"\n```\n\nThis will be useful to know for later.\n\n\n\n### Executing SQL Queries w/Diesel\n\ncrates\n- diesel\n\n```diff\n# Cargo.toml\n\n[package]\nname = \"kanban\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n[dependencies]\ndotenv = \"0.15\"\nchrono = { version = \"0.4\", features = [\"serde\"] }\nlog = \"0.4\"\nfern = \"0.6\"\nserde = { version = \"1.0\", features = [\"derive\"] }\nserde_json = \"1.0\"\n+diesel = { version = \"1.4\", features = [\"postgres\", \"chrono\"] }\n```\n\nWe enable the postgres and chrono feature flags since we'll be connecting to PostgreSQL and deserializing PostgreSQL's timestamp types to chrono types. Updated main file:\n\n```diff\n// src/main.rs\n\n+#[macro_use]\n+extern crate diesel;\n\nmod logger;\nmod models;\n+mod schema;\n\ntype StdErr = Box<dyn std::error::Error>;\n\nfn main() -> Result<(), StdErr> {\n    dotenv::dotenv()?;\n    logger::init()?;\n\n    Ok(())\n}\n```\n\nBefore decorating our models with Diesel's derive macros we have to bring the generated types from the Diesel schema file into scope:\n\n```diff\n// src/models.rs\n\n+use crate::schema::*;\n\n// etc\n```\n\nHowever, if we currently try to run `cargo check` we'd get this:\n\n```none\nerror[E0412]: cannot find type `Status_enum` in this scope\n  --> src/schema.rs:14:19\n   |\n14 |         status -> Status_enum,\n   |                   ^^^^^^^^^^^ not found in this scope\n```\n\nUh oh, now what?\n\n\n\n#### Mapping DB Enums to Rust Enums\n\nAs you may recall from the preceding section we defined an enum type in PostgreSQL like so:\n\n```sql\nCREATE TYPE STATUS_ENUM AS ENUM ('todo', 'doing', 'done');\n```\n\nUnfortunately Diesel does not support mapping DB enums to Rust enums out-of-the-box in a convenient way, so we have to pull in an unofficial 3rd-party library to do this for us:\n\n```diff\n# Cargo.toml\n\n[package]\nname = \"kanban\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n[dependencies]\ndotenv = \"0.15\"\nchrono = { version = \"0.4\", features = [\"serde\"] }\nlog = \"0.4\"\nfern = \"0.6\"\nserde = { version = \"1.0\", features = [\"derive\"] }\nserde_json = \"1.0\"\ndiesel = { version = \"1.4\", features = [\"postgres\", \"chrono\"] }\n+diesel-derive-enum = { version = \"1.1\", features = [\"postgres\"] }\n```\n\nThen we decorate the enum type with the following derive macro and attribute:\n\n```diff\n-#[derive(serde::Serialize, serde::Deserialize)]\n+#[derive(serde::Serialize, serde::Deserialize, diesel_derive_enum::DbEnum)]\n#[serde(rename_all = \"camelCase\")]\n+#[DieselType = \"Status_enum\"]\npub enum Status {\n    Todo,\n    Doing,\n    Done,\n}\n```\n\nThe derive macro generates a new type called `Status_enum` within the same scope, and this type can be used by Diesel to map the `STATUS_ENUM` DB enum to our `Status` Rust enum.\n\nThen we update `diesel.toml` with this:\n\n```diff\n[print_schema]\nfile = \"src/schema.rs\"\n+import_types = [\"diesel::sql_types::*\", \"crate::models::Status_enum\"]\n```\n\nThen we re-generate the Diesel schema file using this command:\n\n```bash\ndiesel print-schema > ./src/schema.rs\n```\n\nWhich updates our Diesel schema file to this:\n\n```diff\n// src/schema.rs\n\ntable! {\n+    use diesel::sql_types::*;\n+    use crate::models::Status_enum;\n\n    boards (id) {\n        id -> Int8,\n        name -> Text,\n        created_at -> Timestamptz,\n    }\n}\n\ntable! {\n+    use diesel::sql_types::*;\n+    use crate::models::Status_enum;\n\n    cards (id) {\n        id -> Int8,\n        board_id -> Int8,\n        description -> Text,\n        status -> Status_enum,\n        created_at -> Timestamptz,\n    }\n}\n\njoinable!(cards -> boards (board_id));\n\nallow_tables_to_appear_in_same_query!(\n    boards,\n    cards,\n);\n```\n\nAnd now when we run `cargo check` everything type checks just fine. Wow, that was quite the annoying hassle, but thankfully it's over.\n\n\n\n#### Fetching Data\n\nAlright, now let's impl some Diesel traits for our models by using the handy derive macros:\n\n```diff\n-#[derive(serde::Serialize)]\n+#[derive(serde::Serialize, diesel::Queryable)]\n#[serde(rename_all = \"camelCase\")]\npub struct Board {\n    pub id: i64,\n    pub name: String,\n    pub created_at: chrono::DateTime<chrono::Utc>,\n}\n```\n\nDeriving `diesel::Queryable` for a struct allows it to be returned as the result of a Diesel query. The order of the struct's members must match the order of the columns in the rows returned from the Diesel query.\n\nThe schema file generated by Diesel exports a DSL we can use to craft DB queries with. One of the major benefits of using the DSL is that it gives us verification at compile-time that all of our SQL queries are syntactically and semantically correct! Here's some commented examples:\n\n```rust\nuse diesel::prelude::*;\nuse diesel::PgConnection;\n\n// generated by diesel-cli from DB schema\nuse crate::schema::boards;\n\n// handwritten by us\nuse crate::models::Board;\n\n// example of connecting to PostgreSQL\nfn get_connection() -> PgConnection {\n    dotenv::dotenv().unwrap();\n    let db_url = env::var(\"DATABASE_URL\").unwrap();\n    PgConnection::establish(&db_url).unwrap()\n}\n\n// fetches all boards from the boards table,\n// diesel can map the DB rows to the Board model\n// because we derived Queryable for it and the\n// DB row data matches the Board's members\nfn all_boards(conn: &PgConnection) -> Vec<Board> {\n    boards::table\n        .load(conn)\n        .unwrap()\n}\n\n// fetching boards in chronological order\nfn all_boards_chronological(conn: &PgConnection) -> Vec<Board> {\n    boards::table\n        .order_by(boards::created_at.asc())\n        .load(conn)\n        .unwrap()\n}\n\n// fetching a board by its id\nfn board_by_id(conn: &PgConnection, board_id: i64) -> Board {\n    boards::table\n        .filter(boards::id.eq(board_id))\n        .first(conn)\n        .unwrap()\n}\n\n// fetching boards by their exact name\nfn board_by_name(conn: &PgConnection, board_name: &str) -> Vec<Board> {\n    boards::table\n        .filter(boards::name.eq(board_name))\n        .load(conn)\n        .unwrap()\n}\n\n// fetching boards if their names contain some string\nfn board_name_contains(conn: &PgConnection, contains: &str) -> Vec<Board> {\n    // in LIKE queries \"%\" means \"match zero or more of any character\"\n    let contains = format!(\"%{}%\", contains);\n    boards::table\n        .filter(boards::name.ilike(contains))\n        .load(conn)\n        .unwrap()\n}\n\n// fetching boards created within the past 24 hours\nfn recent_boards(conn: &PgConnection) -> Vec<Board> {\n    let past_day = chrono::Utc::now() - chrono::Duration::days(1);\n    boards::table\n        .filter(boards::created_at.ge(past_day))\n        .load(conn)\n        .unwrap()\n}\n\n// fetching boards create within the past 24 hours\n// AND whose name contains some string\n// by chaining filter methods\nfn recent_boards_and_name_contains(conn: &PgConnection, contains: &str) -> Vec<Board> {\n    let contains = format!(\"%{}%\", contains);\n    let past_day = chrono::Utc::now() - chrono::Duration::days(1);\n    boards::table\n        .filter(boards::name.ilike(contains))\n        .filter(boards::created_at.ge(past_day))\n        .load(conn)\n        .unwrap()\n}\n\n// fetching boards create within the past 24 hours\n// AND whose name contains some string\n// by composing predicate expressions\nfn recent_boards_and_name_contains_2(conn: &PgConnection, contains: &str) -> Vec<Board> {\n    let contains = format!(\"%{}%\", contains);\n    let past_day = chrono::Utc::now() - chrono::Duration::days(1);\n    let predicate = boards::name.ilike(contains).and(boards::created_at.ge(past_day));\n    boards::table\n        .filter(predicate)\n        .load(conn)\n        .unwrap()\n}\n\n// fetching boards create within the past 24 hours\n// OR whose name contains some string\n// by chaining filter methods\nfn recent_boards_or_name_contains(conn: &PgConnection, contains: &str) -> Vec<Board> {\n    let contains = format!(\"%{}%\", contains);\n    let past_day = chrono::Utc::now() - chrono::Duration::days(1);\n    boards::table\n        .filter(boards::name.ilike(contains))\n        .or_filter(boards::created_at.ge(past_day))\n        .load(conn)\n        .unwrap()\n}\n\n// fetching boards create within the past 24 hours\n// OR whose name contains some string\n// by composing predicate expressions\nfn recent_boards_or_name_contains_2(conn: &PgConnection, contains: &str) -> Vec<Board> {\n    let contains = format!(\"%{}%\", contains);\n    let past_day = chrono::Utc::now() - chrono::Duration::days(1);\n    let predicate = boards::name.ilike(contains).or(boards::created_at.ge(past_day));\n    boards::table\n        .filter(predicate)\n        .load(conn)\n        .unwrap()\n}\n```\n\nOkay, let's also derive `diesel::Queryable` for cards:\n\n```diff\n-#[derive(serde::Serialize)]\n+#[derive(serde::Serialize, diesel::Queryable)]\n#[serde(rename_all = \"camelCase\")]\npub struct Card {\n    pub id: i64,\n    pub board_id: i64,\n    pub description: String,\n    pub status: Status,\n    pub created_at: chrono::DateTime<chrono::Utc>,\n}\n```\n\nWe went over a bunch of query examples above but here's a few more:\n\n```rust\nuse diesel::prelude::*;\nuse diesel::PgConnection;\n\n// generated by diesel-cli from DB schema\nuse crate::schema::cards;\n\n// handwritten by us\nuse crate::models::{Card, Status};\n\n// fetch all cards\nfn all_cards(conn: &PgConnection) -> Vec<Card> {\n    cards::table\n        .load(conn)\n        .unwrap()\n}\n\n// fetch cards by board\nfn cards_by_board(conn: &PgConnection, board_id: i64) -> Vec<Card> {\n    cards::table\n        .filter(cards::board_id.eq(board_id))\n        .load(conn)\n        .unwrap()\n}\n\n// fetch cards by status\nfn cards_by_status(conn: &PgConnection, status: Status) -> Vec<Card> {\n    cards::table\n        .filter(cards::status.eq(status))\n        .load(conn)\n        .unwrap()\n}\n```\n\nSo it seems like we can craft almost every query our server needs to support using Diesel's DSL. _Almost_. One of the queries we'd like to support is returning a \"board summary\" which is the count of all the cards within a board grouped by their status. This is how we'd write the SQL query:\n\n```sql\nSELECT count(*), status\nFROM cards\nWHERE cards.board_id = $1\nGROUP BY status;\n```\n\nUnfortunately we cannot use Diesel's generated DSL to craft this query. Like all ORMs though, Diesel provides a method to run SQL directly, and that method is `diesel::sql_query` so let's talk about how we'd use that to get our board summary.\n\nFirst we need to create a new model which will be the result of our query and derive `diesel::QueryableByName` for it as well as decorate its members with the diesel types they map to:\n\n```rust\n#[derive(Default, serde::Serialize)]\npub struct BoardSummary {\n    pub todo: i64,\n    pub doing: i64,\n    pub done: i64,\n}\n\n// this will be the result of our diesel::sql_query query\n#[derive(diesel::QueryableByName)]\npub struct StatusCount {\n    #[sql_type = \"diesel::sql_types::BigInt\"]\n    pub count: i64,\n    #[sql_type = \"Status_enum\"]\n    pub status: Status,\n}\n\n// converting from a list of StatusCounts to a BoardSummary\nimpl From<Vec<StatusCount>> for BoardSummary {\n    fn from(counts: Vec<StatusCount>) -> BoardSummary {\n        let mut summary = BoardSummary::default();\n        for StatusCount { count, status } in counts {\n            match status {\n                Status::Todo => summary.todo += count,\n                Status::Doing => summary.doing += count,\n                Status::Done => summary.done += count,\n            }\n        }\n        summary\n    }\n}\n```\n\nWhy do structs which are the result of \"regular\" Diesel queries have to derive `diesel::Queryable` but structs which are the result of `diesel::sql_query` queries have to derive `diesel::QueryableByName`? According to the Diesel docs the former deserializes DB row columns by index and the latter deserializes DB row columns by name, and the first one is more performant but the latter is a bit more foolproof, hence its use for arbitrary SQL queries.\n\nAnyway, after jumping through all of the hoops above we can finally implement a function to fetch board summaries:\n\n```rust\n// fetching summary of cards on a board by id\nfn board_summary(conn: &PgConnection, board_id: i64) -> BoardSummary {\n    diesel::sql_query(format!(\n        \"SELECT count(*), status FROM cards WHERE cards.board_id = {} GROUP BY status\",\n        board_id\n    ))\n    .load::<StatusCount>(conn)\n    .unwrap()\n    .into()\n}\n```\n\n\n\n#### Inserting Data\n\nWe don't want to just fetch boards, we'd like to create them as well! As a reminder, the `CreateBoard` model only has a `name` member because the `id` and `created_at` members will be set by the DB. And this is how we'd update our `CreateBoard` model to use it with Diesel's DSL:\n\n```diff\n// boards has to be in scope to be used in table_name attribute\nuse crate::schema::boards;\n\n-#[derive(serde::Deserialize)]\n+#[derive(serde::Deserialize, diesel::Insertable)]\n+#[table_name = \"boards\"]\npub struct CreateBoard {\n    pub name: String,\n}\n```\n\nAfter deriving an `diesel::Insertable` impl for `CreateBoard` we can use it directly in Diesel insert queries:\n\n```rust\nuse diesel::prelude::*;\nuse diesel::PgConnection;\n\nuse crate::schema::boards;\nuse crate::models::{Board, CreateBoard};\n\n// create and return new board from CreateBoard model\nfn create_board(conn: &PgConnection, create_board: CreateBoard) -> Board {\n    diesel::insert_into(boards::table)\n        .values(&create_board)\n        .get_result(conn) // return inserted board result\n        .unwrap()\n}\n\n// same as above except without using the CreateBoard model\nfn create_board_2(conn: &PgConnection, board_name: String) -> Board {\n    diesel::insert_into(boards::table)\n        .values(boards::name.eq(board_name))\n        .get_result(conn) // return inserted board result\n        .unwrap()\n}\n```\n\nWe follow the same steps for the `CreateCard` struct:\n\n```diff\n// cards has to be in scope to be used in table_name attribute\nuse crate::schema::cards;\n\n- #[derive(serde::Deserialize)]\n+ #[derive(serde::Deserialize, diesel::Insertable)]\n#[serde(rename_all = \"camelCase\")]\n+ #[table_name = \"cards\"]\npub struct CreateCard {\n    pub board_id: i64,\n    pub description: String,\n}\n```\n\nExample create functions:\n\n```rust\nuse diesel::prelude::*;\nuse diesel::PgConnection;\n\nuse crate::schema::cards;\nuse crate::models::{Card, CreateCard};\n\n// create and return new card using CreateCard model\nfn create_card(conn: &PgConnection, create_card: CreateCard) -> Card {\n    diesel::insert_into(cards::table)\n        .values(&create_card)\n        .get_result(conn) // return inserted card result\n        .unwrap()\n}\n\n// same as above except without using CreateCard model\nfn create_card_2(conn: &PgConnection, board_id: i64, description: String) -> Card {\n    diesel::insert_into(cards::table)\n        .values((cards::board_id.eq(board_id), cards::description.eq(description)))\n        .get_result(conn) // returns inserted card result\n        .unwrap()\n}\n```\n\n\n\n#### Updating Data\n\nIf we derive `diesel::AsChangeSet` for the `UpdateCard` model:\n\n```diff\n// cards has to be in scope to be used in table_name attribute\nuse crate::schema::cards;\n\n-#[derive(serde::Deserialize)]\n+#[derive(serde::Deserialize, diesel::AsChangeset)]\n+#[table_name = \"cards\"]\npub struct UpdateCard {\n    pub description: String,\n    pub status: Status,\n}\n```\n\nWe can now pass `UpdateCard` directly to the `set` method of Diesel update queries:\n\n```rust\nuse diesel::prelude::*;\nuse diesel::PgConnection;\n\nuse crate::schema::cards;\nuse crate::models::{Card, UpdateCard};\n\n// update card in DB using UpdateCard model\nfn update_card(conn: &PgConnection, card_id: i64, update_card: UpdateCard) -> Card {\n    diesel::update(cards::table.filter(cards::id.eq(card_id)))\n        .set(update_card)\n        .get_result(conn) // return updated card result\n        .unwrap()\n}\n\n// same as above except without using model\nfn update_card_2(conn: &PgConnection, card_id: i64, description: String, status: Status) -> Card {\n    diesel::update(cards::table.filter(cards::id.eq(card_id)))\n        .set((cards::description.eq(description), cards::status.eq(status)))\n        .get_result(conn) // return updated card result\n        .unwrap()\n}\n```\n\n\n\n#### Deleting Data\n\nSome delete query examples:\n\n```rust\nuse diesel::prelude::*;\nuse diesel::PgConnection;\nuse crate::schema::{boards, cards};\n\n// delete all boards\nfn delete_all_boards(conn: &PgConnection) {\n    diesel::delete(boards::table)\n        .execute(conn)\n        .unwrap();\n}\n\n// delete a board by its id\nfn delete_board_by_id(conn: &PgConnection, board_id: i64) {\n    diesel::delete(boards::table.filter(boards::id.eq(board_id)))\n        .execute(conn)\n        .unwrap();\n}\n\n// delete all cards\nfn delete_all_cards(conn: &PgConnection) {\n    diesel::delete(cards::table)\n        .execute(conn)\n        .unwrap();\n}\n\n// delete a card by its id\nfn delete_card_by_id(conn: &PgConnection, card_id: i64) {\n    diesel::delete(cards::table.filter(cards::id.eq(card_id)))\n        .execute(conn)\n        .unwrap();\n}\n\n// delete all the cards on a board\nfn delete_cards_by_board(conn: &PgConnection, board_id: i64) {\n    diesel::delete(cards::table.filter(cards::board_id.eq(board_id)))\n        .execute(conn)\n        .unwrap();\n}\n\n// delete all done cards on a board\nfn delete_done_cards_by_board(conn: &PgConnection, board_id: i64) {\n    diesel::delete(\n        cards::table\n            .filter(cards::board_id.eq(board_id))\n            .filter(cards::status.eq(Status::Done)),\n    )\n    .execute(conn)\n    .unwrap();\n}\n```\n\n\n\n#### Using a Connection Pool w/r2d2\n\ncrates\n- r2d2\n\nCreating DB connections is expensive, so let's use a connection pool library to handle the hard work of managing and reusing DB connections for us. The library we're going to use is r2d2, which comes as a standalone crate but can also can come packaged within Diesel if we enable the r2d2 feature flag, so let's do that:\n\n```diff\n# Cargo.toml\n\n[package]\nname = \"kanban\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n[dependencies]\ndotenv = \"0.15\"\nchrono = { version = \"0.4\", features = [\"serde\"] }\nlog = \"0.4\"\nfern = \"0.6\"\nserde = { version = \"1.0\", features = [\"derive\"] }\nserde_json = \"1.0\"\n-diesel = { version = \"1.4\", features = [\"postgres\", \"chrono\"] }\n+diesel = { version = \"1.4\", features = [\"postgres\", \"chrono\", \"r2d2\"] }\ndiesel-derive-enum = { version = \"1.1\", features = [\"postgres\"] }\n```\n\nHere's how we'd create a pool with the default configuration options:\n\n```rust\nuse diesel::prelude::*;\nuse diesel::PgConnection;\nuse diesel::r2d2;\n\ntype PgPool = r2d2::Pool<r2d2::ConnectionManager<PgConnection>>;\n\nfn get_pool() -> PgPool {\n    dotenv::dotenv().unwrap();\n    let db_url = env::var(\"DATABASE_URL\").unwrap();\n    let manager = r2d2::ConnectionManager::new(db_url);\n    let pool = r2d2::Pool::new(manager).unwrap();\n    pool\n}\n\nfn use_pool(pool: &PgPool) {\n    let connection = pool.get().unwrap();\n    // use connection\n}\n```\n\n\n\n#### Refactoring DB Operations Into a Module\n\nThe rest of our application doesn't need to know or care that we're using Diesel and r2d2, so let's abstract all of those implementation details away within a `Db` struct, which we'll put into a `db` module:\n\n```rust\n// src/db.rs\n\nuse diesel::prelude::*;\nuse diesel::PgConnection;\nuse diesel::r2d2;\n\nuse crate::StdErr;\nuse crate::models::*;\nuse crate::schema::*;\n\ntype PgPool = r2d2::Pool<r2d2::ConnectionManager<PgConnection>>;\n\npub struct Db {\n    pool: PgPool,\n}\n\nimpl Db {\n    pub fn connect() -> Result<Self, StdErr> {\n        let db_url = env::var(\"DATABASE_URL\")?;\n        let manager = r2d2::ConnectionManager::new(db_url);\n        let pool = r2d2::Pool::new(manager)?;\n        Ok(Db { pool })\n    }\n\n    pub fn boards(&self) -> Result<Vec<Board>, StdErr> {\n        let conn = self.pool.get()?;\n        Ok(boards::table.load(&conn)?)\n    }\n\n    pub fn board_summary(&self, board_id: i64) -> Result<BoardSummary, StdErr> {\n        let conn = self.pool.get()?;\n        let counts: Vec<StatusCount> = diesel::sql_query(format!(\n            \"select count(*), status from cards where cards.board_id = {} group by status\",\n            board_id\n        ))\n        .load(&conn)?;\n        Ok(counts.into())\n    }\n\n    pub fn create_board(&self, create_board: CreateBoard) -> Result<Board, StdErr> {\n        let conn = self.pool.get()?;\n        let board = diesel::insert_into(boards::table)\n            .values(&create_board)\n            .get_result(&conn)?;\n        Ok(board)\n    }\n\n    pub fn delete_board(&self, board_id: i64) -> Result<(), StdErr> {\n        let conn = self.pool.get()?;\n        diesel::delete(boards::table.filter(boards::id.eq(board_id))).execute(&conn)?;\n        Ok(())\n    }\n\n    pub fn cards(&self, board_id: i64) -> Result<Vec<Card>, StdErr> {\n        let conn = self.pool.get()?;\n        let cards = cards::table\n            .filter(cards::board_id.eq(board_id))\n            .load(&conn)?;\n        Ok(cards)\n    }\n\n    pub fn create_card(&self, create_card: CreateCard) -> Result<Card, StdErr> {\n        let conn = self.pool.get()?;\n        let card = diesel::insert_into(cards::table)\n            .values(create_card)\n            .get_result(&conn)?;\n        Ok(card)\n    }\n\n    pub fn update_card(&self, card_id: i64, update_card: UpdateCard) -> Result<Card, StdErr> {\n        let conn = self.pool.get()?;\n        let card = diesel::update(cards::table.filter(cards::id.eq(card_id)))\n            .set(update_card)\n            .get_result(&conn)?;\n        Ok(card)\n    }\n\n    pub fn delete_card(&self, card_id: i64) -> Result<(), StdErr> {\n        let conn = self.pool.get()?;\n        diesel::delete(\n            cards::table.filter(cards::id.eq(card_id)),\n        )\n        .execute(&conn)?;\n        Ok(())\n    }\n}\n```\n\nUpdated main file:\n\n```diff\n// src/main.rs\n\n#[macro_use]\nextern crate diesel;\n\n+mod db;\nmod logger;\nmod models;\nmod schema;\n\ntype StdErr = Box<dyn std::error::Error>;\n\nfn main() -> Result<(), StdErr> {\n    dotenv::dotenv()?;\n    logger::init()?;\n\n    Ok(())\n}\n```\n\n\n### HTTP Routing w/Rocket\n\ncrates\n- rocket\n- rocket_contrib\n\n```diff\n# Cargo.toml\n\n[package]\nname = \"kanban\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n[dependencies]\ndotenv = \"0.15\"\nchrono = { version = \"0.4\", features = [\"serde\"] }\nlog = \"0.4\"\nfern = \"0.6\"\nserde = { version = \"1.0\", features = [\"derive\"] }\nserde_json = \"1.0\"\ndiesel = { version = \"1.4\", features = [\"postgres\", \"chrono\", \"r2d2\"] }\ndiesel-derive-enum = { version = \"1.1\", features = [\"postgres\"] }\n+rocket = \"0.4\"\n+rocket_contrib = \"0.4\"\n```\n\nRocket v0.4 depends on some nightly features, some of which are only available on compiler version 1.53.0 since they're later removed, so we'll need to install a specific nightly compiler and then switch to using these commands\n\n```bash\n# install rustc 1.53.0-nightly (07e0e2ec2 2021-03-24)\nrustup install nightly-2021-03-24\n\n# set it as default\nrustup default nightly-2021-03-24\n```\n\nWe also have to add some compiler feature flags to the top of our main:\n\n```diff\n// src/main.rs\n\n+// required for rocket macros to work\n+#![feature(proc_macro_hygiene, decl_macro)]\n\n#[macro_use]\nextern crate diesel;\n\nmod db;\nmod logger;\nmod models;\nmod schema;\n\ntype StdErr = Box<dyn std::error::Error>;\n\nfn main() -> Result<(), StdErr> {\n    dotenv::dotenv()?;\n    logger::init()?;\n\n    Ok(())\n}\n```\n\nWhile we're here let's throw together a quick Rocket hello world:\n\n```diff\n// required for rocket macros to work\n#![feature(proc_macro_hygiene, decl_macro)]\n\n#[macro_use]\nextern crate diesel;\n\nmod db;\nmod logger;\nmod models;\nmod routes;\nmod schema;\n\ntype StdErr = Box<dyn std::error::Error>;\n\n+#[rocket::get(\"/\")]\n+fn hello_world() -> &'static str {\n+   \"Hello, world!\"\n+}\n\nfn main() -> Result<(), StdErr> {\n    dotenv::dotenv()?;\n    logger::init()?;\n\n+   rocket::ignite()\n+       .mount(\"/\", rocket::routes![hello_world])\n+       .launch();\n\n    Ok(())\n}\n```\n\nThe code above does exactly what you think it does. Also, if we `cargo run` it:\n\n```bash\n$ cargo run\n[13:07:21][launch][INFO] Configured for development.\n[13:07:21][launch_][INFO] address: localhost\n[13:07:21][launch_][INFO] port: 8000\n[13:07:21][launch_][INFO] log: normal\n[13:07:21][launch_][INFO] workers: 32\n[13:07:21][launch_][INFO] secret key: generated\n[13:07:21][launch_][INFO] limits: forms = 32KiB\n[13:07:21][launch_][INFO] keep-alive: 5s\n[13:07:21][launch_][INFO] read timeout: 5s\n[13:07:21][launch_][INFO] write timeout: 5s\n[13:07:21][launch_][INFO] tls: disabled\n[13:07:21][rocket::rocket][INFO] Mounting /:\n[13:07:21][_][INFO] GET / (hello_world)\n[13:07:21][launch][INFO] Rocket has launched from http://localhost:8000\n```\n\nLook at all those beautiful logs! I bet you were wondering if, and when, all the logging setup work we did forever ago was going to become useful. Well that time is now! Of course, being good developers who care about being able to debug issues when they arise, we should be logging way more in our application, but I've been intentionally omitting the logging statements because they're noisy and have little educational value. Please imagine that they are there.\n\n\n\n#### Routing Basics\n\nWe can decorate functions with Rocket's procedural macros to turn them into request handlers, example:\n\n```rust\n#[rocket::get(\"/\")]\nfn index() -> &'static str {\n    \"I'm the index route!\"\n}\n\n#[rocket::get(\"/nested/route\")]\nfn index() -> &'static str {\n    \"I'm some nested route!\"\n}\n```\n\nData can be extracted from the path using `<param>` placeholders:\n\n```rust\n#[rocket::get(\"/hello/<name>\")]\nfn greet(name: String) -> String {\n    format!(\"Hello, {}!\", name)\n}\n```\n\nAny type which impls `rocket::request::FromParam` can be extracted from the path:\n\n```rust\nuse rocket::request::FromParam;\n\n// Rocket provides FromParam impls for\n// - all stdlib number types\n// - bool\n// - String\n// - &str\n// - some other misc types\n#[rocket::get(\"/echo/<string>/<num>/<maybe>/etc\")]\nfn echo_path(string: String, num: usize, maybe: bool) -> String {\n    format!(\"got string {}, num {}, and maybe {}\", string, num, maybe)\n}\n\n// Rocket also provides FromParam impls for\n// - Option<T> where T: FromParam\n//     - returns Some(T) on success, None otherwise\n// - Result<T> where T: FromParam\n//     - returns Ok(T) on success, Err(<T as FromParam>::Error) otherwise\n\n// example custom type\nstruct EvenNumber(i32);\n\n// example FromParam impl\nimpl<'a> FromParam<'a> for EvenNumber {\n    type Error = &'static str;\n\n    fn from_param(param: &'a RawStr) -> Result<Self, Self::Error> {\n        let result = i32::from_param(param);\n        if let Ok(num) = result {\n            if num % 2 == 0 {\n                Ok(EvenNumber(num))\n            } else {\n                Err(\"param not an even number\")\n            }\n        } else {\n            Err(\"param not a number\")\n        }\n    }\n}\n\n// extracting our own custom defined type\n#[rocket::get(\"/<even>\")]\nfn even_param(even: EvenNumber) -> String {\n    format!(\"got even number {}\", even.0)\n}\n```\n\nA request handler's return type can be anything that impls `rocket::response::Responder`:\n\n```rust\nuse std::io;\nuse std::fs::File;\nuse rocket::{http, request, response};\nuse rocket::response::{Response, Responder};\n\n// Rocket provides Responder impls for\n// - &str\n// - String\n// - &[u8]\n// - Vec<u8>\n// - File\n// - ()\n// - some other misc types\n#[rocket::get(\"/cargo\")]\nfn returns_cargo() -> File {\n    File::open(\"Cargo.toml\").unwrap()\n}\n\n// Rocket also provides Responder impls for\n// - Option<T> where T: Responder\n//     - returns T if Some(T), 404 Not Found if None\n// - Result<T, E> where T: Responder, E: Debug\n//     - returns T if Ok(T), 500 Internal Server Error if Err(E)\n\n// example custom type\nstruct EvenNumber(i32);\n\n// example Responder impl\nimpl<'r> Responder<'r> for EvenNumber {\n    fn respond_to(self, _req: &request::Request<'_>) -> response::Result<'r> {\n        Response::build()\n            .status(http::Status::Ok)\n            .raw_header(\"X-Number-Parity\", \"Even\")\n            .sized_body(io::Cursor::new(format!(\"returning even number {}\", self.0)))\n            .ok()\n    }\n}\n\n// returning custom defined type\n#[rocket::get(\"/even\")]\nfn returns_even() -> EvenNumber {\n    EvenNumber(2)\n}\n```\n\n\n\n#### GET Requests\n\nThe first problem we need to solve is how to pass our `Db` to our Rocket request handlers. We can achieve this by first passing the `Db` instance to the Rocket application builder via the `manage` method which tells Rocket this is some application state that it should manage for us:\n\n```diff\n// src/main.rs\n\n// required for rocket macros to work\n#![feature(proc_macro_hygiene, decl_macro)]\n\n#[macro_use]\nextern crate diesel;\n\nmod db;\nmod logger;\nmod models;\nmod schema;\nmod routes;\n\ntype StdErr = Box<dyn std::error::Error>;\n\n#[rocket::get(\"/\")]\nfn hello_world() -> &'static str {\n    \"Hello, world!\"\n}\n\nfn main() -> Result<(), StdErr> {\n    dotenv::dotenv()?;\n    logger::init()?;\n\n+   let db = db::Db::connect()?;\n\n    rocket::ignite()\n+       .manage(db)\n        .mount(\"/\", rocket::routes![hello_world])\n        .launch();\n\n    Ok(())\n}\n```\n\nThen we can retrieve the managed application state from Rocket in our request handlers by wrapping the data type we wish to receive with `rocket::State` as one of our function parameters:\n\n```rust\nuse rocket::State;\nuse crate::db::Db;\n\n#[rocket::get(\"/use/db\")]\nfn use_db(db: State<Db>) {\n    // use db\n}\n```\n\nWe can automatically return JSON by wrapping the return type with the `rocket_contrib::json::Json` type which impls `Responder` and will serialize the wrapped type to JSON using serde and set the response header `Content-Type: application/json`, example:\n\n```rust\nuse rocket_contrib::json::Json;\nuse crate::models::Status;\n\n#[rocket::get(\"/example/json\")]\nfn return_json() -> Json<Status> {\n    Json(Status::Todo)\n}\n```\n\nOkay, we now have enough context to write all of our GET request handlers:\n\n```rust\nuse rocket::State;\nuse rocket_contrib::json::Json;\n\nuse crate::StdErr;\nuse crate::db::Db;\nuse crate::models::{Board, Card, BoardSummary};\n\n// GET requests\n\n#[rocket::get(\"/boards\")]\nfn boards(db: State<Db>) -> Result<Json<Vec<Board>>, StdErr> {\n    db.boards().map(Json)\n}\n\n#[rocket::get(\"/boards/<board_id>/summary\")]\nfn board_summary(db: State<Db>, board_id: i64) -> Result<Json<BoardSummary>, StdErr> {\n    db.board_summary(board_id).map(Json)\n}\n\n#[rocket::get(\"/boards/<board_id>/cards\")]\nfn cards(db: State<Db>, board_id: i64) -> Result<Json<Vec<Card>>, StdErr> {\n    db.cards(board_id).map(Json)\n}\n```\n\n\n\n#### POST & PATCH Requests\n\n`rocket_contrib::json::Json` not only impls `Responder` but also impls `rocket::data::FromData` which means we can use it as a function parameter to a request handler and Rocket will attempt deserialize the request's JSON body into the type we specify, so here's how we'd write the POST & PATCH request handlers:\n\n```rust\nuse rocket::State;\nuse rocket_contrib::json::Json;\n\nuse crate::StdErr;\nuse crate::db::Db;\nuse crate::models::{Board, CreateBoard, Card, CreateCard, UpdateCard};\n\n// POST requests\n\n#[rocket::post(\"/boards\", data = \"<create_board>\")]\nfn create_board(db: State<Db>, create_board: Json<CreateBoard>) -> Result<Json<Board>, StdErr> {\n    db.create_board(create_board.0).map(Json)\n}\n\n#[rocket::post(\"/cards\", data = \"<create_card>\")]\nfn create_card(db: State<Db>, create_card: Json<CreateCard>) -> Result<Json<Card>, StdErr> {\n    db.create_card(create_card.0).map(Json)\n}\n\n// PATCH requests\n\n#[rocket::patch(\"/cards/<card_id>\", data = \"<update_card>\")]\nfn update_card(\n    db: State<Db>,\n    card_id: i64,\n    update_card: Json<UpdateCard>,\n) -> Result<Json<Card>, StdErr> {\n    db.update_card(card_id, update_card.0).map(Json)\n}\n```\n\n\n\n#### DELETE Requests\n\nThe DELETE request handlers:\n\n```rust\nuse rocket::State;\nuse rocket_contrib::json::Json;\n\nuse crate::StdErr;\nuse crate::db::Db;\n\n#[rocket::delete(\"/boards/<board_id>\")]\nfn delete_board(db: State<Db>, board_id: i64) -> Result<(), StdErr> {\n    db.delete_board(board_id)\n}\n\n#[rocket::delete(\"/cards/<card_id>\")]\nfn delete_card(db: State<Db>, card_id: i64) -> Result<(), StdErr> {\n    db.delete_card(card_id)\n}\n```\n\n\n\n#### Refactoring API Routes Into A Module\n\nLet's clean up our code and put all of the API routes into their own module:\n\n```rust\n// src/routes.rs\n\nuse rocket::http;\nuse rocket::response;\nuse rocket::request\nuse rocket::State;\nuse rocket_contrib::json::Json;\n\nuse crate::StdErr;\nuse crate::db::Db;\nuse crate::models::{Board, CreateBoard, BoardSummary, Card, CreateCard, UpdateCard};\n\n// board routes\n\n#[rocket::get(\"/boards\")]\nfn boards(db: State<Db>) -> Result<Json<Vec<Board>>, StdErr> {\n    db.boards().map(Json)\n}\n\n#[rocket::post(\"/boards\", data = \"<create_board>\")]\nfn create_board(db: State<Db>, create_board: Json<CreateBoard>) -> Result<Json<Board>, StdErr> {\n    db.create_board(create_board.0).map(Json)\n}\n\n#[rocket::get(\"/boards/<board_id>/summary\")]\nfn board_summary(db: State<Db>, board_id: i64) -> Result<Json<BoardSummary>, StdErr> {\n    db.board_summary(board_id).map(Json)\n}\n\n#[rocket::delete(\"/boards/<board_id>\")]\nfn delete_board(db: State<Db>, board_id: i64) -> Result<(), StdErr> {\n    db.delete_board(board_id)\n}\n\n// card routes\n\n#[rocket::get(\"/boards/<board_id>/cards\")]\nfn cards(db: State<Db>, board_id: i64) -> Result<Json<Vec<Card>>, StdErr> {\n    db.cards(board_id).map(Json)\n}\n\n#[rocket::post(\"/cards\", data = \"<create_card>\")]\nfn create_card(db: State<Db>, create_card: Json<CreateCard>) -> Result<Json<Card>, StdErr> {\n    db.create_card(create_card.0).map(Json)\n}\n\n#[rocket::patch(\"/cards/<card_id>\", data = \"<update_card>\")]\nfn update_card(\n    db: State<Db>,\n    card_id: i64,\n    update_card: Json<UpdateCard>,\n) -> Result<Json<Card>, StdErr> {\n    db.update_card(card_id, update_card.0).map(Json)\n}\n\n#[rocket::delete(\"/cards/<card_id>\")]\nfn delete_card(db: State<Db>, card_id: i64) -> Result<(), StdErr> {\n    db.delete_card(card_id)\n}\n\n// single public function which returns all API routes\n\npub fn api() -> Vec<rocket::Route> {\n    rocket::routes![\n        boards,\n        create_board,\n        board_summary,\n        delete_board,\n        cards,\n        create_card,\n        update_card,\n        delete_card,\n    ]\n}\n```\n\nUpdated main file:\n\n```diff\n// src/main.rs\n\n// required for rocket macros to work\n#![feature(proc_macro_hygiene, decl_macro)]\n\n#[macro_use]\nextern crate diesel;\n\nmod db;\nmod logger;\nmod models;\n+mod routes;\nmod schema;\n\ntype StdErr = Box<dyn std::error::Error>;\n\n#[rocket::get(\"/\")]\nfn hello_world() -> &'static str {\n    \"Hello, world!\"\n}\n\nfn main() -> Result<(), StdErr> {\n    dotenv::dotenv()?;\n    logger::init()?;\n\n    let db = db::Db::connect()?;\n\n    rocket::ignite()\n        .manage(db)\n        .mount(\"/\", rocket::routes![hello_world])\n+       .mount(\"/api\", routes::api())\n        .launch();\n\n    Ok(())\n}\n```\n\nWe're almost there! Only one small piece of the puzzle is missing: authentication.\n\n\n\n#### Authentication\n\nLet's implement token-based authentication for our RESTful API server. When a request comes in, we'll first check if it has a `Authorization: Bearer <token>` header, and if not reject it immediately. Otherwise, we validate the `<token>` by checking that it exists in a `tokens` DB table, and if it's valid we respond to the request.\n\nSince this is a toy project we're not going to implement different access permissions per token, all tokens will have access to all boards and all cards. Also, let's skip the implementing the handler which generates and returns tokens because it's mostly boilerplate and not relevant to us implementing authentication.\n\nAnyway, we're gonna need to create a `tokens` table first:\n\n```bash\ndiesel migration generate create_tokens\n```\n\nSQL query to create the `tokens` table:\n\n```sql\n-- create_tokens up.sql\nCREATE TABLE IF NOT EXISTS tokens (\n    id TEXT PRIMARY KEY,\n    expired_at TIMESTAMP WITH TIME ZONE NOT NULL\n);\n\n-- seed db with some test data for local dev\nINSERT INTO tokens\n(id, expired_at)\nVALUES\n('LET_ME_IN', (CURRENT_TIMESTAMP + INTERVAL '15 minutes') AT TIME ZONE 'utc');\n```\n\nSQL query to drop the `tokens` table:\n\n```sql\n-- create_tokens down.sql\nDROP TABLE IF EXISTS tokens;\n```\n\nThen we run the new migration with:\n\n```bash\ndiesel migration run\n```\n\nThe above command also has the side-effect of updating the generated Diesel schema file with the new tokens table metadata:\n\n```diff\n// src/schema.rs\n\ntable! {\n    use diesel::sql_types::*;\n    use crate::models::Status_enum;\n\n    boards (id) {\n        id -> Int8,\n        name -> Text,\n        created_at -> Timestamptz,\n    }\n}\n\ntable! {\n    use diesel::sql_types::*;\n    use crate::models::Status_enum;\n\n    cards (id) {\n        id -> Int8,\n        board_id -> Int8,\n        description -> Text,\n        status -> Status_enum,\n        created_at -> Timestamptz,\n    }\n}\n\n+table! {\n+   use diesel::sql_types::*;\n+   use crate::models::Status_enum;\n+\n+   tokens (id) {\n+       id -> Text,\n+       expired_at -> Timestamptz,\n+   }\n+}\n\njoinable!(cards -> boards (board_id));\n\nallow_tables_to_appear_in_same_query!(\n    boards,\n    cards,\n+   tokens,\n);\n```\n\nThen we derive a `diesel::Queryable` impl for the `Token` model:\n\n```diff\n// src/models.rs\n\nuse crate::schema::*;\n\n+// for authentication\n+\n+#[derive(diesel::Queryable)]\n+pub struct Token {\n+    pub id: String,\n+    pub expired_at: chrono::DateTime<chrono::Utc>,\n+}\n\n// other models\n```\n\nAnd then add the following method to our `Db` struct to validate tokens:\n\n```diff\nuse std::env;\n\nuse diesel::prelude::*;\nuse diesel::r2d2;\nuse diesel::PgConnection;\n\nuse crate::models::*;\nuse crate::schema::*;\nuse crate::StdErr;\n\ntype PgPool = r2d2::Pool<r2d2::ConnectionManager<PgConnection>>;\n\npub struct Db {\n    pool: PgPool,\n}\n\nimpl Db {\n    pub fn connect() -> Result<Self, StdErr> {\n        let db_url = env::var(\"DATABASE_URL\")?;\n        let manager = r2d2::ConnectionManager::new(db_url);\n        let pool = r2d2::Pool::new(manager)?;\n        Ok(Db { pool })\n    }\n\n+   // token methods\n+\n+   pub fn validate_token(&self, token_id: &str) -> Result<Token, StdErr> {\n+       let conn = self.pool.get()?;\n+       let token = tokens::table\n+           .filter(tokens::id.eq(token_id))\n+           .filter(tokens::expired_at.ge(diesel::dsl::now))\n+           .first(&conn)?;\n+       Ok(token)\n+   }\n\n    // other methods\n}\n```\n\nWe can implement authentication in Rocket in a couple ways, by using either Rocket middleware or Rocket request guards. The official Rocket docs recommend the latter so let's go with that.\n\nA request guard is any type within a handler's parameters which impls `rocket::request::FromRequest`. So all we have to do is just impl that for `Token` and then add `Token` parameters to all our request handlers and we're golden. Here's the `FromRequest` impl on `Token`:\n\n```rust\nuse rocket::request::{FromRequest, Request, Outcome};\nuse crate::models::Token;\n\nimpl<'a, 'r> FromRequest<'a, 'r> for Token {\n    type Error = &'static str;\n    fn from_request(request: &'a Request<'r>) -> Outcome<Self, Self::Error> {\n        // get request headers\n        let headers = request.headers();\n\n        // check that Authorization header exists\n        let maybe_auth_header = headers.get_one(\"Authorization\");\n        if maybe_auth_header.is_none() {\n            return Outcome::Failure((\n                http::Status::Unauthorized,\n                \"missing Authorization header\",\n            ));\n        }\n\n        // and is well-formed\n        let auth_header = maybe_auth_header.unwrap();\n        let mut auth_header_parts = auth_header.split_ascii_whitespace();\n        let maybe_auth_type = auth_header_parts.next();\n        if maybe_auth_type.is_none() {\n            return Outcome::Failure((\n                http::Status::Unauthorized,\n                \"malformed Authorization header\",\n            ));\n        }\n\n        // and uses the Bearer token authorization method\n        let auth_type = maybe_auth_type.unwrap();\n        if auth_type != \"Bearer\" {\n            return Outcome::Failure((\n                http::Status::BadRequest,\n                \"invalid Authorization type\",\n            ));\n        }\n\n        // and the Bearer token is present\n        let maybe_token_id = auth_header_parts.next();\n        if maybe_token_id.is_none() {\n            return Outcome::Failure((http::Status::Unauthorized, \"missing Bearer token\"));\n        }\n        let token_id = maybe_token_id.unwrap();\n\n        // we can use request.guard::<T>() to get a T from a request\n        // which includes managed application state like our Db\n        let outcome_db = request.guard::<State<Db>>();\n        let db: State<Db> = match outcome_db {\n            Outcome::Success(db) => db,\n            _ => return Outcome::Failure((http::Status::InternalServerError, \"internal error\")),\n        };\n\n        // validate token\n        let token_result = db.validate_token(token_id);\n        match token_result {\n            Ok(token) => Outcome::Success(token),\n            Err(_) => Outcome::Failure((\n                http::Status::Unauthorized,\n                \"invalid or expired Bearer token\",\n            )),\n        }\n    }\n}\n```\n\nNow we add a `Token` parameter to every request handler we want to guard, which is effectively how we implement authentication:\n\n```diff\n// src/routes.rs\n\nuse rocket::http;\nuse rocket::State;\nuse rocket::request::{FromRequest, Request, Outcome};\nuse rocket_contrib::json::Json;\n\nuse crate::db::Db;\nuse crate::models::*;\nuse crate::StdErr;\n\nimpl<'a, 'r> FromRequest<'a, 'r> for Token {\n    type Error = &'static str;\n    fn from_request(request: &'a Request<'r>) -> Outcome<Self, Self::Error> {\n        // impl\n    }\n}\n\n// board routes\n\n#[rocket::get(\"/boards\")]\n-fn boards(db: State<Db>) -> Result<Json<Vec<Board>>, StdErr> {\n+fn boards(db: State<Db>, _t: Token) -> Result<Json<Vec<Board>>, StdErr> {\n    db.boards().map(Json)\n}\n\n#[rocket::post(\"/boards\", data = \"<create_board>\")]\n-fn create_board(db: State<Db>, create_board: Json<CreateBoard>) -> Result<Json<Board>, StdErr> {\n+fn create_board(db: State<Db>, create_board: Json<CreateBoard>, _t: Token) -> Result<Json<Board>, StdErr> {\n    db.create_board(create_board.0).map(Json)\n}\n\n#[rocket::get(\"/boards/<board_id>/summary\")]\n-fn board_summary(db: State<Db>, board_id: i64) -> Result<Json<BoardSummary>, StdErr> {\n+fn board_summary(db: State<Db>, board_id: i64, _t: Token) -> Result<Json<BoardSummary>, StdErr> {\n    db.board_summary(board_id).map(Json)\n}\n\n#[rocket::delete(\"/boards/<board_id>\")]\n- fn delete_board(db: State<Db>, board_id: i64) -> Result<(), StdErr> {\n+ fn delete_board(db: State<Db>, board_id: i64, _t: Token) -> Result<(), StdErr> {\n    db.delete_board(board_id)\n}\n\n// card routes\n\n#[rocket::get(\"/boards/<board_id>/cards\")]\n-fn cards(db: State<Db>, board_id: i64) -> Result<Json<Vec<Card>>, StdErr> {\n+fn cards(db: State<Db>, board_id: i64, _t: Token) -> Result<Json<Vec<Card>>, StdErr> {\n    db.cards(board_id).map(Json)\n}\n\n#[rocket::post(\"/cards\", data = \"<create_card>\")]\n-fn create_card(db: State<Db>, create_card: Json<CreateCard>) -> Result<Json<Card>, StdErr> {\n+fn create_card(db: State<Db>, create_card: Json<CreateCard>, _t: Token) -> Result<Json<Card>, StdErr> {\n    db.create_card(create_card.0).map(Json)\n}\n\n#[rocket::patch(\"/cards/<card_id>\", data = \"<update_card>\")]\nfn update_card(\n    db: State<Db>,\n    card_id: i64,\n    update_card: Json<UpdateCard>,\n+   _t: Token,\n) -> Result<Json<Card>, StdErr> {\n    db.update_card(card_id, update_card.0).map(Json)\n}\n\n#[rocket::delete(\"/cards/<card_id>\")]\n-fn delete_card(db: State<Db>, card_id: i64) -> Result<(), StdErr> {\n+fn delete_card(db: State<Db>, card_id: i64, _t: Token) -> Result<(), StdErr> {\n    db.delete_card(card_id)\n}\n\npub fn api() -> Vec<rocket::Route> {\n    rocket::routes![\n        boards,\n        create_board,\n        board_summary,\n        delete_board,\n        cards,\n        create_card,\n        update_card,\n        delete_card,\n    ]\n}\n```\n\nAmazing. We did it. The full source code for the Diesel + Rocket implementation can be found in the [companion code repository](https://github.com/pretzelhammer/kanban/tree/main/diesel-rocket) for this article. Okay, now let's do it again, except this time we'll implement it in async Rust using sqlx and actix-web.\n\n\n\n## Async Implementation\n\nThis section picks up from the same place as the **Sync Implementation** section does: which is right after we added the `serde` & `serde_json` crates to our project's dependencies and created a `models` module.\n\n\n\n### SQL Schema Migrations w/sqlx-cli\n\ncrates\n- sqlx-cli\n\n```bash\ncargo install sqlx-cli\n```\n\nAgain if this fails it's likely because we're missing some development libraries on our system, we can solve this issue with the following commands:\n\n```bash\n# macOS\nbrew install postgresql\n\n# ubuntu\napt-get install pkg-config libssl-dev postgresql libpq-dev\n```\n\nAnd then we can install sqlx-cli with only support for PostgreSQL:\n\n```bash\ncargo install sqlx-cli --no-default-features --features postgres\n```\n\nAs before, let's create a boards and cards tables:\n\n```bash\nsqlx migrate add create_boards\nsqlx migrate add create_cards\n```\n\nThis creates a `migrations` directory with a couple migration files. Here's the migration file to create the boards table:\n\n```sql\n-- create_boards.sql\nCREATE TABLE IF NOT EXISTS boards (\n    id BIGSERIAL PRIMARY KEY,\n    name TEXT NOT NULL,\n    created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT (CURRENT_TIMESTAMP AT TIME ZONE 'utc')\n);\n\n-- seed db with some test data for local dev\nINSERT INTO boards\n(name)\nVALUES\n('Test board 1'),\n('Test board 2'),\n('Test board 3');\n```\n\nAnd here's the migration file to create the cards table:\n\n```sql\n-- create_cards.sql\nCREATE TYPE STATUS AS ENUM ('todo', 'doing', 'done');\n\nCREATE TABLE IF NOT EXISTS cards (\n    id BIGSERIAL PRIMARY KEY,\n    board_id BIGINT NOT NULL,\n    description TEXT NOT NULL,\n    status STATUS NOT NULL DEFAULT 'todo',\n    created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT (CURRENT_TIMESTAMP AT TIME ZONE 'utc'),\n    CONSTRAINT board_fk\n        FOREIGN KEY (board_id)\n        REFERENCES boards(id)\n        ON DELETE CASCADE\n);\n\n-- seed db with some test data for local dev\nINSERT INTO cards\n(board_id, description, status)\nVALUES\n(1, 'Test card 1', 'todo'),\n(1, 'Test card 2', 'doing'),\n(1, 'Test card 3', 'done'),\n(2, 'Test card 4', 'todo'),\n(2, 'Test card 5', 'todo'),\n(3, 'Test card 6', 'done'),\n(3, 'Test card 7', 'done');\n```\n\nWe run the migrations with:\n\n```bash\nsqlx migrate run\n```\n\n\n\n### Executing SQL Queries w/sqlx\n\ncrates\n- sqlx\n\n```diff\n# Cargo.toml\n\n[package]\nname = \"kanban\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n[dependencies]\ndotenv = \"0.15\"\nchrono = { version = \"0.4\", features = [\"serde\"] }\nlog = \"0.4\"\nfern = \"0.6\"\nserde = { version = \"1.0\", features = [\"derive\"] }\nserde_json = \"1.0\"\n+sqlx = { version = \"0.4\", features = [\"runtime-actix-rustls\", \"chrono\", \"postgres\"] }\n```\n\nSince sqlx is an async library that produces futures those futures have to be executed by a runtime, and actix-web provides a runtime which we're gonna add later, but this is the reason why we added the `runtime-actix-rustls` feature flag.\n\n\n\n#### Fetching Data\n\nWe can impl the `sqlx::FromRow` trait for our `Board` model using a derive macro:\n\n```diff\n// src/models.rs\n\n-#[derive(serde::Serialize)]\n+#[derive(serde::Serialize, sqlx::FromRow)]\n#[serde(rename_all = \"camelCase\")]\npub struct Board {\n    pub id: i64,\n    pub name: String,\n    pub created_at: chrono::DateTime<chrono::Utc>,\n}\n```\n\nThis impl allows us to use `Board` as the returned result of SQL queries. Let's look at some examples:\n\n```rust\nuse sqlx::{Connection, PgConnection};\nuse crate::models::Board;\n\n// example of connecting to PostgreSQL\nasync fn get_connection() -> PgConnection {\n    dotenv::dotenv().unwrap();\n    let db_url = std::env::var(\"DATABASE_URL\").unwrap();\n    PgConnection::connect(&db_url).await.unwrap()\n}\n\n// fetch all boards\nasync fn all_boards(conn: &mut PgConnection) -> Vec<Board> {\n    sqlx::query_as(\"SELECT * FROM boards\")\n        .fetch_all(conn)\n        .await\n        .unwrap()\n}\n\n// fetch all boards in order\nasync fn all_boards_chronological(conn: &mut PgConnection) -> Vec<Board> {\n    sqlx::query_as(\"SELECT * FROM boards ORDER BY created_at ASC\")\n        .fetch_all(conn)\n        .await\n        .unwrap()\n}\n\n// fetch board by primary key\nasync fn board_by_id(conn: &mut PgConnection, board_id: i64) -> Board {\n    sqlx::query_as(\"SELECT * FROM boards WHERE id = $1\")\n        .bind(board_id)\n        .fetch_one(conn)\n        .await\n        .unwrap()\n}\n\n// fetch all boards with a specific exact name\nasync fn board_by_name(conn: &mut PgConnection, board_name: &str) -> Vec<Board> {\n    sqlx::query_as(\"SELECT * FROM boards WHERE name = $1\")\n        .bind(board_name)\n        .fetch_all(conn)\n        .await\n        .unwrap()\n}\n\n// fetch all board whose name contains some string\nasync fn board_name_contains(conn: &mut PgConnection, contains: &str) -> Vec<Board> {\n    // in LIKE queries \"%\" means \"match zero or more of any character\"\n    let contains = format!(\"%{}%\", contains);\n    sqlx::query_as(\"SELECT * FROM boards WHERE name ILIKE $1\")\n        .bind(contains)\n        .fetch_all(conn)\n        .await\n        .unwrap()\n}\n\n// fetch all boards created in the past 24 hours\nasync fn recent_boards(conn: &mut PgConnection) -> Vec<Board> {\n    sqlx::query_as(\"SELECT * FROM boards WHERE created_at >= CURRENT_TIMESTAMP - INTERVAL '1 day'\")\n        .fetch_all(conn)\n        .await\n        .unwrap()\n}\n\n// fetch all boards created in the past 24 hours and whose name also contains some string\nasync fn recent_boards_and_name_contains(conn: &mut PgConnection, contains: &str) -> Vec<Board> {\n    let contains = format!(\"%{}%\", contains);\n    sqlx::query_as(\"SELECT * FROM boards WHERE created_at >= CURRENT_TIMESTAMP - INTERVAL '1 day' AND name ILIKE $1\")\n        .bind(contains)\n        .fetch_all(conn)\n        .await\n        .unwrap()\n}\n\n// fetch all boards created in the past 24 hours or whose name contains some string\nasync fn recent_boards_or_name_contains(conn: &mut PgConnection, contains: &str) -> Vec<Board> {\n    let contains = format!(\"%{}%\", contains);\n    sqlx::query_as(\"SELECT * FROM boards WHERE created_at >= CURRENT_TIMESTAMP - INTERVAL '1 day' OR name ILIKE $1\")\n        .bind(contains)\n        .fetch_all(conn)\n        .await\n        .unwrap()\n}\n```\n\nOkay, let's look at fetching cards now:\n\n```diff\n// src/models.rs\n\n-#[derive(serde::Serialize)]\n+#[derive(serde::Serialize, sqlx::FromRow)]\n#[serde(rename_all = \"camelCase\")]\npub struct Card {\n    pub id: i64,\n    pub board_id: i64,\n    pub description: String,\n    pub status: Status,\n    pub created_at: chrono::DateTime<chrono::Utc>,\n}\n\n-#[derive(serde::Deserialize, serde::Serialize)]\n+#[derive(serde::Deserialize, serde::Serialize, sqlx::Type)]\n#[serde(rename_all = \"camelCase\")]\n+#[sqlx(rename_all = \"camelCase\")]\npub enum Status {\n    Todo,\n    Doing,\n    Done,\n}\n```\n\nWe can derive `sqlx::Type` for a Rust enum to make it map to a DB enum of the same name. In this case we're mapping the `Status` Rust enum to the `STATUS` DB enum type we defined earlier:\n\n```sql\nCREATE TYPE STATUS AS ENUM ('todo', 'doing', 'done');\n```\n\nNow let's look at some card query examples:\n\n```rust\nuse sqlx::{Connection, PgConnection};\nuse crate::models::{Card, Status};\n\n// fetch all cards\nasync fn all_cards(conn: &mut PgConnection) -> Vec<Card> {\n    sqlx::query_as(\"SELECT * FROM cards\")\n        .fetch_all(conn)\n        .await\n        .unwrap()\n}\n\n// fetch cards by board\nasync fn cards_by_board(conn: &mut PgConnection, board_id: i64) -> Vec<Card> {\n    sqlx::query_as(\"SELECT * FROM cards WHERE board_id = $1\")\n        .bind(board_id)\n        .fetch_all(conn)\n        .await\n        .unwrap()\n}\n\n// fetch cards by status\nasync fn cards_by_status(conn: &mut PgConnection, status: Status) -> Vec<Card> {\n    sqlx::query_as(\"SELECT * FROM cards WHERE status = $1\")\n        .bind(status)\n        .fetch_all(conn)\n        .await\n        .unwrap()\n}\n```\n\nOkay, the final select request we need to support is getting the board summary. We first need to add a `From<Vec<(i64, Status)>>` impl for `BoardSummary`:\n\n```rust\n// src/models.rs\n\n#[derive(Default, serde::Serialize)]\npub struct BoardSummary {\n    pub todo: i64,\n    pub doing: i64,\n    pub done: i64,\n}\n\n// convert list of status counts into a board summary\nimpl From<Vec<(i64, Status)>> for BoardSummary {\n    fn from(counts: Vec<(i64, Status)>) -> BoardSummary {\n        let mut summary = BoardSummary::default();\n        for (count, status) in counts {\n            match status {\n                Status::Todo => summary.todo += count,\n                Status::Doing => summary.doing += count,\n                Status::Done => summary.done += count,\n            }\n        }\n        summary\n    }\n}\n```\n\nAnd then the function to fetch the board summary is as simple as:\n\n```rust\n// fetch board summary\nasync fn board_summary(conn: &mut PgConnection, board_id: i64) -> BoardSummary {\n    sqlx::query_as(\n        \"SELECT COUNT(*), status FROM cards WHERE board_id = $1 GROUP BY status\",\n    )\n    .bind(board_id)\n    .fetch_all(conn)\n    .await\n    .unwrap()\n    .into()\n}\n```\n\n\n\n#### Inserting Data\n\nExamples of creating boards and cards:\n\n```rust\n// create board from CreateBoard model\nasync fn create_board(conn: &mut PgConnection, create_board: CreateBoard) -> Board {\n    sqlx::query_as(\"INSERT INTO boards (name) VALUES ($1) RETURNING *\")\n        .bind(create_board.name)\n        .fetch_one(conn)\n        .await\n        .unwrap()\n}\n\n// create card from CreateCard model\nasync fn create_card(conn: &mut PgConnection, create_card: CreateCard) -> Card {\n    sqlx::query_as(\"INSERT INTO cards (board_id, description) VALUES ($1, $2) RETURNING *\")\n        .bind(create_card.board_id)\n        .bind(create_card.description)\n        .fetch_one(conn)\n        .await\n        .unwrap()\n}\n```\n\n\n\n#### Updating Data\n\nExample of updating cards:\n\n```rust\n// update card from UpdateCard model\nasync fn update_card(conn: &mut PgConnection, card_id: i64, update_card: UpdateCard) -> Card {\n    sqlx::query_as(\"UPDATE cards SET description = $1, status = $2 WHERE id = $3 RETURNING *\")\n        .bind(update_card.description)\n        .bind(update_card.status)\n        .bind(card_id)\n        .fetch_one(conn)\n        .await\n        .unwrap()\n}\n```\n\n\n\n#### Deleting Data\n\nExamples of deleting boards and cards:\n\n```rust\n// delete all boards\nasync fn delete_all_boards(conn: &mut PgConnection) {\n    sqlx::query(\"DELETE FROM boards\")\n        .execute(conn)\n        .await\n        .unwrap();\n}\n\n// delete a board by its id\nasync fn delete_board_by_id(conn: &mut PgConnection, board_id: i64) {\n    sqlx::query(\"DELETE FROM boards WHERE id = $1\")\n        .bind(board_id)\n        .execute(conn)\n        .await\n        .unwrap();\n}\n\n// delete all cards\nasync fn delete_all_cards(conn: &mut PgConnection) {\n    sqlx::query(\"DELETE FROM cards\")\n    .execute(conn)\n    .await\n    .unwrap();\n}\n\n// delete a card by its id\nasync fn delete_card_by_id(conn: &mut PgConnection, card_id: i64) {\n    sqlx::query(\"DELETE FROM cards WHERE id = $1\")\n        .bind(card_id)\n        .execute(conn)\n        .await\n        .unwrap();\n}\n\n// delete all of the cards on a board\nasync fn delete_cards_by_board(conn: &mut PgConnection, board_id: i64) {\n    sqlx::query(\"DELETE FROM cards WHERE board_id = $1\")\n        .bind(board_id)\n        .execute(conn)\n        .await\n        .unwrap();\n}\n\n// delete all of the done cards on a board\nasync fn delete_done_cards_by_board(conn: &mut PgConnection, board_id: i64) {\n    sqlx::query(\"DELETE FROM cards WHERE board_id = $1 AND status = 'done'\")\n        .bind(board_id)\n        .execute(conn)\n        .await\n        .unwrap();\n}\n```\n\nYou may have noticed we switched from using `sqlx::query_as` to `sqlx::query`. The difference between the two is that the former attempts to map the result rows into some type which impls `sqlx::FromRow` whereas the latter doesn't, so the latter is more appropriate for `DELETE` queries that don't return any rows.\n\n\n#### Compile-Time Verification of SQL Queries\n\nOne interesting feature of sqlx is that it can verify all of our queries are syntactically and semantically valid at compile-time, but this is behavior we have to opt into by using the `sqlx::query!` and `sqlx::query_as!` macros over the `sqlx::query` and `sqlx::query_as` functions. The downsides of the macros are that they're slightly less ergonomic to use than the regular functions and they will increase compiles but the upsides can greatly outweigh the downsides if we're working in a project with lots of complex queries or many tables and entities. I haven't been using this for this project but they're worth knowing about.\n\n\n\n#### Using a Connection Pool w/sqlx\n\nsqlx comes built-in with a connection pool so we don't have to install any additional dependencies!\n\nHere's how we'd create a pool with the default configuration options:\n\n```rust\nuse sqlx::{Connection, PgConnection, Pool, Postgres};\nuse sqlx::postgres::PgPoolOptions;\n\n// example of connecting to Pg Pool\nasync fn get_pool() -> Pool<Postgres> {\n    dotenv::dotenv().unwrap();\n    let db_url = std::env::var(\"DATABASE_URL\").unwrap();\n    PgPoolOptions::new().connect(&db_url).await.unwrap()\n}\n\nasync fn use_pool(pool: &Pool<Postgres>) {\n    // don't need to fetch connection from pool\n    // can pass pool directly to queries, e.g.\n    sqlx::query_as::<_,(String,)>(\"SELECT version()\")\n        .fetch_one(pool) // passing pool directly\n        .await\n        .unwrap();\n}\n```\n\n\n\n\n#### Refactoring DB Operations Into a Module\n\nLet's clean up our code and neatly put everything into a single module:\n\n```rust\n// src/db.rs\n\nuse sqlx::{Connection, PgConnection, Pool, Postgres, postgres::PgPoolOptions};\nuse crate::models::*;\nuse crate::StdErr;\n\npub struct Db {\n    pool: Pool<Postgres>,\n}\n\nimpl Db {\n    pub async fn connect() -> Result<Self, StdErr> {\n        let db_url = std::env::var(\"DATABASE_URL\")?;\n        let pool = PgPoolOptions::new().connect(&db_url).await?;\n        Ok(Db { pool })\n    }\n\n    pub async fn boards(&self) -> Result<Vec<Board>, StdErr> {\n        let boards = sqlx::query_as(\"SELECT * FROM boards\")\n            .fetch_all(&self.pool)\n            .await?;\n        Ok(boards)\n    }\n\n    pub async fn board_summary(&self, board_id: i64) -> Result<BoardSummary, StdErr> {\n        let counts: Vec<(i64, Status)> = sqlx::query_as(\n            \"SELECT count(*), status FROM cards WHERE board_id = $1 GROUP BY status\",\n        )\n        .bind(board_id)\n        .fetch_all(&self.pool)\n        .await?;\n        Ok(counts.into())\n    }\n\n    pub async fn create_board(&self, create_board: CreateBoard) -> Result<Board, StdErr> {\n        let board = sqlx::query_as(\"INSERT INTO boards (name) VALUES ($1) RETURNING *\")\n            .bind(&create_board.name)\n            .fetch_one(&self.pool)\n            .await?;\n        Ok(board)\n    }\n\n    pub async fn delete_board(&self, board_id: i64) -> Result<(), StdErr> {\n        sqlx::query(\"DELETE FROM boards WHERE id = $1\")\n            .bind(board_id)\n            .execute(&self.pool)\n            .await?;\n        Ok(())\n    }\n\n    pub async fn cards(&self, board_id: i64) -> Result<Vec<Card>, StdErr> {\n        let cards = sqlx::query_as(\"SELECT * FROM cards WHERE board_id = $1\")\n            .bind(board_id)\n            .fetch_all(&self.pool)\n            .await?;\n        Ok(cards)\n    }\n\n    pub async fn create_card(&self, create_card: CreateCard) -> Result<Card, StdErr> {\n        let card =\n            sqlx::query_as(\"INSERT INTO cards (board_id, description) VALUES ($1, $2) RETURNING *\")\n                .bind(&create_card.board_id)\n                .bind(&create_card.description)\n                .fetch_one(&self.pool)\n                .await?;\n        Ok(card)\n    }\n\n    pub async fn update_card(&self, card_id: i64, update_card: UpdateCard) -> Result<Card, StdErr> {\n        let card = sqlx::query_as(\n            \"UPDATE cards SET description = $1, status = $2 WHERE id = $3 RETURNING *\",\n        )\n        .bind(&update_card.description)\n        .bind(&update_card.status)\n        .bind(card_id)\n        .fetch_one(&self.pool)\n        .await?;\n        Ok(card)\n    }\n\n    pub async fn delete_card(&self, card_id: i64) -> Result<(), StdErr> {\n        sqlx::query(\"DELETE FROM cards WHERE id = $1\")\n            .bind(card_id)\n            .execute(&self.pool)\n            .await?;\n        Ok(())\n    }\n}\n```\n\nUpdated main file:\n\n```diff\n// src/main.rs\n\n+mod db;\nmod logger;\nmod models;\n\ntype StdErr = Box<dyn std::error::Error>;\n\nfn main() -> Result<(), StdErr> {\n    dotenv::dotenv()?;\n    logger::init()?;\n\n    Ok(())\n}\n```\n\n\n\n\n### HTTP Routing w/actix-web\n\ncrates\n- actix-web\n\n```diff\n# Cargo.toml\n\n[package]\nname = \"kanban\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n[dependencies]\ndotenv = \"0.15\"\nchrono = { version = \"0.4\", features = [\"serde\"] }\nlog = \"0.4\"\nfern = \"0.6\"\nserde = { version = \"1.0\", features = [\"derive\"] }\nserde_json = \"1.0\"\nsqlx = { version = \"0.4\", features = [\"runtime-actix-rustls\", \"chrono\", \"postgres\"] }\n+ actix-web = \"3.3\"\n```\n\nLet's throw together a quick actix-web hello world example into our main:\n\n```diff\nmod db;\nmod logger;\nmod models;\n\ntype StdErr = Box<dyn std::error::Error>;\n\n+#[actix_web::get(\"/\")]\n+async fn hello_world() -> &'static str {\n+    \"Hello, world!\"\n+}\n\n+#[actix_web::main]\n-fn main() -> Result<(), StdErr> {\n+async fn main() -> Result<(), StdErr> {\n    dotenv::dotenv().ok();\n    logger::init()?;\n\n+   actix_web::HttpServer::new(move || actix_web::App::new().service(hello_world))\n+       .bind((\"127.0.0.1\", 8000))?\n+       .run()\n+       .await?;\n\n    Ok(())\n}\n```\n\nWe have to make our main function async and decorate it with the `actix_web::main` procedural macro to tell actix-web to start a runtime and execute our main function as the first task.\n\n\n\n#### Routing Basics\n\nWe can decorate functions with actix-web's procedural macros to route incoming HTTP requests:\n\n```rust\n#[actix_web::get(\"/\")]\nasync fn index() -> &'static str {\n    \"I'm the index route!\"\n}\n\n#[actix_web::get(\"/nested/route\")]\nasync fn nested_route() -> &'static str {\n    \"I'm a nested route!\"\n}\n```\n\nData can be extracted from the path using `{param}` placeholders:\n\n```rust\nuse actix_web::web::Path;\n\n#[actix_web::get(\"/hello/{name}\")]\nasync fn greet(Path(name): Path<String>) -> String {\n    format!(\"Hello, {}!\", name)\n}\n```\n\nAny type which impls `serde::Deserialize` can be extracted from within `actix_web::web::Path`:\n\n```rust\n// actix_web::web::Path can extract anything out of the\n// URL path as long as it impls serde::Deserialize\n#[actix_web::get(\"/echo/{string}/{num}/{maybe}/etc\")]\nasync fn echo_path(Path((string, num, maybe)): Path<(String, usize, bool)>) -> String {\n    format!(\"got string {}, num {}, and maybe {}\", string, num, maybe)\n}\n\n// custom type example\nstruct EvenNumber(i32);\n\n// hand-written deserialize impl, mostly deferring to i32::deserialize\nimpl<'de> Deserialize<'de> for EvenNumber {\n    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>\n    where\n        D: serde::Deserializer<'de>,\n    {\n        let value = i32::deserialize(deserializer)?;\n        if value % 2 == 0 {\n            Ok(EvenNumber(value))\n        } else {\n            Err(D::Error::custom(\"not even\"))\n        }\n    }\n}\n\n// but now we can extract EvenNumbers directly from the Path:\n#[actix_web::get(\"/even/{even_num}\")]\nasync fn echo_even(Path(even_num): Path<EvenNumber>) -> String {\n    format!(\"got even number {}\", even_num.0)\n}\n```\n\nThe response type can be anything that impls `actix_web::Responder`:\n\n```rust\nuse std::future::{ready, Ready};\nuse actix_web::{HttpResponse, HttpRequest};\nuse actix_web::error::InternalError;\n\n// actix_web provides Responder impls for\n// - &'static str\n// - &'static [u8]\n// - String\n// - &String\n// - some other misc types\n// have to use actix_files to get Responder impls for\n// - Files\n#[actix_web::get(\"/cargo\")]\nasync fn returns_cargo() -> actix_files::NamedFile {\n    actix_files::NamedFile::open(\"Cargo.toml\").unwrap()\n}\n\ntype ActixError = actix_web::error::Error;\n\n// actix_web also provides Responder impls for\n// - Option<T> where T: Responder\n//     - returns T if Some(T), 404 Not Found if None\n// - Result<T, E> where T: Responder, E: Into<ActixError>\n//     - returns T if Ok(T), otherwise ActixError::from(e) if Err(e)\n\n// example custom type\nstruct EvenNumber(i32);\n\n// example Responder impl\nimpl Responder for EvenNumber {\n    type Error = InternalError<&'static str>;\n    type Future = Ready<Result<HttpResponse, Self::Error>>;\n\n    fn respond_to(self, _req: &HttpRequest) -> Self::Future {\n        let res = HttpResponse::Ok()\n            .set_header(\"X-Number-Parity\", \"Even\")\n            .body(format!(\"returning even number {}\", self.0));\n        ready(Ok(res))\n    }\n}\n\n// returning custom defined type\n#[actix_web::get(\"/even\")]\nasync fn returns_even() -> EvenNumber {\n    EvenNumber(2)\n}\n```\n\n\n\n#### GET Requests\n\nWe have to pass our `Db` to our actix-web request handlers. We can do this is by passing an instance of the `Db` to the `data` method of the actix-web application factory function, and then we can receive it in our request handlers using the `actix_web::web::Data` extractor.\n\nSince the application factory function creates an application per system thread, the data referenced inside the factory has to be cloneable, so we first have to impl `Clone` for `Db` which is easy since `Pool<Postgres>` already impls `Clone` so we can just derive it:\n\n```diff\n// src/db.rs\n\nuse sqlx::{Pool, Postgres};\n\n+#[derive(Clone)]\npub struct Db {\n    pool: Pool<Postgres>,\n}\n\n// etc\n```\n\nAnd then this is how we'd update our main file:\n\n```diff\n// src/main.rs\n\nmod db;\nmod logger;\nmod models;\nmod routes;\n\ntype StdErr = Box<dyn std::error::Error>;\n\n#[actix_web::get(\"/\")]\nasync fn hello_world() -> &'static str {\n    \"Hello, world!\"\n}\n\n#[actix_web::main]\nasync fn main() -> Result<(), StdErr> {\n    dotenv::dotenv().ok();\n    logger::init()?;\n\n+   let db = db::Db::connect().await?;\n\n    actix_web::HttpServer::new(move || {\n        actix_web::App::new()\n+           .data(db.clone())\n            .service(hello_world)\n    })\n    .bind((\"127.0.0.1\", 8000))?\n    .run()\n    .await?;\n\n    Ok(())\n}\n```\n\nAnd here's how we'd use the `Data` extractor to receive the `Db` instance in our request handlers:\n\n```rust\nuse actix_web::web::Data;\nuse crate::db::Db;\n\n#[actix_web::get(\"/use/db\")]\nfn use_db(db: Data<Db>) {\n    // use db\n}\n```\n\nWe can automatically return JSON by wrapping the return type in `actix_web::web::Json` which impls `actix_web::Responder` and will serialize the wrapped type to JSON using serde and set the response header `Content-Type: application/json`. Example:\n\n```rust\nuse actix_web::web::Json;\nuse crate::models::Status;\n\n#[actix_web::get(\"/example/json\")]\nfn return_json() -> Json<Status> {\n    Json(Status::Todo)\n}\n```\n\nFurthermore, because actix-web does not impl `Responder` for `Box<dyn std::error::Error>` we have to wrap it with some type which does, and we can use the generic `actix_web::error::InternalError` type for this purpose:\n\n```rust\nuse actix_web::error::InternalError;\nuse actix_web::http::StatusCode;\nuse crate::StdErr;\n\nfn some_fallible_function() -> Result<&'static str, StdErr> {\n    todo!()\n}\n\n// map StdErr to an error that impls Responder\nfn to_internal_error(e: StdErr) -> InternalError<StdErr> {\n    InternalError::new(e, StatusCode::INTERNAL_SERVER_ERROR)\n}\n\n#[actix_web::get(\"/error\")]\nasync fn return_error() -> Result<&'static str, InternalError<StdErr>> {\n    some_falliable_function().map_err(to_internal_error)\n}\n```\n\nOkay, we now have enough context to write all of our GET request handlers:\n\n```rust\nuse actix_web::web::{Data, Json};\nuse actix_web::error::InternalError;\nuse actix_web::http::StatusCode;\n\nuse crate::StdErr;\nuse crate::db::Db;\nuse crate::models::{Board, Card, BoardSummary};\n\n// convenience functions\n\nfn to_internal_error(e: StdErr) -> InternalError<StdErr> {\n    InternalError::new(e, StatusCode::INTERNAL_SERVER_ERROR)\n}\n\n// GET requests\n\n#[actix_web::get(\"/boards\")]\nasync fn boards(db: Data<Db>) -> Result<Json<Vec<Board>>, InternalError<StdErr>> {\n    db.boards()\n        .await\n        .map(Json)\n        .map_err(to_internal_error)\n}\n\n#[actix_web::get(\"/boards/{board_id}/summary\")]\nasync fn board_summary(\n    db: Data<Db>,\n    Path(board_id): Path<i64>,\n) -> Result<Json<BoardSummary>, InternalError<StdErr>> {\n    db.board_summary(board_id)\n        .await\n        .map(Json)\n        .map_err(to_internal_error)\n}\n\n#[actix_web::get(\"/boards/{board_id}/cards\")]\nasync fn cards(\n    db: Data<Db>,\n    Path(board_id): Path<i64>,\n) -> Result<Json<Vec<Card>>, InternalError<StdErr>> {\n    db.cards(board_id)\n        .await\n        .map(Json)\n        .map_err(to_internal_error)\n}\n```\n\n\n\n#### POST & PATCH Requests\n\n`actix_web::web::Json` not only impls `actix_web::Responder` but also impls `actix_web::FromRequest` which means we can add it as a function parameter to any request handler and actix-web will attempt deserialize the request's JSON body into the type we specify, so here's how we'd write the POST & PATCH request handlers:\n\n```rust\nuse actix_web::web::{Data, Json};\nuse actix_web::error::InternalError;\nuse actix_web::http::StatusCode;\n\nuse crate::StdErr;\nuse crate::db::Db;\nuse crate::models::{Board, Card, CreateBoard, CreateCard};\n\n// convenience functions\n\nfn to_internal_error(e: StdErr) -> InternalError<StdErr> {\n    InternalError::new(e, StatusCode::INTERNAL_SERVER_ERROR)\n}\n\n// POST requests\n\n#[actix_web::post(\"/boards\")]\nasync fn create_board(\n    db: Data<Db>,\n    create_board: Json<CreateBoard>,\n) -> Result<Json<Board>, InternalError<StdErr>> {\n    db.create_board(create_board.0)\n        .await\n        .map(Json)\n        .map_err(to_internal_error)\n}\n\n#[actix_web::post(\"/cards\")]\nasync fn create_card(\n    db: Data<Db>,\n    create_card: Json<CreateCard>,\n) -> Result<Json<Card>, InternalError<StdErr>> {\n    db.create_card(create_card.0)\n        .await\n        .map(Json)\n        .map_err(to_internal_error)\n}\n\n// PATCH requests\n\n#[actix_web::patch(\"/cards/{card_id}\")]\nasync fn update_card(\n    db: Data<Db>,\n    Path(card_id): Path<i64>,\n    update_card: Json<UpdateCard>,\n) -> Result<Json<Card>, InternalError<StdErr>> {\n    db.update_card(card_id, update_card.0)\n        .await\n        .map(Json)\n        .map_err(to_internal_error)\n}\n```\n\n\n\n#### DELETE Requests\n\nThe DELETE request handlers:\n\n```rust\nuse actix_web::web::{Data, Json};\nuse actix_web::error::InternalError;\nuse actix_web::http::StatusCode;\n\nuse crate::StdErr;\nuse crate::db::Db;\n\n// some convenience functions\n\nfn to_internal_error(e: StdErr) -> InternalError<StdErr> {\n    InternalError::new(e, StatusCode::INTERNAL_SERVER_ERROR)\n}\n\nfn to_ok(_: ()) -> HttpResponse {\n    HttpResponse::new(StatusCode::OK)\n}\n\n// DELETE requests\n\n#[actix_web::delete(\"/boards/{board_id}\")]\nasync fn delete_board(\n    db: Data<Db>,\n    Path(board_id): Path<i64>,\n) -> Result<HttpResponse, InternalError<StdErr>> {\n    db.delete_board(board_id)\n        .await\n        .map(to_ok)\n        .map_err(to_internal_error)\n}\n\n#[actix_web::delete(\"/cards/{card_id}\")]\nasync fn delete_card(\n    db: Data<Db>,\n    Path(card_id): Path<i64>,\n) -> Result<HttpResponse, InternalError<StdErr>> {\n    db.delete_card(card_id)\n        .await\n        .map(to_ok)\n        .map_err(to_internal_error)\n}\n```\n\n\n\n#### Refactoring API Routes Into a Module\n\nLet's clean up the code and put all of the API routes into their own module:\n\n```rust\n// src/routes.rs\n\nuse actix_web::web::{Data, Json, Path};\nuse actix_web::http::StatusCode;\nuse actix_web::error::InternalError;\nuse actix_web::dev::HttpServiceFactory;\nuse actix_web::{HttpResponse, Responder};\n\nuse crate::StdErr;\nuse crate::db::Db;\nuse crate::models::*;\n\n// some convenience functions\n\nfn to_internal_error(e: StdErr) -> InternalError<StdErr> {\n    InternalError::new(e, StatusCode::INTERNAL_SERVER_ERROR)\n}\n\nfn to_ok(_: ()) -> HttpResponse {\n    HttpResponse::new(StatusCode::OK)\n}\n\n// board routes\n\n#[actix_web::get(\"/boards\")]\nasync fn boards(db: Data<Db>) -> Result<Json<Vec<Board>>, InternalError<StdErr>> {\n    db.boards()\n        .await\n        .map(Json)\n        .map_err(to_internal_error)\n}\n\n#[actix_web::post(\"/boards\")]\nasync fn create_board(\n    db: Data<Db>,\n    create_board: Json<CreateBoard>,\n) -> Result<Json<Board>, InternalError<StdErr>> {\n    db.create_board(create_board.0)\n        .await\n        .map(Json)\n        .map_err(to_internal_error)\n}\n\n#[actix_web::get(\"/boards/{board_id}/summary\")]\nasync fn board_summary(\n    db: Data<Db>,\n    Path(board_id): Path<i64>,\n) -> Result<Json<BoardSummary>, InternalError<StdErr>> {\n    db.board_summary(board_id)\n        .await\n        .map(Json)\n        .map_err(to_internal_error)\n}\n\n#[actix_web::delete(\"/boards/{board_id}\")]\nasync fn delete_board(\n    db: Data<Db>,\n    Path(board_id): Path<i64>,\n) -> Result<HttpResponse, InternalError<StdErr>> {\n    db.delete_board(board_id)\n        .await\n        .map(to_ok)\n        .map_err(to_internal_error)\n}\n\n// card routes\n\n#[actix_web::get(\"/boards/{board_id}/cards\")]\nasync fn cards(\n    db: Data<Db>,\n    Path(board_id): Path<i64>,\n) -> Result<Json<Vec<Card>>, InternalError<StdErr>> {\n    db.cards(board_id)\n        .await\n        .map(Json)\n        .map_err(to_internal_error)\n}\n\n#[actix_web::post(\"/cards\")]\nasync fn create_card(\n    db: Data<Db>,\n    create_card: Json<CreateCard>,\n) -> Result<Json<Card>, InternalError<StdErr>> {\n    db.create_card(create_card.0)\n        .await\n        .map(Json)\n        .map_err(to_internal_error)\n}\n\n#[actix_web::patch(\"/cards/{card_id}\")]\nasync fn update_card(\n    db: Data<Db>,\n    Path(card_id): Path<i64>,\n    update_card: Json<UpdateCard>,\n) -> Result<Json<Card>, InternalError<StdErr>> {\n    db.update_card(card_id, update_card.0)\n        .await\n        .map(Json)\n        .map_err(to_internal_error)\n}\n\n#[actix_web::delete(\"/cards/{card_id}\")]\nasync fn delete_card(\n    db: Data<Db>,\n    Path(card_id): Path<i64>,\n) -> Result<HttpResponse, InternalError<StdErr>> {\n    db.delete_card(card_id)\n        .await\n        .map(to_ok)\n        .map_err(to_internal_error)\n}\n\n// single public function which returns all of the API request handlers\n\npub fn api() -> impl HttpServiceFactory + 'static {\n    actix_web::web::scope(\"/api\")\n        .service(boards)\n        .service(board_summary)\n        .service(create_board)\n        .service(delete_board)\n        .service(cards)\n        .service(create_card)\n        .service(update_card)\n        .service(delete_card)\n}\n```\n\nUpdated main file:\n\n```diff\n// src/main.rs\n\nmod db;\nmod logger;\nmod models;\n+mod routes;\n\ntype StdErr = Box<dyn std::error::Error>;\n\n#[actix_web::get(\"/\")]\nasync fn hello_world() -> &'static str {\n    \"Hello, world!\"\n}\n\n#[actix_web::main]\nasync fn main() -> Result<(), StdErr> {\n    dotenv::dotenv().ok();\n    logger::init()?;\n\n    let db = db::Db::connect().await?;\n\n    actix_web::HttpServer::new(move || {\n        actix_web::App::new()\n            .data(db.clone())\n            .service(hello_world)\n+           .service(routes::api())\n    })\n    .bind((\"127.0.0.1\", 8000))?\n    .run()\n    .await?;\n\n    Ok(())\n}\n```\n\n\n\n#### Authentication\n\nLet's now implement token-based authentication by checking the `Authorization` HTTP header in requests.\n\nGenerating a new migration:\n\n```bash\nsqlx migrate add create_tokens\n```\n\nThe create `tokens` table query:\n\n```sql\n-- create_tokens.sql\nCREATE TABLE IF NOT EXISTS tokens (\n    id TEXT PRIMARY KEY,\n    expired_at TIMESTAMP WITH TIME ZONE NOT NULL\n);\n\n-- seed db with some local test data\nINSERT INTO tokens\n(id, expired_at)\nVALUES\n('LET_ME_IN', (CURRENT_TIMESTAMP + INTERVAL '15 minutes') AT TIME ZONE 'utc');\n```\n\nCreating our `Token` model:\n\n```diff\n// src/models.rs\n\n+// for authentication\n+\n+#[derive(sqlx::FromRow)]\n+pub struct Token {\n+    pub id: String,\n+    pub expired_at: chrono::DateTime<chrono::Utc>,\n+}\n\n// other models\n```\n\nValidating tokens using our `Db`:\n\n```diff\nuse sqlx::{postgres::PgPoolOptions, Connection, PgConnection, Pool, Postgres};\nuse crate::models::*;\nuse crate::StdErr;\n\n#[derive(Clone)]\npub struct Db {\n    pool: Pool<Postgres>,\n}\n\nimpl Db {\n    pub async fn connect() -> Result<Self, StdErr> {\n        let db_url = std::env::var(\"DATABASE_URL\")?;\n        let pool = PgPoolOptions::new().connect(&db_url).await?;\n        Ok(Db { pool })\n    }\n\n+   // token methods\n+\n+   pub async fn validate_token<T: AsRef<str>>(&self, token_id: T) -> Result<Token, StdErr> {\n+       let token_id = token_id.as_ref();\n+       let token = sqlx::query_as(\"SELECT * FROM tokens WHERE id = $1 AND expired_at > current_timestamp\")\n+           .bind(token_id)\n+           .fetch_one(&self.pool)\n+           .await?;\n+       Ok(token)\n+   }\n\n    // other methods\n}\n```\n\nThere's a couple ways we can implement authentication in actix-web. We can implement it as middleware or as an extractor. Extractors are the actix-web equivalent to Rocket's request guards, and since we implemented authentication using a request guard in Rocket, let's use an extractor for actix-web.\n\nSince everything in actix-web is async, including the `actix_web::FromRequest` method signature, let's add the `futures` crate to our project for some handy utility future traits and functions:\n\n```diff\n# Cargo.toml\n\n[package]\nname = \"kanban\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n[dependencies]\ndotenv = \"0.15\"\nchrono = { version = \"0.4\", features = [\"serde\"] }\nlog = \"0.4\"\nfern = \"0.6\"\nserde = { version = \"1.0\", features = [\"derive\"] }\nserde_json = \"1.0\"\nsqlx = { version = \"0.4\", features = [\"runtime-actix-rustls\", \"chrono\", \"postgres\"] }\nactix-web = \"3.3\"\n+futures = \"0.3.14\"\n```\n\nOkay, so here's the `actix_web::FromRequest` impl for `Token`:\n\n```rust\nuse std::future::Ready;\nuse std::pin::Pin;\n\nuse actix_web::{FromRequest, HttpRequest};\nuse actix_web::http::StatusCode;\nuse actix_web::error::InternalError;\nuse actix_web::dev::Payload;\nuse futures::{future, Future, FutureExt};\n\nuse crate::StdErr;\nuse crate::db::Db;\nuse crate::models::Token;\n\nimpl FromRequest for Token {\n    type Error = InternalError<&'static str>;\n    type Config = ();\n\n    // we return a Future that is either\n    // - immediately ready (on a bad request with a missing or malformed Authorization header)\n    // - ready later (pending on a SQL query that validates the request's Bearer token)\n    type Future = future::Either<\n        future::Ready<Result<Self, Self::Error>>,\n        Pin<Box<dyn Future<Output = Result<Self, Self::Error>> + 'static>>,\n    >;\n\n    fn from_request(req: &HttpRequest, _payload: &mut Payload) -> Self::Future {\n        // get request headers\n        let headers = req.headers();\n\n        // check that Authorization header exists\n        let maybe_auth = headers.get(\"Authorization\");\n        if maybe_auth.is_none() {\n            return future::err(InternalError::new(\n                \"missing Authorization header\",\n                StatusCode::BAD_REQUEST,\n            ))\n            .left_future();\n        }\n\n        // check Authorization header is valid utf-8\n        let auth_config = maybe_auth.unwrap().to_str();\n        if auth_config.is_err() {\n            return future::err(InternalError::new(\n                \"malformed Authorization header\",\n                StatusCode::BAD_REQUEST,\n            ))\n            .left_future();\n        }\n\n        // check Authorization header specifies some authorization strategy\n        let mut auth_config_parts = auth_config.unwrap().split_ascii_whitespace();\n        let maybe_auth_type = auth_config_parts.next();\n        if maybe_auth_type.is_none() {\n            return future::err(InternalError::new(\n                \"missing Authorization type\",\n                StatusCode::BAD_REQUEST,\n            ))\n            .left_future();\n        }\n\n        // check that authorization strategy is using a bearer token\n        let auth_type = maybe_auth_type.unwrap();\n        if auth_type != \"Bearer\" {\n            return future::err(InternalError::new(\n                \"unsupported Authorization type\",\n                StatusCode::BAD_REQUEST,\n            ))\n            .left_future();\n        }\n\n        // check that bearer token is present\n        let maybe_token_id = auth_config_parts.next();\n        if maybe_token_id.is_none() {\n            return future::err(InternalError::new(\n                \"missing Bearer token\",\n                StatusCode::BAD_REQUEST,\n            ))\n            .left_future();\n        }\n\n        // we can fetch managed application data using HttpRequest.app_data::<T>()\n        let db = req.app_data::<Data<Db>>();\n        if db.is_none() {\n            return future::err(InternalError::new(\n                \"internal error\",\n                StatusCode::INTERNAL_SERVER_ERROR,\n            ))\n            .left_future();\n        }\n\n        // clone these so that we can return an impl Future + 'static\n        let db = db.unwrap().clone();\n        let token_id = maybe_token_id.unwrap().to_owned();\n\n        async move {\n            db.validate_token(token_id)\n                .await\n                .map_err(|_| InternalError::new(\"invalid Bearer token\", StatusCode::UNAUTHORIZED))\n        }\n        .boxed_local()\n        .right_future()\n    }\n}\n```\n\nUpdated routes file:\n\n```diff\nuse std::pin::Pin;\n\nuse actix_web::{FromRequest, HttpRequest, HttpResponse};\nuse actix_web::web::{Data, Json, Path};\nuse actix_web::http::StatusCode;\nuse actix_web::error::InternalError;\nuse actix_web::dev::{HttpServiceFactory, Payload};\nuse futures::{Future, FutureExt, future};\n\nuse crate::StdErr;\nuse crate::db::Db;\nuse crate::models::*;\n\nimpl FromRequest for Token {\n    type Error = InternalError<&'static str>;\n    type Config = ();\n    type Future = future::Either<\n        future::Ready<Result<Self, Self::Error>>,\n        Pin<Box<dyn Future<Output = Result<Self, Self::Error>> + 'static>>,\n    >;\n\n    fn from_request(req: &HttpRequest, _payload: &mut Payload) -> Self::Future {\n       // impl\n    }\n}\n\n// some convenience functions\n\nfn to_internal_error(e: StdErr) -> InternalError<StdErr> {\n    InternalError::new(e, StatusCode::INTERNAL_SERVER_ERROR)\n}\n\nfn to_ok(_: ()) -> HttpResponse {\n    HttpResponse::new(StatusCode::OK)\n}\n\n// board routes\n\n#[actix_web::get(\"/boards\")]\nasync fn boards(\n    db: Data<Db>,\n+   _t: Token\n) -> Result<Json<Vec<Board>>, InternalError<StdErr>> {\n    db.boards()\n        .await\n        .map(Json)\n        .map_err(to_internal_error)\n}\n\n#[actix_web::post(\"/boards\")]\nasync fn create_board(\n    db: Data<Db>,\n    create_board: Json<CreateBoard>,\n+   _t: Token,\n) -> Result<Json<Board>, InternalError<StdErr>> {\n    db.create_board(create_board.0)\n        .await\n        .map(Json)\n        .map_err(to_internal_error)\n}\n\n#[actix_web::get(\"/boards/{board_id}/summary\")]\nasync fn board_summary(\n    db: Data<Db>,\n    Path(board_id): Path<i64>,\n+   _t: Token,\n) -> Result<Json<BoardSummary>, InternalError<StdErr>> {\n    db.board_summary(board_id)\n        .await\n        .map(Json)\n        .map_err(to_internal_error)\n}\n\n#[actix_web::delete(\"/boards/{board_id}\")]\nasync fn delete_board(\n    db: Data<Db>,\n    Path(board_id): Path<i64>,\n+   _t: Token,\n) -> Result<HttpResponse, InternalError<StdErr>> {\n    db.delete_board(board_id)\n        .await\n        .map(to_ok)\n        .map_err(to_internal_error)\n}\n\n// card routes\n\n#[actix_web::get(\"/boards/{board_id}/cards\")]\nasync fn cards(\n    db: Data<Db>,\n    Path(board_id): Path<i64>,\n+   _t: Token,\n) -> Result<Json<Vec<Card>>, InternalError<StdErr>> {\n    db.cards(board_id)\n        .await\n        .map(Json)\n        .map_err(to_internal_error)\n}\n\n#[actix_web::post(\"/cards\")]\nasync fn create_card(\n    db: Data<Db>,\n    create_card: Json<CreateCard>,\n+   _t: Token,\n) -> Result<Json<Card>, InternalError<StdErr>> {\n    db.create_card(create_card.0)\n        .await\n        .map(Json)\n        .map_err(to_internal_error)\n}\n\n#[actix_web::patch(\"/cards/{card_id}\")]\nasync fn update_card(\n    db: Data<Db>,\n    Path(card_id): Path<i64>,\n    update_card: Json<UpdateCard>,\n+   _t: Token,\n) -> Result<Json<Card>, InternalError<StdErr>> {\n    db.update_card(card_id, update_card.0)\n        .await\n        .map(Json)\n        .map_err(to_internal_error)\n}\n\n#[actix_web::delete(\"/cards/{card_id}\")]\nasync fn delete_card(\n    db: Data<Db>,\n    Path(card_id): Path<i64>,\n+   _t: Token,\n) -> Result<HttpResponse, InternalError<StdErr>> {\n    db.delete_card(card_id)\n        .await\n        .map(to_ok)\n        .map_err(to_internal_error)\n}\n\npub fn api() -> impl HttpServiceFactory + 'static {\n    actix_web::web::scope(\"/api\")\n        .service(boards)\n        .service(board_summary)\n        .service(create_board)\n        .service(delete_board)\n        .service(cards)\n        .service(create_card)\n        .service(update_card)\n        .service(delete_card)\n}\n```\n\nWe did it! Again! Look at us go, we're implementation machines! The full source code for the sqlx + actix-web implementation can be found in the [companion code repository](https://github.com/pretzelhammer/kanban/tree/main/sqlx-actix-web) for this article.\n\nSince we have two identical RESTful API servers but with two different implementations let's benchmark them and see which is faster :)\n\n\n\n## Benchmarks\n\n\n\n### Servers\n\nI don't normally benchmark RESTful API servers so I don't know what \"good performance\" is and what \"bad performance\" is. Aside from comparing the Diesel + Rocket server to the sqlx + actix-web server I've decided to throw in a couple node.js servers to make things more interesting. The full source code for the benchmarks as well as all the servers can be found in the [companion code repository](https://github.com/pretzelhammer/kanban) for this article. Here's a list of the servers we will be benchmarking:\n\nServer #1: Diesel + Rocket\n- Nickname: DR\n- Connection pool: r2d2\n- SQL executor: Diesel\n- HTTP routing: Rocket\n- Compiled with: Rust v1.53 (Nightly)\n\nServer #2: sqlx + actix-web\n- Nickname: SA\n- Connection pool: sqlx\n- SQL executor: sqlx\n- HTTP Routing: actix-web\n- Compiled with: Rust v1.53 (Nightly)\n\nServer #3: pg-promise + express.js (single process)\n- Nickname: PES\n- Connection pool: pg-promise\n- SQL executor: pg-promise\n- HTTP Routing: express.js\n- Interpreted with: node.js v16.0.0\n- Mode: single process\n\nServer #4: pg-promise + express.js (multi process)\n- Nickname: PEM\n- Connection pool: pg-promise\n- SQL executor: pg-promise\n- HTTP Routing: express.js\n- Interpreted with: node.js v16.0.0\n- Mode: multi process \n\nTest Machine: DigitalOcean VPS\n- OS: Ubuntu 20.04 (LTS)\n- CPU: 2.3 GHz 4-core Intel\n- Memory: 8 GB\n\nSince almost everyone builds and ships web servers to the cloud nowadays I decided to run all the benchmarks on a DigitalOcean VPS.\n\n\n\n### Methodology\n\nThe tools we're going to use for benchmarking and profiling are vegeta and psutil. Vegeta is an HTTP load testing command line tool written in Go. We can give it a list of targets, a duration, and a number of workers and it will pummel the targets for the given duration using the given number of workers while recording statistics like the number of requests successfully processed, their response times, their status codes, and so on. Psutil is a Python library that we can use to easily write a script that queries the system every second to check how much CPU and memory a process is using.\n\nLet's run all of the HTTP load tests for 60 seconds and use up to a max of 40 workers. Vegeta will naturally scale the workers if the HTTP server can handle the load. Also, let's use two different sets of targets, the first set is going to represent a read-only (RO) workload and the second set is going to represent a more realistic reads + writes (RW) workload.\n\nHere's the RO workload target list:\n\n```none\nGET http://localhost:8000/api/boards\nAuthorization: Bearer LET_ME_IN\n\nGET http://localhost:8000/api/boards/1/summary\nAuthorization: Bearer LET_ME_IN\n\nGET http://localhost:8000/api/boards/1/cards\nAuthorization: Bearer LET_ME_IN\n```\n\nHere's the RW workload target list:\n\n```none\nGET http://localhost:8000/api/boards\nAuthorization: Bearer LET_ME_IN\n\nGET http://localhost:8000/api/boards/1/summary\nAuthorization: Bearer LET_ME_IN\n\nPOST http://localhost:8000/api/boards\nAuthorization: Bearer LET_ME_IN\nContent-Type: application/json\n@post-board.json\n\nDELETE http://localhost:8000/api/boards/10000\nAuthorization: Bearer LET_ME_IN\n\nGET http://localhost:8000/api/boards/1/cards\nAuthorization: Bearer LET_ME_IN\n\nPOST http://localhost:8000/api/cards\nAuthorization: Bearer LET_ME_IN\nContent-Type: application/json\n@post-card.json\n\nPATCH http://localhost:8000/api/cards/1\nAuthorization: Bearer LET_ME_IN\nContent-Type: application/json\n@patch-card.json\n\nDELETE http://localhost:8000/api/cards/10000\nAuthorization: Bearer LET_ME_IN\n```\n\nAnd here are the test JSON payloads:\n\n```js\n// post-board.json\n{\"name\": \"Vegeta Stress Test Board\"}\n\n// post-card.json\n{\"boardId\": 3, \"description\": \"Vegeta Stress Test Card\"}\n\n// patch-card.json\n{\"description\": \"Vegeta Stress Update Card\", \"status\": \"doing\"}\n```\n\nOf course we're going to compile the Rust servers with this command:\n\n```bash\nRUSTFLAGS=\"-C target-cpu=native\" cargo build --release\n```\n\nAnd with this release profile:\n\n```toml\n[profile.release]\ndebug = 0\nlto = true\ncodegen-units = 1\npanic = \"abort\"\n```\n\nAlso, let's disable the logging in the Rust servers for the benchmarks because I didn't bother adding any logging to the node.js servers. And finally, I ran the benchmarks a few times a day over the course of a couple days and took the best results for every individual server and benchmark.\n\n\n\n### Measuring Resource Usage\n\nI'm going to measure CPU usage in CPU seconds and memory usage in megabytes. Everyone knows what megabytes are so I'm not going to explain those, but not everyone is familiar with CPU seconds and they're kinda weird so let's discuss those now.\n\nWhen people say \"CPU second\" what they really mean is \"CPU logical core second.\" For example, a CPU with 16 logical cores can perform 16 CPU seconds of processing for every second of wall clock time. This is why when you open the process manager tool in your operating system of choice you'll occasionally see it report some processes as using over 100% CPU. This makes no sense, as it's not possible to use more than 100% of anything, but it's reported this way because the percent is calculated based on the processing power of a single logical core of the CPU and not the total processing power of the entire CPU. For example, a process running on a CPU with 4 logical cores can use up to \"400%\" of the CPU. Yup, it's dumb, but whatever, now you know.\n\n\n\n### Results\n\nAs a quick reminder, the servers we're benchmarking:\n- DR: Diesel + Rocket\n- SA: sqlx + actix-web\n- PES: pg-promise + express.js (single process)\n- PEM: pg-promise + express.js (multi process)\n\nThe workloads we're using for the benchmarks:\n- Read-only (RO) workload for 60 seconds with up to 40 workers\n- Reads + Writes (RW) workload for 60 seconds with up to 40 workers\n\nThe stats we're tracking:\n- Total requests processed\n- How many of the requests were successful (return 200 status code)\n- CPU usage (in CPU seconds)\n- Memory usage (in megabytes)\n\nAnd we're running these benchmarks on a DigitalOcean VPS with:\n- OS: Ubuntu 20.04 (LTS)\n- CPU: 2.3 GHz 4-core Intel\n- Memory: 8 GB\n\nDisclaimer: Like I said before, I don't normally benchmark anything so it's likely I may have gotten some things wrong or biased the tests toward one server or another, so don't take the results below as proof of anything, they're more for entertainment than anything else.\n\n\n\n#### Read-Only Workload\n\n**Request Throughput**\n\nAbsolute measurements\n\n| Server | Total Requests | Successful Requests | Success Rate | Successful Requests per Second |\n|-|-|-|-|-|\n| **DR** | 171431 req | 171431 req | 100% 🥇 | 2857 req/sec |\n| **SA** | 275803 req 🥇 | 275803 req 🥇 | 100% 🥇 | 4567 req/sec 🥇 |\n| **PES** | 115708 req | 115708 req | 100% 🥇 | 1928 req/sec |\n| **PEM** | 190624 req | 190624 req | 100% 🥇 | 3177 req/sec |\n\nRelative measurements\n\n| Server | Total Requests | Successful Requests | Success Rate | Successful Requests per Second |\n|-|-|-|-|-|\n| **DR** | 0.62x | 0.62x | 1.00x 🥇 | 0.62x |\n| **SA** | 1.00x 🥇 | 1.00x 🥇 | 1.00x 🥇 | 1.00x 🥇 |\n| **PES** | 0.42x | 0.42x | 1.00x 🥇 | 0.42x |\n| **PEM** | 0.69x | 0.69x | 1.00x 🥇 | 0.69x |\n\n**Request Latencies**\n\nAbsolute measurements\n\n| Server | Min | Avg | 50th percentile | 90th percentile | 95th percentile | 99th percentile | Max |\n|-|-|-|-|-|-|-|-|\n| **DR** | 856 µs | 11.5 ms | 10.3 ms | 19.9 ms | 23.4 ms | 32.0 ms | 109.6 ms 🥇 |\n| **SA** | 830 µs 🥇 | 8.6 ms 🥇 | 7.4 ms 🥇 | 14.5 ms 🥇 | 17.7 ms 🥇 | 26.2 ms 🥇 | 191.1 ms |\n| **PES** | 7.5 ms | 20.7 ms | 19.8 ms | 28.0 ms | 31.4 ms | 39.6 ms | 182.0 ms |\n| **PEM** | 889 µs | 12.6 ms | 10.7 ms | 23.4 ms | 28.8 ms | 41.7 ms | 214.2 ms |\n\nRelative measurements\n\n| Server | Min | Avg | 50th percentile | 90th percentile | 95th percentile | 99th percentile | Max |\n|-|-|-|-|-|-|-|-|\n| **DR** | 1.03x | 1.34x | 1.39x | 1.37x | 1.32x | 1.22x | 1.00x 🥇 |\n| **SA** | 1.00x 🥇 | 1.00x 🥇 | 1.00x 🥇 | 1.00x 🥇 | 1.00x 🥇 | 1.00x 🥇 | 1.74x |\n| **PES** | 9.04x | 2.41x | 2.68x | 1.93x | 1.77x | 1.51x | 1.66x |\n| **PEM** | 1.07x | 1.47x | 1.45x | 1.61x | 1.63x | 1.59x | 1.95x |\n\n**Resource Usage**\n\nAbsolute measurements\n\n| Server | Total CPU Seconds | Avg CPU Seconds per Second | Avg CPU Seconds per Successful Request | Max Memory Used |\n|-|-|-|-|-|\n| **DR** | 44.49 cpu 🥇 | 0.74 cpu/sec 🥇 | 0.00026 cpu/req | 14.2 MB |\n| **SA** | 68.77 cpu | 1.15 cpu/sec | 0.00025 cpu/req 🥇 | 10.6 MB 🥇 |\n| **PES** | 52.64 cpu | 0.88 cpu/sec | 0.00045 cpu/req | 117.5 MB |\n| **PEM** | 123.60 cpu | 2.06 cpu/sec | 0.00065 cpu/req | 476.8 MB |\n\nRelative measurements\n\n| Server | Total CPU Seconds | Avg CPU Seconds per Second | Avg CPU Seconds per Successful Request | Max Memory Used |\n|-|-|-|-|-|\n| **DR** | 1.00x 🥇 | 1.00x 🥇 | 1.04x | 1.34x |\n| **SA** | 1.55x | 1.55x | 1.00x 🥇 | 1.00x 🥇 |\n| **PES** | 1.18x | 1.18x | 1.80x | 11.08x |\n| **PEM** | 2.78x | 2.78x | 2.60x | 44.98x |\n\n\nThe DR server had a request throughput of 2857 req/sec with an average response latency of 11.5 ms, an average CPU utilization of 0.74 cpu/sec, and used 14.2 MB of memory. All of that sounds pretty solid to me!\n\nThe SA server had a request throughput of 4567 req/sec, which is 160% the performance of the DR server! The SA server had an average response latency of 7.4 ms, an average CPU utilization of 1.15 cpu/sec, and used 10.6 MB of memory. So it used a bit more CPU than the DR server but a bit less memory.\n\nThe PES server had a request throughput of 1928 req/sec. Not as performant as the Rust servers, but I suppose that's to be expected because node.js is a single-threaded process so it can't take advantage of all 4 cores on the test machine to process multiple requests in parallel. PES had an average response latency of 20.7 ms which is pretty good but it's double that of the Rust servers. PES had an average CPU utilization of 0.88 cpu/sec which is similar to the Rust servers but because its request throughput was so much lower it actually took 0.00045 cpu/req which is almost double the Rust servers. PES also used 117.5 MB which is a lot but it's expected since it's node.js. In short: PES took roughly ~2x as much CPU and ~10x as much memory to only get ~0.5x of the performance of the Rust servers.\n\nThe PEM server had a request throughput of 3177 req/sec with an average response latency of 12.6 ms which is competitive with the Rust servers. Where it stops being competitive is in its resource usage, consuming an average of 2.06 cpu/sec and 476.8 MB of memory, which is signcantly higher than all the other servers.\n\n\n\n#### Reads + Writes Workload\n\n**Request Throughput**\n\nAbsolute measurements\n\n| Server | Total Requests | Successful Requests | Success Rate | Successful Requests per Second |\n|-|-|-|-|-|\n| **DR** | 88778 req 🥇 | 74021 req 🥇 | 83% | 1234 req/sec 🥇 |\n| **SA** | 62362 req | 62362 req | 100% 🥇 | 1039 req/sec |\n| **PES** | 31683 req | 31683 req | 100% 🥇 | 528 req/sec |\n| **PEM** | 56380 req | 56380 req | 100% 🥇 | 940 req/sec |\n\nRelative measurements\n\n| Server | Total Requests | Successful Requests | Success Rate | Successful Requests per Second |\n|-|-|-|-|-|\n| **DR** | 1.00x 🥇 | 1.00x 🥇 | 0.83x | 1.00x 🥇 |\n| **SA** | 0.70x | 0.84x | 1.00x 🥇 | 0.84x |\n| **PES** | 0.36x | 0.43x | 1.00x 🥇 | 0.43x |\n| **PEM** | 0.64x | 0.76x | 1.00x 🥇 | 0.76x |\n\n**Request Latencies**\n\nAbsolute measurements\n\n| Server | Min | Avg | 50th percentile | 90th percentile | 95th percentile | 99th percentile | Max |\n|-|-|-|-|-|-|-|-|\n| **DR** | 31 µs 🥇 | 19.4 ms 🥇 | 15.2 ms 🥇 | 40.4 ms 🥇 | 51.4 ms 🥇 | 79.3 ms 🥇 | 277.5 ms |\n| **SA** | 829 µs | 38.3 ms | 33.4 ms | 80.7 ms | 94.7 ms | 125.6 ms | 236.9 ms 🥇 |\n| **PES** | 10.4 ms | 75.9 ms | 55.3 ms | 106.5 ms | 274.3 ms | 448.7 ms | 573.4 ms |\n| **PEM** | 2.0 ms | 42.6 ms | 25.4 ms | 87.9 ms | 151.2 ms | 325.1 ms | 668.3 ms |\n\nRelative measurements\n\n| Server | Min | Avg | 50th percentile | 90th percentile | 95th percentile | 99th percentile | Max |\n|-|-|-|-|-|-|-|-|\n| **DR** | 1.00x 🥇 | 1.00x 🥇 | 1.00x 🥇 | 1.00x 🥇 | 1.00x 🥇 | 1.00x 🥇 | 1.17x |\n| **SA** | 26.74x | 1.97x | 2.20x | 2.00x | 1.84x | 1.584x | 1.00x 🥇 |\n| **PES** | 335.48x | 3.91x | 3.64x | 2.64x | 5.34x | 5.66x | 2.42x |\n| **PEM** | 64.52x | 2.20x | 1.67x | 2.18x | 2.94x | 4.10x | 2.82x |\n\n**Resource Usage**\n\nAbsolute measurements\n\n| Server | Total CPU Seconds | Avg CPU Seconds per Second | Avg CPU Seconds per Successful Request | Max Memory Used |\n|-|-|-|-|-|\n| **DR** | 67.17 cpu | 1.12 cpu/sec | 0.00091 cpu/req 🥇 | 97.8 MB |\n| **SA** | 149.11 cpu | 2.49 cpu/sec | 0.00239 cpu/req | 45.3 MB 🥇 |\n| **PES** | 59.11 cpu 🥇 | 0.99 cpu/sec 🥇 | 0.00187 cpu/req | 154.5 MB |\n| **PEM** | 163.38 cpu | 2.72 cpu/sec | 0.00290 cpu/req | 571.4 MB |\n\nRelative measurements\n\n| Server | Total CPU Seconds | Avg CPU Seconds per Second | Avg CPU Seconds per Successful Request | Max Memory Used |\n|-|-|-|-|-|\n| **DR** | 1.14x | 1.14x | 1.00x 🥇 | 2.16x |\n| **SA** | 2.52x | 2.52x | 2.63x | 1.00x 🥇 |\n| **PES** | 1.00x 🥇 | 1.00x 🥇 | 2.05x | 3.41x |\n| **PEM** | 2.76x | 2.76x | 3.19x | 12.61x |\n\nI was expecting these results to be a repeat of the previous results but slower but to my surprise they came out very differently! Request throughputs went down across the board. CPU utilization, memory utilization, and average response latencies went up across the board.\n\nFor starters, the DR server is the only server which failed to successfully process all requests, but despite that it still had the highest request throughput at 1234 req/sec! Technically it has the best performance but if I was working with a server that dropped 1 out of 5 requests I would be very annoyed.\n\nThe SA server had a request throughput of 1039 req/sec which is 84% the performance of the DR server, but it at least processed all request successfully, so I'm not sure which is better in practice. I was sure after the first benchmark that actix-web was faster than Rocket, but now I'm not so sure. It's possible the difference in these results might be caused by Diesel having better performance for write queries than sqlx. I'm just speculating here, don't take anything I say too seriously. SA used ~2.6x as much CPU but ~0.5x as much memory as DR.\n\nNothing too interesting to say about the node.js servers in this benchmark, similarly to the previous benchmark they used a lot more CPU and memory to get worse performance relative to the Rust servers.\n\n\n\n## Concluding Thoughts\n\n\n\n### Diesel vs sqlx\n\nI'm gonna be upfront about my biases here: I love SQL and I hate ORMs.\n\nIn my opinion, SQL is already an amazing abstraction. It's high-level, elegant, declarative, flexible, composable, intuitive, and powerful. ORMs which attempt to abstract over SQL rarely capture all of these qualities, and usually the result is an underpowered, inflexible, leaky API that gives users the ability to perform only a small fraction of the queries that they could more easily and concisely express in SQL.\n\nWhat I like about Diesel v1.4:\n- diesel-cli is really nice, especially for authoring, running, and reverting migrations.\n- The derive macros `diesel::Queryable`, `diesel::QueryableByName`, `diesel::Insertable`, and `diesel::AsChangeSet` are pretty nice.\n\nWhere I think Diesel v1.4 could improve:\n- More guides would be nice, I think it's a bit strange that associations are not covered in any guide and the only way to learn about that feature is to stumble across it in the API docs.\n- More logging would be nice, if I set the log level to `TRACE` I see nothing from Diesel.\n- Something like a `diesel_contrib` crate, similar to how Rocket has `rocket` for core stuff and `rocket_contrib` for commonly requested nice-to-haves, would be great. It was not fun having to find and use an unofficial 3rd-party crate just to map DB enums to Rust enums.\n- Almost all popular Rust libraries use macros, but Diesel especially seems to use a ton. It's still unclear to me why there needs to be a `diesel::Queryable` and a `diesel::QueryableByName` macro, as those seem like they can be consolidated. Also, if the generated Diesel schema file is not suppose to be edited by hand, why does it use macros at all? Why not just generate the code the macros would generate in the first place?\n- Diesel overall felt underwhelming compared to feature-rich and batteries-included ORMs available in other languages. I think calling Diesel an \"ORM\" probably falsely expectations for a lot of users, or at least it did for me. I've seen similar libraries in other languages call themselves \"micro ORMs\" or \"query builders\" which I think would be much more appropriate descriptions for Diesel.\n- No support for async/await and because the implementation seems to be blocked by some Rust compiler bug that nobody is interested in fixing it seems like async/await is not going to come to Diesel any time soon.\n\nWhat I like about sqlx v0.4:\n- Lets me just write and run SQL, which is what I want to do in the first place anyway.\n- The derive macros `sqlx::FromRow` and `sqlx::Type` are really nice.\n- Logs every executed query, how many rows it returned, and how long the query took at an `INFO` level. Very nice!\n\nWhere I think sqlx v0.4 can improve:\n- More documentation please! The docs on sqlx-cli especially are almost nonexistent.\n- Please add all of diesel-cli's migration-related functionality to sqlx-cli, including the ability to revert migrations.\n- Derive macros similar to `diesel::Insertable` and `diesel::AsChangeSet` which I could use to decorate structs and then pass those structs as-is to the `bind` method of parameterized queries would be pretty nice.\n\nThe benchmarks we performed above were probably skewed a lot by Rocket and actix-web, so it's not really fair to use them to compare Diesel and sqlx. If you would like to see the results of detailed benchmarks run specifically to profile Diesel and sqlx then you can find [the results for those here](https://github.com/diesel-rs/metrics/) and [the source code for them here](https://github.com/diesel-rs/diesel/tree/master/diesel_bench). Disclaimer: this benchmark suite is maintained by the Diesel team.\n\n\n\n### Rocket vs actix-web\n\nWhat I like about Rocket v0.4:\n- Super good DX (developer experience)!\n- Amazing documentation!\n- Amazing logs!\n- Procedural macros check that all path and data parameters are used in the request handler function!\n- All of the guard-related traits are great: `FromRequest`, `FromParam`, `FromData`, and so on.\n\nWhere I think Rocket v0.4 can improve:\n- Please get off nightly Rust and use stable Rust. (Note: this is coming in Rocket v0.5)\n- Please support async/await. (Note: this is coming in Rocket v0.5)\n\nWhat I like about actix-web v3.3:\n- Good documentation.\n- Using procedural macros to decorate request handlers is optional and there's a non-macro API.\n\nWhere I think actix-web v3.3 can improve:\n- Providing a `Responder` impl for `()` that returns `204 No Content` would be really nice.\n- Providing a `ResponseError` impl for `E where E: std::error::Error` that returns `500 Server Error` and prints the error message on debug builds and prints a generic error message on release builds would be really nice.\n- Please log more, like way more! Even when I set the logging level to `TRACE` the logs were still almost useless when it came to helping me debug issues.\n- On one hand, the `FromRequest` impl on `Path<T> where T: DeserializeOwned` is lowkey brilliant, but on the other hand if the type is not trivially deserializable (e.g. any situation where a member has to be validated) then it's hostile to users who have never written a `serde::Deserialize` impl by hand before, which is most users.\n\n\n\n### Sync Rust vs Async Rust\n\nWe didn't really get into \"advanced\" async programming in this article, and in a way that's a good thing! One of the big selling points of introducing the `async` and `await` keywords to Rust is that it would make async programming as simple and straight-forward as sync programming, and I believe they delivered on that promise in this project given how similar the async implementation was to the sync implementation.\n\nAlthough with that said, while async Rust _can be_ as simple as sync Rust, it also can be way more complicated! I wasn't completely forthcoming or transparent about all of my struggles in this article, but writing the `actix_web::FromRequest` impl for `Token` was really, really hard. There were also some things I tried to do in the async implementation that never made it into the article because I just couldn't get them to compile. While I believe this is _partially_ due to my own inexperience with async programming Rust, I also think the async stuff is just inherently harder and more complex. I'd like to tackle all of these things head-on so I'll probably write an _\"Advanced Async Patterns in Rust\"_ article or something like that in the future.\n\n\n\n### Rust vs JS\n\nI noticed I _feel_ very productive in Rust because I'm making a lot of decisions, but most of the time most of the decisions are unrelated to solving the problem at hand, so my _actual_ progress and productivity is kinda low. I'm well past the newbie stage so I rarely have issues with lifetimes or borrowing anymore, but like I mentioned above: working with futures and async Rust can still be really challenging.\n\nThe one big thing I missed from Rust when re-writing the RESTful API servers in JS was the static type checking, but that's not really an argument for Rust, it's more of an argument for TypeScript. One of my personal takeaways from this project is that I should probably learn TypeScript. \n\n\n\n### In Summary\n\nIn the future, if I find myself writing another RESTful API server in Rust, I'm definitely going to use sqlx over Diesel, but this is to satisfy my own personal preferences, I don't think Diesel is a bad choice at all for those would prefer using an ORM over SQL.\n\nIf I had to pick a web framework right now I'd probably pick Rocket, because although actix-web seems to have better performance Rocket wins in almost every other possible metric: documentation, logging, easy-to-use APIs, and overall developer friendliness. I'm eagerly awaiting the release of Rocket v0.5, which should fix all the issues I have with Rocket v0.4, including improving the performance which hopefully will put it on par with actix-web.\n\n\n\n## Discuss\n\nDiscuss this article on\n- [Github](https://github.com/pretzelhammer/rust-blog/discussions)\n- [learnrust subreddit](https://www.reddit.com/r/learnrust/comments/nanar9/restful_api_in_sync_async_rust/)\n- [official Rust users forum](https://users.rust-lang.org/t/blog-post-restful-api-in-sync-async-rust/59713)\n- [rust subreddit](https://www.reddit.com/r/rust/comments/nnp6j4/restful_api_in_sync_async_rust/)\n\n\n## Further Reading\n\n- [Common Rust Lifetime Misconceptions](./common-rust-lifetime-misconceptions.md)\n- [Tour of Rust's Standard Library Traits](./tour-of-rusts-standard-library-traits.md)\n- [Beginner's Guide to Concurrent Programming: Coding a Multithreaded Chat Server using Tokio](./chat-server.md)\n- [Learning Rust in 2024](./learning-rust-in-2024.md)\n- [Using Rust in Non-Rust Servers to Improve Performance](./rust-in-non-rust-servers.md)\n- [Sizedness in Rust](./sizedness-in-rust.md)\n- [Learn Assembly with Entirely Too Many Brainfuck Compilers](./too-many-brainfuck-compilers.md)\n\n\n\n## Notifications\n\nGet notified when a new blog post gets published by\n- Subscribing to this repo's [releases RSS feed](https://github.com/pretzelhammer/rust-blog/releases.atom) or\n- Watching this repo's releases (click `Watch` → click `Custom` → select `Releases` → click `Apply`)\n"
  },
  {
    "path": "posts/rust-in-non-rust-servers.md",
    "content": "\n\n# Using Rust in Non-Rust Servers to Improve Performance\n_22 October 2024 · #rust · #wasm · #ffi · #performance_\n\n\n\n**Table of contents**\n- [Intro](#intro)\n- [The strategies](#the-strategies)\n    - [Tier 0: No Rust](#tier-0-no-rust)\n    - [Tier 1: Rust CLI Tool](#tier-1-rust-cli-tool)\n    - [Tier 2: Rust Wasm Module](#tier-2-rust-wasm-module)\n        - [Wasm bindings by hand](#wasm-bindings-by-hand)\n    - [Tier 3: Rust Native Function](#tier-3-rust-native-function)\n    - [Tier 4: Rust Rewrite](#tier-4-rust-rewrite)\n- [Concluding thoughts](#concluding-thoughts)\n- [Discuss](#discuss)\n- [Further reading](#further-reading)\n- [Notifications](#notifications)\n\n\n\n## Intro\n\nIn this article I'll discuss different strategies for incrementally adding Rust into a server written in another language, such as JavaScript, Python, Java, Go, PHP, Ruby, etc. The main reason why you'd want to do this is because you've profiled your server, identified a hot function which is not meeting your performance requirements because it's bottlenecked by the CPU, and the usual techniques of memoizing the function or improving its algorithm wouldn't be feasible or effective in this situation for whatever reason. You have come to the conclusion that it would be worth investigating swapping out the function implementation for something written in a more CPU-efficient language, like Rust. Great, then this is definitely the article for you.\n\nThe strategies are ordered in tiers, where \"tier\" is short for \"tier of Rust adoption.\" The first tier would be not using Rust at all. The last tier would be rewriting the entire server in Rust.\n\nThe example server which we'll be applying and benchmarking the strategies on will be implemented in JS, running on the Node.js runtime. The strategies can be generalized to any other language or runtime though.\n\n> [!NOTE]\n> The full source code for every example in this article can be found in [this repository](https://github.com/pretzelhammer/using-rust-in-non-rust-servers).\n\n\n\n## The strategies\n\n\n\n### Tier 0: No Rust\n\nLet's say we have a Node.js server with an HTTP endpoint that takes a string of text as a query parameter and returns a 200px by 200px PNG image of the text encoded as a QR code.\n\nHere's what the server code would look like:\n\n```js\nconst express = require('express');\nconst generateQrCode = require('./generate-qr.js');\n\nconst app = express();\napp.get('/qrcode', async (req, res) => {\n    const { text } = req.query;\n\n    if (!text) {\n        return res.status(400).send('missing \"text\" query param');\n    }\n\n    if (text.length > 512) {\n        return res.status(400).send('text must be <= 512 bytes');\n    }\n\n    try {\n        const qrCode = await generateQrCode(text);\n        res.setHeader('Content-Type', 'image/png');\n        res.send(qrCode);\n    } catch (err) {\n        res.status(500).send('failed generating QR code');\n    }\n});\n\napp.listen(42069, '127.0.0.1');\n```\n\nAnd here's what the hot function would look like:\n\n```js\nconst QRCode = require('qrcode');\n\n/**\n * @param {string} text - text to encode\n * @returns {Promise<Buffer>|Buffer} - qr code\n */\nmodule.exports = function generateQrCode(text) {\n    return QRCode.toBuffer(text, {\n        type: 'png',\n        errorCorrectionLevel: 'L',\n        width: 200,\n        rendererOpts: {\n            // these options were chosen since\n            // they offered the best balance\n            // between speed and compression\n            // during testing\n            deflateLevel: 9, // 0 - 9\n            deflateStrategy: 3, // 1 - 4\n        },\n    });\n};\n```\n\nWe can hit that endpoint by calling:\n\n```\nhttp://localhost:42069/qrcode?text=https://www.reddit.com/r/rustjerk/top/?t=all\n```\n\nWhich will correctly produce this QR code PNG:\n\n![QR code for rustjerk subreddit](../assets/rustjerk-subreddit-qr-code.png)\n\nAnyway, let's throw tens of thousands of requests at this server for 30 seconds and see how it performs:\n\n| Tier | Throughput | Avg Latency | p99 Latency | Avg Response | Memory |\n|-|-|-|-|-|-|\n| Tier 0 | 1464 req/sec | 68 ms | 96 ms | 1506 bytes | 1353 MB |\n\nSince I haven't described my benchmarking methodology these results are meaningless on their own, we can't say whether this is \"good\" or \"bad\" performance. That's okay, since we don't care about the absolute numbers, we're going to use these results as a baseline to compare all of the following implementations against. Every server is tested in the same environment so relative comparisons will be accurate.\n\nRegarding the abnormally high memory usage, it's because I'm running Node.js in \"cluster mode\", which spawns 12 processes for each of the 12 CPU cores on my test machine, and each process is a standalone Node.js instance which is why it takes up 1300+ MB of memory even though we have a very simple server. JS is single-threaded so this is what we have to do if we want a Node.js server to make full use of a multi-core CPU.\n\n\n\n### Tier 1: Rust CLI Tool\n\nFor this strategy we rewrite the hot function in Rust, compile it as a standalone CLI tool, and then call it from our host server.\n\nLet's start by rewriting the function in Rust:\n\n```rust\n/** qr_lib/lib.rs **/\n\nuse qrcode::{QrCode, EcLevel};\nuse image::Luma;\nuse image::codecs::png::{CompressionType, FilterType, PngEncoder};\n\npub type StdErr = Box<dyn std::error::Error>;\n\npub fn generate_qr_code(text: &str) -> Result<Vec<u8>, StdErr> {\n    let qr = QrCode::with_error_correction_level(text, EcLevel::L)?;\n    let img_buf = qr.render::<Luma<u8>>()\n        .min_dimensions(200, 200)\n        .build();\n    let mut encoded_buf = Vec::with_capacity(512);\n    let encoder = PngEncoder::new_with_quality(\n        &mut encoded_buf,\n        // these options were chosen since\n        // they offered the best balance\n        // between speed and compression\n        // during testing\n        CompressionType::Default,\n        FilterType::NoFilter,\n    );\n    img_buf.write_with_encoder(encoder)?;\n    Ok(encoded_buf)\n}\n```\n\nThen let's make it a CLI tool:\n\n```rust\n/** qr_cli/main.rs **/\n\nuse std::{env, process};\nuse std::io::{self, BufWriter, Write};\nuse qr_lib::StdErr;\n\nfn main() -> Result<(), StdErr> {\n    let mut args = env::args();\n    if args.len() != 2 {\n        eprintln!(\"Usage: qr-cli <text>\");\n        process::exit(1);\n    }\n\n    let text = args.nth(1).unwrap();\n    let qr_png = qr_lib::generate_qr_code(&text)?;\n\n    let stdout = io::stdout();\n    let mut handle = BufWriter::new(stdout.lock());\n    handle.write_all(&qr_png)?;\n\n    Ok(())\n}\n```\n\nWe can use this CLI like so:\n\n```bash\nqr-cli https://youtu.be/cE0wfjsybIQ?t=74 > crab-rave.png\n```\n\nWhich correctly produces this QR code PNG:\n\n![QR code for crab rave youtube video](../assets/crab-rave-qr-code.png)\n\nNow let's update the hot function in our host server to call this CLI:\n\n```js\nconst { spawn } = require('child_process');\nconst path = require('path');\nconst qrCliPath = path.resolve(__dirname, './qr-cli');\n\n/**\n * @param {string} text - text to encode\n * @returns {Promise<Buffer>} - qr code\n */\nmodule.exports = function generateQrCode(text) {\n    return new Promise((resolve, reject) => {\n        const qrCli = spawn(qrCliPath, [text]);\n        const qrCodeData = [];\n        qrCli.stdout.on('data', (data) => {\n            qrCodeData.push(data);\n        });\n        qrCli.stderr.on('data', (data) => {\n            reject(new Error(`error generating qr code: ${data}`));\n        });\n        qrCli.on('error', (err) => {\n            reject(new Error(`failed to start qr-cli ${err}`));\n        });\n        qrCli.on('close', (code) => {\n            if (code === 0) {\n                resolve(Buffer.concat(qrCodeData));\n            } else {\n                reject(new Error('qr-cli exited unsuccessfully'));\n            }\n        });\n    });\n};\n```\n\nNow let's see how this change affected performance:\n\nAbsolute measurements\n\n| Tier | Throughput | Avg Latency | p99 Latency | Avg Response | Memory |\n|-|-|-|-|-|-|\n| Tier 0 | 1464 req/sec | 68 ms | 96 ms | 1506 bytes | 1353 MB |\n| Tier 1 | 2572 req/sec 🥇 | 39 ms 🥇 | 78 ms 🥇 | 778 bytes 🥇 | 1240 MB 🥇 |\n\nRelative measurements\n\n| Tier | Throughput | Avg Latency | p99 Latency | Avg Response | Memory |\n|-|-|-|-|-|-|\n| Tier 0 | 1.00x | 1.00x | 1.00x | 1.00x | 1.00x |\n| Tier 1 | 1.76x 🥇 | 0.57x 🥇 | 0.82x 🥇 | 0.52x 🥇 | 0.92x 🥇 |\n\nWow, I was not expecting throughput to increase by 76%! This is a very caveman-brain strategy so it's funny to see that it was that effective. Average response size also halved from 1506 bytes to 778 bytes, the compression algo in the Rust library must be better than the one in the JS library. We're serving significantly more requests per second and returning significantly smaller responses, so I'd say this is a great result.\n\n\n\n### Tier 2: Rust Wasm Module\n\nFor this strategy we'll compile the Rust function into a Wasm module, and then load and run it from the host server using a Wasm runtime. Some links to Wasm runtimes across different languages:\n\n| Language | Wasm runtime | Github stars |\n|-|-|-|\n| JavaScript | built-in | - |\n| Multiple | [Wasmer](https://github.com/wasmerio/wasmer) | 19.2K+ |\n| Multiple | [Wasmtime](https://github.com/bytecodealliance/wasmtime) | 15.7K+ |\n| Multiple | [WasmEdge](https://github.com/WasmEdge/WasmEdge) | 8.7K+ |\n| Multiple | [wasm3](https://github.com/wasm3/wasm3) | 7.4k+ |\n| Go | [Wazero](https://github.com/tetratelabs/wazero) | 5.1k+ |\n| Multiple | [Extism](https://github.com/extism/extism) | 4.6k+ |\n| Java | [Chicory](https://github.com/dylibso/chicory) | 560+ |\n\nSince we're integrating into a Node.js server let's use `wasm-bindgen` to generate the glue code that our Rust Wasm code and our JS code will use to interact with each other.\n\nHere's the updated Rust code:\n\n```rust\n/** qr_wasm_bindgen/lib.rs **/\n\nuse wasm_bindgen::prelude::*;\n\n#[wasm_bindgen(js_name = generateQrCode)]\npub fn generate_qr_code(text: &str) -> Result<Vec<u8>, JsError> {\n    qr_lib::generate_qr_code(text)\n        .map_err(|e| JsError::new(&e.to_string()))\n}\n```\n\nAfter compiling that code using `wasm-pack`, we can copy the built assets over to our Node.js server and use them in the hot function like this:\n\n```js\nconst wasm = require('./qr_wasm_bindgen.js');\n\n/**\n * @param {string} text - text to encode\n * @returns {Buffer} - QR code\n */\nmodule.exports = function generateQrCode(text) {\n    return Buffer.from(wasm.generateQrCode(text));\n};\n```\n\nUpdated benchmarks:\n\nAbsolute measurements\n\n| Tier | Throughput | Avg Latency | p99 Latency | Avg Response | Memory |\n|-|-|-|-|-|-|\n| Tier 0 | 1464 req/sec | 68 ms | 96 ms | 1506 bytes | 1353 MB |\n| Tier 1 | 2572 req/sec | 39 ms | 78 ms | 778 bytes 🥇 | 1240 MB 🥇 |\n| Tier 2 | 2978 req/sec 🥇 | 34 ms 🥇 | 63 ms 🥇 | 778 bytes 🥇 | 1286 MB |\n\nRelative measurements\n\n| Tier | Throughput | Avg Latency | p99 Latency | Avg Response | Memory |\n|-|-|-|-|-|-|\n| Tier 0 | 1.00x | 1.00x | 1.00x | 1.00x | 1.00x |\n| Tier 1 | 1.76x | 0.57x | 0.82x | 0.52x 🥇 | 0.92x 🥇 |\n| Tier 2 | 2.03x 🥇 | 0.50x 🥇 | 0.66x 🥇 | 0.52x 🥇 | 0.95x |\n\nUsing Wasm doubled our throughput compared to the baseline! However the jump in performance compared to the earlier caveman-brain strategy of calling a CLI tool is smaller than I would have expected.\n\nAnyway, while `wasm-bindgen` is an excellent JS to Rust Wasm binding generator there's no equivalent of it for other languages such as Python, Java, Go, PHP, Ruby, etc. I don't want to leave those folks out to dry, so I'll explain how to write the bindings by hand. Disclaimer: the code is going to get ugly, so unless you're really interested in seeing how the sausage is made you can just skip over the next section.\n\n\n\n#### Wasm bindings by hand\n\nThe funny thing about Wasm is that it only supports four data types: `i32`, `i64`, `f32`, and `f64`. Yet for our use-case we need to pass a string from the host to a Wasm function, and the Wasm function needs to return an array to the host. Wasm doesn't have strings or arrays. So how are we supposed to solve this problem?\n\nThe answer hinges on having a couple insights:\n- The Wasm module's memory is shared between the Wasm instance and the host, both can read and modify it.\n- A Wasm module can only request up to 4GB of memory, so every possible memory address can be encoded as an `i32`, so this data type is also used as a memory address pointer.\n\nIf we want to pass a string from the host to a Wasm function the host has to directly write the string into the Wasm module's memory, and then pass two `i32`s to the Wasm function: one pointing to the string's memory address and another specifying the string's byte length.\n\nAnd if we want to pass an array from a Wasm function to the host, the host first needs to provide the Wasm function an `i32` pointing to the memory address where the array should be written, and then when the Wasm function completes it returns an `i32` which represents the number of bytes that were written.\n\nHowever, now we have a new problem: when the host writes to the Wasm module's memory, how can it ensure it doesn't overwrite memory that the Wasm module is using? For the host to be able to safely write to memory, it must first ask the Wasm module to allocate space for it.\n\nOkay, now with all of that context out of the way we can finally look at this code and actually understand it:\n\n```rust\n/** qr_wasm/lib.rs **/\n\nuse std::{alloc::Layout, mem, slice, str};\n\n// host calls this function to allocate space where\n// it can safely write data to\n#[no_mangle]\npub unsafe extern \"C\" fn alloc(size: usize) -> *mut u8 {\n    let layout = Layout::from_size_align_unchecked(\n        size * mem::size_of::<u8>(),\n        mem::align_of::<usize>(),\n    );\n    std::alloc::alloc(layout)\n}\n\n// after allocating a text buffer and output buffer,\n// host calls this function to generate the QR code PNG\n#[no_mangle]\npub unsafe extern \"C\" fn generateQrCode(\n    text_ptr: *const u8,\n    text_len: usize,\n    output_ptr: *mut u8,\n    output_len: usize,\n) -> usize {\n    // read text from memory, where it was written to by the host\n    let text_slice = slice::from_raw_parts(text_ptr, text_len);\n    let text = str::from_utf8_unchecked(text_slice);\n\n    let qr_code = match qr_lib::generate_qr_code(text) {\n        Ok(png_data) => png_data,\n        // error: unable to generate QR code\n        Err(_) => return 0,\n    };\n\n    if qr_code.len() > output_len {\n        // error: output buffer is too small\n        return 0;\n    }\n\n    // write generated QR code PNG to output buffer,\n    // where the host will read it from after this\n    // function returns\n    let output_slice = slice::from_raw_parts_mut(output_ptr, qr_code.len());\n    output_slice.copy_from_slice(&qr_code);\n\n    // return written length of PNG data\n    qr_code.len()\n}\n```\n\nAfter compiling this Wasm module here's how we'd use it from JS:\n\n```js\nconst path = require('path');\nconst fs = require('fs');\n\n// fetch Wasm file\nconst qrWasmPath = path.resolve(__dirname, './qr_wasm.wasm');\nconst qrWasmBinary = fs.readFileSync(qrWasmPath);\n\n// instantiate Wasm module\nconst qrWasmModule = new WebAssembly.Module(qrWasmBinary);\nconst qrWasmInstance = new WebAssembly.Instance(\n    qrWasmModule,\n    {},\n);\n\n// JS strings are UTF16, but we need to re-encode them\n// as UTF8 before passing them to our Wasm module\nconst textEncoder = new TextEncoder();\n\n// tell Wasm module to allocate two buffers for us:\n// - 1st buffer: an input buffer which we'll\n//               write UTF8 strings into that\n//               the generateQrCode function\n//               will read\n// - 2nd buffer: an output buffer that the\n//               generateQrCode function will\n//               write QR code PNG bytes into\n//               and that we'll read\nconst textMemLen = 1024;\nconst textMemOffset = qrWasmInstance.exports.alloc(textMemLen);\nconst outputMemLen = 4096;\nconst outputMemOffset = qrWasmInstance.exports.alloc(outputMemLen);\n\n/**\n * @param {string} text - text to encode\n * @returns {Buffer} - QR code\n */\nmodule.exports = function generateQrCode(text) {\n    // convert UTF16 JS string to Uint8Array\n    let encodedText = textEncoder.encode(text);\n    let encodedTextLen = encodedText.length;\n\n    // write string into Wasm memory\n    qrWasmMemory = new Uint8Array(qrWasmInstance.exports.memory.buffer);\n    qrWasmMemory.set(encodedText, textMemOffset);\n\n    const wroteBytes = qrWasmInstance.exports.generateQrCode(\n        textMemOffset,\n        encodedTextLen,\n        outputMemOffset,\n        outputMemLen,\n    );\n\n    if (wroteBytes === 0) {\n        throw new Error('failed to generate qr');\n    }\n\n    // read QR code PNG bytes from Wasm memory & return\n    return Buffer.from(\n        qrWasmInstance.exports.memory.buffer,\n        outputMemOffset,\n        wroteBytes,\n    );\n};\n```\n\nThis is what is generated under-the-hood when we use a library like `wasm-bindgen`. Anyway, I benchmarked it and the performance of the handwritten bindings were virtually identical to the performance of the generated bindings in this case.\n\nSo writing Wasm glue code between the host and the guest is obviously not fun. Fortunately, the people actively contributing to the Wasm specification are aware of this and they are currently working on the \"Component Model\" proposal that will standardize an IDL (Interface Definition Language) called WIT (Wasm Interface Type) that binding generators and Wasm runtimes can be built around.\n\nAt the moment there's a Rust project called `wit-bindgen` that will generate the glue code for Wasm modules written in Rust given a WIT file, however you'd need a separate tool to generate the host glue code, like `jco`, which can generate JS glue code given a Wasm and WIT file.\n\nUsing `wit-bingen` + `jco` will give you a similar result to just using `wasm-bindgen`, but the hope is that more WIT host binding generators for other languages will be written in the future, so that Python, Java, Go, PHP, Ruby, etc programmers have a solution that's as convenience and easy-to-use as `wasm-bindgen` is today for JS programmers.\n\n\n\n### Tier 3: Rust Native Function\n\nFor this strategy we're going to write the function in Rust, compile it to native code, and then load and execute it from the host runtime. Table of Rust bindgen libraries for various languages:\n\n| Language | Rust bindgen | Github stars |\n|-|-|-|\n| Python | [pyo3](https://github.com/pyo3/pyo3) | 12.7k+ |\n| JavaScript | [napi-rs](https://github.com/napi-rs/napi-rs) | 6.3k+ |\n| Erlang | [rustler](https://github.com/rusterlium/rustler) | 4.4k+ |\n| Multiple | [uniffi-rs](https://github.com/mozilla/uniffi-rs) | 3k+ |\n| Java | [jni-rs](https://github.com/jni-rs/jni-rs) | 1.3k+ |\n| Ruby | [rutie](https://github.com/danielpclark/rutie) | 970+ |\n| PHP | [ext-php-rs](https://github.com/davidcole1340/ext-php-rs) | 610+ |\n| Multiple | [diplomat](https://github.com/rust-diplomat/diplomat) | 560+ |\n\nSince our example server is written in JS we're going to use `napi-rs`. Here's the Rust code:\n\n```rust\nuse napi::bindgen_prelude::*;\nuse napi_derive::napi;\n\n#[napi]\npub fn generate_qr_code(text: String) -> Result<Vec<u8>, Status> {\n    qr_lib::generate_qr_code(&text)\n        .map_err(|e| Error::from_reason(e.to_string()))\n}\n```\n\nI love how easy it is. After writing a Wasm module from scratch in Rust in the preceding section I have a newfound appreciation and respect for people who implement and maintain binding generator libraries.\n\nAfter building the code above here's how we'd use it from Node.js:\n\n```js\nconst native = require('./qr_napi.node');\n\n/**\n * @param {string} text - text to encode\n * @returns {Buffer} - QR code\n */\nmodule.exports = function generateQrCode(text) {\n    return Buffer.from(native.generateQrCode(text));\n};\n```\n\nNow let's see if this puppy can fly:\n\nAbsolute measurements\n\n| Tier | Throughput | Avg Latency | p99 Latency | Avg Response | Memory |\n|-|-|-|-|-|-|\n| Tier 0 | 1464 req/sec | 68 ms | 96 ms | 1506 bytes | 1353 MB |\n| Tier 1 | 2572 req/sec | 39 ms | 78 ms | 778 bytes 🥇 | 1240 MB 🥇 |\n| Tier 2 | 2978 req/sec | 34 ms | 63 ms | 778 bytes 🥇 | 1286 MB |\n| Tier 3 | 5490 req/sec 🥇 | 18 ms 🥇 | 37 ms 🥇 | 778 bytes 🥇 | 1309 MB |\n\nRelative measurements\n\n| Tier | Throughput | Avg Latency | p99 Latency | Avg Response | Memory |\n|-|-|-|-|-|-|\n| Tier 0 | 1.00x | 1.00x | 1.00x | 1.00x | 1.00x |\n| Tier 1 | 1.76x | 0.57x | 0.82x | 0.52x 🥇 | 0.92x 🥇 |\n| Tier 2 | 2.03x | 0.50x | 0.66x | 0.52x 🥇 | 0.95x |\n| Tier 3 | 3.75x 🥇 | 0.26x 🥇 | 0.39x 🥇 | 0.52x 🥇 | 0.97x |\n\nIt turns out native code is pretty fast! We've almost quadrupled our throughput compared to the baseline, and doubled it compared to the Wasm implementations.\n\n\n\n### Tier 4: Rust Rewrite\n\nIn this strategy we're going to rewrite the host server in Rust. Admittedly, this is impractical for most real-world cases, where it's not unusual to see server codebases with 100k+ lines of code. In those situations we could instead only rewrite a subset of the host server. Nowadays most people run everything on their backend behind a reverse proxy anyway, so deploying a new Rust server and modifying the reverse proxy config to route some requests to the Rust server doesn't introduce that much additional operational overhead to many people's backend setups.\n\nSo here's the server rewritten in Rust:\n\n```rust\n/** qr-server/main.rs **/\n\nuse std::process;\nuse axum::{\n    extract::Query,\n    http::{header, StatusCode},\n    response::{IntoResponse, Response},\n    routing::get,\n    Router,\n};\n\n#[derive(serde::Deserialize)]\nstruct TextParam {\n    text: String,\n}\n\n#[tokio::main]\nasync fn main() {\n    let app = Router::new().route(\"/qrcode\", get(handler));\n    let listener = tokio::net::TcpListener::bind(\"127.0.0.1:42069\")\n        .await\n        .unwrap();\n    println!(\n        \"server {} listening on {}\",\n        process::id(),\n        listener.local_addr().unwrap(),\n    );\n    axum::serve(listener, app).await.unwrap();\n}\n\nasync fn handler(\n    Query(param): Query<TextParam>\n) -> Result<Response, (StatusCode, &'static str)> {\n    if param.text.len() > 512 {\n        return Err((\n            StatusCode::BAD_REQUEST,\n            \"text must be <= 512 bytes\"\n        ));\n    }\n    match qr_lib::generate_qr_code(&param.text) {\n        Ok(bytes) => Ok((\n            [(header::CONTENT_TYPE, \"image/png\"),],\n            bytes,\n        ).into_response()),\n        Err(_) => Err((\n            StatusCode::INTERNAL_SERVER_ERROR,\n            \"failed to generate qr code\"\n        )),\n    }\n}\n```\n\nLet's see if it lives up to the hype:\n\nAbsolute measurements\n\n| Tier | Throughput | Avg Latency | p99 Latency | Avg Response | Memory |\n|-|-|-|-|-|-|\n| Tier 0 | 1464 req/sec | 68 ms | 96 ms | 1506 bytes | 1353 MB |\n| Tier 1 | 2572 req/sec | 39 ms | 78 ms | 778 bytes 🥇 | 1240 MB |\n| Tier 2 | 2978 req/sec | 34 ms | 63 ms | 778 bytes 🥇 | 1286 MB |\n| Tier 3  | 5490 req/sec | 18 ms | 37 ms | 778 bytes 🥇 | 1309 MB |\n| Tier 4 | 7212 req/sec 🥇 | 14 ms 🥇 | 27 ms 🥇 | 778 bytes 🥇 | 13 MB 🥇 |\n\nRelative measurements\n\n| Tier  | Throughput | Avg Latency | p99 Latency | Avg Response | Memory |\n|-|-|-|-|-|-|\n| Tier 0 | 1.00x | 1.00x | 1.00x | 1.00x | 1.00x |\n| Tier 1 | 1.76x | 0.57x | 0.82x | 0.52x 🥇 | 0.92x |\n| Tier 2 | 2.03x | 0.50x | 0.66x | 0.52x 🥇 | 0.95x |\n| Tier 3 | 3.75x | 0.26x | 0.39x | 0.52x 🥇 | 0.97x |\n| Tier 4 | 4.93x 🥇 | 0.21x 🥇 | 0.28x 🥇 | 0.52x 🥇 | 0.01x 🥇 |\n\nThat's not a typo. The Rust server really only used 13 MB of memory while serving 7200+ requests per second. I'd say it lived up to the hype for sure!\n\n\n\n## Concluding thoughts\n\nI think all of the strategies are good, but Tier 3 stands out as being the best bang for the buck. If you can use an off-the-shelf binding generator library then writing a native function in Rust is super easy and it can have a profound effect on performance.\n\nThe hardest part of Tier 3 is probably learning Rust if you don't know it already, but if you're in that boat you should read [Learning Rust in 2024](./learning-rust-in-2024.md) which will help you figure out how to begin.\n\n\n\n## Discuss\n\nDiscuss this article on\n- [Github](https://github.com/pretzelhammer/rust-blog/discussions/87)\n- [official Rust users forum](https://users.rust-lang.org/t/using-rust-in-non-rust-servers-to-improve-performance/120121)\n- [rust subreddit](https://www.reddit.com/r/rust/comments/1gabrdh/using_rust_in_nonrust_servers_to_improve/)\n- [Hackernews](https://news.ycombinator.com/item?id=41941451)\n\n\n\n## Further reading\n\n- [Common Rust Lifetime Misconceptions](./common-rust-lifetime-misconceptions.md)\n- [Tour of Rust's Standard Library Traits](./tour-of-rusts-standard-library-traits.md)\n- [Beginner's Guide to Concurrent Programming: Coding a Multithreaded Chat Server using Tokio](./chat-server.md)\n- [Learning Rust in 2024](./learning-rust-in-2024.md)\n- [Sizedness in Rust](./sizedness-in-rust.md)\n- [RESTful API in Sync & Async Rust](./restful-api-in-sync-and-async-rust.md)\n- [Learn Assembly with Entirely Too Many Brainfuck Compilers](./too-many-brainfuck-compilers.md)\n\n\n\n## Notifications\n\nGet notified when a new blog post gets published by\n- Subscribing to this repo's [releases RSS feed](https://github.com/pretzelhammer/rust-blog/releases.atom) or\n- Watching this repo's releases (click `Watch` → click `Custom` → select `Releases` → click `Apply`)\n"
  },
  {
    "path": "posts/sizedness-in-rust.md",
    "content": "# Sizedness in Rust\n\n_22 July 2020 · #rust · #sizedness_\n\n**Table of Contents**\n\n- [Intro](#intro)\n- [Sizedness](#sizedness)\n- [`Sized` Trait](#sized-trait)\n- [`Sized` in Generics](#sized-in-generics)\n- [Unsized Types](#unsized-types)\n    - [Slices](#slices)\n    - [Trait Objects](#trait-objects)\n    - [Trait Object Limitations](#trait-object-limitations)\n        - [Cannot Cast Unsized Types to Trait Objects](#cannot-cast-unsized-types-to-trait-objects)\n        - [Cannot create Multi-Trait Objects](#cannot-create-multi-trait-objects)\n    - [User-Defined Unsized Types](#user-defined-unsized-types)\n- [Zero-Sized Types](#zero-sized-types)\n    - [Unit Type](#unit-type)\n    - [User-Defined Unit Structs](#user-defined-unit-structs)\n    - [Never Type](#never-type)\n    - [User-Defined Pseudo Never Types](#user-defined-pseudo-never-types)\n    - [PhantomData](#phantomdata)\n- [Conclusion](#conclusion)\n- [Discuss](#discuss)\n- [Further Reading](#further-reading)\n- [Notifications](#notifications)\n\n\n\n## Intro\n\nSizedness is lowkey one of the most important concepts to understand in Rust. It intersects a bunch of other language features in often subtle ways and only rears its ugly head in the form of _\"x doesn't have size known at compile time\"_ error messages which every Rustacean is all too familiar with. In this article we'll explore all flavors of sizedness from sized types, to unsized types, to zero-sized types while examining their use-cases, benefits, pain points, and workarounds.\n\nTable of phrases I use and what they're supposed to mean:\n\n| Phrase | Shorthand for |\n|-|-|\n| sizedness | property of being sized or unsized |\n| sized type | type with a known size at compile time |\n| 1) unsized type _or_<br>2) DST | dynamically-sized type, i.e. size not known at compile time |\n| ?sized type | type that may or may not be sized |\n| unsized coercion | coercing a sized type into an unsized type |\n| ZST | zero-sized type, i.e. instances of the type are 0 bytes in size |\n| width | single unit of measurement of pointer width |\n| 1) thin pointer _or_<br>2) single-width pointer | pointer that is _1 width_ |\n| 1) fat pointer _or_<br>2) double-width pointer | pointer that is _2 widths_ |\n| 1) pointer _or_<br>2) reference | some pointer of some width, width will be clarified by context |\n| slice | double-width pointer to a dynamically sized view into some array |\n\n\n\n## Sizedness\n\nIn Rust a type is sized if its size in bytes can be determined at compile-time. Determining a type's size is important for being able to allocate enough space for instances of that type on the stack. Sized types can be passed around by value or by reference. If a type's size can't be determined at compile-time then it's referred to as an unsized type or a DST, Dynamically-Sized Type. Since unsized types can't be placed on the stack they can only be passed around by reference. Some examples of sized and unsized types:\n\n```rust\nuse std::mem::size_of;\n\nfn main() {\n    // primitives\n    assert_eq!(4, size_of::<i32>());\n    assert_eq!(8, size_of::<f64>());\n\n    // tuples\n    assert_eq!(8, size_of::<(i32, i32)>());\n\n    // arrays\n    assert_eq!(0, size_of::<[i32; 0]>());\n    assert_eq!(12, size_of::<[i32; 3]>());\n\n    struct Point {\n        x: i32,\n        y: i32,\n    }\n\n    // structs\n    assert_eq!(8, size_of::<Point>());\n\n    // enums\n    assert_eq!(8, size_of::<Option<i32>>());\n\n    // get pointer width, will be\n    // 4 bytes wide on 32-bit targets or\n    // 8 bytes wide on 64-bit targets\n    const WIDTH: usize = size_of::<&()>();\n\n    // pointers to sized types are 1 width\n    assert_eq!(WIDTH, size_of::<&i32>());\n    assert_eq!(WIDTH, size_of::<&mut i32>());\n    assert_eq!(WIDTH, size_of::<Box<i32>>());\n    assert_eq!(WIDTH, size_of::<fn(i32) -> i32>());\n\n    const DOUBLE_WIDTH: usize = 2 * WIDTH;\n\n    // unsized struct\n    struct Unsized {\n        unsized_field: [i32],\n    }\n\n    // pointers to unsized types are 2 widths\n    assert_eq!(DOUBLE_WIDTH, size_of::<&str>()); // slice\n    assert_eq!(DOUBLE_WIDTH, size_of::<&[i32]>()); // slice\n    assert_eq!(DOUBLE_WIDTH, size_of::<&dyn ToString>()); // trait object\n    assert_eq!(DOUBLE_WIDTH, size_of::<Box<dyn ToString>>()); // trait object\n    assert_eq!(DOUBLE_WIDTH, size_of::<&Unsized>()); // user-defined unsized type\n\n    // unsized types\n    size_of::<str>(); // compile error\n    size_of::<[i32]>(); // compile error\n    size_of::<dyn ToString>(); // compile error\n    size_of::<Unsized>(); // compile error\n}\n```\n\nHow we determine the size of sized types is straight-forward: all primitives and pointers have known sizes and all structs, tuples, enums, and arrays are just made up of primitives and pointers or other nested structs, tuples, enums, and arrays so we can just count up the bytes recursively, taking into account extra bytes needed for padding and alignment. We can't determine the size of unsized types for similarly straight-forward reasons: slices can have any number of elements in them and can thus be of any size at run-time and trait objects can be implemented by any number of structs or enums and thus can also be of any size at run-time.\n\n**Pro tips**\n- pointers of dynamically sized views into arrays are called slices in Rust, e.g. a `&str` is a _\"string slice\"_, a `&[i32]` is an _\"i32 slice\"_\n- slices are double-width because they store a pointer to the array and the number of elements in the array\n- trait object pointers are double-width because they store a pointer to the data and a pointer to a vtable\n- unsized structs pointers are double-width because they store a pointer to the struct data and the size of the struct\n- unsized structs can only have 1 unsized field and it must be the last field in the struct\n\nTo really hammer home the point about double-width pointers for unsized types here's a commented code example comparing arrays to slices:\n\n```rust\nuse std::mem::size_of;\n\nconst WIDTH: usize = size_of::<&()>();\nconst DOUBLE_WIDTH: usize = 2 * WIDTH;\n\nfn main() {\n    // data length stored in type\n    // an [i32; 3] is an array of three i32s\n    let nums: &[i32; 3] = &[1, 2, 3];\n\n    // single-width pointer\n    assert_eq!(WIDTH, size_of::<&[i32; 3]>());\n\n    let mut sum = 0;\n\n    // can iterate over nums safely\n    // Rust knows it's exactly 3 elements\n    for num in nums {\n        sum += num;\n    }\n\n    assert_eq!(6, sum);\n\n    // unsized coercion from [i32; 3] to [i32]\n    // data length now stored in pointer\n    let nums: &[i32] = &[1, 2, 3];\n\n    // double-width pointer required to also store data length\n    assert_eq!(DOUBLE_WIDTH, size_of::<&[i32]>());\n\n    let mut sum = 0;\n\n    // can iterate over nums safely\n    // Rust knows it's exactly 3 elements\n    for num in nums {\n        sum += num;\n    }\n\n    assert_eq!(6, sum);\n}\n```\n\nAnd here's another commented code example comparing structs to trait objects:\n\n```rust\nuse std::mem::size_of;\n\nconst WIDTH: usize = size_of::<&()>();\nconst DOUBLE_WIDTH: usize = 2 * WIDTH;\n\ntrait Trait {\n    fn print(&self);\n}\n\nstruct Struct;\nstruct Struct2;\n\nimpl Trait for Struct {\n    fn print(&self) {\n        println!(\"struct\");\n    }\n}\n\nimpl Trait for Struct2 {\n    fn print(&self) {\n        println!(\"struct2\");\n    }\n}\n\nfn print_struct(s: &Struct) {\n    // always prints \"struct\"\n    // this is known at compile-time\n    s.print();\n    // single-width pointer\n    assert_eq!(WIDTH, size_of::<&Struct>());\n}\n\nfn print_struct2(s2: &Struct2) {\n    // always prints \"struct2\"\n    // this is known at compile-time\n    s2.print();\n    // single-width pointer\n    assert_eq!(WIDTH, size_of::<&Struct2>());\n}\n\nfn print_trait(t: &dyn Trait) {\n    // print \"struct\" or \"struct2\" ?\n    // this is unknown at compile-time\n    t.print();\n    // Rust has to check the pointer at run-time\n    // to figure out whether to use Struct's\n    // or Struct2's implementation of \"print\"\n    // so the pointer has to be double-width\n    assert_eq!(DOUBLE_WIDTH, size_of::<&dyn Trait>());\n}\n\nfn main() {\n    // single-width pointer to data\n    let s = &Struct; \n    print_struct(s); // prints \"struct\"\n    \n    // single-width pointer to data\n    let s2 = &Struct2;\n    print_struct2(s2); // prints \"struct2\"\n    \n    // unsized coercion from Struct to dyn Trait\n    // double-width pointer to point to data AND Struct's vtable\n    let t: &dyn Trait = &Struct;\n    print_trait(t); // prints \"struct\"\n    \n    // unsized coercion from Struct2 to dyn Trait\n    // double-width pointer to point to data AND Struct2's vtable\n    let t: &dyn Trait = &Struct2;\n    print_trait(t); // prints \"struct2\"\n}\n```\n\n**Key Takeaways**\n- only instances of sized types can be placed on the stack, i.e. can be passed around by value\n- instances of unsized types can't be placed on the stack and must be passed around by reference\n- pointers to unsized types are double-width because aside from pointing to data they need to do an extra bit of bookkeeping to also keep track of the data's length _or_ point to a vtable\n\n\n\n## `Sized` Trait\n\nThe `Sized` trait in Rust is an auto trait and a marker trait.\n\nAuto traits are traits that get automatically implemented for a type if it passes certain conditions. Marker traits are traits that mark a type as having a certain property. Marker traits do not have any trait items such as methods, associated functions, associated constants, or associated types. All auto traits are marker traits but not all marker traits are auto traits. Auto traits must be marker traits so the compiler can provide an automatic default implementation for them, which would not be possible if the trait had any trait items.\n\nA type gets an auto `Sized` implementation if all of its members are also `Sized`. What \"members\" means depends on the containing type, for example: fields of a struct, variants of an enum, elements of an array, items of a tuple, and so on. Once a type has been \"marked\" with a `Sized` implementation that means its size in bytes is known at compile time.\n\nOther examples of auto marker traits are the `Send` and `Sync` traits. A type is `Send` if it is safe to send that type across threads. A type is `Sync` if it's safe to share references of that type between threads. A type gets auto `Send` and `Sync` implementations if all of its members are also `Send` and `Sync`. What makes `Sized` somewhat special is that it's not possible to opt-out of unlike with the other auto marker traits which are possible to opt-out of.\n\n```rust\n#![feature(negative_impls)]\n\n// this type is Sized, Send, and Sync\nstruct Struct;\n\n// opt-out of Send trait\nimpl !Send for Struct {} // ✅\n\n// opt-out of Sync trait\nimpl !Sync for Struct {} // ✅\n\n// can't opt-out of Sized\nimpl !Sized for Struct {} // ❌\n```\n\nThis seems reasonable since there might be reasons why we wouldn't want our type to be sent or shared across threads, however it's hard to imagine a scenario where we'd want the compiler to \"forget\" the size of our type and treat it as an unsized type as that offers no benefits and merely makes the type more difficult to work with.\n\nAlso, to be super pedantic `Sized` is not technically an auto trait since it's not defined using the `auto` keyword but the special treatment it gets from the compiler makes it behave very similarly to auto traits so in practice it's okay to think of it as an auto trait.\n\n**Key Takeaways**\n- `Sized` is an \"auto\" marker trait\n\n\n\n## `Sized` in Generics\n\nIt's not immediately obvious that whenever we write any generic code every generic type parameter gets auto-bound with the `Sized` trait by default.\n\n```rust\n// this generic function...\nfn func<T>(t: T) {}\n\n// ...desugars to...\nfn func<T: Sized>(t: T) {}\n\n// ...which we can opt-out of by explicitly setting ?Sized...\nfn func<T: ?Sized>(t: T) {} // ❌\n\n// ...which doesn't compile since it doesn't have\n// a known size so we must put it behind a pointer...\nfn func<T: ?Sized>(t: &T) {} // ✅\nfn func<T: ?Sized>(t: Box<T>) {} // ✅\n```\n\n**Pro tips**\n- `?Sized` can be pronounced _\"optionally sized\"_ or _\"maybe sized\"_ and adding it to a type parameter's bounds allows the type to be sized or unsized\n- `?Sized` in general is referred to as a _\"widening bound\"_ or a _\"relaxed bound\"_ as it relaxes rather than constrains the type parameter\n- `?Sized` is the only relaxed bound in Rust\n\nSo why does this matter? Well, any time we're working with a generic type and that type is behind a pointer we almost always want to opt-out of the default `Sized` bound to make our function more flexible in what argument types it will accept. Also, if we don't opt-out of the default `Sized` bound we'll eventually get some surprising and confusing compile error messages.\n\nLet me take you on the journey of the first generic function I ever wrote in Rust. I started learning Rust before the `dbg!` macro landed in stable so the only way to print debug values was to type out `println!(\"{:?}\", some_value);` every time which is pretty tedious so I decided to write a `debug` helper function like this:\n\n```rust\nuse std::fmt::Debug;\n\nfn debug<T: Debug>(t: T) { // T: Debug + Sized\n    println!(\"{:?}\", t);\n}\n\nfn main() {\n    debug(\"my str\"); // T = &str, &str: Debug + Sized ✅\n}\n```\n\nSo far so good, but the function takes ownership of any values passed to it which is kinda annoying so I changed the function to only take references instead:\n\n```rust\nuse std::fmt::Debug;\n\nfn dbg<T: Debug>(t: &T) { // T: Debug + Sized\n    println!(\"{:?}\", t);\n}\n\nfn main() {\n    dbg(\"my str\"); // &T = &str, T = str, str: Debug + !Sized ❌\n}\n```\n\nWhich now throws this error:\n\n```none\nerror[E0277]: the size for values of type `str` cannot be known at compilation time\n --> src/main.rs:8:9\n  |\n3 | fn dbg<T: Debug>(t: &T) {\n  |        - required by this bound in `dbg`\n...\n8 |     dbg(\"my str\");\n  |         ^^^^^^^^ doesn't have a size known at compile-time\n  |\n  = help: the trait `std::marker::Sized` is not implemented for `str`\n  = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>\nhelp: consider relaxing the implicit `Sized` restriction\n  |\n3 | fn dbg<T: Debug + ?Sized>(t: &T) {\n  |   \n```\n\nWhen I first saw this I found it incredibly confusing. Despite making my function more restrictive in what arguments it takes than before it now somehow throws a compile error! What is going on?\n\nI've already kinda spoiled the answer in the code comments above, but basically: Rust performs pattern matching when resolving `T` to its concrete types during compilation. Here's a couple tables to help clarify:\n\n| Type | `T` | `&T` |\n|------------|---|----|\n| `&str` | `T` = `&str` | `T` = `str` |\n\n| Type | `Sized` |\n|-|-|\n| `str` | ❌ |\n| `&str` | ✅ |\n| `&&str` | ✅ |\n\nThis is why I had to add a `?Sized` bound to make the function work as intended after changing it to take references. The working function below:\n\n```rust\nuse std::fmt::Debug;\n\nfn debug<T: Debug + ?Sized>(t: &T) { // T: Debug + ?Sized\n    println!(\"{:?}\", t);\n}\n\nfn main() {\n    debug(\"my str\"); // &T = &str, T = str, str: Debug + !Sized ✅\n}\n```\n\n**Key Takeaways**\n- all generic type parameters are auto-bound with `Sized` by default\n- if we have a generic function which takes an argument of some `T` behind a pointer, e.g. `&T`, `Box<T>`, `Rc<T>`, et cetera, then we almost always want to opt-out of the default `Sized` bound with `T: ?Sized`\n\n\n\n## Unsized Types\n\n\n\n### Slices\n\nThe most common slices are string slices `&str` and array slices `&[T]`. What's nice about slices is that many other types coerce to them, so leveraging slices and Rust's auto type coercions allow us to write flexible APIs.\n\nType coercions can happen in several places but most notably on function arguments and at method calls. The kinds of type coercions we're interested in are deref coercions and unsized coercions. A deref coercion is when a `T` gets coerced into a `U` following a deref operation, i.e. `T: Deref<Target = U>`, e.g. `String.deref() -> str`. An unsized coercion is when a `T` gets coerced into a `U` where `T` is a sized type and `U` is an unsized type, i.e. `T: Unsize<U>`, e.g. `[i32; 3] -> [i32]`.\n\n```rust\ntrait Trait {\n    fn method(&self) {}\n}\n\nimpl Trait for str {\n    // can now call \"method\" on\n    // 1) str or\n    // 2) String since String: Deref<Target = str>\n}\nimpl<T> Trait for [T] {\n    // can now call \"method\" on\n    // 1) any &[T]\n    // 2) any U where U: Deref<Target = [T]>, e.g. Vec<T>\n    // 3) [T; N] for any N, since [T; N]: Unsize<[T]>\n}\n\nfn str_fun(s: &str) {}\nfn slice_fun<T>(s: &[T]) {}\n\nfn main() {\n    let str_slice: &str = \"str slice\";\n    let string: String = \"string\".to_owned();\n\n    // function args\n    str_fun(str_slice);\n    str_fun(&string); // deref coercion\n\n    // method calls\n    str_slice.method();\n    string.method(); // deref coercion\n\n    let slice: &[i32] = &[1];\n    let three_array: [i32; 3] = [1, 2, 3];\n    let five_array: [i32; 5] = [1, 2, 3, 4, 5];\n    let vec: Vec<i32> = vec![1];\n\n    // function args\n    slice_fun(slice);\n    slice_fun(&vec); // deref coercion\n    slice_fun(&three_array); // unsized coercion\n    slice_fun(&five_array); // unsized coercion\n\n    // method calls\n    slice.method();\n    vec.method(); // deref coercion\n    three_array.method(); // unsized coercion\n    five_array.method(); // unsized coercion\n}\n```\n\n**Key Takeaways**\n- leveraging slices and Rust's auto type coercions allows us to write flexible APIs\n\n\n\n### Trait Objects\n\nTraits are `?Sized` by default. This program:\n\n```rust\ntrait Trait: ?Sized {}\n```\n\nThrows this error:\n\n```none\nerror: `?Trait` is not permitted in supertraits\n --> src/main.rs:1:14\n  |\n1 | trait Trait: ?Sized {}\n  |              ^^^^^^\n  |\n  = note: traits are `?Sized` by default\n```\n\nWe'll get into why traits are `?Sized` by default soon but first let's ask ourselves what are the implications of a trait being `?Sized`? Let's desugar the above example:\n\n```rust\ntrait Trait where Self: ?Sized {}\n```\n\nOkay, so by default traits allow `self` to possibly be an unsized type. As we learned earlier we can't pass unsized types around by value, so that limits us in the kind of methods we can define in the trait. It should be impossible to write a method the takes or returns `self` by value and yet this surprisingly compiles:\n\n```rust\ntrait Trait {\n    fn method(self); // ✅\n}\n```\n\nHowever the moment we try to implement the method, either by providing a default implementation or by implementing the trait for an unsized type, we get compile errors:\n\n```rust\ntrait Trait {\n    fn method(self) {} // ❌\n}\n\nimpl Trait for str {\n    fn method(self) {} // ❌\n}\n```\n\nThrows:\n\n```none\nerror[E0277]: the size for values of type `Self` cannot be known at compilation time\n --> src/lib.rs:2:15\n  |\n2 |     fn method(self) {}\n  |               ^^^^ doesn't have a size known at compile-time\n  |\n  = help: the trait `std::marker::Sized` is not implemented for `Self`\n  = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>\n  = note: all local variables must have a statically known size\n  = help: unsized locals are gated as an unstable feature\nhelp: consider further restricting `Self`\n  |\n2 |     fn method(self) where Self: std::marker::Sized {}\n  |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nerror[E0277]: the size for values of type `str` cannot be known at compilation time\n --> src/lib.rs:6:15\n  |\n6 |     fn method(self) {}\n  |               ^^^^ doesn't have a size known at compile-time\n  |\n  = help: the trait `std::marker::Sized` is not implemented for `str`\n  = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>\n  = note: all local variables must have a statically known size\n  = help: unsized locals are gated as an unstable feature\n```\n\nIf we're determined to pass `self` around by value we can fix the first error by explicitly binding the trait with `Sized`:\n\n```rust\ntrait Trait: Sized {\n    fn method(self) {} // ✅\n}\n\nimpl Trait for str { // ❌\n    fn method(self) {}\n}\n```\n\nNow throws:\n\n```none\nerror[E0277]: the size for values of type `str` cannot be known at compilation time\n --> src/lib.rs:7:6\n  |\n1 | trait Trait: Sized {\n  |              ----- required by this bound in `Trait`\n...\n7 | impl Trait for str {\n  |      ^^^^^ doesn't have a size known at compile-time\n  |\n  = help: the trait `std::marker::Sized` is not implemented for `str`\n  = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>\n```\n\nWhich is okay, as we knew upon binding the trait with `Sized` we'd no longer be able to implement it for unsized types such as `str`. If on the other hand we really wanted to implement the trait for `str` an alternative solution would be to keep the trait `?Sized` and pass `self` around by reference:\n\n```rust\ntrait Trait {\n    fn method(&self) {} // ✅\n}\n\nimpl Trait for str {\n    fn method(&self) {} // ✅\n}\n```\n\nInstead of marking the entire trait as `?Sized` or `Sized` we have the more granular and precise option of marking individual methods as `Sized` like so:\n\n```rust\ntrait Trait {\n    fn method(self) where Self: Sized {}\n}\n\nimpl Trait for str {} // ✅!?\n\nfn main() {\n    \"str\".method(); // ❌\n}\n```\n\nIt's surprising that Rust compiles `impl Trait for str {}` without any complaints, but it eventually catches the error when we attempt to call `method` on an unsized type so all is fine. It's a little weird but affords us some flexibility in implementing traits with some `Sized` methods for unsized types as long as we never call the `Sized` methods:\n\n```rust\ntrait Trait {\n    fn method(self) where Self: Sized {}\n    fn method2(&self) {}\n}\n\nimpl Trait for str {} // ✅\n\nfn main() {\n    // we never call \"method\" so no errors\n    \"str\".method2(); // ✅\n}\n```\n\nNow back to the original question, why are traits `?Sized` by default? The answer is trait objects. Trait objects are inherently unsized because any type of any size can implement a trait, therefore we can only implement `Trait` for `dyn Trait` if `Trait: ?Sized`. To put it in code:\n\n```rust\ntrait Trait: ?Sized {}\n\n// the above is REQUIRED for\n\nimpl Trait for dyn Trait {\n    // compiler magic here\n}\n\n// since `dyn Trait` is unsized\n\n// and now we can use `dyn Trait` in our program\n\nfn function(t: &dyn Trait) {} // ✅\n```\n\nIf we try to actually compile the above program we get:\n\n```none\nerror[E0371]: the object type `(dyn Trait + 'static)` automatically implements the trait `Trait`\n --> src/lib.rs:5:1\n  |\n5 | impl Trait for dyn Trait {\n  | ^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Trait + 'static)` automatically implements trait `Trait`\n```\n\nWhich is the compiler telling us to chill since it automatically provides the implementation of `Trait` for `dyn Trait`. Again, since `dyn Trait` is unsized the compiler can only provide this implementation if `Trait: ?Sized`. If we bound `Trait` by `Sized` then `Trait` becomes _\"object unsafe\"_ which is a term that means we can't cast types which implement `Trait` to trait objects of `dyn Trait`. As expected this program does not compile:\n\n```rust\ntrait Trait: Sized {}\n\nfn function(t: &dyn Trait) {} // ❌\n```\n\nThrows:\n\n```none\nerror[E0038]: the trait `Trait` cannot be made into an object\n --> src/lib.rs:3:18\n  |\n1 | trait Trait: Sized {}\n  |       -----  ----- ...because it requires `Self: Sized`\n  |       |\n  |       this trait cannot be made into an object...\n2 | \n3 | fn function(t: &dyn Trait) {}\n  |                ^^^^^^^^^^ the trait `Trait` cannot be made into an object\n```\n\nLet's try to make an `?Sized` trait with a `Sized` method and see if we can cast it to a trait object:\n\n```rust\ntrait Trait {\n    fn method(self) where Self: Sized {}\n    fn method2(&self) {}\n}\n\nfn function(arg: &dyn Trait) { // ✅\n    arg.method(); // ❌\n    arg.method2(); // ✅\n}\n```\n\nAs we saw before everything is okay as long as we don't call the `Sized` method on the trait object.\n\n**Key Takeaways**\n- all traits are `?Sized` by default\n- `Trait: ?Sized` is required for `impl Trait for dyn Trait`\n- we can require `Self: Sized` on a per-method basis\n- traits bound by `Sized` can't be made into trait objects\n\n\n\n### Trait Object Limitations\n\nEven if a trait is object-safe there are still sizedness-related edge cases which limit what types can be cast to trait objects and how many and what kind of traits can be represented by a trait object.\n\n\n\n#### Cannot Cast Unsized Types to Trait Objects\n\n```rust\nfn generic<T: ToString>(t: T) {}\nfn trait_object(t: &dyn ToString) {}\n\nfn main() {\n    generic(String::from(\"String\")); // ✅\n    generic(\"str\"); // ✅\n    trait_object(&String::from(\"String\")); // ✅ - unsized coercion\n    trait_object(\"str\"); // ❌ - unsized coercion impossible\n}\n```\n\nThrows:\n\n```none\nerror[E0277]: the size for values of type `str` cannot be known at compilation time\n --> src/main.rs:8:18\n  |\n8 |     trait_object(\"str\");\n  |                  ^^^^^ doesn't have a size known at compile-time\n  |\n  = help: the trait `std::marker::Sized` is not implemented for `str`\n  = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>\n  = note: required for the cast to the object type `dyn std::string::ToString`\n```\n\nThe reason why passing a `&String` to a function expecting a `&dyn ToString` works is because of type coercion. `String` implements `ToString` and we can convert a sized type such as `String` into an unsized type such as `dyn ToString` via an unsized coercion. `str` also implements `ToString` and converting `str` into a `dyn ToString` would also require an unsized coercion but `str` is already unsized! How do we unsize an already unsized type into another unsized type?\n\n`&str` pointers are double-width, storing a pointer to the data and the data length. `&dyn ToString` pointers are also double-width, storing a pointer to the data and a pointer to a vtable. To coerce a `&str` into a `&dyn toString` would require a triple-width pointer to store a pointer to the data, the data length, and a pointer to a vtable. Rust does not support triple-width pointers so casting an unsized type to a trait object is not possible.\n\nPrevious two paragraphs summarized in a table:\n\n| Type | Pointer to Data | Data Length | Pointer to VTable | Total Width |\n|-|-|-|-|-|\n| `&String` | ✅ | ❌ | ❌ | 1 ✅ |\n| `&str` | ✅ | ✅ | ❌ | 2 ✅ |\n| `&String as &dyn ToString` | ✅ | ❌ | ✅ | 2 ✅ |\n| `&str as &dyn ToString` | ✅ | ✅ | ✅ | 3 ❌ |\n\n\n\n#### Cannot create Multi-Trait Objects\n\n```rust\ntrait Trait {}\ntrait Trait2 {}\n\nfn function(t: &(dyn Trait + Trait2)) {}\n```\n\nThrows:\n\n```none\nerror[E0225]: only auto traits can be used as additional traits in a trait object\n --> src/lib.rs:4:30\n  |\n4 | fn function(t: &(dyn Trait + Trait2)) {}\n  |                      -----   ^^^^^^\n  |                      |       |\n  |                      |       additional non-auto trait\n  |                      |       trait alias used in trait object type (additional use)\n  |                      first non-auto trait\n  |                      trait alias used in trait object type (first use)\n```\n\nRemember that a trait object pointer is double-width: storing 1 pointer to the data and another to the vtable, but there's 2 traits here so there's 2 vtables which would require the `&(dyn Trait + Trait2)` pointer to be 3 widths. Auto-traits like `Sync` and `Send` are allowed since they don't have methods and thus don't have vtables.\n\nThe workaround for this is to combine vtables by combining the traits using another trait like so:\n\n```rust\ntrait Trait {\n    fn method(&self) {}\n}\n\ntrait Trait2 {\n    fn method2(&self) {}\n}\n\ntrait Trait3: Trait + Trait2 {}\n\n// auto blanket impl Trait3 for any type that also impls Trait & Trait2\nimpl<T: Trait + Trait2> Trait3 for T {}\n\n// from `dyn Trait + Trait2` to `dyn Trait3` \nfn function(t: &dyn Trait3) {\n    t.method(); // ✅\n    t.method2(); // ✅\n}\n```\n\nOne downside of this workaround is that Rust does not support supertrait upcasting. What this means is that if we have a `dyn Trait3` we can't use it where we need a `dyn Trait` or a `dyn Trait2`. This program does not compile:\n\n```rust\ntrait Trait {\n    fn method(&self) {}\n}\n\ntrait Trait2 {\n    fn method2(&self) {}\n}\n\ntrait Trait3: Trait + Trait2 {}\n\nimpl<T: Trait + Trait2> Trait3 for T {}\n\nstruct Struct;\nimpl Trait for Struct {}\nimpl Trait2 for Struct {}\n\nfn takes_trait(t: &dyn Trait) {}\nfn takes_trait2(t: &dyn Trait2) {}\n\nfn main() {\n    let t: &dyn Trait3 = &Struct;\n    takes_trait(t); // ❌\n    takes_trait2(t); // ❌\n}\n```\n\nThrows:\n\n```none\nerror[E0308]: mismatched types\n  --> src/main.rs:22:17\n   |\n22 |     takes_trait(t);\n   |                 ^ expected trait `Trait`, found trait `Trait3`\n   |\n   = note: expected reference `&dyn Trait`\n              found reference `&dyn Trait3`\n\nerror[E0308]: mismatched types\n  --> src/main.rs:23:18\n   |\n23 |     takes_trait2(t);\n   |                  ^ expected trait `Trait2`, found trait `Trait3`\n   |\n   = note: expected reference `&dyn Trait2`\n              found reference `&dyn Trait3`\n```\n\nThis is because `dyn Trait3` is a distinct type from `dyn Trait` and `dyn Trait2` in the sense that they have different vtable layouts, although `dyn Trait3` does contain all the methods of `dyn Trait` and `dyn Trait2`. The workaround here is to add explicit casting methods:\n\n```rust\ntrait Trait {}\ntrait Trait2 {}\n\ntrait Trait3: Trait + Trait2 {\n    fn as_trait(&self) -> &dyn Trait;\n    fn as_trait2(&self) -> &dyn Trait2;\n}\n\nimpl<T: Trait + Trait2> Trait3 for T {\n    fn as_trait(&self) -> &dyn Trait {\n        self\n    }\n    fn as_trait2(&self) -> &dyn Trait2 {\n        self\n    }\n}\n\nstruct Struct;\nimpl Trait for Struct {}\nimpl Trait2 for Struct {}\n\nfn takes_trait(t: &dyn Trait) {}\nfn takes_trait2(t: &dyn Trait2) {}\n\nfn main() {\n    let t: &dyn Trait3 = &Struct;\n    takes_trait(t.as_trait()); // ✅\n    takes_trait2(t.as_trait2()); // ✅\n}\n```\n\nThis is a simple and straight-forward workaround that seems like something the Rust compiler could automate for us. Rust is not shy about performing type coercions as we have seen with deref and unsized coercions, so why isn't there a trait upcasting coercion? This is a good question with a familiar answer: the Rust core team is working on other higher-priority and higher-impact features. Fair enough.\n\n**Key Takeaways**\n- Rust doesn't support pointers wider than 2 widths so\n    - we can't cast unsized types to trait objects\n    - we can't have multi-trait objects, but we can work around this by coalescing multiple traits into a single trait\n\n\n\n### User-Defined Unsized Types\n\n```rust\nstruct Unsized {\n    unsized_field: [i32],\n}\n```\n\nWe can define an unsized struct by giving the struct an unsized field. Unsized structs can only have 1 unsized field and it must be the last field in the struct. This is a requirement so that the compiler can determine the starting offset of every field in the struct at compile-time, which is important for efficient and fast field access. Furthermore, a single unsized field is the most that can be tracked using a double-width pointer, as more unsized fields would require more widths.\n\nSo how do we even instantiate this thing? The same way we do with any unsized type: by first making a sized version of it then coercing it into the unsized version. However, `Unsized` is always unsized by definition, there's no way to make a sized version of it! The only workaround is to make the struct generic so that it can exist in both sized and unsized versions:\n\n```rust\nstruct MaybeSized<T: ?Sized> {\n    maybe_sized: T,\n}\n\nfn main() {\n    // unsized coercion from MaybeSized<[i32; 3]> to MaybeSized<[i32]>\n    let ms: &MaybeSized<[i32]> = &MaybeSized { maybe_sized: [1, 2, 3] };\n}\n```\n\nSo what are the use-cases of this? There aren't any particularly compelling ones, user-defined unsized types are a pretty half-baked feature right now and their limitations outweigh any benefits. They're mentioned here purely for the sake of comprehensiveness.\n\n**Fun fact:** `std::ffi::OsStr` and `std::path::Path` are 2 unsized structs in the standard library that you've probably used before without realizing!\n\n**Key Takeaways**\n- user-defined unsized types are a half-baked feature right now and their limitations outweigh any benefits\n\n\n\n## Zero-Sized Types\n\nZSTs sound exotic at first but they're used everywhere.\n\n\n\n### Unit Type\n\nThe most common ZST is the unit type: `()`. All empty blocks `{}` evaluate to `()` and if the block is non-empty but the last expression is discarded with a semicolon `;` then it also evaluates to `()`. Example:\n\n```rust\nfn main() {\n    let a: () = {};\n    let b: i32 = {\n        5\n    };\n    let c: () = {\n        5;\n    };\n}\n```\n\nEvery function which doesn't have an explicit return type returns `()` by default.\n\n```rust\n// with sugar\nfn function() {}\n\n// desugared\nfn function() -> () {}\n```\n\nSince `()` is zero bytes all instances of `()` are the same which makes for some really simple `Default`, `PartialEq`, and `Ord` implementations:\n\n```rust\nuse std::cmp::Ordering;\n\nimpl Default for () {\n    fn default() {}\n}\n\nimpl PartialEq for () {\n    fn eq(&self, _other: &()) -> bool {\n        true\n    }\n    fn ne(&self, _other: &()) -> bool {\n        false\n    }\n}\n\nimpl Ord for () {\n    fn cmp(&self, _other: &()) -> Ordering {\n        Ordering::Equal\n    }\n}\n```\n\nThe compiler understands `()` is zero-sized and optimizes away interactions with instances of `()`. For example, a `Vec<()>` will never make any heap allocations, and pushing and popping `()` from the `Vec` just increments and decrements its `len` field:\n\n```rust\nfn main() {\n    // zero capacity is all the capacity we need to \"store\" infinitely many ()\n    let mut vec: Vec<()> = Vec::with_capacity(0);\n    // causes no heap allocations or vec capacity changes\n    vec.push(()); // len++\n    vec.push(()); // len++\n    vec.push(()); // len++\n    vec.pop(); // len--\n    assert_eq!(2, vec.len());\n}\n```\n\nThe above example has no practical applications, but is there any situation where we can take advantage of the above idea in a meaningful way? Surprisingly yes, we can get an efficient `HashSet<Key>` implementation from a `HashMap<Key, Value>` by setting the `Value` to `()` which is exactly how `HashSet` in the Rust standard library works:\n\n```rust\n// std::collections::HashSet\npub struct HashSet<T> {\n    map: HashMap<T, ()>,\n}\n```\n\n**Key Takeaways**\n- all instances of a ZST are equal to each other\n- Rust compiler knows to optimize away interactions with ZSTs\n\n\n\n### User-Defined Unit Structs\n\nA unit struct is any struct without any fields, e.g.\n\n```rust\nstruct Struct;\n```\n\nProperties that make unit structs more useful than `()`:\n- we can implement whatever traits we want on our own unit structs, Rust's trait orphan rules prevent us from implementing traits for `()` as it's defined in the standard library\n- unit structs can be given meaningful names within the context of our program\n- unit structs, like all structs, are non-Copy by default, which may be important in the context of our program\n\n\n\n### Never Type\n\nThe second most common ZST is the never type: `!`. It's called the never type because it represents computations that never resolve to any value at all.\n\nA couple interesting properties of `!` that make it different from `()`:\n- `!` can be coerced into any other type\n- it's not possible to create instances of `!`\n\nThe first interesting property is very useful for ergonomics and allows us to use handy macros like these:\n\n```rust\n// nice for quick prototyping\nfn example<T>(t: &[T]) -> Vec<T> {\n    unimplemented!() // ! coerced to Vec<T>\n}\n\nfn example2() -> i32 {\n    // we know this parse call will never fail\n    match \"123\".parse::<i32>() {\n        Ok(num) => num,\n        Err(_) => unreachable!(), // ! coerced to i32\n    }\n}\n\nfn example3(some_condition: bool) -> &'static str {\n    if !some_condition {\n        panic!() // ! coerced to &str\n    } else {\n        \"str\"\n    }\n}\n```\n\n`break`, `continue`, and `return` expressions also have type `!`:\n\n```rust\nfn example() -> i32 {\n    // we can set the type of x to anything here\n    // since the block never evaluates to any value\n    let x: String = {\n        return 123 // ! coerced to String\n    };\n}\n\nfn example2(nums: &[i32]) -> Vec<i32> {\n    let mut filtered = Vec::new();\n    for num in nums {\n        filtered.push(\n            if *num < 0 {\n                break // ! coerced to i32\n            } else if *num % 2 == 0 {\n                *num\n            } else {\n                continue // ! coerced to i32\n            }\n        );\n    }\n    filtered\n}\n```\n\nThe second interesting property of `!` allows us to mark certain states as impossible on a type level. Let's take this function signature as an example:\n\n```rust\nfn function() -> Result<Success, Error>;\n```\n\nWe know that if the function returns and was successful the `Result` will contain some instance of type `Success` and if it errored `Result` will contain some instance of type `Error`. Now let's compare that to this function signature:\n\n```rust\nfn function() -> Result<Success, !>;\n```\n\nWe know that if the function returns and was successful the `Result` will hold some instance of type `Success` and if it errored... but wait, it can never error, since it's impossible to create instances of `!`. Given the above function signature we know this function will never error. How about this function signature:\n\n```rust\nfn function() -> Result<!, Error>;\n```\n\nThe inverse of the previous is now true: if this function returns we know it must have errored as success is impossible.\n\nA practical application of the former example would be the `FromStr` implementation for `String` as it's impossible to fail converting a `&str` into a `String`:\n\n```rust\n#![feature(never_type)]\n\nuse std::str::FromStr;\n\nimpl FromStr for String {\n    type Err = !;\n    fn from_str(s: &str) -> Result<String, Self::Err> {\n        Ok(String::from(s))\n    }\n}\n```\n\nA practical application of the latter example would be a function that runs an infinite loop that's never meant to return, like a server responding to client requests, unless there's some error:\n\n```rust\n#![feature(never_type)]\n\nfn run_server() -> Result<!, ConnectionError> {\n    loop {\n        let (request, response) = get_request()?;\n        let result = request.process();\n        response.send(result);\n    }\n}\n```\n\nThe feature flag is necessary because while the never type exists and works within Rust internals using it in user-code is still considered experimental.\n\n**Key Takeaways**\n- `!` can be coerced into any other type\n- it's not possible to create instances of `!` which we can use to mark certain states as impossible at a type level\n\n\n\n### User-Defined Pseudo Never Types\n\nWhile it's not possible to define a type that can coerce to any other type it is possible to define a type which is impossible to create instances of such as an `enum` without any variants:\n\n```rust\nenum Void {}\n```\n\nThis allows us to remove the feature flag from the previous two examples and implement them using stable Rust:\n\n```rust\nenum Void {}\n\n// example 1\nimpl FromStr for String {\n    type Err = Void;\n    fn from_str(s: &str) -> Result<String, Self::Err> {\n        Ok(String::from(s))\n    }\n}\n\n// example 2\nfn run_server() -> Result<Void, ConnectionError> {\n    loop {\n        let (request, response) = get_request()?;\n        let result = request.process();\n        response.send(result);\n    }\n}\n```\n\nThis is the technique the Rust standard library uses, as the `Err` type for the `FromStr` implementation of `String` is `std::convert::Infallible` which is defined as:\n\n```rust\npub enum Infallible {}\n```\n\n\n\n### PhantomData\n\nThe third most commonly used ZST is probably `PhantomData`. `PhantomData` is a zero-sized marker struct which can be used to \"mark\" a containing struct as having certain properties. It's similar in purpose to its auto marker trait cousins such as `Sized`, `Send`, and `Sync` but being a marker struct is used a little bit differently. Giving a thorough explanation of `PhantomData` and exploring all of its use-cases is outside the scope of this article so let's only briefly go over a single simple example. Recall this code snippet presented earlier:\n\n```rust\n#![feature(negative_impls)]\n\n// this type is Send and Sync\nstruct Struct;\n\n// opt-out of Send trait\nimpl !Send for Struct {}\n\n// opt-out of Sync trait\nimpl !Sync for Struct {}\n```\n\nIt's unfortunate that we have to use a feature flag, can we accomplish the same result using only stable Rust? As we've learned, a type is only `Send` and `Sync` if all of its members are also `Send` and `Sync`, so we can add a `!Send` and `!Sync` member to `Struct` like `Rc<()>`:\n\n```rust\nuse std::rc::Rc;\n\n// this type is not Send or Sync\nstruct Struct {\n    // adds 8 bytes to every instance\n    _not_send_or_sync: Rc<()>,\n}\n```\n\nThis is less than ideal because it adds size to every instance of `Struct` and we now also have to conjure a `Rc<()>` from thin air every time we want to create a `Struct`. Since `PhantomData` is a ZST it solves both of these problems:\n\n```rust\nuse std::rc::Rc;\nuse std::marker::PhantomData;\n\ntype NotSendOrSyncPhantom = PhantomData<Rc<()>>;\n\n// this type is not Send or Sync\nstruct Struct {\n    // adds no additional size to instances\n    _not_send_or_sync: NotSendOrSyncPhantom,\n}\n```\n\n**Key Takeaways**\n- `PhantomData` is a zero-sized marker struct which can be used to \"mark\" a containing struct as having certain properties\n\n\n\n## Conclusion\n\n- only instances of sized types can be placed on the stack, i.e. can be passed around by value\n- instances of unsized types can't be placed on the stack and must be passed around by reference\n- pointers to unsized types are double-width because aside from pointing to data they need to do an extra bit of bookkeeping to also keep track of the data's length _or_ point to a vtable\n- `Sized` is an \"auto\" marker trait\n- all generic type parameters are auto-bound with `Sized` by default\n- if we have a generic function which takes an argument of some `T` behind a pointer, e.g. `&T`, `Box<T>`, `Rc<T>`, et cetera, then we almost always want to opt-out of the default `Sized` bound with `T: ?Sized`\n- leveraging slices and Rust's auto type coercions allows us to write flexible APIs\n- all traits are `?Sized` by default\n- `Trait: ?Sized` is required for `impl Trait for dyn Trait`\n- we can require `Self: Sized` on a per-method basis\n- traits bound by `Sized` can't be made into trait objects\n- Rust doesn't support pointers wider than 2 widths so\n    - we can't cast unsized types to trait objects\n    - we can't have multi-trait objects, but we can work around this by coalescing multiple traits into a single trait\n- user-defined unsized types are a half-baked feature right now and their limitations outweigh any benefits\n- all instances of a ZST are equal to each other\n- Rust compiler knows to optimize away interactions with ZSTs\n- `!` can be coerced into any other type\n- it's not possible to create instances of `!` which we can use to mark certain states as impossible at a type level\n- `PhantomData` is a zero-sized marker struct which can be used to \"mark\" a containing struct as having certain properties\n\n\n\n## Discuss\n\nDiscuss this article on\n- [official Rust users forum](https://users.rust-lang.org/t/blog-post-sizedness-in-rust/46293?u=pretzelhammer)\n- [learnrust subreddit](https://www.reddit.com/r/learnrust/comments/hx2jd0/sizedness_in_rust/)\n- [rust subreddit](https://www.reddit.com/r/rust/comments/hxips7/sizedness_in_rust/)\n- [Github](https://github.com/pretzelhammer/rust-blog/discussions)\n\n\n## Further Reading\n\n- [Common Rust Lifetime Misconceptions](./common-rust-lifetime-misconceptions.md)\n- [Tour of Rust's Standard Library Traits](./tour-of-rusts-standard-library-traits.md)\n- [Beginner's Guide to Concurrent Programming: Coding a Multithreaded Chat Server using Tokio](./chat-server.md)\n- [Learning Rust in 2024](./learning-rust-in-2024.md)\n- [Using Rust in Non-Rust Servers to Improve Performance](./rust-in-non-rust-servers.md)\n- [RESTful API in Sync & Async Rust](./restful-api-in-sync-and-async-rust.md)\n- [Learn Assembly with Entirely Too Many Brainfuck Compilers](./too-many-brainfuck-compilers.md)\n\n\n## Notifications\n\nGet notified when a new blog post gets published by\n- Subscribing to this repo's [releases RSS feed](https://github.com/pretzelhammer/rust-blog/releases.atom) or\n- Watching this repo's releases (click `Watch` → click `Custom` → select `Releases` → click `Apply`)\n"
  },
  {
    "path": "posts/too-many-brainfuck-compilers.md",
    "content": "# Learn Assembly by Writing Entirely Too Many Brainfuck Compilers\n\n_01 November 2020 · #assembly · #compilers_\n\n**Table of Contents**\n- [Intro](#intro)\n- [What is brainfuck?](#what-is-brainfuck)\n- [Interpreting brainfuck](#interpreting-brainfuck)\n- [What is assembly?](#what-is-assembly)\n- [Intro to x86](#intro-to-x86)\n- [Compiling brainfuck to x86](#compiling-brainfuck-to-x86)\n- [Intro to ARM](#intro-to-arm)\n- [Compiling brainfuck to ARM](#compiling-brainfuck-to-arm)\n- [Intro to WebAssembly](#intro-to-webassembly)\n- [Compiling brainfuck to WebAssembly](#compiling-brainfuck-to-webassembly)\n- [Intro to LLVM](#intro-to-llvm)\n- [Compiling brainfuck to LLVM](#compiling-brainfuck-to-llvm)\n- [Optimization opportunities](#optimization-opportunities)\n- [Concluding thoughts](#concluding-thoughts)\n- [Discuss](#discuss)\n- [Further Reading](#further-reading)\n- [Notifications](#notifications)\n\n\n\n## Intro\n\nHey you! Have you ever wanted to become a _CPU Whisperer_? Me too! I'm a frontend web developer by trade but low-level assembly code and compilers have always fascinated me. I've procrastinated on learning either for a long time but after I recently picked up Rust and have been hanging out in a lot of online Rust communities it's given me the kick in the butt to dive in. Rustaceans use fancy words and acronyms like _auto-vectorization_, _inlining_, _alignment_, _padding_, _linking_, _custom allocators_, _endianness_, _system calls_, _LLVM_, _SIMD_, _ABI_, _TLS_ and I feel bad for not being able to follow the discussions because I don't know what any of that stuff is. All I know is that it vaguely relates to low-level assembly code somehow so I decided I'd learn assembly by writing entirely too many brainfuck compilers in Rust. How many is too many? Four! My compile targets are going to be x86, ARM, WebAssembly, and LLVM.\n\nThe goal of this article is to be easily-digestible for anyone who has a modest amount of programming experience under their belt, even if they've never written a single line of assembly before.\n\nSo why x86? x86 is not just an ISA but it is _the_ ISA. Most servers, desktop PCs, laptops, and home gaming consoles use x86 CPUs.\n\nWhy ARM? ARM is not just an ISA but it is _the other_ ISA. Most mobile phones, tablets, mobile gaming consoles, and microcontrollers use ARM CPUs. Also Apple announced they will be switching all their laptops and desktops from x86 to ARM CPUs in 2021 which seems like a Pretty Big Deal.\n\nWhy WebAssembly? WebAssembly has the potential to be the future of the web and also the future of containerized applications in general! Solomon Hykes, the creator of Docker, has tweeted _\"If WASM + WASI existed in 2008, we wouldn't have needed to create Docker. That's how important it is. WebAssembly on the server is the future of computing. A standardized system interface was the missing link. Let's hope WASI is up to the task!\"_\n\nWhy LLVM? LLVM because it can compile to x86, ARM, or WebAssembly. Also because many modern and successful programming languages like Rust and Swift compile to LLVM instead of to assembly directly.\n\nSince all of the above targets go by many names here's a quick list of their aliases:\n- 64-bit x86 is also called: x86_64, x64, AMD64\n- 64-bit ARM is also called: aarch64, ARM64\n- 32-bit WebAssembly is also called: wasm32\n- LLVM is short for LLVM IR (Intermediate Representation)\n\nIf you'd like to play around with the code in this article yourself then you're in luck! The article comes with a [companion code repository](https://github.com/pretzelhammer/brainfuck_compilers) which contains all the code and instructions on how to run it. Following along using the companion code repository is completely optional and the article can be easily read without it.\n\n\n\n## What is brainfuck?\n\nBrainfuck is, oxymoronically, the most well-known esoteric programming language. It's fame largely comes from the fact it has the word \"fuck\" in its name but hobbyist compiler developers like it because it's a tiny language which makes it easy to write compilers for. Fun fact: people have written more brainfuck compilers than actual brainfuck programs. Fun fact: I did zero research for that previous fun fact but it's probably true.\n\nOverview of brainfuck:\n\n- Brainfuck programs have an implicit pointer, \"the pointer\", which is free to move around an array of 30k unsigned bytes, all initially set to 0.\n- Decrementing the pointer below 0 or incrementing the pointer above 30k is undefined behavior.\n- Decrementing a byte below 0 or incrementing a byte above 255 wraps its value.\n- The newline character is read and written as the value 10.\n- The EOF (End of File) character is read as the value 0.\n\nBrainfuck commands:\n\n| Command | Description |\n|-|-|\n| `>` | increment pointer |\n| `<` | decrement pointer |\n| `+` | increment current byte |\n| `-` | decrement current byte |\n| `.` | write current byte to stdout |\n| `,` | read byte from stdin and store value in current byte |\n| `[` | jump past matching `]` if current byte is zero |\n| `]` | jump back to matching `[` if current byte is nonzero |\n| any other character | ignore, treat as comment |\n\nAs is customary in introducing any new programming language, here's _\"Hello world!\"_ in brainfuck:\n\n```bf\n++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.\n```\n\n\n\n## Interpreting brainfuck\n\nLet's write a quick brainfuck interpreter first. We're going to parse brainfuck programs into an `Vec<Inst>` where `Inst` is defined as:\n\n```rust\nstruct Inst {\n    idx: usize,         // index of instruction\n    kind: InstKind,     // kind of instruction\n    times: usize,       // run-length encoding of instruction\n}\n\nenum InstKind {\n    IncPtr,\n    DecPtr,\n    IncByte,\n    DecByte,\n    WriteByte,\n    ReadByte,\n    // end_idx = index of instruction after matching LoopEnd\n    LoopStart { end_idx: usize },\n    // start_idx = index of instruction after matching LoopStart\n    LoopEnd { start_idx: usize },\n}\n```\n\nParsing brainfuck programs into the above format, namely: keeping track of every instruction's run-length encoding and calculating the `start_idx` and `end_idx` of loop instructions ahead of time, will allow us to write a much more efficient interpreter and also produce much more efficient assembly from our compilers.\n\nWe'll skip going over the remaining brainfuck interpreter code as it's very unexciting. Let's get to the fun part and try interpreting some brainfuck programs!\n\n> If you're following along using the [companion code repository](https://github.com/pretzelhammer/brainfuck_compilers) the command we'll be using to interpret brainfuck programs is `just interpret {{name}}` where `{{name}}` is the name of the brainfuck source file in the `./input` directory.\n\n```sh\n# prints \"Hello world!\"\n> just interpret hello_world\nHello World!\n\n# prints fibonacci numbers under 100\n> just interpret fibonacci\n1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89\n\n# encrypts lines from stdin using rot13 cipher\n> just interpret rot13\nunencrypted text\nharapelcgrq grkg\n```\n\nCool, we have a working brainfuck interpreter. Let's start digging into assembly.\n\n\n\n## What is assembly?\n\nA slightly better first question is what is an ISA? ISA stands for Instruction Set Architecture. An ISA is an interface which CPUs can implement. The most popular ISAs today are x86_64 and aarch64. If we write code using x86_64 instructions then any CPU which implements the x86_64 ISA will be able to run that code. So is \"assembly\" the same thing as an ISA? Well, not quite. The short answer is that \"assembly\" is any syntax understood by an assembler. An assembler is a utility program that allows people to write machine-code in a more human-friendly way, like with comments, whitespace, and symbolic names for machine instructions. \"Assembly\" therefore is a thin layer of abstraction over an ISA offered by an assembler. The assembler we will be using to assemble all of our x86_64 and aarch64 programs will be the GNU Assembler, often abbreviated to GAS. We'll be using Intel syntax instead of the default AT&T syntax for x86_64 assembly because it's closer to ARM syntax for aarch64 assembly which makes it less jarring to switch between the two. If that last sentence made no sense to you don't worry you're in good company. Also, we'll be executing all the compiled binaries in a Linux environment so we'll be making direct Linux system calls in our assembly programs when necessary.\n\n\n\n## Intro to x86\n\nx86_64 is a register-based ISA. A register is a container where we can store data. We can store data in RAM too but RAM is very far from the CPU whereas registers are directly _in_ the CPU and are where the CPU does all of its actual work. All of the instructions in x86_64 operate on registers directly or indirectly in some way. There are many different kinds of registers: some store integers, some store floats, some store vectors of integers, some are general purpose and some have a special purpose, and some we can modify directly and others we can only modify indirectly (as a byproduct of certain instructions). For the purposes of this article the only registers we'll be using are `rax`, `rdi`, `rsi`, `rdx`, and `r12` which all store 64-bit integers.\n\nLet's learn some instructions.\n\n```s\nmov <dest>, <src>       # dest <- src\n```\n\n`mov` moves something from `<src>` to `<dest>` where `<src>` can be a literal value, register, or memory address and `<dest>` can be a register or memory address.\n\n```s\nmov rax, 5              # store 5 in rax\nmov rsi, rdi            # copy value in rdi to rsi\nmov [r12], 15           # store 15 at the memory address in r12\n```\n\nThe last instruction is actually illegal because it's ambiguous. In the first 2 examples it's clear we're working with 64-bit integers since we're using 64-bit registers as operands, however in the last example we're trying to store the value 15 in the memory address in `r12` but how \"big\" is the value \"15\"? Does it take up 1, 2, 4, or 8 bytes? We need to know how many bytes to write to memory, after all. We can clear up ambiguities by suffixing the ambiguous instruction with `b` (byte), `w` (word, 2 bytes), `l` (longword, 4 bytes), or `q` (quadword, 8 bytes). So we can fix the last instruction in any number of these ways:\n\n```s\nmovb [r12], 15           # write 15 as 1 byte to memory address in r12\nmovw [r12], 15           # write 15 as 2 bytes to memory address in r12\nmovl [r12], 15           # write 15 as 4 bytes to memory address in r12\nmovq [r12], 15           # write 15 as 8 bytes to memory address in r12\n```\n\nAlso, although it may have already been made obvious, if we want to dereference a memory address stored in a register or label we wrap it with square brackets `[]`.\n\n```s\nmov rax, r12            # copy value from r12 to rax\nmov rax, [r12]          # copy value from memory address stored in r12 to rax\n```\n\nSome arithmetic instructions:\n\n```s\nadd <dest>, <src>       # dest <- dest + src\nsub <dest>, <src>       # dest <- dest - src\n```\n\nComparing values:\n\n```s\ncmp <op1>, <op2>        # compare op1 to op2, set flags in special rflags register\n```\n\nControl flow:\n\n```s\njmp <label>             # unconditional jump to <label>\n\n# all instructions below are conditional jumps which check the flags in the rflags register\n\nje <label>              # jump to <label> if equal \njne <label>             # jump to <label> if not equal\njg <label>              # jump to <label> if greater than\njge <label>             # jump to <label> if greater than or equal to\njl <label>              # jump to <label> if less than\njle <label>             # jump to <label> if less than or equal to\n```\n\nPutting all of the above together into an example:\n\n```s\nmov rax, 5              # store 5 in rax\nmov r12, 10             # store 10 in r12\nadd rax, r12            # rax <- rax + r12 = 15\ncmp rax, r12            # set flags in rflags\njge RAX_IS_LARGER       # read flags in rflags, jump to RAX_IS_LARGER\n\nR12_IS_LARGER:\n# some instructions\njmp END\n\nRAX_IS_LARGER:\n# some other instructions\n\nEND:\n# more instructions\n```\n\nThe rules for how to use registers before, during, and after a function call for both the caller and callee is called a _Calling Convention_. The problem with calling conventions is that it seems everyone and their grandma has one. ISAs, Operating Systems, and programming languages which compile to assembly can each define their own different calling conventions. Luckily for us it's not possible to define functions in brainfuck so we don't have to get into the nitty gritty details of any calling conventions in this article.\n\nTo make a system call we use the `syscall` instruction after setting the system call number in `rax` and the system call arguments in the `rdi`, `rsi`, and `rdx` registers.\n\n```s\n# direct Linux system calls\n\nmov rax, 60             # syscall number for exit(code)\nmov rdi, 0              # exit code, 0 for success\nsyscall                 # make system call\n\nmov rax, 0              # syscall number for read(fd, buf_adr, buf_len)\nmov rdi, 0              # file descriptor for stdin\nmov rsi, 1234           # memory address to some buffer\nmov rdx, 1              # buffer's length in bytes\nsyscall                 # make system call\n# syscall returns number of bytes read in rax\n\nmov rax, 1              # syscall number for write(fd, buf_adr, buf_len)\nmov rdi, 1              # file descriptor for stdout\nmov rsi, 1234           # memory address to some buffer\nmov rdx, 1              # buffer's length in bytes\nsyscall                 # make system call\n# syscall returns number of bytes written in rax\n```\n\nWe now know a handful of x86_64 instructions, enough to write a brainfuck compiler actually, and yet we still haven't put together a single complete program yet. This is where the assembler comes in. As mentioned above we'll be using GNU Assembler for all our x86_64 code. Let's take a look at a simple x86_64 program that just exits.\n\n```s\n# ./examples/x86_64/exit.s\n\n# GNU Assembler, Intel syntax, x86_64 Linux\n\n.data\n\n.equ SYS_EXIT, 60\n.equ EXIT_CODE, 0\n\n.text\n\n.global _start\n\n_start:\n    # exit(code)\n    mov rax, SYS_EXIT\n    mov rdi, EXIT_CODE\n    syscall\n```\n\nUnpacking the new stuff:\n- Words prefixed with a dot `.` are called _assembler directives_ and they direct the assembler on how to assemble our assembly.\n- `.data` means _\"Everything below this directive is program data.\"_\n- `.equ <symbol>, <literal>` means declare a constant `<symbol>` equal to value `<literal>`.\n- `.text` means _\"Everything below this directive is program instructions.\"_\n- Words suffixed by a colon `:` are labels and they can point to data or instructions. The `_start` label points to the first instruction of our program.\n- `.global <label>` means _\"Make `<label>` visible to the linker.\"_ The linker is a program which converts the assembled output of our assembler into an actual executable program, and it needs to know where our program begins, hence the `_start` label.\n\nTo make our program a little more exciting let's read a character from stdin, and if it's lowercase we'll make it uppercase, and if it's uppercase we'll make it lowercase, and then we'll write the switched case character to stdout.\n\n```s\n# ./examples/x86_64/switch_case.s\n\n# GNU Assembler, Intel syntax, x86_64 Linux\n\n.data\n\n# exit(code)\n.equ SYS_EXIT, 60\n.equ EXIT_CODE, 0\n\n# write(fd, buf_adr, buf_len)\n.equ SYS_WRITE, 1\n.equ STDOUT, 1\n\n# read(fd, buf_adr, buf_len)\n.equ SYS_READ, 0\n.equ STDIN, 0\n\n# ASCII code for lowercase 'a'\n.equ ASCII_A, 97\n\n# Quick ASCII refresher:\n# 65 - 91 = 'A' - 'Z'\n# 97 - 123 = 'a' - 'z'\n\n# e.g.\n# 'A' + 32 = 'a'\n# 'a' - 32 = 'A' \n.equ CASE_DIFF, 32\n\n# single byte in memory\nCHAR:\n    .byte 0\n\n.text\n\n.global _start\n\n_start:\n    # read(STDIN, CHAR, 1)\n    mov rax, SYS_READ\n    mov rdi, STDIN\n    mov rsi, offset CHAR\n    mov rdx, 1\n    syscall\n\n    cmpb [CHAR], ASCII_A        # if byte at CHAR is lowercase\n    jge MAKE_UPPERCASE          # make it uppercase\n\nMAKE_LOWERCASE:                 # else make it lowercase\n    addb [CHAR], CASE_DIFF      # lowercase byte at CHAR\n    jmp WRITE                   # then write it to stdout\n\nMAKE_UPPERCASE:\n    subb [CHAR], CASE_DIFF      # uppercase byte at CHAR\n\nWRITE:                          # write byte to stdout\n    # write(STDOUT, CHAR, 1)\n    mov rax, SYS_WRITE\n    mov rdi, STDOUT\n    mov rsi, offset CHAR\n    mov rdx, 1\n    syscall\n\n    # exit(EXIT_CODE)\n    mov rax, SYS_EXIT\n    mov rdi, EXIT_CODE\n    syscall\n```\n\nUnpacking the new stuff:\n- `.byte` allows us to define an array of bytes by writing a comma-separated list of integer literals. In the above program we only needed 1 byte.\n- By default, GAS dereferences labels, so `mov rsi, CHAR` would copy the value `0` into `rsi`. However, we don't want to copy the value at `CHAR` but we want to copy the literal value of `CHAR` itself, i.e. its memory address. We can do this using the `offset` keyword, which we do in `mov rsi, offset CHAR`.\n\n> If you're following along using the [companion code repository](https://github.com/pretzelhammer/brainfuck_compilers) the command we'll be using to compile and run x86_64 example programs is `just carx {{name}}` where `{{name}}` is the name of the x86_64 source file in the `./examples/x86_64` directory.\n\n```sh\n# reads char from stdin, switches its case, prints to stdout\n\n> just carx switch_case\na\nA\nExit code: 0\n\n> just carx switch_case\nA\na\nExit code: 0\n```\n\n\n\n## Compiling brainfuck to x86\n\nAlright, first thing's first, we need a zero-initialized array of 30k bytes. Given what we learned in the previous section we could generate the following code with our compiler:\n\n```s\n.data\n\nARRAY:\n    .byte 0, 0, 0, 0, 0, ... (29,995 more times)\n```\n\nHowever, even for a compiler generated solution, it looks pretty dumb. Luckily for us there's an easier way to define large amounts of zero-initialized data:\n\n```s\n.bss\n\n.lcomm ARRAY, 30000\n```\n\n`.bss` is similar to `.data` in the sense that we define data items below it, but the main difference is we don't initialize the data items, we just declare their size, and they are automatically zero initialized for us. `.lcomm ARRAY, 30000` means, _\"Make symbol `ARRAY` point to a zero-initialized array of 30k bytes.\"_\n\nOne last tiny decision we have to make is which register we'll be using to store our array pointer. There's a lot to choose from, but let's go with `r12` because it's a general-purpose callee-saved register which means if we make any function or system calls we're guaranteed those calls won't overwrite `r12`.\n\nNow that we have that out of the way we can generate the header and footer boilerplate for any compiled brainfuck program:\n\n```s\n### header boilerplate ###\n\n# GNU Assembler, Intel syntax, x86_64 Linux\n\n.data\n\n.equ SYS_EXIT, 60\n.equ SUCCESS, 9\n\n.equ SYS_WRITE, 1\n.equ STDOUT, 1\n\n.equ SYS_READ, 0\n.equ STDIN, 0 \n\n.bss\n\n.lcomm ARRAY, 30000\n\n.text\n\n.global _start\n\n_start:\n    mov r12, offset ARRAY\n\n###############################################\n# actual compiled brainfuck program goes here #\n###############################################\n\n### footer boilerplate ###\n\n    mov rax, SYS_EXIT\n    mov rdi, SUCCESS\n    syscall\n```\n\nLet's now map brainfuck commands to x86_64 instructions. We should also consider how we can coalesce multiple repeating commands into single instructions.\n\n```s\n# increment array pointer\n\n# >\nadd r12, 1\n\n# >>\nadd r12, 2\n\n# decrement array pointer\n\n# <\nsub r12, 1\n\n# <<\nsub r12, 2\n\n# increment byte at pointer\n\n# +\naddb [r12], 1\n\n# ++\naddb [r12], 2\n\n# decrement byte at pointer\n\n# -\nsubb [r12], 1\n\n# --\nsubb [r12], 2\n\n# read byte from stdin & store at pointer\n\n# ,\nmov rax, SYS_READ\nmov rdi, STDIN\nmov rsi, r12\nmov rdx, 1\nsyscall\n\n# ,,\nmov rax, SYS_READ\nmov rdi, STDIN\nmov rsi, r12\nmov rdx, 1\nsyscall\nmov rax, SYS_READ\nmov rdi, STDIN\nmov rsi, r12\nmov rdx, 1\nsyscall\n\n# write byte at pointer to stdout\n\n# .\nmov rax, SYS_WRITE\nmov rdi, STDOUT\nmov rsi, r12\nmov rdx, 1\nsyscall\n\n# ..\nmov rax, SYS_WRITE\nmov rdi, STDOUT\nmov rsi, r12\nmov rdx, 1\nsyscall\nmov rax, SYS_WRITE\nmov rdi, STDOUT\nmov rsi, r12\nmov rdx, 1\nsyscall\n```\n\nUnfortunately there's no simple way to coalesce multiple `,` or `.` commands into less instructions than it takes to execute a single `,` or `.` because the registers we set up for the system calls can be overwritten by the system call procedures so we have to reset the registers again before every call.\n\n```s\n# loops\n\n# [\ncmpb [r12], 0\nje LOOP_END_1\nLOOP_START_0:\n\n# ]\ncmpb [r12], 0\njne LOOP_START_0\nLOOP_END_1:\n```\n\nGenerating matching labels for matching loops is a problem we already solved in our parser. To examine the simplest case, our parser will parse the following brainfuck program `[-]` like so:\n\n```rust\n[\n    Inst {\n        idx: 0,\n        kind: InstKind::LoopStart { end_idx: 3 },\n        times: 1,\n    },\n    Inst {\n        idx: 1,\n        kind: InstKind::DecByte,\n        times: 1,\n    },\n    Inst {\n        idx: 2,\n        kind: InstKind::LoopEnd { start_idx: 1 },\n        times: 1,\n    },\n]\n```\n\nUsing the data available to us inside the `LoopStart` instruction we can generate the following labels:\n\n- `LOOP_START_<idx>`\n- `LOOP_END_<end_idx-1>`\n\nUsing the data available to us inside the `LoopEnd` instruction we can generate the following labels:\n\n- `LOOP_END_<idx>`\n- `LOOP_START_<start_idx-1>`\n\nFollowing this label generation scheme we're guaranteed matching labels for matching loops.\n\n```s\n# loops\n\n# [[\ncmpb [r12], 0\nje LOOP_END_1\nLOOP_START_0:\n\n# ]]\ncmpb [r12], 0\njne LOOP_START_0\nLOOP_END_1:\n```\n\nMultiple stacked loops is interesting because it's not any different than a single loop. If the current byte is zero it doesn't matter how many `[` we have in a row because it will jump past all of them to the outermost matching `]`. Also, if the current byte is nonzero then it doesn't matter how many `]` we have in a row because it'll jump back to the innermost matching `[`. Our parser handles the hard work of figuring out which jumps to make so our label generation scheme stays the same regardless of how many stacked loops we have in the source code.\n\nAnd we're done, time to give our compiler a test drive.\n\n> If you're following along using the [companion code repository](https://github.com/pretzelhammer/brainfuck_compilers) the command we'll be using to compile brainfuck programs to x86_64 and run them is `just carbx {{name}}` where `{{name}}` is the name of the brainfuck source file in the `./input` directory.\n\n```sh\n# prints \"Hello world!\"\n> just carbx hello_world\nHello World!\n\n# prints fibonacci numbers under 100\n> just carbx fibonacci\n1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89\n\n# encrypts lines from stdin using rot13 cipher\n> just carbx rot13\nunencrypted text\nharapelcgrq grkg\n```\n\nEverything works as expected. I'm curious how much faster the compiled programs are compared to the interpreter so I'll run a very unscientific and informal benchmark by timing how long it takes to interpret the most CPU-intensive brainfuck program `./input/mandelbrot.b` vs how long the x86_64 compiled version takes to execute.\n\n```sh\n> just benchmark mandelbrot\n\n# program outputs omitted\n\n# interpreted mandelbrot.b\n4.95s user 0.01s system 99% cpu 4.960 total\n\n# x86_64 compiled mandelbrot.b\nreal    0m1.214s\nuser    0m1.149s\nsys     0m0.041s\n```\n\nWow, not bad! Our compiled version runs over 4x as fast as the interpreted version. In my opinion this is an impressive improvement given how simplistic brainfuck programs are, we're just moving a single pointer around in a single array and adding or subtracting some bytes.\n\n\n\n## Intro to ARM\n\nLike x86_64, aarch64 is a register-based ISA. We'll be using the following 64-bit registers for our examples and for our compiler `x0`, `x1`, `x2`, `x8`, `x19`, and `x20`.\n\nLet's learn some instructions.\n\n```s\nmov <dest>, <src>       // dest <- src\n```\n\n`mov` moves something from `<src>` to `<dest>` where `<src>` can be a literal value or register and `<dest>` is a register. As you may have noticed, unlike the x86_64 version of `mov`, the aarch64 version of `mov` cannot operate directly on memory. This is not just true for the `mov` instruction but is generally true for all aarch64 instructions. The only aarch64 instructions that can operate on memory are `ldr` and  `str` where `ldr` loads data from memory into registers and `str` stores data from registers into memory. So for example, this single x86_64 instruction:\n\n```s\naddq [r12], 100         // add 100 to the 8-byte integer stored at the memory address in r12\n```\n\nWould take three aarch64 instructions to express:\n\n```s\nldr x20, [x19]          // load 8-byte integer stored at memory address in x19 into x20\nadd x20, x20, 100       // add 100 to integer in x20 and store in x20\nstr x20, [x19]          // store 8-byte integer in x20 to memory address in x19\n```\n\nThis does not mean that x86_64 is 3x \"faster\" or \"more efficient\" than aarch64 because under-the-hood the x86_64 CPU still has to load the value from memory into a register before it can add to it and then it still has to store the updated value back into memory. x86_64 simply offers us the convenience of expressing these 3 operations in a single instruction and aarch64 does not. Similarly to x86_64, both `ldr` and `str` instructions can be appended with suffixes to disambiguate data size: `b` (byte), and `h` (halfword, 2 bytes). To load or store 4 bytes of data we refer to registers with a `w` (word, 4 bytes) prefix instead of the usual `x` (extended word, 8 bytes) prefix. Here's some examples:\n\n```s\nldr x20, [x19]          // load 8 bytes from [x19] into x20\nldr w20, [x19]          // load 4 bytes from [x19] into x20\nldrh w20, [x19]         // load 2 bytes from [x19] into x20\nldrb w20, [x19]         // load 1 byte from [x19] into x20\n\nstr x20, [x19]          // store 8 bytes from x20 into [x19]\nstr w20, [x19]          // store 4 bytes from x20 into [x19]\nstrh w20, [x19]         // store 2 bytes from x20 into [x19]\nstrb w20, [x19]         // store 1 byte from x20 to [x19]\n```\n\nImportant note: `x20` and `w20` are the same register, it's just that referring to it by `x20` accesses all 64 bits of the register and referring to it by `w20` accesses only the lower 32 bits of the register.\n\nSome arithmetic instructions:\n\n```s\nadd <dest>, <op1>, <op2>    // dest <- op1 + op2\nsub <dest>, <op1>, <op2>    // dest <- op1 - op2\n```\n\nComparing values:\n\n```s\ncmp <op1>, <op2>        // compares op1 to op2 and sets flags in the special NZCV register \n```\n\nControl flow:\n\n```s\nb <label>               // unconditionally branch to <label>\n\n// all instructions below are conditional and check the flags in the NZCV register\n\nb.eq <label>            // branch to <label> if equal\nb.ne <label>            // branch to <label> if not equal\nb.gt <label>            // branch to <label> if greater than\nb.ge <label>            // branch to <label> if greater than or equal\nb.lt <label>            // branch to <label> is less than\nb.le <label>            // branch to <label> if less than or equal\n```\n\nTo make a system call we use the `svc 0` instruction after setting the system call number in `x8` and the system call arguments in the `x0`, `x1`, and `x2` registers:\n\n```s\n// direct Linux system calls\n\nmov x8, 93              // syscall number for exit(code)\nmov x0, 0               // exit code, 0 for success\nsvc 0                   // make system call\n\nmov x8, 63              // syscall number for read(fd, buf_adr, buf_len)\nmov x0, 0               // file descriptor for stdin\nmov x1, 1234            // memory address to some buffer\nmov x2, 1               // buffer's length in bytes\nsvc 0                   // make system call\n\nmov x8, 64              // syscall number for write(fd, buf_adr, buf_len)\nmov x0, 1               // file descriptor for stdout\nmov x1, 1234            // memory address to some buffer\nmov x2, 1               // buffer's length in bytes\nsvc 0                   // make system call\n```\n\nAs you may have noticed, the syscall numbers for the same Linux system calls are different between x86_64 and aarch64. As far as I'm aware there's no good reason for this. Also, `svc` is short for _Supervisor Call_ and the `0` just needs to be there.\n\nHere's our `switch_case.s` program from before except ported to aarch64:\n\n```s\n// ./examples/aarch64/switch_case.s\n\n// GNU Assembler, ARM syntax, aarch64 Linux\n\n.data\n\n// exit(code)\n.equ SYS_EXIT, 93\n.equ EXIT_CODE, 0\n\n// write(fd, buf_adr, buf_len)\n.equ SYS_WRITE, 64\n.equ STDOUT, 1\n\n// read(fd, buf_adr, buf_len)\n.equ SYS_READ, 63\n.equ STDIN, 0 \n\n// ASCII code for lowercase 'a'\n.equ ASCII_A, 97\n\n// Quick ASCII refresher:\n// 65 - 91 = 'A' - 'Z'\n// 97 - 123 = 'a' - 'z'\n\n// e.g.\n// 'A' + 32 = 'a'\n// 'a' - 32 = 'A' \n.equ CASE_DIFF, 32\n\nCHAR:\n    .byte 0\n\n.text\n\n.global _start\n\n_start:\n    // read(STDIN, CHAR, 1)\n    mov x8, SYS_READ\n    mov x0, STDIN\n    ldr x1, =CHAR\n    mov x2, 1\n    svc 0\n\n    ldr x19, =CHAR              // load CHAR memory address into x19\n    ldrb w20, [x19]             // load byte at [x19] into w20\n    cmp w20, ASCII_A            // if byte in w20 is lowercase\n    b.ge MAKE_UPPERCASE         // make it uppercase\n\nMAKE_LOWERCASE:                 // else make it lowercase\n    add w20, w20, CASE_DIFF     // lowercase byte in w20\n    b WRITE                     // then write it to stdout\n\nMAKE_UPPERCASE:\n    sub w20, w20, CASE_DIFF     // uppercase byte in w20\n\nWRITE:\n    strb w20, [x19]             // store byte in w20 in [x19]\n\n    // write(STDOUT, CHAR, 1)\n    mov x8, SYS_WRITE\n    mov x0, STDOUT\n    ldr x1, =CHAR\n    mov x2, 1\n    svc 0\n\n    // exit(EXIT_CODE)\n    mov x8, SYS_EXIT\n    mov x0, EXIT_CODE\n    svc 0\n```\n\n> If you're following along using the [companion code repository](https://github.com/pretzelhammer/brainfuck_compilers) the command we'll be using to compile and run aarch64 example programs is `just cara {{name}}` where `{{name}}` is the name of the aarch64 source file in the `./examples/aarch64` directory.\n\n```sh\n# reads char from stdin, switches its case, prints to stdout\n\n> just cara switch_case\nd\nD\nExit code: 0\n\n> just cara switch_case\nG\ng\nExit code: 0\n```\n\n\n\n## Compiling brainfuck to ARM\n\nWe declare a zero-initialized array of 30k bytes with:\n\n```s\n.bss\n\n.lcomm ARRAY, 30000\n```\n\nAs for our pointer and memory storage registers let's use `x19` and `x20` as they are general-purpose callee-saved registers so we're guaranteed they won't be overwritten if we need to make any function or system calls.\n\nOur aarch64 boilerplate:\n\n```s\n// header boilerplate //\n\n// GNU Assembler, ARM syntax, aarch64 Linux\n\n.data\n\n.equ SYS_EXIT, 93\n.equ SUCCESS, 0\n\n.equ SYS_WRITE, 64\n.equ STDOUT, 1\n\n.equ SYS_READ, 63\n.equ STDIN, 0 \n\n.bss\n\n.lcomm ARRAY, 30000\n\n.text\n\n.global _start\n\n_start:\n    ldr x19, =ARRAY\n\n/////////////////////////////////////////////////\n// actual compiled brainfuck program goes here //\n/////////////////////////////////////////////////\n\n// footer boilerplate //\n\n    mov x8, SYS_EXIT\n    mov x0, SUCCESS\n    svc 0\n```\n\nMapping brainfuck commands to aarch64 instructions:\n\n```s\n// increment array pointer\n\n// >\nadd x19, x19, 1\n\n// >>\nadd x19, x19, 2\n\n// decrement array pointer\n\n// <\nsub x19, x19, 1\n\n// <<\nsub x19, x19, 2\n\n// increment byte at pointer\n\n// +\nldrb w20, [x19]\nadd w20, w20, 1\nstrb w20, [x19]\n\n// ++\nldrb w20, [x19]\nadd w20, w20, 2\nstrb w20, [x19]\n\n// decrement byte at pointer\n\n// -\nldrb w20, [x19]\nsub w20, w20, 1\nstrb w20, [x19]\n\n// --\nldrb w20, [x19]\nsub w20, w20, 2\nstrb w20, [x19]\n\n// read byte from stdin & store at pointer\n\n// ,\nmov x8, SYS_READ\nmov x0, STDIN\nmov x1, x19\nmov x2, 1\nsvc 0\n\n// ,,\nmov x8, SYS_READ\nmov x0, STDIN\nmov x1, x19\nmov x2, 1\nsvc 0\nmov x8, SYS_READ\nmov x0, STDIN\nmov x1, x19\nmov x2, 1\nsvc 0\n\n// write byte at pointer to stdout\n\n// .\nmov x8, SYS_WRITE\nmov x0, STDOUT\nmov x1, x19\nmov x2, 1\nsvc 0\n\n// ..\nmov x8, SYS_WRITE\nmov x0, STDOUT\nmov x1, x19\nmov x2, 1\nsvc 0\nmov x8, SYS_WRITE\nmov x0, STDOUT\nmov x1, x19\nmov x2, 1\nsvc 0\n\n// loops\n\n// [\nldrb w20, [x19]\ncmp w20, 0\nb.eq LOOP_END_1\nLOOP_START_0:\n\n// ]\nldrb w20, [x19]\ncmp w20, 0\nb.ne LOOP_START_0\nLOOP_END_1:\n```\n\nWe're done with our compiler. Let's give it a test drive.\n\n> If you're following along using the [companion code repository](https://github.com/pretzelhammer/brainfuck_compilers) the command we'll be using to compile brainfuck programs to aarch64 and run them is `just carba {{name}}` where `{{name}}` is the name of the brainfuck source file in the `./input` directory.\n\n```sh\n# prints \"Hello world!\"\n> just carba hello_world\nHello World!\n\n# prints fibonacci numbers under 100\n> just carba fibonacci\n1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89\n\n# encrypts lines from stdin using rot13 cipher\n> just carba rot13\nunencrypted text\nharapelcgrq grkg\n```\n\nAnd to perform another unscientific and informal benchmark:\n\n```sh\n> just benchmark mandelbrot\n\n# program outputs omitted\n\n# interpreted mandelbrot.b\n4.95s user 0.01s system 99% cpu 4.960 total\n\n# x86_64 compiled mandelbrot.b\nreal    0m1.214s\nuser    0m1.149s\nsys     0m0.041s\n\n# aarch64 compiled mandelbrot.b\nreal    0m4.206s\nuser    0m4.103s\nsys     0m0.083s\n```\n\nThe compiled aarch64 program is only a little faster than the interpreter, and much slower than the compiled x86_64 program, however that's to be expected since I'm running the aarch64 program on an x86_64 machine and using QEMU as an aarch64 CPU emulator. If I was running the aarch64 program on an aarch64 machine I imagine it'd be just as fast as the compiled x86_64 program.\n\n\n\n## Intro to WebAssembly\n\nUnlike both x86_64 and aarch64, wasm32 is a stack-based ISA. All wasm32 instructions operate by pushing and popping values from an implicit stack. Let's start with a simple example:\n\n```wat\ni32.const 4     ;; push value 4 onto stack\ni32.const 5     ;; push value 5 onto stack\ni32.add         ;; pop 2 values from stack, add them, push result onto stack\n```\n\nAfter `i32.const 4` the stack looks like this:\n\n```\n+---------+\n|    4    |\n+---------+\n```\n\nAfter `i32.const 5` the stack looks like this:\n\n```\n+---------+\n|    4    |\n+---------+\n|    5    |\n+---------+\n```\n\nAfter `i32.add` the stack looks like this:\n\n```\n+---------+\n|    9    |\n+---------+\n```\n\nWebAssembly Textual Format (WAT) supports writing instructions using S-expressions so we could also write the above example like this:\n\n```wat\n(i32.add (i32.const 4) (i32.const 5))\n```\n\nBoth formats, a flat list of instructions and instructions in S-expressions, can be used in the same source file and we'll be using both interchangeably in our examples wherever each helps improve readability.\n\nIf we're not interested in a value on the stack we can discard it using the `drop` instruction.\n\n```wat\ni32.const 14        ;; pushes 14 onto stack\ndrop                ;; pops 14 from stack and discards it\n```\n\nUnlike in x86_64 and aarch64, all values and instructions in wasm32 are strongly typed. There are only four data types in wasm32: `i32`, `i64`, `f32`, and `f64`. If we try to mix types between values and instructions we will get a compile error:\n\n```wat\ni32.const 4\ni32.const 5\ni64.add             ;; type mismatch compile error, expected i64s found i32s\n```\n\nFor simplicity and consistency we'll only be using `i32`s for all our examples and our compiler.\n\nSimilarly to aarch64, wasm32 does not allow us to operate on memory directly, so we have to load values from memory to the stack, operate on them, and then store the updated values from the stack back to memory.\n\n```wat\n;; all instructions below pop a memory address from the stack\n;; then push the i32 value at that memory address onto the stack\n\ni32.load8_u         ;; loads unsigned byte value from memory\ni32.load8_s         ;; loads signed byte value from memory\ni32.load16_u        ;; loads unsigned 2-byte value from memory\ni32.load16_s        ;; loads signed 2-byte value from memory\ni32.load            ;; loads 4-byte value from memory\n\n;; example\ni32.const 1000      ;; push memory address 1000 onto stack\ni32.load            ;; loads 4-byte value from memory address 1000\n                    ;; loaded result pushed onto stack\n\n;; all instructions below pop a memory address & value from the stack\n;; and then store that value at that memory address\n\ni32.store8          ;; stores byte at memory address\ni32.store16         ;; stores 2 bytes at memory address\ni32.store           ;; stores 4 bytes at memory address\n\n;; example\ni32.const 1000      ;; push memory address 1000 onto stack\ni32.const 123       ;; push value 123 onto stack\ni32.store           ;; stores 123 at memory address 1000\n```\n\nSome arithmetic instructions:\n\n```wat\n;; both instructions pop 2 values from the stack then push their result onto stack\ni32.add\ni32.sub\n```\n\nComparing values:\n\n```wat\n;; instructions below pop 2 values from the stack\n;; then push the result of the comparison onto the stack\n\ni32.eq              ;; equal\ni32.ne              ;; not equal\ni32.lt_u            ;; less than (unsigned)\ni32.lt_s            ;; less than (signed)\ni32.gt_u            ;; greater than (unsigned)\ni32.gt_s            ;; greater than (signed)\ni32.le_u            ;; less than or equal (unsigned)\ni32.le_s            ;; less than or equal (signed)\ni32.ge_u            ;; greater than or equal (unsigned)\ni32.ge_s            ;; greater than or equal (signed)\n\n;; instruction below pops 1 value from the stack\n;; then pushes the result onto the stack\n\ni32.eqz             ;; equal to zero\n```\n\nIn wasm32 there are no booleans types. Any non-zero integer is interpreted as true and zero is interpreted as false.\n\nUnlike in x86_64 and aarch64, wasm32 doesn't support branching to arbitrary labels. All control flow in wasm32 is \"structured\" and must terminate with an `end` instruction. Furthermore, the behavior of the branching instructions `br` and `br_if` depend on their context within the control flow structure.\n\n```wat\n;; simple if / else example\n\n;; \"if\" pops a value from the stack\nif\n    ;; instructions to run if popped value was true, i.e. non-zero\nelse\n    ;; instructions to run if popped value was false, i.e. zero\nend\n\n;; branching within blocks\n\nblock\n    br 0            ;; unconditionally branches to end of block\n    br_if 0         ;; conditionally branches to end of block \nend\n\n;; branching within loops\n\nloop\n    br 0            ;; unconditionally branches to start of loop\n    br_if 0         ;; conditionally branches to start of loop\nend\n```\n\nSince control flow structures can be nested the number after the `br` and `br_if` instructions refers to which structure to perform the branch on, where `br 0` within a `block` would mean _\"branch to the end of my current block\"_ and `br 1` within a pair of nested `block`s would mean _\"branch to the end of my parent block\"_ and `br 2` within three nested `block`s would mean _\"branch to the end of my grandparent block\"_ and so on. This allows us to build a _\"branch to the end of the loop\"_ instruction by wrapping a `loop` with a `block` and using `br 1` or `br_if 1` like so:\n\n```wat\nblock\n    loop\n        br_if 1     ;; conditionally branch to end of parent block (also end of loop)\n        br_if 0     ;; conditionally branch to start of loop\n    end\nend\n```\n\nwasm32 instructions cannot exist on their own, they must be inside a function. Here's how we define a function:\n\n```wat\n(func $optional_name <optional params> <optional return> <optional locals>\n    <list of instructions>\n)\n```\n\nFunctions begin with an empty stack, but can push their params onto the stack using `local.get <index or $label>` where `index` is the param's index in the parameter list and `$label` is the param's optional label (if it was given one).\n\n```wat\n;; without labels\n(func $my_add (param i32 i32) (result i32)\n    local.get 0\n    local.get 1\n    i32.add\n)\n\n;; with labels\n(func $my_add (param $first i32) (param $second i32) (result i32)\n    local.get $first\n    local.get $second\n    i32.add\n)\n```\n\nFunctions can return at most one value (although this restriction will be relaxed in the future). If the function returns a value then the stack at the end of the function must have exactly 1 value in it. If the function doesn't return a value then the stack at the end of the function must be empty.\n\nFunctions can use `local.set <index or $label>` to pop a value off the stack and store it in a local variable where `index` is the index of that variable within the list of local variables (including params) and `$label` is its optional label (if it was given one). Often we'd like to set a local variable while leaving its value on the stack, which is what the `local.tee` instruction is for, it's basically a shortcut for writing `local.set <index or $label>` immediately followed by `local.get <same index or $label>`.\n\n```wat\n;; without labels\n(func $add_and_double (param i32 i32) (result i32) (local i32)\n    local.get 0     ;; get 1st param\n    local.get 1     ;; get 2nd param\n    i32.add\n    local.tee 2     ;; set & get 1st local var\n    local.get 2     ;; get 1st local var again\n    i32.add\n)\n\n;; with labels\n(func $add_and_double (param $first i32) (param $second i32) (result i32) (local $local i32)\n    local.get $first\n    local.get $second\n    i32.add\n    local.tee $local\n    local.get $local\n    i32.add\n)\n```\n\nWe can set up a function call by pushing the function's arguments onto the stack and then calling the function with the `call $label` instruction.\n\n```wat\ni32.const 4\ni32.const 5\ncall $my_add            ;; pops 4 & 5 off stack & pushes 9 onto stack\ndrop                    ;; discard result\n\ni32.const 4\ni32.const 5\ncall $add_and_double    ;; pops 4 & 5 off stack & pushes 18 onto stack\n```\n\nLike instructions, functions also cannot exist on their own and must be inside a module. A module is the fundamental unit of code in WebAssembly. Modules can define functions, memory segments, imports, and exports. Things that can be imported and exported include functions and memory segments. Here's a wasm32 module that defines a single function:\n\n```wat\n(module\n    (func $_start\n        ;; instructions\n    )\n)\n```\n\nMemory segments can be defined with `(memory <pages>)` where `<pages>` is how many pages large the memory segment should be. WebAssembly defines a page to be 65536 bytes in size so memory segments can only be multiples of this number. All memory segments are zero-initialized by default. Currently, modules can only define a single memory segment (but this restriction will be relaxed in the future). Here's a WebAssembly module that defines a single memory segment which is 1 page large:\n\n```wat\n(module\n    ;; defines zero-initialized 65536 byte linear memory segment\n    (memory 1)\n)\n```\n\nModules can also export functions and memory segments using `export \"<exported name>\" (<type> <index or $label>)`.\n\n```wat\n(module\n    ;; zero-initialized 65536 byte linear memory segment\n    (memory 1)\n\n    (func $_start\n        ;; instructions\n    )\n\n    ;; export our only defined memory segment by index as \"memory\"\n    (export \"memory\" (memory 0))\n\n    ;; export our $_start function as \"_start\"\n    (export \"_start\" (func $_start))\n)\n```\n\nWebAssembly modules can't make system calls on their own, that's where WASI comes in. WASI stands for WebAssembly System Interface and defines a set of functions that WASM VMs can implement and wasm32 modules can import to make system calls. To import functions into our module we have to use `(import \"<namespace>\" \"<func name>\" (func $<label> <params> <result>)`:\n\n```wat\n;; proc_exit(code)\n(import \"wasi_snapshot_preview1\" \"proc_exit\"\n    (func $proc_exit (param i32)))\n\n;; fd_read(fd, iovec[]*, iovec_len, bytes_read*) -> error_number\n(import \"wasi_snapshot_preview1\" \"fd_read\"\n    (func $fd_read (param i32 i32 i32 i32) (result i32)))\n\n;; fd_write(fd, iovec[]*, iovec_len, bytes_written*) -> error_number\n(import \"wasi_snapshot_preview1\" \"fd_write\"\n    (func $fd_write (param i32 i32 i32 i32) (result i32)))\n\n;; An \"iovec\" is an 8-byte struct with two 4-byte members:\n;; 1) buffer address (0-byte offset from start of iovec)\n;; 2) buffer length (4-byte offset from start of iovec)\n\n;; for example, if we had a 27-byte buffer at memory address\n;; 1000 this is how we would construct an iovec struct stored\n;; at memory address 3000 to point to that buffer:\n\n;; store 1st iovec struct member\ni32.const 3000      ;; 1st member at 3000 (3000 + 0 offset)\ni32.const 1000      ;; buffer memory address\ni32.store\n\n;; store 2nd iovec struct member\ni32.const 3004      ;; 2nd member at 3004 (3000 + 4 offset)\ni32.const 27        ;; buffer length in bytes\ni32.store\n\n;; examples\n\n;; proc_exit(code)\ni32.const 0         ;; 0 exit code means success\ncall $proc_exit\n\n;; fd_read(fd, iovec[]*, iovec_len, bytes_read*) -> error_number\ni32.const 0         ;; file descriptor for stdin\ni32.const 3000      ;; memory address to array of iovec structs\ni32.const 1         ;; number of iovec structs in array\ni32.const 5678      ;; memory address where to write bytes_read\ncall $fd_read       ;; pop 4 values from stack, pushes error_number to stack\ndrop                ;; discard error_number\n\n;; fd_write(fd, iovec[]*, iovec_len, bytes_written*) -> error_number\ni32.const 1         ;; file descriptor for stdout\ni32.const 3000      ;; memory address to array of iovec structs\ni32.const 1         ;; number of iovec structs in array\ni32.const 5678      ;; memory address where to write bytes_written\ncall $fd_write      ;; pop 4 values from stack, pushes error_number to stack\ndrop                ;; discard error_number\n```\n\nOkay, we've _finally_ established enough context that we can now port `switch_case.s` to wasm32-wasi. As a refresher, this program reads 1 character from stdin, switches its case, writes the character to stdout, and then exits:\n\n```wat\n;; ./examples/wasm32-wasi/switch_case.wat\n\n(module\n    (import \"wasi_snapshot_preview1\" \"proc_exit\"\n        (func $proc_exit (param i32)))\n\n    (import \"wasi_snapshot_preview1\" \"fd_write\"\n        (func $fd_write (param i32 i32 i32 i32) (result i32)))\n\n    (import \"wasi_snapshot_preview1\" \"fd_read\"\n        (func $fd_read (param i32 i32 i32 i32) (result i32)))\n\n    (memory 1)\n\n    (func $_start (local $char i32)\n        ;; treat mem[0] as a 1 byte buffer\n\n        ;; set up iovec at mem[4-12] to point to buffer\n        i32.const 4     ;; memory address 4 (4 + 0 offset)\n        i32.const 0     ;; memory address of buffer\n        i32.store       ;; mem[4-8] = 0, 1st iovec member\n        i32.const 8     ;; memory address 8 (4 + 4 offset)\n        i32.const 1     ;; buffer length (1 byte)\n        i32.store       ;; mem[8-12] = 1, 2nd iovec member\n\n        ;; recap:\n        ;; mem[0] = 1 byte buffer\n        ;; mem[4-12] = iovec { buf_adr, buf_len }\n        \n        ;; $fd_read(STDIN, mem[4], 1, mem[12])\n        i32.const 0         ;; 0 = STDIN\n        i32.const 4         ;; mem[4] = iovec[]\n        i32.const 1         ;; 1 = # of iovecs\n        i32.const 12        ;; mem[12] = bytes_read address\n        call $fd_read       ;; pop 4 values from stack, push error_num\n        drop                ;; drop error_num (assume success)\n\n        i32.const 0\n        i32.load8_u         ;; load byte at mem[0]\n        local.tee $char     ;; $char = mem[0]\n        i32.const 97\n        i32.ge_u            ;; is $char >= 97 ?\n\n        if                  ;; if true make $char uppercase\n            i32.const 0\n            local.get $char\n            i32.const 32\n            i32.sub\n            i32.store8      ;; mem[0] = $char - 32\n        else                ;; if false make $char lowercase\n            i32.const 0\n            local.get $char\n            i32.const 32\n            i32.add\n            i32.store8      ;; mem[0] = $char + 32\n        end\n\n        ;; $fd_write(STDOUT, mem[4], 1, mem[12])\n        i32.const 1         ;; 1 = STDOUT\n        i32.const 4         ;; mem[4] = iovec[]\n        i32.const 1         ;; 1 = # of iovecs\n        i32.const 12        ;; mem[12] = bytes_written address\n        call $fd_write      ;; pop 4 values from stack, push error_num\n        drop                ;; drop error_num (assume success)\n\n        ;; $proc_exit(0)\n        i32.const 0\n        call $proc_exit\n    )\n\n    ;; export \"memory\" & \"_start\" to runtime\n    (export \"memory\" (memory 0))\n    (export \"_start\" (func $_start))\n)\n```\n\n> If you're following along using the [companion code repository](https://github.com/pretzelhammer/brainfuck_compilers) the command we'll be using to compile and run WebAssembly examples is `just carw {{name}}` where `{{name}}` is the name of the WebAssembly source file in the `./examples/wasm32-wasi` directory.\n\n```sh\n# reads char from stdin, switches its case, prints to stdout\n\n> just carw switch_case\nf\nF\nExit code: 0\n\n> just carw switch_case\nQ\nq\nExit code: 0\n```\n\n\n\n## Compiling brainfuck to WebAssembly\n\nDefining a zero-initialized memory segment in wasm32 is easy and we covered that in the previous section. What's not as easy is deciding where to store our iovec, which is a required in-memory struct that we need to use for `fd_read` and `fd_write` system calls. Since we're using the first 30k bytes of our memory segment for our brainfuck program let's store the iovec at memory address 30004. For our array pointer let's store it a function local variable and copy it over to the iovec struct before reads and writes. We've now made enough decisions to generate a wasm32-wasi boilerplate for our compiled brainfuck programs:\n\n```wat\n;; header boilerplate ;;\n\n(module\n    (import \"wasi_snapshot_preview1\" \"fd_write\"\n        (func $fd_write (param i32 i32 i32 i32) (result i32)))\n\n    (import \"wasi_snapshot_preview1\" \"proc_exit\"\n        (func $proc_exit (param i32)))\n\n    (import \"wasi_snapshot_preview1\" \"fd_read\"\n        (func $fd_read (param i32 i32 i32 i32) (result i32)))\n\n    (memory 1)\n\n    (func $_start (local $ptr i32)\n        ;; set up array pointer\n        i32.const 0\n        local.set $ptr\n\n        ;; set up 1st iovec member\n        i32.const 30004     ;; 30004 address (30004 + 0 offset)\n        local.get $ptr      ;; initial index = 0\n        i32.store           ;; mem[30004-30008] = 0\n\n        ;; set up 2nd iovec member\n        i32.const 30008     ;; 30008 address (30004 + 4 offset)\n        i32.const 1         ;; buffer length is 1 byte\n        i32.store           ;; mem[30008-30012] = 1\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n;; actual compiled brainfuck program goes here ;;\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n;; footer boilerplate ;;\n\n        i32.const 0\n        call $proc_exit\n    )\n\n    (export \"memory\" (memory 0))\n    (export \"_start\" (func $_start))\n)\n```\n\nAlright let's map brainfuck commands to wasm32 instructions:\n\n```wat\n;; increment array pointer\n\n;; >\nlocal.get $ptr\ni32.const 1\ni32.add\nlocal.set $ptr\n\n;; >>\nlocal.get $ptr\ni32.const 2\ni32.add\nlocal.set $ptr\n\n;; decrement array pointer\n\n;; <\nlocal.get $ptr\ni32.const 1\ni32.sub\nlocal.set $ptr\n\n;; <<\nlocal.get $ptr\ni32.const 2\ni32.sub\nlocal.set $ptr\n\n;; increment byte at pointer\n\n;; +\nlocal.get $ptr\nlocal.get $ptr\ni32.load8_u\ni32.const 1\ni32.add\ni32.store8\n\n;; ++\nlocal.get $ptr\nlocal.get $ptr\ni32.load8_u\ni32.const 2\ni32.add\ni32.store8\n\n;; decrement byte at pointer\n\n;; -\nlocal.get $ptr\nlocal.get $ptr\ni32.load8_u\ni32.const 1\ni32.sub\ni32.store8\n\n;; --\nlocal.get $ptr\nlocal.get $ptr\ni32.load8_u\ni32.const 2\ni32.sub\ni32.store8\n\n;; read byte from stdin & store at pointer\n\n;; ,\ni32.const 30004\nlocal.get $ptr\ni32.store\ni32.const 0\ni32.const 30004\ni32.const 1\ni32.const 30012\ncall $fd_read\ndrop\n\n;; ,,\ni32.const 30004\nlocal.get $ptr\ni32.store\ni32.const 0\ni32.const 30004\ni32.const 1\ni32.const 30012\ncall $fd_read\ndrop\ni32.const 0\ni32.const 30004\ni32.const 1\ni32.const 30012\ncall $fd_read\ndrop\n\n;; write byte at pointer to stdout\n\n;; .\ni32.const 30004\nlocal.get $ptr\ni32.store\ni32.const 0\ni32.const 30004\ni32.const 1\ni32.const 30012\ncall $fd_write\ndrop\n\n;; ..\ni32.const 30004\nlocal.get $ptr\ni32.store\ni32.const 0\ni32.const 30004\ni32.const 1\ni32.const 30012\ncall $fd_write\ndrop\ni32.const 0\ni32.const 30004\ni32.const 1\ni32.const 30012\ncall $fd_write\ndrop\n\n;; loops\n\n;; [\nblock\nlocal.get $ptr\ni32.load8_u\ni32.eqz\nbr_if 0\nloop\n\n;; ]\nlocal.get $ptr\ni32.load8_u\nbr_if 0\nend\nend\n```\n\nThat was surprisingly way more work than the x86_64 and aarch64 compilers! Thankfully we're done.\n\n> If you're following along using the [companion code repository](https://github.com/pretzelhammer/brainfuck_compilers) the command we'll be using to compile brainfuck programs to WebAssembly and run them is `just carbw {{name}}` where `{{name}}` is the brainfuck source file in the `./input` directory.\n\n```sh\n# prints \"Hello world!\"\n> just carbw hello_world\nHello World!\n\n# prints fibonacci numbers under 100\n> just carbw fibonacci\n1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89\n\n# encrypts lines from stdin using rot13 cipher\n> just carbw rot13\nunencrypted text\nharapelcgrq grkg\n```\n\nAnother unscientific and informal benchmark:\n\n```sh\n> just benchmark mandelbrot\n\n# program outputs omitted\n\n# interpreted mandelbrot.b\n4.95s user 0.01s system 99% cpu 4.960 total\n\n# x86_64 compiled mandelbrot.b\nreal    0m1.214s\nuser    0m1.149s\nsys     0m0.041s\n\n# aarch64 compiled mandelbrot.b\nreal    0m4.206s\nuser    0m4.103s\nsys     0m0.083s\n\n# wasm32-wasi compiled mandelbrot.b\nreal    0m1.480s\nuser    0m1.429s\nsys     0m0.046s\n```\n\nThe compiled wasm32-wasi version is 3.3x faster than the interpreted version and only 0.8x as fast as the x86_64 version. Pretty good! The promise that WASM programs execute at near-native speeds holds up!\n\n\n\n## Intro to LLVM\n\nUnlike x86_64, aarch64, and WebAssembly, LLVM IR isn't really a register-based or stack-based ISA. LLVM IR has variables like a high-level language. However, unlike high-level languages, LLVM IR variables must follow Static Single-Assignment (SSA) form which requires that every variable is assigned to exactly once. This is annoying because it means we can't reuse variable names.\n\n```ll\n%i = add i8 1, 2\n%i = add i8 3, 4       ; illegal, %i assigned to twice\n```\n\nUnlike x86_64 and aarch64, but similarly to WebAssembly, all variables and instructions in LLVM IR are strongly typed. LLVM IR supports many types but the ones most relevant to us are integers, arrays, functions, and pointers:\n\n```ll\n; integer types\n\ni<bit-width>            ; integer that is <bit-width> bits wide\n\n; examples\n\ni1                      ; 1 bit integer\ni64                     ; 64 bit integer\n\n; array types\n\n[<quantity> x <type>]   ; array of <quantity> <type>\n\n; examples\n\n[4 x i32]               ; array of 4 32-bit integers\n[12 x [2 x i8]]         ; array of 12 arrays of 2 bytes\n\n; function types\n\n<return_type> (<param_list>)\n\n; examples\n\ni32 (i32)               ; function taking and returning one i32\nvoid (i8, i8)           ; function taking 2 bytes and returning void\n\n; pointer types\n\n<type>*                 ; pointer to <type>\n\n; examples\n\ni8*                     ; byte pointer\n[10 x i32]*             ; pointer to array of 10 32-bit integers\ni32 (i32)*              ; pointer to function taking and returning one i32\n```\n\nThere's an LLVM IR instruction called `atomicrmw` that allows us to atomically modify memory values directly using a subset of the available arithmetic instructions but learning and using that instruction before we've learned the basics of `load` and `store` kinda feels like cheating so let's go over those instead. We'll explicitly load and store values for our examples and in our compiler.\n\n```ll\n; load\n\n%val = load <type>, <type>* %ptr\n\n; store\n\nstore <type> <value>, <type>* %ptr\n\n; example\n\n; assume %byte is some i8*\n; below we add 1 to the value at %byte\n\n%b.0 = load i8, i8* %byte\n%b.1 = add i8 %b.0, 1\nstore i8 %b.1, i8* %byte\n```\n\nWe can set global variables (outside of any function) using the following syntax:\n\n```ll\n@<name> = global <type> <value>\n\n; where @<name> will have type <type>*\n\n; example\n\n@counter = global i32 0\n\n; @counter has type i32*\n```\n\nUnfortunately setting local variables isn't as concise. There's this \"shortcut\" but it feels kinda hacky:\n\n```ll\n%var = add i32 0, 10        ; why am I adding 0 + 10 to set %var to 10 ?\n```\n\nThe correct way to set a local variable is to do this:\n\n```ll\n%var = alloca i32           ; allocate space for an i32 on the stack\nstore i32 10, i32* %var     ; store 10 in %var\n```\n\nWhich seems really inefficient but after an optimization pass LLVM transforms it into a single instruction where the literal value is set directly in a register (instead of on the stack).\n\nSome arithmetic instructions:\n\n```ll\n%result = add <type> <op1>, <op2>\n%result = sub <type> <op1>, <op2>\n```\n\nComparing values:\n\n```ll\n%result = icmp <cond> <type> <op1>, <op2>\n\n; where %result is an i1 and 1 = true, 0 = false\n\n; where <cond> can be\n;   - eq                ; equal\n;   - ne                ; not equal\n;   - ugt               ; unsigned greater than\n;   - uge               ; unsigned greater than or equal\n;   - ult               ; unsigned less than\n;   - ule               ; unsigned less than or equal\n;   - sgt               ; signed greater than\n;   - sge               ; signed greater than or equal\n;   - slt               ; signed less than\n;   - sle               ; signed less than or equal\n\n; examples\n\n%true = icmp eq i8 0, 0\n%false = icmp ugt i32 5, 9\n%bool = icmp ne i64 %somevar, %othervar\n```\n\nControl flow:\n\n```ll\n; unconditional branch to <label>\nbr label %<label>\n\n; conditional branch to <true> if <bool> is true, to <false> otherwise\nbr i1 <bool>, label %<true>, label %<false>\n\n; return value <value> of type <type> from function\nret <type> <value>\n```\n\nFunctions:\n\n```ll\n; declare external function\ndeclare <return_type> @<name>(<args>)\n\n; define function\ndefine <return_type> @<name>(<args>) {\n    <instructions>\n}\n\n; call function with call instruction\n%result = call <return_type> @<name>(<args>)\n\n; where <args> is a comma-separated list of <type> %<name>\n```\n\nLLVM refers to labeled blocks of instructions (note: the block of instructions inside a function body gets an implicit label) as _basic blocks_ and all _basic blocks_ must be terminated with a _terminator instruction_ that produces control flow to some other _basic block_ so _terminator instructions_ naturally include all the control flow instructions like `br` and `ret`. This is important to explain because there's no \"fall through\" between blocks in LLVM IR like there is in x86_64 and aarch64. Example:\n\n```ll\ndefine i32 @max(i32 %a, i32 %b) {\n    %max = alloca i32\n    %bool = icmp ugt i32 %a, %b\n    br i1 %bool, label %A_IS_BIGGER, label %B_IS_BIGGER\n\nA_IS_BIGGER:\n    store i32 %a, i32* %max\n    br label %RETURN\n\nB_IS_BIGGER:\n    store i32 %b, i32* %max\n    br label %RETURN ; this seemingly pointless instruction is *required*\n\nRETURN:\n    %ret = load i32, i32* %max\n    ret i32 %ret\n}\n```\n\nThere's a handy `select` instruction that allows us to condense the above example down to just a few lines:\n\n```ll\n; select i1 %<bool>, <type> <val>, <type> <val>\n\ndefine i32 @max(i32 %a, i32 %b) {\n    %bool = icmp ugt i32 %a, %b\n    %ret = select i1 %bool, i32 %a, i32 %b\n    ret i32 %ret\n}\n```\n\nOkay, so we could make direct system calls by writing inline assembly in LLVM IR but that would beat the point of using LLVM IR in the first place so instead we're going to use functions from the C standard library, often just called libc, which abstract away having to deal with all the individual quirks of system calls across different platforms and targets. Here's `switch_case.s` ported to LLVM IR:\n\n```ll\n; ./examples/llvm_ir/switch_case.ll\n\n; libc functions\ndeclare i8 @putchar(i8)\ndeclare i8 @getchar()\n\n; main function called by libc\n; the return value is set as program's exit code\ndefine i8 @main() {\n    %switched = alloca i8\n    %char = call i8 @getchar()\n    %bool = icmp uge i8 %char, 97 ; %char >= 97 ?\n    br i1 %bool, label %MAKE_UPPERCASE, label %MAKE_LOWERCASE\n\nMAKE_UPPERCASE:\n    %upper = sub i8 %char, 32\n    store i8 %upper, i8* %switched\n    br label %WRITE\n\nMAKE_LOWERCASE:\n    %lower = add i8 %char, 32\n    store i8 %lower, i8* %switched\n    br label %WRITE\n    \nWRITE:\n    %result = load i8, i8* %switched\n    call i8 @putchar(i8 %result)\n    ret i8 0\n}\n```\n\n> If you're following along using the [companion code repository](https://github.com/pretzelhammer/brainfuck_compilers) the command we'll be using to compile and run LLVM IR examples is `just carl {{name}}` where `{{name}}` is the LLVM IR source file in the `./examples/llvm_ir` directory.\n\n```sh\n# reads char from stdin, switches its case, prints to stdout\n\n> just carl switch_case\nj\nJ\nExit code: 0\n\n> just carl switch_case\nT\nt\nExit code: 0\n```\n\n\n\n## Compiling brainfuck to LLVM\n\nWe can create a global zero-initialized array of 30k bytes using the handy `zeroinitializer` keyword.\n\n```ll\n@array = global [ 300000 x i8 ] zeroinitializer\n```\n\nWe could maintain a pointer into this array but LLVM IR doesn't make that easy on us because there are no pointer arithmetic instructions. To do pointer arithmetic in LLVM IR we have to convert the pointer to an integer with `ptrtoint`, do the arithmetic, and then convert it back with `inttoptr`. This is verbose and not fun. Instead let's maintain a global index variable and use the `getelementptr` instruction to get pointers into our global array.\n\n```ll\n@index = global i64 0\n\n; generic template for getting a pointer into an array using an index:\n; %ptr = getelementptr <type>, <type>* <array>, i64 0, i64 <index>\n\n; example\n%index = load i64, i64* @index\n%ptr = getelementptr [ 30000 x i8 ], [ 30000 x i8 ]* @array, i64 0, i64 %index\n```\n\nIt's not pretty, but the alternatives are even uglier, so it's the best we have to work with. But now with that out of the way we can generate an LLVM IR boilerplate for our compiled brainfuck programs:\n\n```ll\n; header boilerplate ;\n\n@array = global [ 30000 x i8 ] zeroinitializer\n@index = global i64 0\n\ndeclare i8 @putchar(i8)\ndeclare i8 @getchar()\n\ndefine i8 @main() {\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n; actual compiled brainfuck program goes here ;\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n; footer boilerplate ;\n\n    ret i8 0\n}\n```\n\nMapping brainfuck commands to LLVM IR instructions:\n\n```ll\n; increment array pointer\n\n; >\n%idx.0 = load i64, i64* @index\n%idx.1 = add i64 %idx.0, 1\nstore i64 %idx.1, i64* @index\n\n; >>\n%idx.2 = load i64, i64* @index\n%idx.3 = add i64 %idx.2, 2\nstore i64 %idx.3, i64* @index\n\n; decrement array pointer\n\n; <\n%idx.4 = load i64, i64* @index\n%idx.5 = sub i64 %idx.4, 1\nstore i64 %idx.5, i64* @index\n\n; <<\n%idx.6 = load i64, i64* @index\n%idx.7 = sub i64 %idx.6, 2\nstore i64 %idx.7, i64* @index\n\n; increment byte at pointer\n\n; +\n%idx.8 = load i64, i64* @index\n%ptr.0 = getelementptr [ 30000 x i8 ], [ 30000 x i8 ]* @array, i64 0, i64 %idx.8\n%byte.0 = load i8, i8* %ptr.0\n%byte.1 = add i8 %byte.0, 1\nstore i8 %byte.1, i8* %ptr.0\n\n; ++\n%idx.9 = load i64, i64* @index\n%ptr.1 = getelementptr [ 30000 x i8 ], [ 30000 x i8 ]* @array, i64 0, i64 %idx.9\n%byte.2 = load i8, i8* %ptr.1\n%byte.3 = add i8 %byte.2, 2\nstore i8 %byte.3, i8* %ptr.1\n\n; decrement byte at pointer\n\n; -\n%idx.10 = load i64, i64* @index\n%ptr.2 = getelementptr [ 30000 x i8 ], [ 30000 x i8 ]* @array, i64 0, i64 %idx.10\n%byte.4 = load i8, i8* %ptr.2\n%byte.5 = sub i8 %byte.4, 1\nstore i8 %byte.5, i8* %ptr.2\n\n; --\n%idx.11 = load i64, i64* @index\n%ptr.3 = getelementptr [ 30000 x i8 ], [ 30000 x i8 ]* @array, i64 0, i64 %idx.11\n%byte.6 = load i8, i8* %ptr.3\n%byte.7 = sub i8 %byte.6, 2\nstore i8 %byte.7, i8* %ptr.3\n\n; read byte from stdin & store at pointer\n\n; ,\n%idx.12 = load i64, i64* @index\n%ptr.4 = getelementptr [ 30000 x i8 ], [ 30000 x i8 ]* @array, i64 0, i64 %idx.12\n%char.0 = call i8 @getchar()\n%bool.0 = icmp eq i8 -1, %char.0\n%char.1 = select i1 %bool.0, i8 0, i8 %char.0\nstore i8 %char.1, i8* %ptr.4\n\n; ,,\n%idx.13 = load i64, i64* @index\n%ptr.5 = getelementptr [ 30000 x i8 ], [ 30000 x i8 ]* @array, i64 0, i64 %idx.13\ncall i8 @getchar()\n%char.2 = call i8 @getchar()\n%bool.1 = icmp eq i8 -1, %char.2\n%char.3 = select i1 %bool.1, i8 0, i8 %char.2\nstore i8 %char.3, i8* %ptr.5\n\n; write byte at pointer to stdout\n\n; .\n%idx.14 = load i64, i64* @index\n%ptr.6 = getelementptr [ 30000 x i8 ], [ 30000 x i8 ]* @array, i64 0, i64 %idx.14\n%char.4 = load i8, i8* %ptr.6\ncall i8 @putchar(i8 %char.4)\n\n; ..\n%idx.15 = load i64, i64* @index\n%ptr.7 = getelementptr [ 30000 x i8 ], [ 30000 x i8 ]* @array, i64 0, i64 %idx.15\n%char.5 = load i8, i8* %ptr.7\ncall i8 @putchar(i8 %char.5)\ncall i8 @putchar(i8 %char.5)\n\n; loops\n\n; [\n%idx.16 = load i64, i64* @index\n%ptr.8 = getelementptr [ 30000 x i8 ], [ 30000 x i8 ]* @array, i64 0, i64 %idx.16\n%byte.8 = load i8, i8* %ptr.8\n%bool.2 = icmp eq i8 0, %byte.8\nbr i1 %bool.2, label %LOOP_END_1, label %LOOP_START_0\nLOOP_START_0:\n\n; ]\n%idx.18 = load i64, i64* @index\n%ptr.10 = getelementptr [ 30000 x i8 ], [ 30000 x i8 ]* @array, i64 0, i64 %idx.18\n%byte.11 = load i8, i8* %ptr.10\n%bool.3 = icmp ne i8 0, %byte.11\nbr i1 %bool.3, label %LOOP_START_0, label %LOOP_END_0\nLOOP_END_0:\n```\n\nEagle-eyed readers may have noticed something slightly unusual in the implementation for `,`. The reason why we need to perform an `icmp` and `select` in our implementation of `,` is because the libc `getchar()` function returns `-1` on EOF but the semantics of our brainfuck compiler is that all EOFs should be read and stored as the value `0` so if we get a `-1` from `getchar()` we have to map it to a `0` before storing it in our array.\n\n> If you're following along using the [companion code repository](https://github.com/pretzelhammer/brainfuck_compilers) the command we'll be using to compile brainfuck programs to LLVM IR and run them is `just carbl {{name}}` where `{{name}}` is the brainfuck source file in the `./input` directory.\n\n```sh\n# prints \"Hello world!\"\n> just carbl hello_world\nHello World!\n\n# prints fibonacci numbers under 100\n> just carbl fibonacci\n1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89\n\n# encrypts lines from stdin using rot13 cipher\n> just carbl rot13\nunencrypted text\nharapelcgrq grkg\n```\n\nAnother totally unscientific and informal benchmark:\n\n```sh\n> just benchmark mandelbrot\n\n# program outputs omitted\n\n# interpreted mandelbrot.b\n4.95s user 0.01s system 99% cpu 4.960 total\n\n# x86_64 compiled mandelbrot.b\nreal    0m1.214s\nuser    0m1.149s\nsys     0m0.041s\n\n# aarch64 compiled mandelbrot.b\nreal    0m4.206s\nuser    0m4.103s\nsys     0m0.083s\n\n# wasm32-wasi compiled mandelbrot.b\nreal    0m1.480s\nuser    0m1.429s\nsys     0m0.046s\n\n# llvm-ir compiled mandelbrot.b\nreal    0m0.896s\nuser    0m0.887s\nsys     0m0.001s\n```\n\nThe LLVM IR compiled version is not only 5.5x faster than the interpreted version but it's also 1.3x faster than the x86_64 compiled version. What!? How!? That's nuts. Given how incredibly simplistic brainfuck programs are I'm surprised the LLVM IR optimizer still found so much room for improvement.\n\n\n\n## Optimization opportunities\n\nThere's 3 ways we can massively improve the performance of all our compilers.\n\n\n### Interpret during compilation and capture output\n\nBrainfuck programs that don't have any `,` (read byte from stdin) commands have deterministic outputs so if a brainfuck program completes in a finite amount of time (as some brainfuck programs are written to execute indefinitely until they get a SIGKILL) then we can interpret it during compilation, capture its output, and then write a compiled program that just prints that output to stdout. This is \"the ultimate\" optimization as all compiled programs, regardless of how complex their source code was, will finish execution nearly instantly and no other optimizations are required. The following 2 optimizations are listed only to take into account brainfuck programs where this optimization cannot be applied (which are programs with `,` in their source code or programs that run indefinitely).\n\n\n### Un-loop-ify simple loops\n\nWhile looking through the source code of brainfuck programs I noticed this command pattern a lot: `[-]`. It's clear what it's doing, it's zeroing the byte at the current pointer. However the code we're generating for this simple case is wildly inefficient. Our x86_64 compiler will generate the following instructions:\n\n```s\n# [\ncmpb [r12], 0\nje LOOP_END_2\nLOOP_START_0:\n\n# - (subtract in loop until 0)\nsubb [r12], 1\n\n# ]\ncmpb [r12], 0\njne LOOP_START_0\nLOOP_END_2:\n```\n\nWhen all it needs to generate is just this:\n\n```s\n# [-]\nmovb [r12], 0\n```\n\nA slightly more complex command pattern is this `[->+<]` which zeros the byte at the pointer _and_ adds its value to its neighbor in the array. Our x86_64 compiler would generate the following instructions for this command pattern:\n\n```s\n# [\ncmpb [r12], 0\nje LOOP_END_5\nLOOP_START_0:\n\n# - (decrement byte until 0 in loop)\nsubb [r12], 1\n\n# > (move to neighbor)\nadd r12, 1\n\n# + (increment neighbor)\naddb [r12], 1\n\n# < (move back to original byte)\nsub r12, 1\n\n# ]\ncmpb [r12], 0\njne LOOP_START_0\nLOOP_END_5:\n```\n\nHowever all it needs to generate is:\n\n```s\n# [->+<]\nmovb r13b, [r12]        # save current byte value\naddb [r12 + 1], r13b    # add current byte value to neighbor\nmovb [r12], 0           # zero current byte\n```\n\nMost simple flat loops in brainfuck can be reduced to just a few instructions. A sufficiently smart compiler should be able to identify these scenarios, and it can maybe explain how the LLVM IR optimizer produces compiled brainfuck programs that run 1.3x faster than our naive x86_64 compiler.\n\n\n\n### Buffer reads and writes\n\nSystem calls are expensive, even without including the cost of switching from user-space to kernel-space they just take a lot of instructions to set up and invoke. Our compilers could all be made more efficient if they wrote bytes to an internal buffer and only invoked the system call to write the bytes to stdout when absolutely necessary: like when the buffer fills up, or an `,` command is reached, or the end of the program is reached.\n\n\n\n## Concluding thoughts\n\nI learned a lot and still far less than I thought I would. Remember that laundry list of fancy terms I mentioned back in the intro of this article? Yeah well, I still don't know what half of that stuff is.\n\nWhile doing the research and programming for this project I finally learned what _auto-vectorization_, _inlining_, _endianness_, _system calls_, _LLVM_, _SIMD_, and _ABI_ are. I kinda get what _linking_ is on a very basic level but I still get lost whenever I read anything about _linking_ because it seems like the linker does a whole bunch of really crazy complicated code manipulations other than just playing connect-the-dots with some global symbols, so I don't feel like I \"fully get\" what a linker actually does. I get what _custom allocators_ are in concept but I don't get why, for example, Allocator X is more performant than Allocator Y for certain workloads. This project never forced me to figure out how heap allocations work in assembly so it makes sense that allocators are still a mystery to me. I know that _TLS_ stands for Thread Local Storage and people love talking about it but I don't know why. I know _padding_ is a thing that exists purely to serve _alignment_ but I have no clue why _alignment_ is so important. Apparently if the data in your program is _aligned_ everything is faster and if it's _unaligned_ it's either slow or completely unusable. But why? What is it with all this magical _alignment_ stuff?\n\nI was very surprised by how much easier it was to write the x86_64 and aarch64 compilers compared to the WebAssembly and LLVM IR compilers. I think this mostly has to do with the fact that brainfuck is a super simple language that maps very cleanly to low-level assembly instructions and if I was writing compilers for a higher-level language it'd be easier to map higher-level constructs to WebAssembly and LLVM IR than x86_64 and aarch64 but I've never tried to do this so I can't say 100% for sure.\n\nThe documentation online for x86_64 and aarch64 is pretty terrible. It seems like if you seriously want to get into x86_64 or aarch64 programming you're probably better off buying some assembly books on Amazon and reading the 5000+ page programming manual for x86_64 on Intel's website or the 8000+ page programming manual for aarch64 on ARM's website. It's not very beginner-friendly.\n\nThe documentation online for WebAssembly is good _if you're writing a WASM VM_. If you're approaching WebAssembly as an application or compiler developer then it's terrible. There's no beginner-friendly tutorials on how to do anything and you have to figure everything out for yourself.\n\nThe documentation online for LLVM IR is by far the best. The [LLVM IR Language Reference](https://llvm.org/docs/LangRef.html) not only thoroughly explains every instruction but also shows example usages for all of the instructions! LLVM also maintains an official tutorial called [My First Language Frontend with LLVM](https://llvm.org/docs/tutorial/MyFirstLanguageFrontend/index.html) that shows how to implement an LLVM IR compiler for a simple programming language in C++. I don't know C++ so I didn't read the tutorial but the fact they have an official maintained tutorial is nice. Also there's a free online ebook called [Mapping High Level Constructs to LLVM IR](https://mapping-high-level-constructs-to-llvm-ir.readthedocs.io/en/latest/README.html) which is also pretty great.\n\nIf I had to write a compiler in the future I think I'll definitely stick with LLVM IR. It has the best documentation, it has a kick-ass optimizer, and it can compile down to x86_64, aarch64, or WebAssembly (plus a whole bunch of other targets)!\n\n\n\n## Discuss\n\nDiscuss this article on\n- [compilers subreddit](https://www.reddit.com/r/Compilers/comments/jpqnws/learn_assembly_with_entirely_too_many_brainfuck/)\n- [asm subreddit](https://www.reddit.com/r/asm/comments/jqbq47/learn_assembly_with_entirely_too_many_brainfuck/)\n- [coding subreddit](https://www.reddit.com/r/coding/comments/jqxl19/learn_assembly_with_entirely_too_many_brainfuck/)\n- [ProgrammingLanguages subreddit](https://www.reddit.com/r/ProgrammingLanguages/comments/jsf9cr/learn_assembly_by_writing_entirely_too_many/)\n- [programming subreddit](https://www.reddit.com/r/programming/comments/jrlljd/learn_assembly_with_entirely_too_many_brainfuck/)\n- [Official Rust users forum](https://users.rust-lang.org/t/learn-assembly-by-writing-entirely-too-many-brainfuck-compilers-in-rust/51333?u=pretzelhammer)\n- [rust subreddit](https://www.reddit.com/r/rust/comments/jsvdsy/learn_assembly_by_writing_entirely_too_many/)\n- [Hackernews](https://news.ycombinator.com/item?id=25069243)\n- [Github](https://github.com/pretzelhammer/rust-blog/discussions)\n\n\n\n## Further Reading\n\nRust\n- [Common Rust Lifetime Misconceptions](./common-rust-lifetime-misconceptions.md)\n- [Tour of Rust's Standard Library Traits](./tour-of-rusts-standard-library-traits.md)\n- [Beginner's Guide to Concurrent Programming: Coding a Multithreaded Chat Server using Tokio](./chat-server.md)\n- [Learning Rust in 2024](./learning-rust-in-2024.md)\n- [Using Rust in Non-Rust Servers to Improve Performance](./rust-in-non-rust-servers.md)\n- [Sizedness in Rust](./sizedness-in-rust.md)\n- [RESTful API in Sync & Async Rust](./restful-api-in-sync-and-async-rust.md)\n\nISAs\n- [What does RISC and CISC mean in 2020?](https://medium.com/swlh/what-does-risc-and-cisc-mean-in-2020-7b4d42c9a9de)\n\nGNU Assembler\n- [GNU Assembler Manual](https://sourceware.org/binutils/docs/as/)\n\nx86\n- [StackOverflow x86 Tag Wiki](https://stackoverflow.com/tags/x86/info)\n- [CDOT x86_64 Quick Start](https://wiki.cdot.senecacollege.ca/wiki/X86_64_Register_and_Instruction_Quick_Start)\n- [Intel's Software Developer Manuals](https://software.intel.com/content/www/us/en/develop/articles/intel-sdm.html)\n- [AMD's Architecture Programmer's Manuals](https://developer.amd.com/resources/developer-guides-manuals/)\n\nARM\n- [CDOT aarch64 Quick Start](https://wiki.cdot.senecacollege.ca/wiki/AArch64_Register_and_Instruction_Quick_Start)\n- [Azeria Labs ARM Assembly Basics Tutorial](https://azeria-labs.com/writing-arm-assembly-part-1/)\n- [modexp's Guide to aarch64 Assembly](https://modexp.wordpress.com/2018/10/30/arm64-assembly/)\n- [ARM Programmer's Guide for ARMv8-A](https://developer.arm.com/documentation/den0024/a)\n- [ARM Architecture Reference Manual for ARMv8-A](https://developer.arm.com/documentation/ddi0487/latest)\n\nWebAssembly\n- [WebAssembly Specification](https://webassembly.github.io/spec/core/index.html)\n- [MDN's Understanding WebAssembly Text Format](https://developer.mozilla.org/en-US/docs/WebAssembly/Understanding_the_text_format)\n- [sunfishcode's WASM Reference Manual](https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md)\n\nLLVM IR\n- [LLVM Language Reference Manual](https://llvm.org/docs/LangRef.html)\n- [Mapping High Level Constructs to LLVM IR](https://mapping-high-level-constructs-to-llvm-ir.readthedocs.io/en/latest/README.html)\n- [My First Language Frontend with LLVM Tutorial](https://llvm.org/docs/tutorial/MyFirstLanguageFrontend/index.html)\n\n\n\n## Notifications\n\nGet notified when a new blog post gets published by\n- Subscribing to this repo's [releases RSS feed](https://github.com/pretzelhammer/rust-blog/releases.atom) or\n- Watching this repo's releases (click `Watch` → click `Custom` → select `Releases` → click `Apply`)\n"
  },
  {
    "path": "posts/tour-of-rusts-standard-library-traits.md",
    "content": "# Tour of Rust's Standard Library Traits\n\n_31 March 2021 · #rust · #traits_\n\n**Table of Contents**\n- [Intro](#intro)\n- [Trait Basics](#trait-basics)\n    - [Trait Items](#trait-items)\n        - [Self](#self)\n        - [Functions](#functions)\n        - [Methods](#methods)\n        - [Associated Types](#associated-types)\n        - [Generic Parameters](#generic-parameters)\n        - [Generic Types vs Associated Types](#generic-types-vs-associated-types)\n    - [Scope](#scope)\n    - [Derive Macros](#derive-macros)\n    - [Default Impls](#default-impls)\n    - [Generic Blanket Impls](#generic-blanket-impls)\n    - [Subtraits & Supertraits](#subtraits--supertraits)\n    - [Trait Objects](#trait-objects)\n    - [Marker Traits](#marker-traits)\n    - [Auto Traits](#auto-traits)\n    - [Unsafe Traits](#unsafe-traits)\n- [Auto Traits](#auto-traits-1)\n    - [Send & Sync](#send--sync)\n    - [Sized](#sized)\n- [General Traits](#general-traits)\n    - [Default](#default)\n    - [Clone](#clone)\n    - [Copy](#copy)\n    - [Any](#any)\n- [Formatting Traits](#formatting-traits)\n    - [Display & ToString](#display--tostring)\n    - [Debug](#debug)\n- [Operator Traits](#operator-traits)\n    - [Comparison Traits](#comparison-traits)\n        - [PartialEq & Eq](#partialeq--eq)\n        - [Hash](#hash)\n        - [PartialOrd & Ord](#partialord--ord)\n    - [Arithmetic Traits](#arithmetic-traits)\n        - [Add & AddAssign](#add--addassign)\n    - [Closure Traits](#closure-traits)\n        - [FnOnce, FnMut, & Fn](#fnonce-fnmut--fn)\n    - [Other Traits](#other-traits)\n        - [Deref & DerefMut](#deref--derefmut)\n        - [Index & IndexMut](#index--indexmut)\n        - [Drop](#drop)\n- [Conversion Traits](#conversion-traits)\n    - [From & Into](#from--into)\n- [Error Handling](#error-handling)\n    - [Error](#error)\n- [Conversion Traits Continued](#conversion-traits-continued)\n    - [TryFrom & TryInto](#tryfrom--tryinto)\n    - [FromStr](#fromstr)\n    - [AsRef & AsMut](#asref--asmut)\n    - [Borrow & BorrowMut](#borrow--borrowmut)\n    - [ToOwned](#toowned)\n- [Iteration Traits](#iteration-traits)\n    - [Iterator](#iterator)\n    - [ExactSizeIterator](#exactsizeiterator)\n    - [IntoIterator](#intoiterator)\n    - [Extend](#extend)\n    - [FromIterator](#fromiterator)\n- [I/O Traits](#io-traits)\n    - [Read & Write](#read--write)\n- [Conclusion](#conclusion)\n- [Discuss](#discuss)\n- [Further Reading](#further-reading)\n- [Notifications](#notifications)\n\n\n\n## Intro\n\nHave you ever wondered what the difference is between:\n- `Deref<Target = T>`, `AsRef<T>`, and `Borrow<T>`?\n- `Clone`, `Copy`, and `ToOwned`?\n- `From<T>` and `Into<T>`?\n- `TryFrom<&str>` and `FromStr`?\n- `FnOnce`, `FnMut`, `Fn`, and `fn`?\n\nOr ever asked yourself the questions:\n- _\"When do I use associated types vs generic types in my trait?\"_\n- _\"What are generic blanket impls?\"_\n- _\"How do subtraits and supertraits work?\"_\n- _\"Why does this trait not have any methods?\"_\n\nWell then this is the article for you! It answers all of the above questions and much much more. Together we'll do a quick flyby tour of all of the most popular and commonly used traits from the Rust standard library!\n\nYou can read this article in order, section by section, or jump around to whichever traits interest you the most, because each trait section begins with a list of links to **Prerequisite** sections that you should read to have adequate context to understand the current section's explanations.\n\n\n\n## Trait Basics\n\nWe'll cover just enough of the basics so that the rest of the article can be streamlined without having to repeat the same explanations of the same concepts over and over, as they reappear in different traits.\n\n\n\n### Trait Items\n\nTrait items are any items that are part of a trait declaration.\n\n\n\n#### Self\n\n`Self` always refers to the implementing type.\n\n```rust\ntrait Trait {\n    // always returns i32\n    fn returns_num() -> i32;\n\n    // returns implementing type\n    fn returns_self() -> Self;\n}\n\nstruct SomeType;\nstruct OtherType;\n\nimpl Trait for SomeType {\n    fn returns_num() -> i32 {\n        5\n    }\n\n    // Self == SomeType\n    fn returns_self() -> Self {\n        SomeType\n    }\n}\n\nimpl Trait for OtherType {\n    fn returns_num() -> i32 {\n        6\n    }\n\n    // Self == OtherType\n    fn returns_self() -> Self {\n        OtherType\n    }\n}\n```\n\n\n\n#### Functions\n\nA trait function is any function whose first parameter does not use the `self` keyword.\n\n```rust\ntrait Default {\n    // function\n    fn default() -> Self;\n}\n```\n\nTrait functions can be called via the namespace of the trait or of the implementing type:\n\n```rust\nfn main() {\n    let zero: i32 = Default::default();\n    let zero = i32::default();\n}\n```\n\n\n\n#### Methods\n\nA trait method is any function whose first parameter uses the `self` keyword and is of type `Self`, `&Self`, `&mut Self`. The former types can also be wrapped with a `Box`, `Rc`, `Arc`, or `Pin`.\n\n```rust\ntrait Trait {\n    // methods\n    fn takes_self(self);\n    fn takes_immut_self(&self);\n    fn takes_mut_self(&mut self);\n\n    // above methods desugared\n    fn takes_self(self: Self);\n    fn takes_immut_self(self: &Self);\n    fn takes_mut_self(self: &mut Self);\n}\n\n// example from standard library\ntrait ToString {\n    fn to_string(&self) -> String;\n}\n```\n\nMethods can be called using the dot operator on the implementing type:\n\n```rust\nfn main() {\n    let five = 5.to_string();\n}\n```\n\nHowever, similarly to functions, they can also be called namespaced by the trait or implementing type:\n\n```rust\nfn main() {\n    let five = ToString::to_string(&5);\n    let five = i32::to_string(&5);\n}\n```\n\n\n\n#### Associated Types\n\nA trait can have associated types. This is useful when we need to use some type other than `Self` within function signatures, but we would still like the type to be chosen by the implementer rather than being hardcoded in the trait declaration:\n\n```rust\ntrait Trait {\n    type AssociatedType;\n    fn func(arg: Self::AssociatedType);\n}\n\nstruct SomeType;\nstruct OtherType;\n\n// any type implementing Trait can\n// choose the type of AssociatedType\n\nimpl Trait for SomeType {\n    type AssociatedType = i8; // chooses i8\n    fn func(arg: Self::AssociatedType) {}\n}\n\nimpl Trait for OtherType {\n    type AssociatedType = u8; // chooses u8\n    fn func(arg: Self::AssociatedType) {}\n}\n\nfn main() {\n    SomeType::func(-1_i8); // can only call func with i8 on SomeType\n    OtherType::func(1_u8); // can only call func with u8 on OtherType\n}\n```\n\n\n\n#### Generic Parameters\n\nThe term _\"generic parameters\"_ broadly refers to generic type parameters, generic lifetime parameters, and generic const parameters. Since all of those are a mouthful to say, people commonly abbreviate them to _\"generic types\"_, _\"lifetimes\"_, and _\"generic consts\"_. Since generic consts are not used in any of the standard library traits we'll be covering, they're outside the scope of this article.\n\nWe can generalize a trait declaration using parameters:\n\n```rust\n// trait declaration generalized with lifetime & type parameters\ntrait Trait<'a, T> {\n    // signature uses generic type\n    fn func1(arg: T);\n    \n    // signature uses lifetime\n    fn func2(arg: &'a i32);\n    \n    // signature uses generic type & lifetime\n    fn func3(arg: &'a T);\n}\n\nstruct SomeType;\n\nimpl<'a> Trait<'a, i8> for SomeType {\n    fn func1(arg: i8) {}\n    fn func2(arg: &'a i32) {}\n    fn func3(arg: &'a i8) {}\n}\n\nimpl<'b> Trait<'b, u8> for SomeType {\n    fn func1(arg: u8) {}\n    fn func2(arg: &'b i32) {}\n    fn func3(arg: &'b u8) {}\n}\n```\n\nIt's possible to provide default values for generic types. The most commonly used default value is `Self`, but any type works:\n\n```rust\n// make T = Self by default\ntrait Trait<T = Self> {\n    fn func(t: T) {}\n}\n\n// any type can be used as the default\ntrait Trait2<T = i32> {\n    fn func2(t: T) {}\n}\n\nstruct SomeType;\n\n// omitting the generic type will\n// cause the impl to use the default\n// value, which is Self here\nimpl Trait for SomeType {\n    fn func(t: SomeType) {}\n}\n\n// default value here is i32\nimpl Trait2 for SomeType {\n    fn func2(t: i32) {}\n}\n\n// the default is overridable as we'd expect\nimpl Trait<String> for SomeType {\n    fn func(t: String) {}\n}\n\n// overridable here too\nimpl Trait2<String> for SomeType {\n    fn func2(t: String) {}\n}\n```\n\nAside from parameterizing the trait, it's also possible to parameterize individual functions and methods:\n\n```rust\ntrait Trait {\n    fn func<'a, T>(t: &'a T);\n}\n```\n\n\n#### Generic Types vs Associated Types\n\nBoth generic types and associated types defer the decision to the implementer on which concrete types should be used in the trait's functions and methods, so this section seeks to explain when to use one over the other.\n\nThe general rule-of-thumb is:\n- Use associated types when there should only be a single impl of the trait per type.\n- Use generic types when there can be many possible impls of the trait per type.\n\nLet's say we want to define a trait called `Add` that allows us to add values together. Here's an initial design and impl that only uses associated types:\n\n```rust\ntrait Add {\n    type Rhs;\n    type Output;\n    fn add(self, rhs: Self::Rhs) -> Self::Output;\n}\n\nstruct Point {\n    x: i32,\n    y: i32,\n}\n\nimpl Add for Point {\n    type Rhs = Point;\n    type Output = Point;\n    fn add(self, rhs: Point) -> Point {\n        Point {\n            x: self.x + rhs.x,\n            y: self.y + rhs.y,\n        }\n    }\n}\n\nfn main() {\n    let p1 = Point { x: 1, y: 1 };\n    let p2 = Point { x: 2, y: 2 };\n    let p3 = p1.add(p2);\n    assert_eq!(p3.x, 3);\n    assert_eq!(p3.y, 3);\n}\n```\n\nLet's say we wanted to introduce the ability to add `i32`s to `Point`s, where the `i32` would be added to both the `x` and `y` members:\n\n```rust\ntrait Add {\n    type Rhs;\n    type Output;\n    fn add(self, rhs: Self::Rhs) -> Self::Output;\n}\n\nstruct Point {\n    x: i32,\n    y: i32,\n}\n\nimpl Add for Point {\n    type Rhs = Point;\n    type Output = Point;\n    fn add(self, rhs: Point) -> Point {\n        Point {\n            x: self.x + rhs.x,\n            y: self.y + rhs.y,\n        }\n    }\n}\n\nimpl Add for Point { // ❌\n    type Rhs = i32;\n    type Output = Point;\n    fn add(self, rhs: i32) -> Point {\n        Point {\n            x: self.x + rhs,\n            y: self.y + rhs,\n        }\n    }\n}\n\nfn main() {\n    let p1 = Point { x: 1, y: 1 };\n    let p2 = Point { x: 2, y: 2 };\n    let p3 = p1.add(p2);\n    assert_eq!(p3.x, 3);\n    assert_eq!(p3.y, 3);\n    \n    let p1 = Point { x: 1, y: 1 };\n    let int2 = 2;\n    let p3 = p1.add(int2); // ❌\n    assert_eq!(p3.x, 3);\n    assert_eq!(p3.y, 3);\n}\n```\n\nThrows:\n\n```none\nerror[E0119]: conflicting implementations of trait `Add` for type `Point`:\n  --> src/main.rs:23:1\n   |\n12 | impl Add for Point {\n   | ------------------ first implementation here\n...\n23 | impl Add for Point {\n   | ^^^^^^^^^^^^^^^^^^ conflicting implementation for `Point`\n```\n\nSince the `Add` trait is not parameterized by any generic types, we can only impl it once per type, which means we can only pick the types for both `Rhs` and `Output` once! To allow adding both `Points`s and `i32`s to `Point` we have to refactor `Rhs` from an associated type to a generic type, which would allow us to impl the trait multiple times for `Point` with different type arguments for `Rhs`:\n\n```rust\ntrait Add<Rhs> {\n    type Output;\n    fn add(self, rhs: Rhs) -> Self::Output;\n}\n\nstruct Point {\n    x: i32,\n    y: i32,\n}\n\nimpl Add<Point> for Point {\n    type Output = Self;\n    fn add(self, rhs: Point) -> Self::Output {\n        Point {\n            x: self.x + rhs.x,\n            y: self.y + rhs.y,\n        }\n    }\n}\n\nimpl Add<i32> for Point { // ✅\n    type Output = Self;\n    fn add(self, rhs: i32) -> Self::Output {\n        Point {\n            x: self.x + rhs,\n            y: self.y + rhs,\n        }\n    }\n}\n\nfn main() {\n    let p1 = Point { x: 1, y: 1 };\n    let p2 = Point { x: 2, y: 2 };\n    let p3 = p1.add(p2);\n    assert_eq!(p3.x, 3);\n    assert_eq!(p3.y, 3);\n    \n    let p1 = Point { x: 1, y: 1 };\n    let int2 = 2;\n    let p3 = p1.add(int2); // ✅\n    assert_eq!(p3.x, 3);\n    assert_eq!(p3.y, 3);\n}\n```\n\nLet's say we add a new type called `Line` that contains two `Point`s, and now there are contexts within our program where adding two `Point`s should produce a `Line` instead of a `Point`. This is not possible given the current design of the `Add` trait where `Output` is still an associated type, but we can satisfy these new requirements by also refactoring `Output` from an associated type into a generic type:\n\n```rust\ntrait Add<Rhs, Output> {\n    fn add(self, rhs: Rhs) -> Output;\n}\n\nstruct Point {\n    x: i32,\n    y: i32,\n}\n\nimpl Add<Point, Point> for Point {\n    fn add(self, rhs: Point) -> Point {\n        Point {\n            x: self.x + rhs.x,\n            y: self.y + rhs.y,\n        }\n    }\n}\n\nimpl Add<i32, Point> for Point {\n    fn add(self, rhs: i32) -> Point {\n        Point {\n            x: self.x + rhs,\n            y: self.y + rhs,\n        }\n    }\n}\n\nstruct Line {\n    start: Point,\n    end: Point,\n}\n\nimpl Add<Point, Line> for Point { // ✅\n    fn add(self, rhs: Point) -> Line {\n        Line {\n            start: self,\n            end: rhs,\n        }\n    }\n}\n\nfn main() {\n    let p1 = Point { x: 1, y: 1 };\n    let p2 = Point { x: 2, y: 2 };\n    let p3: Point = p1.add(p2);\n    assert!(p3.x == 3 && p3.y == 3);\n\n    let p1 = Point { x: 1, y: 1 };\n    let int2 = 2;\n    let p3 = p1.add(int2);\n    assert!(p3.x == 3 && p3.y == 3);\n\n    let p1 = Point { x: 1, y: 1 };\n    let p2 = Point { x: 2, y: 2 };\n    let l: Line = p1.add(p2); // ✅\n    assert!(l.start.x == 1 && l.start.y == 1 && l.end.x == 2 && l.end.y == 2)\n}\n```\n\nSo which `Add` trait above is the best? It really depends on the requirements of your program! They're all good in the right situations.\n\n\n\n### Scope\n\nTrait items cannot be used unless the trait is in scope. Most Rustaceans learn this the hard way the first time they try to write a program that does anything with I/O, because the `Read` and `Write` traits are not in the standard library prelude:\n\n```rust\nuse std::fs::File;\nuse std::io;\n\nfn main() -> Result<(), io::Error> {\n    let mut file = File::open(\"Cargo.toml\")?;\n    let mut buffer = String::new();\n    file.read_to_string(&mut buffer)?; // ❌ read_to_string not found in File\n    Ok(())\n}\n```\n\n`read_to_string(buf: &mut String)` is declared by the `std::io::Read` trait and implemented by the `std::fs::File` struct, but in order to call it, `std::io::Read` must be in scope:\n\n```rust\nuse std::fs::File;\nuse std::io;\nuse std::io::Read; // ✅\n\nfn main() -> Result<(), io::Error> {\n    let mut file = File::open(\"Cargo.toml\")?;\n    let mut buffer = String::new();\n    file.read_to_string(&mut buffer)?; // ✅\n    Ok(())\n}\n```\n\nThe standard library prelude is a module in the standard library, i.e. `std::prelude::v1`, that gets auto-imported at the top of every other module, i.e. `use std::prelude::v1::*`. Thus the following traits are always in scope and we never have to explicitly import them ourselves, because they're part of the prelude:\n- [AsMut](#asref--asmut)\n- [AsRef](#asref--asmut)\n- [Clone](#clone)\n- [Copy](#copy)\n- [Default](#default)\n- [Drop](#drop)\n- [Eq](#partialeq--eq)\n- [Fn](#fnonce-fnmut--fn)\n- [FnMut](#fnonce-fnmut--fn)\n- [FnOnce](#fnonce-fnmut--fn)\n- [From](#from--into)\n- [Into](#from--into)\n- [ToOwned](#toowned)\n- [IntoIterator](#intoiterator)\n- [Iterator](#iterator)\n- [PartialEq](#partialeq--eq)\n- [PartialOrd](#partialord--ord)\n- [Send](#send--sync)\n- [Sized](#sized)\n- [Sync](#send--sync)\n- [ToString](#display--tostring)\n- [Ord](#partialord--ord)\n\n\n\n### Derive Macros\n\nThe standard library exports a handful of derive macros, which we can use to quickly and conveniently impl a trait on a type if all of its members also impl the trait. The derive macros are named after the traits they impl:\n- [Clone](#clone)\n- [Copy](#copy)\n- [Debug](#debug)\n- [Default](#default)\n- [Eq](#partialeq--eq)\n- [Hash](#hash)\n- [Ord](#partialord--ord)\n- [PartialEq](#partialeq--eq)\n- [PartialOrd](#partialord--ord)\n\nExample usage:\n\n```rust\n// macro derives Copy & Clone impl for SomeType\n#[derive(Copy, Clone)]\nstruct SomeType;\n```\n\nNote: derive macros are just procedural macros and can do anything. There's no hard rule that they must impl a trait, or that they can only work if all the members of the type impl a trait. These are just the conventions followed by the derive macros in the standard library.\n\n\n\n### Default Impls\n\nTraits can provide default impls for their functions and methods.\n\n```rust\ntrait Trait {\n    fn method(&self) {\n        println!(\"default impl\");\n    }\n}\n\nstruct SomeType;\nstruct OtherType;\n\n// use default impl for Trait::method\nimpl Trait for SomeType {}\n\nimpl Trait for OtherType {\n    // use our own impl for Trait::method\n    fn method(&self) {\n        println!(\"OtherType impl\");\n    }\n}\n\nfn main() {\n    SomeType.method(); // prints \"default impl\"\n    OtherType.method(); // prints \"OtherType impl\"\n}\n```\n\nThis is especially handy if some of the trait methods can be implemented solely using other trait methods.\n\n```rust\ntrait Greet {\n    fn greet(&self, name: &str) -> String;\n    fn greet_loudly(&self, name: &str) -> String {\n        self.greet(name) + \"!\"\n    }\n}\n\nstruct Hello;\nstruct Hola;\n\nimpl Greet for Hello {\n    fn greet(&self, name: &str) -> String {\n        format!(\"Hello {}\", name)\n    }\n    // use default impl for greet_loudly\n}\n\nimpl Greet for Hola {\n    fn greet(&self, name: &str) -> String {\n        format!(\"Hola {}\", name)\n    }\n    // override default impl\n    fn greet_loudly(&self, name: &str) -> String {\n        let mut greeting = self.greet(name);\n        greeting.insert_str(0, \"¡\");\n        greeting + \"!\"\n    }\n}\n\nfn main() {\n    println!(\"{}\", Hello.greet(\"John\")); // prints \"Hello John\"\n    println!(\"{}\", Hello.greet_loudly(\"John\")); // prints \"Hello John!\"\n    println!(\"{}\", Hola.greet(\"John\")); // prints \"Hola John\"\n    println!(\"{}\", Hola.greet_loudly(\"John\")); // prints \"¡Hola John!\"\n}\n```\n\nMany traits in the standard library provide default impls for many of their methods.\n\n\n\n### Generic Blanket Impls\n\nA generic blanket impl is an impl on a generic type instead of a concrete type. To explain why and how we'd use one, let's start by writing an `is_even` method for number types:\n\n```rust\ntrait Even {\n    fn is_even(self) -> bool;\n}\n\nimpl Even for i8 {\n    fn is_even(self) -> bool {\n        self % 2_i8 == 0_i8\n    }\n}\n\nimpl Even for u8 {\n    fn is_even(self) -> bool {\n        self % 2_u8 == 0_u8\n    }\n}\n\nimpl Even for i16 {\n    fn is_even(self) -> bool {\n        self % 2_i16 == 0_i16\n    }\n}\n\n// etc\n\n#[test] // ✅\nfn test_is_even() {\n    assert!(2_i8.is_even());\n    assert!(4_u8.is_even());\n    assert!(6_i16.is_even());\n    // etc\n}\n```\n\nObviously, this is very verbose. Also, all of our impls are almost identical. Furthermore, in the unlikely but still possible event that Rust decides to add more number types in the future, we have to remember to come back to this code and update it with the new number types. We can solve all these problems using a generic blanket impl:\n\n```rust\nuse std::fmt::Debug;\nuse std::convert::TryInto;\nuse std::ops::Rem;\n\ntrait Even {\n    fn is_even(self) -> bool;\n}\n\n// generic blanket impl\nimpl<T> Even for T\nwhere\n    T: Rem<Output = T> + PartialEq<T> + Sized,\n    u8: TryInto<T>,\n    <u8 as TryInto<T>>::Error: Debug,\n{\n    fn is_even(self) -> bool {\n        // these unwraps will never panic\n        self % 2.try_into().unwrap() == 0.try_into().unwrap()\n    }\n}\n\n#[test] // ✅\nfn test_is_even() {\n    assert!(2_i8.is_even());\n    assert!(4_u8.is_even());\n    assert!(6_i16.is_even());\n    // etc\n}\n```\n\nUnlike default impls, which provide _an_ impl, generic blanket impls provide _the_ impl, so they are not overridable.\n\n```rust\nuse std::fmt::Debug;\nuse std::convert::TryInto;\nuse std::ops::Rem;\n\ntrait Even {\n    fn is_even(self) -> bool;\n}\n\nimpl<T> Even for T\nwhere\n    T: Rem<Output = T> + PartialEq<T> + Sized,\n    u8: TryInto<T>,\n    <u8 as TryInto<T>>::Error: Debug,\n{\n    fn is_even(self) -> bool {\n        self % 2.try_into().unwrap() == 0.try_into().unwrap()\n    }\n}\n\nimpl Even for u8 { // ❌\n    fn is_even(self) -> bool {\n        self % 2_u8 == 0_u8\n    }\n}\n```\n\nThrows:\n\n```none\nerror[E0119]: conflicting implementations of trait `Even` for type `u8`:\n  --> src/lib.rs:22:1\n   |\n10 | / impl<T> Even for T\n11 | | where\n12 | |     T: Rem<Output = T> + PartialEq<T> + Sized,\n13 | |     u8: TryInto<T>,\n...  |\n19 | |     }\n20 | | }\n   | |_- first implementation here\n21 | \n22 |   impl Even for u8 {\n   |   ^^^^^^^^^^^^^^^^ conflicting implementation for `u8`\n```\n\nThese impls overlap, hence they conflict, hence Rust rejects the code to ensure trait coherence. Trait coherence is the property that there exists at most one impl of a trait for any given type. The rules Rust uses to enforce trait coherence, the implications of those rules, and workarounds for the implications are outside the scope of this article.\n\n\n\n### Subtraits & Supertraits\n\nThe \"sub\" in \"subtrait\" refers to subset and the \"super\" in \"supertrait\" refers to superset. If we have this trait declaration:\n\n```rust\ntrait Subtrait: Supertrait {}\n```\n\nAll of the types which impl `Subtrait` are a subset of all the types which impl `Supertrait`, or to put it in opposite but equivalent terms: all the types which impl `Supertrait` are a superset of all the types which impl `Subtrait`.\n\nAlso, the above is just syntax sugar for:\n\n```rust\ntrait Subtrait where Self: Supertrait {}\n```\n\nIt's a subtle yet important distinction to understand that the bound is on `Self`, i.e. the type impling `Subtrait`, and not on `Subtrait` itself. The latter would not make any sense, since trait bounds can only be applied to concrete types which can impl traits. Traits cannot impl other traits:\n\n```rust\ntrait Supertrait {\n    fn method(&self) {\n        println!(\"in supertrait\");\n    }\n}\n\ntrait Subtrait: Supertrait {\n    // this looks like it might impl or\n    // override Supertrait::method but it\n    // does not\n    fn method(&self) {\n        println!(\"in subtrait\")\n    }\n}\n\nstruct SomeType;\n\n// adds Supertrait::method to SomeType\nimpl Supertrait for SomeType {}\n\n// adds Subtrait::method to SomeType\nimpl Subtrait for SomeType {}\n\n// both methods exist on SomeType simultaneously\n// neither overriding or shadowing the other\n\nfn main() {\n    SomeType.method(); // ❌ ambiguous method call\n    // must disambiguate using fully-qualified syntax\n    <SomeType as Supertrait>::method(&SomeType); // ✅ prints \"in supertrait\"\n    <SomeType as Subtrait>::method(&SomeType); // ✅ prints \"in subtrait\"\n}\n```\n\nFurthermore, there are no rules for how a type must impl both a subtrait and a supertrait. It can use the methods from either in the impl of the other.\n\n```rust\ntrait Supertrait {\n    fn super_method(&mut self);\n}\n\ntrait Subtrait: Supertrait {\n    fn sub_method(&mut self);\n}\n\nstruct CallSuperFromSub;\n\nimpl Supertrait for CallSuperFromSub {\n    fn super_method(&mut self) {\n        println!(\"in super\");\n    }\n}\n\nimpl Subtrait for CallSuperFromSub {\n    fn sub_method(&mut self) {\n        println!(\"in sub\");\n        self.super_method();\n    }\n}\n\nstruct CallSubFromSuper;\n\nimpl Supertrait for CallSubFromSuper {\n    fn super_method(&mut self) {\n        println!(\"in super\");\n        self.sub_method();\n    }\n}\n\nimpl Subtrait for CallSubFromSuper {\n    fn sub_method(&mut self) {\n        println!(\"in sub\");\n    }\n}\n\nstruct CallEachOther(bool);\n\nimpl Supertrait for CallEachOther {\n    fn super_method(&mut self) {\n        println!(\"in super\");\n        if self.0 {\n            self.0 = false;\n            self.sub_method();\n        }\n    }\n}\n\nimpl Subtrait for CallEachOther {\n    fn sub_method(&mut self) {\n        println!(\"in sub\");\n        if self.0 {\n            self.0 = false;\n            self.super_method();\n        }\n    }\n}\n\nfn main() {\n    CallSuperFromSub.super_method(); // prints \"in super\"\n    CallSuperFromSub.sub_method(); // prints \"in sub\", \"in super\"\n    \n    CallSubFromSuper.super_method(); // prints \"in super\", \"in sub\"\n    CallSubFromSuper.sub_method(); // prints \"in sub\"\n    \n    CallEachOther(true).super_method(); // prints \"in super\", \"in sub\"\n    CallEachOther(true).sub_method(); // prints \"in sub\", \"in super\"\n}\n```\n\nHopefully, the examples above show that the relationship between subtraits and supertraits can be complex. Before introducing a mental model that neatly encapsulates all of that complexity, let's quickly review and establish the mental model we use for understanding trait bounds on generic types:\n\n```rust\nfn function<T: Clone>(t: T) {\n    // impl\n}\n```\n\nWithout knowing anything about the impl of this function we could reasonably guess that `t.clone()` gets called at some point, because when a generic type is bounded by a trait, that strongly implies it has a dependency on the trait. The mental model for understanding the relationship between generic types and their trait bounds is a simple and intuitive one: generic types _depend on_ their trait bounds.\n\nNow let's look the trait declaration for `Copy`:\n\n```rust\ntrait Copy: Clone {}\n```\n\nThe syntax above looks very similar to the syntax for applying a trait bound on a generic type and yet `Copy` doesn't depend on `Clone` at all. The mental model we developed earlier doesn't help us here. In my opinion, the most simple and elegant mental model for understanding the relationship between subtraits and supertraits is: subtraits _refine_ their supertraits.\n\n\"Refinement\" is intentionally kept somewhat vague, because it can mean different things in different contexts:\n- a subtrait might make its supertrait's methods' impls more specialized, faster, or use less memory, e.g. `Copy: Clone`\n- a subtrait might make additional guarantees about the supertrait's methods' impls, e.g. `Eq: PartialEq`, `Ord: PartialOrd`, `ExactSizeIterator: Iterator`\n- a subtrait might make the supertrait's methods more flexible or easier to call, e.g. `FnMut: FnOnce`, `Fn: FnMut`\n- a subtrait might extend a supertrait and add new methods, e.g. `DoubleEndedIterator: Iterator`, `ExactSizeIterator: Iterator`\n\n\n\n### Trait Objects\n\nGenerics give us compile-time polymorphism, while trait objects give us run-time polymorphism. We can use trait objects to allow functions to dynamically return different types at run-time:\n\n```rust\nfn example(condition: bool, vec: Vec<i32>) -> Box<dyn Iterator<Item = i32>> {\n    let iter = vec.into_iter();\n    if condition {\n        // Has type:\n        // Box<Map<IntoIter<i32>, Fn(i32) -> i32>>\n        // But is cast to:\n        // Box<dyn Iterator<Item = i32>>\n        Box::new(iter.map(|n| n * 2))\n    } else {\n        // Has type:\n        // Box<Filter<IntoIter<i32>, Fn(&i32) -> bool>>\n        // But is cast to:\n        // Box<dyn Iterator<Item = i32>>\n        Box::new(iter.filter(|&n| n >= 2))\n    }\n}\n```\n\nTrait objects also allow us to store heterogeneous types in collections:\n\n```rust\nuse std::f64::consts::PI;\n\nstruct Circle {\n    radius: f64,\n}\n\nstruct Square {\n    side: f64\n}\n\ntrait Shape {\n    fn area(&self) -> f64;\n}\n\nimpl Shape for Circle {\n    fn area(&self) -> f64 {\n        PI * self.radius * self.radius\n    }\n}\n\nimpl Shape for Square {\n    fn area(&self) -> f64 {\n        self.side * self.side\n    }\n}\n\nfn get_total_area(shapes: Vec<Box<dyn Shape>>) -> f64 {\n    shapes.into_iter().map(|s| s.area()).sum()\n}\n\nfn example() {\n    let shapes: Vec<Box<dyn Shape>> = vec![\n        Box::new(Circle { radius: 1.0 }), // Box<Circle> cast to Box<dyn Shape>\n        Box::new(Square { side: 1.0 }), // Box<Square> cast to Box<dyn Shape>\n    ];\n    assert_eq!(PI + 1.0, get_total_area(shapes)); // ✅\n}\n```\n\nTrait objects are unsized, so they must always be behind a pointer. We can tell the difference between a concrete type and a trait object at the type level, based on the presence of the `dyn` keyword within the type:\n\n```rust\nstruct Struct;\ntrait Trait {}\n\n// regular struct\n&Struct\nBox<Struct>\nRc<Struct>\nArc<Struct>\n\n// trait objects\n&dyn Trait\nBox<dyn Trait>\nRc<dyn Trait>\nArc<dyn Trait>\n```\n\nNot all traits can be converted into trait objects. A trait is object-safe if it meets these requirements:\n- trait doesn't require `Self: Sized`\n- all of the trait's methods are object-safe\n\nA trait method is object-safe if it meets these requirements:\n- method requires `Self: Sized` or\n- method only uses a `Self` type in receiver position\n\nUnderstanding why these requirements are what they are is not relevant to the rest of this article, but if you're still curious, it's covered in [Sizedness in Rust](./sizedness-in-rust.md).\n\n\n\n### Marker Traits\n\nMarker traits are traits that have no trait items. Their job is to \"mark\" the implementing type as having some property which is otherwise not possible to represent using the type system.\n\n```rust\n// Impling PartialEq for a type promises\n// that equality for the type has these properties:\n// - symmetry: a == b implies b == a, and\n// - transitivity: a == b && b == c implies a == c\n// But DOES NOT promise this property:\n// - reflexivity: a == a\ntrait PartialEq {\n    fn eq(&self, other: &Self) -> bool;\n}\n\n// Eq has no trait items! The eq method is already\n// declared by PartialEq, but \"impling\" Eq\n// for a type promises this additional equality property:\n// - reflexivity: a == a\ntrait Eq: PartialEq {}\n\n// f64 impls PartialEq but not Eq because NaN != NaN\n// i32 impls PartialEq & Eq because there's no NaNs :)\n```\n\n\n\n### Auto Traits\n\nAuto traits are traits that get automatically implemented for a type if all of its members also impl the trait. What \"members\" means depends on the type, for example: fields of a struct, variants of an enum, elements of an array, items of a tuple, and so on.\n\nAll auto traits are marker traits but not all marker traits are auto traits. Auto traits must be marker traits so the compiler can provide an automatic default impl for them, which would not be possible if they had any trait items.\n\nExamples of auto traits:\n\n```rust\n// implemented for types which are safe to send between threads\nunsafe auto trait Send {}\n\n// implemented for types whose references are safe to send between threads\nunsafe auto trait Sync {}\n```\n\n\n\n### Unsafe Traits\n\nTraits can be marked unsafe to indicate that impling the trait might require unsafe code. Both `Send` and `Sync` are marked `unsafe`, because if they aren't automatically implemented for a type, that means it must contains some non-`Send` or non-`Sync` member, and we have to take extra care as the implementers to make sure there are no data races if we want to manually mark the type as `Send` and `Sync`.\n\n```rust\n// SomeType is not Send or Sync\nstruct SomeType {\n    not_send_or_sync: *const (),\n}\n\n// but if we're confident that our impl doesn't have any data races,\n// we can explicitly mark it as Send and Sync using unsafe\nunsafe impl Send for SomeType {}\nunsafe impl Sync for SomeType {}\n```\n\n\n\n## Auto Traits\n\n\n\n### Send & Sync\n\nPrerequisites\n- [Marker Traits](#marker-traits)\n- [Auto Traits](#auto-traits)\n- [Unsafe Traits](#unsafe-traits)\n\n```rust\nunsafe auto trait Send {}\nunsafe auto trait Sync {}\n```\n\nIf a type is `Send`, that means it's safe to send between threads. If a type is `Sync`, that means it's safe to share references of it between threads. In more precise terms, some type `T` is `Sync` if and only if `&T` is `Send`.\n\nAlmost all types are `Send` and `Sync`. The only notable `Send` exception is `Rc` and the only notable `Sync` exceptions are `Rc`, `Cell`, and `RefCell`. If we need a `Send` version of `Rc`, we can use `Arc`. If we need a `Sync` version of `Cell` or `RefCell`, we can use `Mutex` or `RwLock`. Although, if we're using the `Mutex` or `RwLock` to just wrap a primitive type, it's often better to use the atomic primitive types provided by the standard library, such as `AtomicBool`, `AtomicI32`, `AtomicUsize`, and so on.\n\nThat almost all types are `Sync` might be a surprise to some people, but yup, it's true even for types without any internal synchronization. This is possible thanks to Rust's strict borrowing rules.\n\nWe can pass many immutable references to the same data to many threads, and we're guaranteed that there are no data races, because as long as any immutable references exist, Rust statically guarantees that the underlying data cannot be mutated:\n\n```rust\nuse crossbeam::thread;\n\nfn main() {\n    let mut greeting = String::from(\"Hello\");\n    let greeting_ref = &greeting;\n    \n    thread::scope(|scoped_thread| {\n        // spawn 3 threads\n        for n in 1..=3 {\n            // greeting_ref copied into every thread\n            scoped_thread.spawn(move |_| {\n                println!(\"{} {}\", greeting_ref, n); // prints \"Hello {n}\"\n            });\n        }\n        \n        // line below could cause UB or data races but compiler rejects it\n        greeting += \" world\"; // ❌ cannot mutate greeting while immutable refs exist\n    });\n    \n    // can mutate greeting after every thread has joined\n    greeting += \" world\"; // ✅\n    println!(\"{}\", greeting); // prints \"Hello world\"\n}\n```\n\nLikewise, we can pass a single mutable reference to some data to a single thread, and we're guaranteed that there will be no data races, because Rust statically guarantees that aliased mutable references cannot exist, and that the underlying data cannot be mutated through anything other than the single existing mutable reference:\n\n```rust\nuse crossbeam::thread;\n\nfn main() {\n    let mut greeting = String::from(\"Hello\");\n    let greeting_ref = &mut greeting;\n    \n    thread::scope(|scoped_thread| {\n        // greeting_ref moved into thread\n        scoped_thread.spawn(move |_| {\n            *greeting_ref += \" world\";\n            println!(\"{}\", greeting_ref); // prints \"Hello world\"\n        });\n        \n        // line below could cause UB or data races but compiler rejects it\n        greeting += \"!!!\"; // ❌ cannot mutate greeting while mutable refs exist\n    });\n    \n    // can mutate greeting after the thread has joined\n    greeting += \"!!!\"; // ✅\n    println!(\"{}\", greeting); // prints \"Hello world!!!\"\n}\n```\n\nThis is why most types are `Sync` without requiring any explicit synchronization. In the event that we need to simultaneously mutate some data `T` across multiple threads, the compiler won't let us, until we wrap the data in a `Arc<Mutex<T>>` or `Arc<RwLock<T>>`, so the compiler enforces that explicit synchronization is used when it's needed.\n\n\n\n### Sized\n\nPrerequisites\n- [Marker Traits](#marker-traits)\n- [Auto Traits](#auto-traits)\n\nIf a type is `Sized`, that means its size in bytes is known at compile-time, and it's possible to put instances of the type on the stack.\n\nSizedness of types, and its implications, is a subtle, yet huge, topic that affects a lot of different aspects of the language. It's so important that I wrote an entire article on it called [Sizedness in Rust](./sizedness-in-rust.md), which I highly recommend reading for anyone who would like to understand sizedness in-depth. I'll summarize a few key things which are relevant to this article.\n\n1. All generic types get an implicit `Sized` bound.\n\n```rust\nfn func<T>(t: &T) {}\n\n// example above desugared\nfn func<T: Sized>(t: &T) {}\n```\n\n2. Since there's an implicit `Sized` bound on all generic types, if we want to opt-out of this implicit bound, we need to use the special _\"relaxed bound\"_ syntax `?Sized`, which currently only exists for the `Sized` trait:\n\n```rust\n// now T can be unsized\nfn func<T: ?Sized>(t: &T) {}\n```\n\n3. There's an implicit `?Sized` bound on all traits.\n\n```rust\ntrait Trait {}\n\n// example above desugared\ntrait Trait: ?Sized {}\n```\n\nThis is so that trait objects can impl the trait. Again, all of the nitty gritty details are in [Sizedness in Rust](./sizedness-in-rust.md).\n\n\n\n## General traits\n\n\n\n### Default\n\nPrerequisites\n- [Self](#self)\n- [Functions](#functions)\n- [Derive Macros](#derive-macros)\n\n```rust\ntrait Default {\n    fn default() -> Self;\n}\n```\n\nIt's possible to construct default values of `Default` types.\n\n```rust\nstruct Color {\n    r: u8,\n    g: u8,\n    b: u8,\n}\n\nimpl Default for Color {\n    // default color is black\n    fn default() -> Self {\n        Color {\n            r: 0,\n            g: 0,\n            b: 0,\n        }\n    }\n}\n```\n\nThis is useful for quick prototyping, but also in any instance where we just need an instance of a type, and we aren't picky about what it is:\n\n```rust\nfn main() {\n    // just give me some color!\n    let color = Color::default();\n}\n```\n\nThis is also useful when providing an optional parameter to functions:\n\n```rust\nstruct Canvas;\nenum Shape {\n    Circle,\n    Rectangle,\n}\n\nimpl Canvas {\n    // let user optionally pass a color\n    fn paint(&mut self, shape: Shape, color: Option<Color>) {\n        // if no color is passed, use the default color\n        let color = color.unwrap_or_default();\n        // etc\n    }\n}\n```\n\n`Default` is also useful in generic contexts where we need to construct generic types:\n\n```rust\nfn guarantee_length<T: Default>(mut vec: Vec<T>, min_len: usize) -> Vec<T> {\n    for _ in 0..min_len.saturating_sub(vec.len()) {\n        vec.push(T::default());\n    }\n    vec\n}\n```\n\nAnother way we can take advantage of `Default` types is for partial initialization of structs using Rust's struct update syntax. We may have a `new` constructor for `Color` that takes every member as an argument:\n\n```rust\nimpl Color {\n    fn new(r: u8, g: u8, b: u8) -> Self {\n        Color {\n            r,\n            g,\n            b,\n        }\n    }\n}\n```\n\nHowever, we can also have convenience constructors that only accept a particular struct member, and fall back to the default values for the other struct members:\n\n```rust\nimpl Color {\n    fn red(r: u8) -> Self {\n        Color {\n            r,\n            ..Color::default()\n        }\n    }\n    fn green(g: u8) -> Self {\n        Color {\n            g,\n            ..Color::default()\n        }\n    }\n    fn blue(b: u8) -> Self {\n        Color {\n            b,\n            ..Color::default()\n        }\n    }\n}\n```\n\nThere's also a `Default` derive macro, which works when all of a types's members are `Default`, so we can write `Color` like this:\n\n```rust\n// default color is black\n// because u8::default() == 0\n#[derive(Default)]\nstruct Color {\n    r: u8,\n    g: u8,\n    b: u8\n}\n```\n\n\n\n### Clone\n\nPrerequisites\n- [Self](#self)\n- [Methods](#methods)\n- [Default Impls](#default-impls)\n- [Derive Macros](#derive-macros)\n\n```rust\ntrait Clone {\n    fn clone(&self) -> Self;\n\n    // provided default impls\n    fn clone_from(&mut self, source: &Self);\n}\n```\n\nWe can convert immutable references of `Clone` types into owned values, i.e. `&T` -> `T`. `Clone` makes no promises about the efficiency of this conversion, so it can be slow and expensive. To quickly impl `Clone` on a type, we can use the derive macro:\n\n```rust\n#[derive(Clone)]\nstruct SomeType {\n    cloneable_member1: CloneableType1,\n    cloneable_member2: CloneableType2,\n    // etc\n}\n\n// macro generates impl below\nimpl Clone for SomeType {\n    fn clone(&self) -> Self {\n        SomeType {\n            cloneable_member1: self.cloneable_member1.clone(),\n            cloneable_member2: self.cloneable_member2.clone(),\n            // etc\n        }\n    }\n}\n```\n\n`Clone` can also be useful when constructing instances of a type within a generic context. Here's a modified example from the previous section, but uses `Clone` instead of `Default`:\n\n```rust\nfn guarantee_length<T: Clone>(mut vec: Vec<T>, min_len: usize, fill_with: &T) -> Vec<T> {\n    for _ in 0..min_len.saturating_sub(vec.len()) {\n        vec.push(fill_with.clone());\n    }\n    vec\n}\n```\n\nPeople also commonly use cloning as an escape hatch, to avoid dealing with the borrow checker. Managing structs with references can be challenging, but we can turn the references into owned values by cloning them.\n\n```rust\n// oof, we gotta worry about lifetimes 😟\nstruct SomeStruct<'a> {\n    data: &'a Vec<u8>,\n}\n\n// now we're on easy street 😎\nstruct SomeStruct {\n    data: Vec<u8>,\n}\n```\n\nIf we're working on a program where performance is not the utmost concern, then we don't need to sweat cloning data. Rust is a low-level language that exposes a lot of low-level details, so it's easy to get caught up in premature optimizations instead of actually solving the problem at hand. For many programs, the best order of priorities is usually to build for correctness first, elegance second, and performance third, and only focus on performance after the program has been profiled and the performance bottlenecks have been identified. This is good general advice to follow, and if it doesn't apply to your particular program, then you would know.\n\n\n\n### Copy\n\nPrerequisites\n- [Marker Traits](#marker-traits)\n- [Subtraits & Supertraits](#subtraits--supertraits)\n- [Derive Macros](#derive-macros)\n\n```rust\ntrait Copy: Clone {}\n```\n\nWe copy `Copy` types, e.g. `T` -> `T`. `Copy` promises the copy operation will be a simple bitwise copy, so it will be very fast and efficient. We cannot impl `Copy` ourselves, only the compiler can provide an impl, but we can tell it to do so by using the `Copy` derive macro, together with the `Clone` derive macro since `Copy` is a subtrait of `Clone`:\n\n```rust\n#[derive(Copy, Clone)]\nstruct SomeType;\n```\n\n`Copy` refines `Clone`. A clone may be slow and expensive but a copy is guaranteed to be fast and cheap, so a copy is just a fast clone. If a type impls `Copy`, that makes the `Clone` impl trivial:\n\n```rust\n// this is what the derive macro generates\nimpl<T: Copy> Clone for T {\n    // the clone method becomes just a copy\n    fn clone(&self) -> Self {\n        *self\n    }\n}\n```\n\nImpling `Copy` for a type changes its behavior when it gets moved. By default, all types have _move semantics_, but once a type impls `Copy`, it gets _copy semantics_. To explain the difference between the two, let's examine these simple scenarios:\n\n```rust\n// a \"move\", src: !Copy\nlet dest = src; \n\n// a \"copy\", src: Copy\nlet dest = src;\n```\n\nIn both cases, `dest = src` performs a simple bitwise copy of `src`'s contents and moves the result into `dest`. The only difference is that in the case of _\"a move\"_, the borrow checker invalidates the `src` variable, and makes sure it's not used anywhere else later, and in the case of _\"a copy\"_, `src` remains valid and usable.\n\nIn a nutshell: Copies _are_ moves. Moves _are_ copies. The only difference is how they're treated by the borrow checker.\n\n#### Move example\n\nFor a more concrete example of a move, imagine `src` was a `Vec<i32>`, and its contents looked something like this:\n\n```rust\n{ data: *mut [i32], length: usize, capacity: usize }\n```\n\nNote that `Vec` does not implement `Copy`, and has move semantics.\n\nWhen we write `dest = src`, we end up with:\n\n```rust\nsrc = { data: *mut [i32], length: usize, capacity: usize }\ndest = { data: *mut [i32], length: usize, capacity: usize }\n```\n\nAt this point, both `src` and `dest` have aliased mutable references to the same data, which is a big no-no, so the borrow checker invalidates the `src` variable, and it can't be used again without throwing a compile error.\n\n#### Copy example\n\nFor a more concrete example of a copy, imagine `src` was an `Option<i32>` and its contents looked something like this:\n\n```rust\n{ is_valid: bool, data: i32 }\n```\n\nNow when we write `dest = src` we end up with:\n\n```rust\nsrc = { is_valid: bool, data: i32 }\ndest = { is_valid: bool, data: i32 }\n```\n\nThese are both usable simultaneously! Hence `Option<i32>` is `Copy`.\n\nAlthough `Copy` could be an auto trait, the Rust language designers decided that it's simpler and safer for types to explicitly opt into copy semantics, rather than silently inheriting copy semantics whenever the type is eligible, as the latter can cause surprising confusing behavior, which often leads to bugs.\n\n\n\n### Any\n\nPrerequisites\n- [Self](#self)\n- [Generic Blanket Impls](#generic-blanket-impls)\n- [Subtraits & Supertraits](#subtraits--supertraits)\n- [Trait Objects](#trait-objects)\n\n```rust\ntrait Any: 'static {\n    fn type_id(&self) -> TypeId;\n}\n```\n\nRust's style of polymorphism is parametric, but if we're looking to use a more ad-hoc style of polymorphism, similar to dynamically-typed languages, then we can emulate that using the `Any` trait. We don't have to manually impl this trait for our types, because it's already covered by this generic blanket impl:\n\n```rust\nimpl<T: 'static + ?Sized> Any for T {\n    fn type_id(&self) -> TypeId {\n        TypeId::of::<T>()\n    }\n}\n```\n\nThe way we get a `T` out of a `dyn Any` is by using the `downcast_ref::<T>()` and `downcast_mut::<T>()` methods:\n\n```rust\nuse std::any::Any;\n\n#[derive(Default)]\nstruct Point {\n    x: i32,\n    y: i32,\n}\n\nimpl Point {\n    fn inc(&mut self) {\n        self.x += 1;\n        self.y += 1;\n    }\n}\n\nfn inc_any(mut any: Box<dyn Any>) -> Box<dyn Any> {\n    if let Some(num) = any.downcast_mut::<i32>() {\n        *num += 1;\n    } else if let Some(string) = any.downcast_mut::<String>() {\n        *string += \"!\";\n    } else if let Some(point) = any.downcast_mut::<Point>() {\n        point.inc();\n    }\n    any\n}\n\nfn main() {\n    let mut vec: Vec<Box<dyn Any>> = vec![\n        Box::new(0),\n        Box::new(String::from(\"a\")),\n        Box::new(Point::default()),\n    ];\n    // vec = [0, \"a\", Point { x: 0, y: 0 }]\n    vec = vec.into_iter().map(inc_any).collect();\n    // vec = [1, \"a!\", Point { x: 1, y: 1 }]\n}\n```\n\nThis trait rarely _needs_ to be used, because on top of parametric polymorphism being superior to ad-hoc polymorphism in most scenarios, the latter can also be emulated using enums, which are more type-safe and require less indirection. For example, we could have written the above example like this:\n\n```rust\n#[derive(Default)]\nstruct Point {\n    x: i32,\n    y: i32,\n}\n\nimpl Point {\n    fn inc(&mut self) {\n        self.x += 1;\n        self.y += 1;\n    }\n}\n\nenum Stuff {\n    Integer(i32),\n    String(String),\n    Point(Point),\n}\n\nfn inc_stuff(mut stuff: Stuff) -> Stuff {\n    match &mut stuff {\n        Stuff::Integer(num) => *num += 1,\n        Stuff::String(string) => *string += \"!\",\n        Stuff::Point(point) => point.inc(),\n    }\n    stuff\n}\n\nfn main() {\n    let mut vec = vec![\n        Stuff::Integer(0),\n        Stuff::String(String::from(\"a\")),\n        Stuff::Point(Point::default()),\n    ];\n    // vec = [0, \"a\", Point { x: 0, y: 0 }]\n    vec = vec.into_iter().map(inc_stuff).collect();\n    // vec = [1, \"a!\", Point { x: 1, y: 1 }]\n}\n```\n\nDespite `Any` rarely being _needed_, it can still be convenient to use sometimes, as we'll later see in the **Error Handling** section.\n\n\n\n## Formatting Traits\n\nWe can serialize types into strings using the formatting macros in `std::fmt`, the most well-known of the bunch being `println!`. We can pass formatting parameters to the `{}` placeholders used within format `str`s, which are then used to select which trait impl to use to serialize the placeholder's argument.\n\n| Trait | Placeholder | Description |\n|-------|-------------|-------------|\n| `Display` | `{}` | display representation |\n| `Debug` | `{:?}` | debug representation |\n| `Octal` | `{:o}` | octal representation |\n| `LowerHex` | `{:x}` | lowercase hex representation |\n| `UpperHex` | `{:X}` | uppercase hex representation |\n| `Pointer` | `{:p}` | memory address |\n| `Binary` | `{:b}` | binary representation |\n| `LowerExp` | `{:e}` | lowercase exponential representation |\n| `UpperExp` | `{:E}` | uppercase exponential representation |\n\n\n\n### Display & ToString\n\nPrerequisites\n- [Self](#self)\n- [Methods](#methods)\n- [Generic Blanket Impls](#generic-blanket-impls)\n\n```rust\ntrait Display {\n    fn fmt(&self, f: &mut Formatter<'_>) -> Result;\n}\n```\n\n`Display` types can be serialized into `String`s that are friendly to the end users of the program. Example impl for `Point`:\n\n```rust\nuse std::fmt;\n\n#[derive(Default)]\nstruct Point {\n    x: i32,\n    y: i32,\n}\n\nimpl fmt::Display for Point {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        write!(f, \"({}, {})\", self.x, self.y)\n    }\n}\n\nfn main() {\n    println!(\"origin: {}\", Point::default());\n    // prints \"origin: (0, 0)\"\n\n    // get Point's Display representation as a String\n    let stringified_point = format!(\"{}\", Point::default());\n    assert_eq!(\"(0, 0)\", stringified_point); // ✅\n}\n```\n\nIn addition to using the `format!` macro to get a type's display representation as a `String`, we can use the `ToString` trait:\n\n```rust\ntrait ToString {\n    fn to_string(&self) -> String;\n}\n```\n\nThere's no need for us to impl this ourselves. In fact, we can't, because of this generic blanket impl that already automatically impls `ToString` for any type which impls `Display`:\n\n```rust\nimpl<T: Display + ?Sized> ToString for T;\n```\n\nUsing `ToString` with `Point`:\n\n```rust\n#[test] // ✅\nfn display_point() {\n    let origin = Point::default();\n    assert_eq!(format!(\"{}\", origin), \"(0, 0)\");\n}\n\n#[test] // ✅\nfn point_to_string() {\n    let origin = Point::default();\n    assert_eq!(origin.to_string(), \"(0, 0)\");\n}\n\n#[test] // ✅\nfn display_equals_to_string() {\n    let origin = Point::default();\n    assert_eq!(format!(\"{}\", origin), origin.to_string());\n}\n```\n\n\n\n### Debug\n\nPrerequisites\n- [Self](#self)\n- [Methods](#methods)\n- [Derive Macros](#derive-macros)\n- [Display & ToString](#display--tostring)\n\n```rust\ntrait Debug {\n    fn fmt(&self, f: &mut Formatter<'_>) -> Result;\n}\n```\n\n`Debug` has an identical signature to `Display`. The only difference is that the `Debug` impl is called when we use the `{:?}` formatting specifier.\n\nWhile the result of `Display` is intended to be seen by end users of a program, the `Debug` result is intended to only be shown to developers. The standard library implements `Display` for many built-in types, such as numbers, but does not implement `Display` for most types.  However, the standard library does implement `Debug` for a variety of common types such as tuples, `Vec`, `HashMap`, and other collections, as a way to easily print out values while debugging and developing.\n\n`Debug` can be derived on a type if all of its members are `Debug`:\n\n```rust\nuse std::fmt;\n\n#[derive(Debug)]\nstruct Point {\n    x: i32,\n    y: i32,\n}\n\n// derive macro generates impl below\nimpl fmt::Debug for Point {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.debug_struct(\"Point\")\n            .field(\"x\", &self.x)\n            .field(\"y\", &self.y)\n            .finish()\n    }\n}\n```\n\nImpling `Debug` for a type also allows it to be used within the `dbg!` macro, which is superior to `println!` for quick and dirty print logging. Some of its advantages:\n\n1. `dbg!` prints to stderr instead of stdout so the debug logs are easy to separate from the actual stdout output of our program.\n2. `dbg!` prints the expression passed to it as well as the value the expression evaluated to.\n3. `dbg!` takes ownership of its arguments and returns them so you can use it within expressions:\n\n```rust\nfn some_condition() -> bool {\n    true\n}\n\n// no logging\nfn example() {\n    if some_condition() {\n        // some code\n    }\n}\n\n// println! logging\nfn example_println() {\n    // 🤦\n    let result = some_condition();\n    println!(\"{}\", result); // just prints \"true\"\n    if result {\n        // some code\n    }\n}\n\n// dbg! logging\nfn example_dbg() {\n    // 😍\n    if dbg!(some_condition()) { // prints \"[src/main.rs:22] some_condition() = true\"\n        // some code\n    }\n}\n```\n\nThe only downside is that `dbg!` isn't automatically stripped in release builds, so we have to manually remove it from our code if we don't want to ship it in the final executable.\n\n\n\n## Operator Traits\n\nAll operators in Rust are associated with traits. If we'd like to impl operators for our types, we have to impl the associated traits.\n\n| Trait(s) | Category | Operator(s) | Description |\n|----------|----------|-------------|-------------|\n| `Eq`, `PartialEq` | comparison | `==` | equality |\n| `Ord`, `PartialOrd` | comparison | `<`, `>`, `<=`, `>=` | comparison |\n| `Add` | arithmetic | `+` | addition |\n| `AddAssign` | arithmetic | `+=` | addition assignment |\n| `BitAnd` | arithmetic | `&` | bitwise AND |\n| `BitAndAssign` | arithmetic | `&=` | bitwise assignment |\n| `BitXor` | arithmetic | `^` | bitwise XOR |\n| `BitXorAssign` | arithmetic | `^=` | bitwise XOR assignment |\n| `Div` | arithmetic | `/` | division |\n| `DivAssign` | arithmetic | `/=` | division assignment |\n| `Mul` | arithmetic | `*` | multiplication |\n| `MulAssign` | arithmetic | `*=` | multiplication assignment |\n| `Neg` | arithmetic | `-` | unary negation |\n| `Not` | arithmetic | `!` | unary logical negation |\n| `Rem` | arithmetic | `%` | remainder |\n| `RemAssign` | arithmetic | `%=` | remainder assignment |\n| `Shl` | arithmetic | `<<` | left shift |\n| `ShlAssign` | arithmetic | `<<=` | left shift assignment |\n| `Shr` | arithmetic | `>>` | right shift |\n| `ShrAssign` | arithmetic | `>>=` | right shift assignment |\n| `Sub` | arithmetic | `-` | subtraction |\n| `SubAssign` | arithmetic | `-=` | subtraction assignment |\n| `Fn` | closure | `(...args)` | immutable closure invocation |\n| `FnMut` | closure | `(...args)` | mutable closure invocation |\n| `FnOnce` | closure | `(...args)` | one-time closure invocation |\n| `Deref` | other | `*` | immutable dereference |\n| `DerefMut` | other | `*` | mutable dereference |\n| `Drop` | other | - | type destructor |\n| `Index` | other | `[]` | immutable index |\n| `IndexMut` | other | `[]` | mutable index |\n| `RangeBounds` | other | `..` | range |\n\n\n\n### Comparison Traits\n\n| Trait(s) | Category | Operator(s) | Description |\n|----------|----------|-------------|-------------|\n| `Eq`, `PartialEq` | comparison | `==` | equality |\n| `Ord`, `PartialOrd` | comparison | `<`, `>`, `<=`, `>=` | comparison |\n\n\n#### PartialEq & Eq\n\nPrerequisites\n- [Self](#self)\n- [Methods](#methods)\n- [Generic Parameters](#generic-parameters)\n- [Default Impls](#default-impls)\n- [Generic Blanket Impls](#generic-blanket-impls)\n- [Marker Traits](#marker-traits)\n- [Subtraits & Supertraits](#subtraits--supertraits)\n- [Sized](#sized)\n\n```rust\ntrait PartialEq<Rhs = Self> \nwhere\n    Rhs: ?Sized, \n{\n    fn eq(&self, other: &Rhs) -> bool;\n\n    // provided default impls\n    fn ne(&self, other: &Rhs) -> bool;\n}\n```\n\n`PartialEq<Rhs>` types can be checked for equality to `Rhs` types using the `==` operator.\n\nAll `PartialEq<Rhs>` impls must ensure that equality is symmetric and transitive. That means for all `a`, `b`, and `c`:\n- `a == b` implies `b == a` (symmetry)\n- `a == b && b == c` implies `a == c` (transitivity) \n\nBy default `Rhs = Self` because we almost always want to compare instances of a type to each other, and not to instances of different types. This also automatically guarantees our impl is symmetric and transitive.\n\n```rust\nstruct Point {\n    x: i32,\n    y: i32\n}\n\n// Rhs == Self == Point\nimpl PartialEq for Point {\n    // impl automatically symmetric & transitive\n    fn eq(&self, other: &Point) -> bool {\n        self.x == other.x && self.y == other.y\n    }\n}\n```\n\nIf all the members of a type impl `PartialEq` then it can be derived:\n\n```rust\n#[derive(PartialEq)]\nstruct Point {\n    x: i32,\n    y: i32\n}\n\n#[derive(PartialEq)]\nenum Suit {\n    Spade,\n    Heart,\n    Club,\n    Diamond,\n}\n```\n\nOnce we impl `PartialEq` for our type, we also get equality comparisons between references of our type for free, thanks to these generic blanket impls:\n\n```rust\n// this impl only gives us: Point == Point\n#[derive(PartialEq)]\nstruct Point {\n    x: i32,\n    y: i32\n}\n\n// all of the generic blanket impls below\n// are provided by the standard library\n\n// this impl gives us: &Point == &Point\nimpl<A, B> PartialEq<&'_ B> for &'_ A\nwhere A: PartialEq<B> + ?Sized, B: ?Sized;\n\n// this impl gives us: &mut Point == &Point\nimpl<A, B> PartialEq<&'_ B> for &'_ mut A\nwhere A: PartialEq<B> + ?Sized, B: ?Sized;\n\n// this impl gives us: &Point == &mut Point\nimpl<A, B> PartialEq<&'_ mut B> for &'_ A\nwhere A: PartialEq<B> + ?Sized, B: ?Sized;\n\n// this impl gives us: &mut Point == &mut Point\nimpl<A, B> PartialEq<&'_ mut B> for &'_ mut A\nwhere A: PartialEq<B> + ?Sized, B: ?Sized;\n```\n\nSince this trait is generic, we can define equality between different types. The standard library leverages this to allow checking equality between the many string-like types, such as `String`, `&str`, `PathBuf`, `&Path`, `OsString`, `&OsStr`, and so on.\n\nGenerally, we should only impl equality between different types _if they contain the same kind of data_, and the only difference between the types is how they represent the data or how they allow interacting with the data.\n\nHere's a cute but bad example of how someone might be tempted to impl `PartialEq` to check equality between different types that don't meet the above criteria:\n\n```rust\n#[derive(PartialEq)]\nenum Suit {\n    Spade,\n    Club,\n    Heart,\n    Diamond,\n}\n\n#[derive(PartialEq)]\nenum Rank {\n    Ace,\n    Two,\n    Three,\n    Four,\n    Five,\n    Six,\n    Seven,\n    Eight,\n    Nine,\n    Ten,\n    Jack,\n    Queen,\n    King,\n}\n\n#[derive(PartialEq)]\nstruct Card {\n    suit: Suit,\n    rank: Rank,\n}\n\n// check equality of Card's suit\nimpl PartialEq<Suit> for Card {\n    fn eq(&self, other: &Suit) -> bool {\n        self.suit == *other\n    }\n}\n\n// check equality of Card's rank\nimpl PartialEq<Rank> for Card {\n    fn eq(&self, other: &Rank) -> bool {\n        self.rank == *other\n    }\n}\n\nfn main() {\n    let AceOfSpades = Card {\n        suit: Suit::Spade,\n        rank: Rank::Ace,\n    };\n    assert!(AceOfSpades == Suit::Spade); // ✅\n    assert!(AceOfSpades == Rank::Ace); // ✅\n}\n```\n\nIt works and kinda makes sense. A card which is an Ace of Spades is both an Ace and a Spade, and if we're writing a library to handle playing cards, it's reasonable that we'd want to make it easy and convenient to individually check the suit and rank of a card. However, something's missing: symmetry! We can `Card == Suit` and `Card == Rank`, but we cannot `Suit == Card` or `Rank == Card`, so let's fix that:\n\n```rust\n// check equality of Card's suit\nimpl PartialEq<Suit> for Card {\n    fn eq(&self, other: &Suit) -> bool {\n        self.suit == *other\n    }\n}\n\n// added for symmetry\nimpl PartialEq<Card> for Suit {\n    fn eq(&self, other: &Card) -> bool {\n        *self == other.suit\n    }\n}\n\n// check equality of Card's rank\nimpl PartialEq<Rank> for Card {\n    fn eq(&self, other: &Rank) -> bool {\n        self.rank == *other\n    }\n}\n\n// added for symmetry\nimpl PartialEq<Card> for Rank {\n    fn eq(&self, other: &Card) -> bool {\n        *self == other.rank\n    }\n}\n```\n\nWe have symmetry! Great. But adding symmetry just broke transitivity! Oops. This is now possible:\n\n```rust\nfn main() {\n    // Ace of Spades\n    let a = Card {\n        suit: Suit::Spade,\n        rank: Rank::Ace,\n    };\n    let b = Suit::Spade;\n    // King of Spades\n    let c = Card {\n        suit: Suit::Spade,\n        rank: Rank::King,\n    };\n    assert!(a == b && b == c); // ✅\n    assert!(a == c); // ❌\n}\n```\n\nA good example of impling `PartialEq` to check equality between different types would be a program that works with distances, and which uses different types to represent different units of measurement.\n\n```rust\n#[derive(PartialEq)]\nstruct Foot(u32);\n\n#[derive(PartialEq)]\nstruct Yard(u32);\n\n#[derive(PartialEq)]\nstruct Mile(u32);\n\nimpl PartialEq<Mile> for Foot {\n    fn eq(&self, other: &Mile) -> bool {\n        self.0 == other.0 * 5280\n    }\n}\n\nimpl PartialEq<Foot> for Mile {\n    fn eq(&self, other: &Foot) -> bool {\n        self.0 * 5280 == other.0\n    }    \n}\n\nimpl PartialEq<Mile> for Yard {\n    fn eq(&self, other: &Mile) -> bool {\n        self.0 == other.0 * 1760\n    }\n}\n\nimpl PartialEq<Yard> for Mile {\n    fn eq(&self, other: &Yard) -> bool {\n        self.0 * 1760 == other.0\n    }    \n}\n\nimpl PartialEq<Foot> for Yard {\n    fn eq(&self, other: &Foot) -> bool {\n        self.0 * 3 == other.0\n    }\n}\n\nimpl PartialEq<Yard> for Foot {\n    fn eq(&self, other: &Yard) -> bool {\n        self.0 == other.0 * 3\n    }\n}\n\nfn main() {\n    let a = Foot(5280);\n    let b = Yard(1760);\n    let c = Mile(1);\n    \n    // symmetry\n    assert!(a == b && b == a); // ✅\n    assert!(b == c && c == b); // ✅\n    assert!(a == c && c == a); // ✅\n\n    // transitivity\n    assert!(a == b && b == c && a == c); // ✅\n    assert!(c == b && b == a && c == a); // ✅\n}\n```\n\n`Eq` is a marker trait and a subtrait of `PartialEq<Self>`.\n\n```rust\ntrait Eq: PartialEq<Self> {}\n```\n\nIf we impl `Eq` for a type, on top of the symmetry & transitivity properties required by `PartialEq`, we're also guaranteeing reflexivity, i.e. `a == a` for all `a`. In this sense, `Eq` refines `PartialEq` because it represents a stricter version of equality. If all members of a type impl `Eq`, then the `Eq` impl can be derived for the type.\n\nFloats are `PartialEq` but not `Eq`, because `NaN != NaN`. Almost all other `PartialEq` types are trivially `Eq`, unless, of course, they contain floats.\n\nOnce a type impls `PartialEq` and `Debug`, we can use it in the `assert_eq!` macro. We can also compare collections of `PartialEq` types.\n\n```rust\n#[derive(PartialEq, Debug)]\nstruct Point {\n    x: i32,\n    y: i32,\n}\n\nfn example_assert(p1: Point, p2: Point) {\n    assert_eq!(p1, p2);\n}\n\nfn example_compare_collections<T: PartialEq>(vec1: Vec<T>, vec2: Vec<T>) {\n    // if T: PartialEq this now works!\n    if vec1 == vec2 {\n        // some code\n    } else {\n        // other code\n    }\n}\n```\n\n\n\n#### Hash\n\nPrerequisites\n- [Self](#self)\n- [Methods](#methods)\n- [Generic Parameters](#generic-parameters)\n- [Default Impls](#default-impls)\n- [Derive Macros](#derive-macros)\n- [PartialEq & Eq](#partialeq--eq)\n\n```rust\ntrait Hash {\n    fn hash<H: Hasher>(&self, state: &mut H);\n\n    // provided default impls\n    fn hash_slice<H: Hasher>(data: &[Self], state: &mut H);\n}\n```\n\nThis trait is not associated with any operator, but the best time to talk about it is right after `PartialEq` & `Eq`, so here it is. `Hash` types can be hashed using a `Hasher`.\n\n```rust\nuse std::hash::Hasher;\nuse std::hash::Hash;\n\nstruct Point {\n    x: i32,\n    y: i32,\n}\n\nimpl Hash for Point {\n    fn hash<H: Hasher>(&self, hasher: &mut H) {\n        hasher.write_i32(self.x);\n        hasher.write_i32(self.y);\n    }\n}\n```\n\nThere's a derive macro, which generates the same impl as above:\n\n```rust\n#[derive(Hash)]\nstruct Point {\n    x: i32,\n    y: i32,\n}\n```\n\nIf a type impls both `Hash` and `Eq`, those impls must agree with each other, such that for all `a` and `b`, if `a == b` then `a.hash() == b.hash()`. So we should always use the derive macro to impl both or manually impl both, but not mix the two, otherwise we risk breaking the above invariant.\n\nThe main benefit of impling `Eq` and `Hash` for a type is that it allows us to store that type as keys in `HashMap`s and `HashSet`s.\n\n```rust\nuse std::collections::HashSet;\n\n// now our type can be stored\n// in HashSets and HashMaps!\n#[derive(PartialEq, Eq, Hash)]\nstruct Point {\n    x: i32,\n    y: i32,\n}\n\nfn example_hashset() {\n    let mut points = HashSet::new();\n    points.insert(Point { x: 0, y: 0 }); // ✅\n}\n```\n\n\n\n#### PartialOrd & Ord\n\nPrerequisites\n- [Self](#self)\n- [Methods](#methods)\n- [Generic Parameters](#generic-parameters)\n- [Default Impls](#default-impls)\n- [Subtraits & Supertraits](#subtraits--supertraits)\n- [Derive Macros](#derive-macros)\n- [Sized](#sized)\n- [PartialEq & Eq](#partialeq--eq)\n\n```rust\nenum Ordering {\n    Less,\n    Equal,\n    Greater,\n}\n\ntrait PartialOrd<Rhs = Self>: PartialEq<Rhs> \nwhere\n    Rhs: ?Sized, \n{\n    fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;\n\n    // provided default impls\n    fn lt(&self, other: &Rhs) -> bool;\n    fn le(&self, other: &Rhs) -> bool;\n    fn gt(&self, other: &Rhs) -> bool;\n    fn ge(&self, other: &Rhs) -> bool;\n}\n```\n\n`PartialOrd<Rhs>` types can be compared to `Rhs` types using the `<`, `<=`, `>`, and `>=` operators.\n\nAll `PartialOrd` impls must ensure that comparisons are asymmetric and transitive. That means for all `a`, `b`, and `c`:\n- `a < b` implies `!(a > b)` (asymmetry)\n- `a < b && b < c` implies `a < c` (transitivity)\n\n`PartialOrd` is a subtrait of `PartialEq`, and their impls must always agree with each other.\n\n```rust\nfn must_always_agree<T: PartialOrd + PartialEq>(t1: T, t2: T) {\n    assert_eq!(t1.partial_cmp(&t2) == Some(Ordering::Equal), t1 == t2);\n}\n```\n\n`PartialOrd` refines `PartialEq` in the sense that when comparing `PartialEq` types we can check if they are equal or not equal, but when comparing `PartialOrd` types, we can not only check if they are equal or not equal, but when they are not equal, we can further check if the first item is less than or greater than the second item.\n\nBy default, `Rhs = Self`, because we almost always want to compare instances of a type to each other, and not to instances of different types. This also automatically guarantees our impl is symmetric and transitive.\n\n```rust\nuse std::cmp::Ordering;\n\n#[derive(PartialEq, PartialOrd)]\nstruct Point {\n    x: i32,\n    y: i32\n}\n\n// Rhs == Self == Point\nimpl PartialOrd for Point {\n    // impl automatically symmetric & transitive\n    fn partial_cmp(&self, other: &Point) -> Option<Ordering> {\n        Some(match self.x.cmp(&other.x) {\n            Ordering::Equal => self.y.cmp(&other.y),\n            ordering => ordering,\n        })\n    }\n}\n```\n\nIf all the members of a type impl `PartialOrd` then it can be derived:\n\n```rust\n#[derive(PartialEq, PartialOrd)]\nstruct Point {\n    x: i32,\n    y: i32,\n}\n\n#[derive(PartialEq, PartialOrd)]\nenum Stoplight {\n    Red,\n    Yellow,\n    Green,\n}\n```\n\nThe `PartialOrd` derive macro orders types based on the lexicographical order of their members:\n\n```rust\n// generates PartialOrd impl that orders\n// Points based on x member first and\n// y member second, because that's the order\n// they appear in the source code\n#[derive(PartialOrd, PartialEq)]\nstruct Point {\n    x: i32,\n    y: i32,\n}\n\n// generates DIFFERENT PartialOrd impl\n// that orders Points based on y member\n// first and x member second\n#[derive(PartialOrd, PartialEq)]\nstruct Point {\n    y: i32,\n    x: i32,\n}\n```\n\n`Ord` is a subtrait of `Eq` and `PartialOrd<Self>`:\n\n```rust\ntrait Ord: Eq + PartialOrd<Self> {\n    fn cmp(&self, other: &Self) -> Ordering;\n\n    // provided default impls\n    fn max(self, other: Self) -> Self;\n    fn min(self, other: Self) -> Self;\n    fn clamp(self, min: Self, max: Self) -> Self;\n}\n```\n\nIf we impl `Ord` for a type, on top of the asymmetry & transitivity properties required by `PartialOrd`, we're also guaranteeing that the asymmetry is total, i.e. exactly one of `a < b`, `a == b` or `a > b` is true for any given `a` and `b`. In this sense `Ord` refines `Eq` and `PartialOrd`, because it represents a stricter version of comparisons. If a type impls `Ord`, we can use that impl to trivially impl `PartialOrd`, `PartialEq`, and `Eq`:\n\n```rust\nuse std::cmp::Ordering;\n\n// of course we can use the derive macros here\n#[derive(Ord, PartialOrd, Eq, PartialEq)]\nstruct Point {\n    x: i32,\n    y: i32,\n}\n\n// note: as with PartialOrd, the Ord derive macro\n// orders a type based on the lexicographical order\n// of its members\n\n// but here's the impls if we wrote them out by hand\nimpl Ord for Point {\n    fn cmp(&self, other: &Self) -> Ordering {\n        match self.x.cmp(&other.x) {\n            Ordering::Equal => self.y.cmp(&other.y),\n            ordering => ordering,\n        }\n    }\n}\nimpl PartialOrd for Point {\n    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {\n        Some(self.cmp(other))\n    }\n}\nimpl PartialEq for Point {\n    fn eq(&self, other: &Self) -> bool {\n        self.cmp(other) == Ordering::Equal\n    }\n}\nimpl Eq for Point {}\n```\n\nFloats impl `PartialOrd`, but not `Ord`, because both `NaN < 0 == false` and `NaN >= 0 == false` are simultaneously true. Almost all other `PartialOrd` types are trivially `Ord`, unless, of course, they contain floats.\n\nOnce a type impls `Ord`, we can store it in `BTreeMap`s and `BTreeSet`s, as well as easily sort it using the `sort()` method on slices, and any types which deref to slices such as arrays, `Vec`s, and `VecDeque`s.\n\n```rust\nuse std::collections::BTreeSet;\n\n// now our type can be stored\n// in BTreeSets and BTreeMaps!\n#[derive(Ord, PartialOrd, PartialEq, Eq)]\nstruct Point {\n    x: i32,\n    y: i32,\n}\n\nfn example_btreeset() {\n    let mut points = BTreeSet::new();\n    points.insert(Point { x: 0, y: 0 }); // ✅\n}\n\n// we can also .sort() Ord types in collections!\nfn example_sort<T: Ord>(mut sortable: Vec<T>) -> Vec<T> {\n    sortable.sort();\n    sortable\n}\n```\n\n\n\n### Arithmetic Traits\n\n| Trait(s) | Category | Operator(s) | Description |\n|----------|----------|-------------|-------------|\n| `Add` | arithmetic | `+` | addition |\n| `AddAssign` | arithmetic | `+=` | addition assignment |\n| `BitAnd` | arithmetic | `&` | bitwise AND |\n| `BitAndAssign` | arithmetic | `&=` | bitwise assignment |\n| `BitXor` | arithmetic | `^` | bitwise XOR |\n| `BitXorAssign` | arithmetic | `^=` | bitwise XOR assignment |\n| `Div` | arithmetic | `/` | division |\n| `DivAssign` | arithmetic | `/=` | division assignment |\n| `Mul` | arithmetic | `*` | multiplication |\n| `MulAssign` | arithmetic | `*=` | multiplication assignment |\n| `Neg` | arithmetic | `-` | unary negation |\n| `Not` | arithmetic | `!` | unary logical negation |\n| `Rem` | arithmetic | `%` | remainder |\n| `RemAssign` | arithmetic | `%=` | remainder assignment |\n| `Shl` | arithmetic | `<<` | left shift |\n| `ShlAssign` | arithmetic | `<<=` | left shift assignment |\n| `Shr` | arithmetic | `>>` | right shift |\n| `ShrAssign` | arithmetic | `>>=` | right shift assignment |\n| `Sub` | arithmetic | `-` | subtraction |\n| `SubAssign` | arithmetic | `-=` | subtraction assignment |\n\n\nGoing over all of these would be very redundant. Most of these only apply to number types anyway. We'll only go over `Add` and `AddAssign`, since the `+` operator is commonly overloaded to do other stuff like adding items to collections or concatenating things together.  That way, we cover the most interesting ground and don't repeat ourselves.\n\n\n#### Add & AddAssign\n\nPrerequisites\n- [Self](#self)\n- [Methods](#methods)\n- [Associated Types](#associated-types)\n- [Generic Parameters](#generic-parameters)\n- [Generic Types vs Associated Types](#generic-types-vs-associated-types)\n- [Derive Macros](#derive-macros)\n\n```rust\ntrait Add<Rhs = Self> {\n    type Output;\n    fn add(self, rhs: Rhs) -> Self::Output;\n}\n```\n\n`Add<Rhs, Output = T>` types can be added to `Rhs` types and will produce `T` as output.\n\nExample `Add<Point, Output = Point>` impl for `Point`:\n\n```rust\n#[derive(Clone, Copy)]\nstruct Point {\n    x: i32,\n    y: i32,\n}\n\nimpl Add for Point {\n    type Output = Point;\n    fn add(self, rhs: Point) -> Point {\n        Point {\n            x: self.x + rhs.x,\n            y: self.y + rhs.y,\n        }\n    }\n}\n\nfn main() {\n    let p1 = Point { x: 1, y: 2 };\n    let p2 = Point { x: 3, y: 4 };\n    let p3 = p1 + p2;\n    assert_eq!(p3.x, p1.x + p2.x); // ✅\n    assert_eq!(p3.y, p1.y + p2.y); // ✅\n}\n```\n\nBut what if we only had references to `Point`s? Can we still add them then? Let's try:\n\n```rust\nfn main() {\n    let p1 = Point { x: 1, y: 2 };\n    let p2 = Point { x: 3, y: 4 };\n    let p3 = &p1 + &p2; // ❌\n}\n```\n\nUnfortunately not. The compiler throws:\n\n```none\nerror[E0369]: cannot add `&Point` to `&Point`\n  --> src/main.rs:50:25\n   |\n50 |     let p3: Point = &p1 + &p2;\n   |                     --- ^ --- &Point\n   |                     |\n   |                     &Point\n   |\n   = note: an implementation of `std::ops::Add` might be missing for `&Point`\n```\n\nWithin Rust's type system, for some type `T`, the types `T`, `&T`, and `&mut T` are all treated as unique distinct types, which means we have to provide trait impls for each of them separately. Let's define an `Add` impl for `&Point`:\n\n```rust\nimpl Add for &Point {\n    type Output = Point;\n    fn add(self, rhs: &Point) -> Point {\n        Point {\n            x: self.x + rhs.x,\n            y: self.y + rhs.y,\n        }\n    }\n}\n\nfn main() {\n    let p1 = Point { x: 1, y: 2 };\n    let p2 = Point { x: 3, y: 4 };\n    let p3 = &p1 + &p2; // ✅\n    assert_eq!(p3.x, p1.x + p2.x); // ✅\n    assert_eq!(p3.y, p1.y + p2.y); // ✅\n}\n```\n\nHowever, something still doesn't feel quite right. We have two separate impls of `Add` for `Point` and `&Point` and they _happen_ to do the same thing currently, but there's no guarantee that they will in the future! For example, let's say we decide that when we add two `Point`s together we want to create a `Line` containing those two `Point`s instead of creating a new `Point`.  We'd update our `Add` impl like this:\n\n```rust\nuse std::ops::Add;\n\n#[derive(Copy, Clone)]\nstruct Point {\n    x: i32,\n    y: i32,\n}\n\n#[derive(Copy, Clone)]\nstruct Line {\n    start: Point,\n    end: Point,\n}\n\n// we updated this impl\nimpl Add for Point {\n    type Output = Line;\n    fn add(self, rhs: Point) -> Line {\n        Line {\n            start: self,\n            end: rhs,\n        }\n    }\n}\n\n// but forgot to update this impl, uh oh!\nimpl Add for &Point {\n    type Output = Point;\n    fn add(self, rhs: &Point) -> Point {\n        Point {\n            x: self.x + rhs.x,\n            y: self.y + rhs.y,\n        }\n    }\n}\n\nfn main() {\n    let p1 = Point { x: 1, y: 2 };\n    let p2 = Point { x: 3, y: 4 };\n    let line: Line = p1 + p2; // ✅\n\n    let p1 = Point { x: 1, y: 2 };\n    let p2 = Point { x: 3, y: 4 };\n    let line: Line = &p1 + &p2; // ❌ expected Line, found Point\n}\n```\n\nOur current impl of `Add` for `&Point` creates an unnecessary maintenance burden. We want the `&Point` impl to match `Point`'s impl without having to manually update it every time we change `Point`'s impl. We'd like to keep our code as DRY (Don't Repeat Yourself) as possible. Luckily this is achievable:\n\n```rust\n// updated, DRY impl\nimpl Add for &Point {\n    type Output = <Point as Add>::Output;\n    fn add(self, rhs: &Point) -> Self::Output {\n        Point::add(*self, *rhs)\n    }\n}\n\nfn main() {\n    let p1 = Point { x: 1, y: 2 };\n    let p2 = Point { x: 3, y: 4 };\n    let line: Line = p1 + p2; // ✅\n\n    let p1 = Point { x: 1, y: 2 };\n    let p2 = Point { x: 3, y: 4 };\n    let line: Line = &p1 + &p2; // ✅\n}\n```\n\nThe `AddAssign<Rhs>` trait allows us to modify a type, by adding a `Rhs` type to it, which is what the `+=` operator does.\n\nNote that there is no `Output` associated type.  Instead, it mutates `Self` in-place. Here's the trait declaration:\n\n```rust\ntrait AddAssign<Rhs = Self> {\n    fn add_assign(&mut self, rhs: Rhs);\n}\n```\n\nExample impls for `Point` and `&Point`:\n\n```rust\nuse std::ops::AddAssign;\n\n#[derive(Copy, Clone)]\nstruct Point {\n    x: i32,\n    y: i32\n}\n\nimpl AddAssign for Point {\n    fn add_assign(&mut self, rhs: Point) {\n        self.x += rhs.x;\n        self.y += rhs.y;\n    }\n}\n\nimpl AddAssign<&Point> for Point {\n    fn add_assign(&mut self, rhs: &Point) {\n        Point::add_assign(self, *rhs);\n    }\n}\n\nfn main() {\n    let mut p1 = Point { x: 1, y: 2 };\n    let p2 = Point { x: 3, y: 4 };\n    p1 += &p2;\n    p1 += p2;\n    assert!(p1.x == 7 && p1.y == 10);\n}\n```\n\n\n\n### Closure Traits\n\n| Trait(s) | Category | Operator(s) | Description |\n|----------|----------|-------------|-------------|\n| `Fn` | closure | `(...args)` | immutable closure invocation |\n| `FnMut` | closure | `(...args)` | mutable closure invocation |\n| `FnOnce` | closure | `(...args)` | one-time closure invocation |\n\n\n\n#### FnOnce, FnMut, & Fn\n\nPrerequisites\n- [Self](#self)\n- [Methods](#methods)\n- [Associated Types](#associated-types)\n- [Generic Parameters](#generic-parameters)\n- [Generic Types vs Associated Types](#generic-types-vs-associated-types)\n- [Subtraits & Supertraits](#subtraits--supertraits)\n\n```rust\ntrait FnOnce<Args> {\n    type Output;\n    fn call_once(self, args: Args) -> Self::Output;\n}\n\ntrait FnMut<Args>: FnOnce<Args> {\n    fn call_mut(&mut self, args: Args) -> Self::Output;\n}\n\ntrait Fn<Args>: FnMut<Args> {\n    fn call(&self, args: Args) -> Self::Output;\n}\n```\n\nAlthough these traits exist, it's not possible to impl them for our own types in stable Rust. The only types we can create which impl these traits are closures. Depending on what the closure captures from its environment determines whether it impls `FnOnce`, `FnMut`, or `Fn`.\n\nAn `FnOnce` closure can only be called once, because it consumes some value as part of its execution:\n\n```rust\nfn main() {\n    let range = 0..10;\n    let get_range_count = || range.count();\n    assert_eq!(get_range_count(), 10); // ✅\n    get_range_count(); // ❌\n}\n```\n\nThe `.count()` method on iterators consumes the iterator so it can only be called once. Hence our closure can only be called once. This is why when we try to call it a second time we get this error:\n\n```none\nerror[E0382]: use of moved value: `get_range_count`\n --> src/main.rs:5:5\n  |\n4 |     assert_eq!(get_range_count(), 10);\n  |                ----------------- `get_range_count` moved due to this call\n5 |     get_range_count();\n  |     ^^^^^^^^^^^^^^^ value used here after move\n  |\nnote: closure cannot be invoked more than once because it moves the variable `range` out of its environment\n --> src/main.rs:3:30\n  |\n3 |     let get_range_count = || range.count();\n  |                              ^^^^^\nnote: this value implements `FnOnce`, which causes it to be moved when called\n --> src/main.rs:4:16\n  |\n4 |     assert_eq!(get_range_count(), 10);\n  |                ^^^^^^^^^^^^^^^\n```\n\nAn `FnMut` closure can be called multiple times and can also mutate variables it has captured from its environment. We might say `FnMut` closures perform side-effects or are stateful. Here's an example of a closure that filters out all non-ascending values from an iterator by keeping track of the smallest value it has seen so far:\n\n```rust\nfn main() {\n    let nums = vec![0, 4, 2, 8, 10, 7, 15, 18, 13];\n    let mut min = i32::MIN;\n    let ascending = nums.into_iter().filter(|&n| {\n        if n <= min {\n            false\n        } else {\n            min = n;\n            true\n        }\n    }).collect::<Vec<_>>();\n    assert_eq!(vec![0, 4, 8, 10, 15, 18], ascending); // ✅\n}\n```\n\n`FnMut` refines `FnOnce` in the sense that `FnOnce` requires taking ownership of its arguments and can only be called once, but `FnMut` requires only taking mutable references and can be called multiple times. `FnMut` can be used anywhere `FnOnce` can be used.\n\nAn `Fn` closure can be called multiple times and does not mutate any variables it has captured from its environment. We might say `Fn` closures have no side-effects or are stateless. Here's an example closure used with an iterator, which filters out all values less than some stack variable that the closure captures from its environment:\n\n```rust\nfn main() {\n    let nums = vec![0, 4, 2, 8, 10, 7, 15, 18, 13];\n    let min = 9;\n    let greater_than_9 = nums.into_iter().filter(|&n| n > min).collect::<Vec<_>>();\n    assert_eq!(vec![10, 15, 18, 13], greater_than_9); // ✅\n}\n```\n\n`Fn` refines `FnMut` in the sense that `FnMut` requires mutable references and can be called multiple times, but `Fn` only requires immutable references and can be called multiple times. `Fn` can be used anywhere `FnMut` can be used, which includes anywhere `FnOnce` can be used.\n\nIf a closure doesn't capture anything from its environment, it's technically not a closure, but just an anonymously declared inline function, which can be casted to, used, and passed around as a regular function pointer, i.e. `fn`. Function pointers can be used anywhere `Fn` can be used, which includes anywhere `FnMut` and `FnOnce` can be used.\n\n```rust\nfn add_one(x: i32) -> i32 {\n    x + 1\n}\n\nfn main() {\n    let mut fn_ptr: fn(i32) -> i32 = add_one;\n    assert_eq!(fn_ptr(1), 2); // ✅\n    \n    // capture-less closure cast to fn pointer\n    fn_ptr = |x| x + 1; // same as add_one\n    assert_eq!(fn_ptr(1), 2); // ✅\n}\n```\n\nExample of passing a regular function pointer in place of a closure:\n\n```rust\nfn main() {\n    let nums = vec![-1, 1, -2, 2, -3, 3];\n    let absolutes: Vec<i32> = nums.into_iter().map(i32::abs).collect();\n    assert_eq!(vec![1, 1, 2, 2, 3, 3], absolutes); // ✅\n}\n```\n\n\n\n### Other Traits\n\n| Trait(s) | Category | Operator(s) | Description |\n|----------|----------|-------------|-------------|\n| `Deref` | other | `*` | immutable dereference |\n| `DerefMut` | other | `*` | mutable dereference |\n| `Drop` | other | - | type destructor |\n| `Index` | other | `[]` | immutable index |\n| `IndexMut` | other | `[]` | mutable index |\n| `RangeBounds` | other | `..` | range |\n\n\n\n#### Deref & DerefMut\n\nPrerequisites\n- [Self](#self)\n- [Methods](#methods)\n- [Associated Types](#associated-types)\n- [Subtraits & Supertraits](#subtraits--supertraits)\n- [Sized](#sized)\n\n```rust\ntrait Deref {\n    type Target: ?Sized;\n    fn deref(&self) -> &Self::Target;\n}\n\ntrait DerefMut: Deref {\n    fn deref_mut(&mut self) -> &mut Self::Target;\n}\n```\n\n`Deref<Target = T>` types can be dereferenced to `T` types using the dereference operator `*`. This has obvious use-cases for smart pointer types like `Box` and `Rc`. However, we rarely see the dereference operator explicitly used in Rust code, and that's because of a Rust feature called _deref coercion_.\n\nRust automatically dereferences types when they're being passed as function arguments, returned from a function, or used as part of a method call. This explains why we can pass `&String` and `&Vec<T>` to functions expecting `&str` and `&[T]`, because `String` impls `Deref<Target = str>` and `Vec<T>` impls `Deref<Target = [T]>`.\n\n`Deref` and `DerefMut` should only be implemented for smart pointer types. The most common way people attempt to misuse and abuse these traits is to try to shoehorn some kind of OOP-style data inheritance into Rust. This does not work. Rust is not OOP. Let's examine a few different situations where, how, and why it does not work. Let's start with this example:\n\n```rust\nuse std::ops::Deref;\n\nstruct Human {\n    health_points: u32,\n}\n\nenum Weapon {\n    Spear,\n    Axe,\n    Sword,\n}\n\n// a Soldier is just a Human with a Weapon\nstruct Soldier {\n    human: Human,\n    weapon: Weapon,\n}\n\nimpl Deref for Soldier {\n    type Target = Human;\n    fn deref(&self) -> &Human {\n        &self.human\n    }\n}\n\nenum Mount {\n    Horse,\n    Donkey,\n    Cow,\n}\n\n// a Knight is just a Soldier with a Mount\nstruct Knight {\n    soldier: Soldier,\n    mount: Mount,\n}\n\nimpl Deref for Knight {\n    type Target = Soldier;\n    fn deref(&self) -> &Soldier {\n        &self.soldier\n    }\n}\n\nenum Spell {\n    MagicMissile,\n    FireBolt,\n    ThornWhip,\n}\n\n// a Mage is just a Human who can cast Spells\nstruct Mage {\n    human: Human,\n    spells: Vec<Spell>,\n}\n\nimpl Deref for Mage {\n    type Target = Human;\n    fn deref(&self) -> &Human {\n        &self.human\n    }\n}\n\nenum Staff {\n    Wooden,\n    Metallic,\n    Plastic,\n}\n\n// a Wizard is just a Mage with a Staff\nstruct Wizard {\n    mage: Mage,\n    staff: Staff,\n}\n\nimpl Deref for Wizard {\n    type Target = Mage;\n    fn deref(&self) -> &Mage {\n        &self.mage\n    }\n}\n\nfn borrows_human(human: &Human) {}\nfn borrows_soldier(soldier: &Soldier) {}\nfn borrows_knight(knight: &Knight) {}\nfn borrows_mage(mage: &Mage) {}\nfn borrows_wizard(wizard: &Wizard) {}\n\nfn example(human: Human, soldier: Soldier, knight: Knight, mage: Mage, wizard: Wizard) {\n    // all types can be used as Humans\n    borrows_human(&human);\n    borrows_human(&soldier);\n    borrows_human(&knight);\n    borrows_human(&mage);\n    borrows_human(&wizard);\n    // Knights can be used as Soldiers\n    borrows_soldier(&soldier);\n    borrows_soldier(&knight);\n    // Wizards can be used as Mages\n    borrows_mage(&mage);\n    borrows_mage(&wizard);\n    // Knights & Wizards passed as themselves\n    borrows_knight(&knight);\n    borrows_wizard(&wizard);\n}\n```\n\nAt first glance the above looks pretty good! However, it quickly breaks down upon further scrutiny. First of all, deref coercion only works on references, so it doesn't work when we actually want to pass ownership:\n\n```rust\nfn takes_human(human: Human) {}\n\nfn example(human: Human, soldier: Soldier, knight: Knight, mage: Mage, wizard: Wizard) {\n    // all types CANNOT be used as Humans\n    takes_human(human);\n    takes_human(soldier); // ❌\n    takes_human(knight); // ❌\n    takes_human(mage); // ❌\n    takes_human(wizard); // ❌\n}\n```\n\nFurthermore, deref coercion doesn't work in generic contexts. Let's say we impl some trait only on humans:\n\n```rust\ntrait Rest {\n    fn rest(&self);\n}\n\nimpl Rest for Human {\n    fn rest(&self) {}\n}\n\nfn take_rest<T: Rest>(rester: &T) {\n    rester.rest()\n}\n\nfn example(human: Human, soldier: Soldier, knight: Knight, mage: Mage, wizard: Wizard) {\n    // all types CANNOT be used as Rest types, only Human\n    take_rest(&human);\n    take_rest(&soldier); // ❌\n    take_rest(&knight); // ❌\n    take_rest(&mage); // ❌\n    take_rest(&wizard); // ❌\n}\n```\n\nAlso, although deref coercion works in a lot of places, it doesn't work everywhere. It doesn't work on operands, even though operators are just syntax sugar for method calls. Let's say, to be cute, we wanted `Mage`s to learn `Spell`s using the `+=` operator:\n\n```rust\nimpl DerefMut for Wizard {\n    fn deref_mut(&mut self) -> &mut Mage {\n        &mut self.mage\n    }\n}\n\nimpl AddAssign<Spell> for Mage {\n    fn add_assign(&mut self, spell: Spell) {\n        self.spells.push(spell);\n    }\n}\n\nfn example(mut mage: Mage, mut wizard: Wizard, spell: Spell) {\n    mage += spell;\n    wizard += spell; // ❌ wizard not coerced to mage here\n    wizard.add_assign(spell); // oof, we have to call it like this 🤦\n}\n```\n\nIn languages with OOP-style data inheritance, the value of `self` within a method is always equal to the type that called the method, but in the case of Rust, the value of `self` is always equal to the type that implemented the method:\n\n```rust\nstruct Human {\n    profession: &'static str,\n    health_points: u32,\n}\n\nimpl Human {\n    // self will always be a Human here, even if we call it on a Soldier\n    fn state_profession(&self) {\n        println!(\"I'm a {}!\", self.profession);\n    }\n}\n\nstruct Soldier {\n    profession: &'static str,\n    human: Human,\n    weapon: Weapon,\n}\n\nfn example(soldier: &Soldier) {\n    assert_eq!(\"servant\", soldier.human.profession);\n    assert_eq!(\"spearman\", soldier.profession);\n    soldier.human.state_profession(); // prints \"I'm a servant!\"\n    soldier.state_profession(); // still prints \"I'm a servant!\" 🤦\n}\n```\n\nThe above gotcha is especially damning when impling `Deref` or `DerefMut` on a newtype. Let's say we want to create a `SortedVec` type, which is just a `Vec` but it's always in sorted order. Here's how we might do that:\n\n```rust\nstruct SortedVec<T: Ord>(Vec<T>);\n\nimpl<T: Ord> SortedVec<T> {\n    fn new(mut vec: Vec<T>) -> Self {\n        vec.sort();\n        SortedVec(vec)\n    }\n    fn push(&mut self, t: T) {\n        self.0.push(t);\n        self.0.sort();\n    }\n}\n```\n\nObviously we cannot impl `DerefMut<Target = Vec<T>>` here or anyone using `SortedVec` would be able to trivially break the sorted order. However, impling `Deref<Target = Vec<T>>` surely must be safe, right? Try to spot the bug in the program below:\n\n```rust\nuse std::ops::Deref;\n\nstruct SortedVec<T: Ord>(Vec<T>);\n\nimpl<T: Ord> SortedVec<T> {\n    fn new(mut vec: Vec<T>) -> Self {\n        vec.sort();\n        SortedVec(vec)\n    }\n    fn push(&mut self, t: T) {\n        self.0.push(t);\n        self.0.sort();\n    }\n}\n\nimpl<T: Ord> Deref for SortedVec<T> {\n    type Target = Vec<T>;\n    fn deref(&self) -> &Vec<T> {\n        &self.0\n    }\n}\n\nfn main() {\n    let sorted = SortedVec::new(vec![2, 8, 6, 3]);\n    sorted.push(1);\n    let sortedClone = sorted.clone();\n    sortedClone.push(4);\n}\n```\n\nWe never implemented `Clone` for `SortedVec` so when we call the `.clone()` method the compiler is using deref coercion to resolve that method call on `Vec` and so it returns a `Vec` and not a `SortedVec`!\n\n```rust\nfn main() {\n    let sorted: SortedVec<i32> = SortedVec::new(vec![2, 8, 6, 3]);\n    sorted.push(1); // still sorted\n\n    // calling clone on SortedVec actually returns a Vec 🤦\n    let sortedClone: Vec<i32> = sorted.clone();\n    sortedClone.push(4); // sortedClone no longer sorted 💀\n}\n```\n\nAnyway, none of the above limitations, constraints, or gotchas are faults of Rust, because Rust was never designed to be an OO language or to support any OOP patterns in the first place.\n\nThe main takeaway from this section is: do not try to be cute or clever with `Deref` and `DerefMut` impls. They're really only appropriate for smart pointer types, which can only be implemented within the standard library for now, as smart pointer types currently require unstable features and compiler magic to work. If we want functionality and behavior similar to `Deref` and `DerefMut`, then what we're actually probably looking for is `AsRef` and `AsMut`, which we'll get to later.\n\n\n\n#### Index & IndexMut\n\nPrerequisites\n- [Self](#self)\n- [Methods](#methods)\n- [Associated Types](#associated-types)\n- [Generic Parameters](#generic-parameters)\n- [Generic Types vs Associated Types](#generic-types-vs-associated-types)\n- [Subtraits & Supertraits](#subtraits--supertraits)\n- [Sized](#sized)\n\n```rust\ntrait Index<Idx: ?Sized> {\n    type Output: ?Sized;\n    fn index(&self, index: Idx) -> &Self::Output;\n}\n\ntrait IndexMut<Idx>: Index<Idx> where Idx: ?Sized {\n    fn index_mut(&mut self, index: Idx) -> &mut Self::Output;\n}\n```\n\nWe can index `[]` into `Index<T, Output = U>` types with `T` values, and the index operation will return `&U` values. For syntax sugar, the compiler auto inserts a deref operator `*` in front of any value returned from an index operation:\n\n```rust\nfn main() {\n    // Vec<i32> impls Index<usize, Output = i32> so\n    // indexing Vec<i32> should produce &i32s and yet...\n    let vec = vec![1, 2, 3, 4, 5];\n    let num_ref: &i32 = vec[0]; // ❌ expected &i32 found i32\n    \n    // above line actually desugars to\n    let num_ref: &i32 = *vec[0]; // ❌ expected &i32 found i32\n\n    // both of these alternatives work\n    let num: i32 = vec[0]; // ✅\n    let num_ref = &vec[0]; // ✅\n}\n```\n\nIt's kinda confusing at first, because it seems like the `Index` trait does not follow its own method signature, but really it's just questionable syntax sugar.\n\nSince `Idx` is a generic type, the `Index` trait can be implemented many times for a given type, and in the case of `Vec<T>` not only can we index into it using `usize`, but we can also index into it using `Range<usize>`s to get slices.\n\n```rust\nfn main() {\n    let vec = vec![1, 2, 3, 4, 5];\n    assert_eq!(&vec[..], &[1, 2, 3, 4, 5]); // ✅\n    assert_eq!(&vec[1..], &[2, 3, 4, 5]); // ✅\n    assert_eq!(&vec[..4], &[1, 2, 3, 4]); // ✅\n    assert_eq!(&vec[1..4], &[2, 3, 4]); // ✅\n}\n```\n\nTo show off how we might impl `Index` ourselves, here's a fun example, which shows how we can use a newtype and the `Index` trait to impl wrapping indexes and negative indexes on a `Vec`:\n\n```rust\nuse std::ops::Index;\n\nstruct WrappingIndex<T>(Vec<T>);\n\nimpl<T> Index<usize> for WrappingIndex<T> {\n    type Output = T;\n    fn index(&self, index: usize) -> &T {\n        &self.0[index % self.0.len()]\n    }\n}\n\nimpl<T> Index<i128> for WrappingIndex<T> {\n    type Output = T;\n    fn index(&self, index: i128) -> &T {\n        let self_len = self.0.len() as i128;\n        let idx = (((index % self_len) + self_len) % self_len) as usize;\n        &self.0[idx]\n    }\n}\n\n#[test] // ✅\nfn indexes() {\n    let wrapping_vec = WrappingIndex(vec![1, 2, 3]);\n    assert_eq!(1, wrapping_vec[0_usize]);\n    assert_eq!(2, wrapping_vec[1_usize]);\n    assert_eq!(3, wrapping_vec[2_usize]);\n}\n\n#[test] // ✅\nfn wrapping_indexes() {\n    let wrapping_vec = WrappingIndex(vec![1, 2, 3]);\n    assert_eq!(1, wrapping_vec[3_usize]);\n    assert_eq!(2, wrapping_vec[4_usize]);\n    assert_eq!(3, wrapping_vec[5_usize]);\n}\n\n#[test] // ✅\nfn neg_indexes() {\n    let wrapping_vec = WrappingIndex(vec![1, 2, 3]);\n    assert_eq!(1, wrapping_vec[-3_i128]);\n    assert_eq!(2, wrapping_vec[-2_i128]);\n    assert_eq!(3, wrapping_vec[-1_i128]);\n}\n\n#[test] // ✅\nfn wrapping_neg_indexes() {\n    let wrapping_vec = WrappingIndex(vec![1, 2, 3]);\n    assert_eq!(1, wrapping_vec[-6_i128]);\n    assert_eq!(2, wrapping_vec[-5_i128]);\n    assert_eq!(3, wrapping_vec[-4_i128]);\n}\n```\n\nThere's no requirement that the `Idx` type has to be a number type or a `Range`, it could be an enum! Here's an example using basketball positions to index into a basketball team to retrieve players on the team:\n\n```rust\nuse std::ops::Index;\n\nenum BasketballPosition {\n    PointGuard,\n    ShootingGuard,\n    Center,\n    PowerForward,\n    SmallForward,\n}\n\nstruct BasketballPlayer {\n    name: &'static str,\n    position: BasketballPosition,\n}\n\nstruct BasketballTeam {\n    point_guard: BasketballPlayer,\n    shooting_guard: BasketballPlayer,\n    center: BasketballPlayer,\n    power_forward: BasketballPlayer,\n    small_forward: BasketballPlayer,\n}\n\nimpl Index<BasketballPosition> for BasketballTeam {\n    type Output = BasketballPlayer;\n    fn index(&self, position: BasketballPosition) -> &BasketballPlayer {\n        match position {\n            BasketballPosition::PointGuard => &self.point_guard,\n            BasketballPosition::ShootingGuard => &self.shooting_guard,\n            BasketballPosition::Center => &self.center,\n            BasketballPosition::PowerForward => &self.power_forward,\n            BasketballPosition::SmallForward => &self.small_forward,\n        }\n    }\n}\n```\n\n\n\n#### Drop\n\nPrerequisites\n- [Self](#self)\n- [Methods](#methods)\n\n```rust\ntrait Drop {\n    fn drop(&mut self);\n}\n```\n\nIf a type impls `Drop`, then `drop` will be called on the type when it goes out of scope but before it's destroyed. We will rarely need to impl this for our types, but a good example of where it's useful is if a type holds on to some external resources that need to be cleaned up when the type is destroyed.\n\nThere's a `BufWriter` type in the standard library that allows us to buffer writes to `Write` types. However, what if the `BufWriter` gets destroyed before the content in its buffer has been flushed to the underlying `Write` type? Thankfully, that's not possible! The `BufWriter` impls the `Drop` trait so that `flush` is always called on it whenever it goes out of scope!\n\n```rust\nimpl<W: Write> Drop for BufWriter<W> {\n    fn drop(&mut self) {\n        self.flush_buf();\n    }\n}\n```\n\nAlso, `Mutex`s in Rust don't have `unlock()` methods because they don't need them! Calling `lock()` on a `Mutex` returns a `MutexGuard`, which automatically unlocks the `Mutex` when it goes out of scope, thanks to its `Drop` impl:\n\n```rust\nimpl<T: ?Sized> Drop for MutexGuard<'_, T> {\n    fn drop(&mut self) {\n        unsafe {\n            self.lock.inner.raw_unlock();\n        }\n    }\n}\n```\n\nIn general, if you're impling an abstraction over some resource that needs to be cleaned up after use, then that's a great reason to make use of the `Drop` trait.\n\n\n\n## Conversion Traits\n\n\n\n### From & Into\n\nPrerequisites\n- [Self](#self)\n- [Functions](#functions)\n- [Methods](#methods)\n- [Generic Parameters](#generic-parameters)\n- [Generic Blanket Impls](#generic-blanket-impls)\n- [Subtraits & Supertraits](#subtraits--supertraits)\n- [Sized](#sized)\n\n```rust\ntrait From<T>: Sized {\n    fn from(T) -> Self;\n}\n```\n\n`From<T>` types allow us to convert `T` into `Self`.\n\n```rust\ntrait Into<T>: Sized {\n    fn into(self) -> T;\n}\n```\n\n`Into<T>` types allow us to convert `Self` into `T`.\n\nThese traits are two different sides of the same coin. We should only impl `From<T>` for our types, because the `Into<T>` impl is automatically provided by this generic blanket impl:\n\n```rust\nimpl<T, U: From<T>> Into<U> for T {\n    fn into(self) -> U {\n        U::from(self)\n    }\n}\n```\n\nThe reason both traits exist is to allow writing trait bounds on generic types in a slightly different way:\n\n```rust\nfn function<T>(t: T)\nwhere\n    // these bounds are equivalent\n    T: From<i32>,\n    i32: Into<T>\n{\n    // these examples are equivalent\n    let example: T = T::from(0);\n    let example: T = 0.into();\n}\n```\n\nThere are no hard rules about when to use one or the other, so go with whatever makes the most sense for each situation.\n\nNow let's look at some example impls on `Point`:\n\n```rust\nstruct Point {\n    x: i32,\n    y: i32,\n}\n\nimpl From<(i32, i32)> for Point {\n    fn from((x, y): (i32, i32)) -> Self {\n        Point { x, y }\n    }\n}\n\nimpl From<[i32; 2]> for Point {\n    fn from([x, y]: [i32; 2]) -> Self {\n        Point { x, y }\n    }\n}\n\nfn example() {\n    // using From\n    let origin = Point::from((0, 0));\n    let origin = Point::from([0, 0]);\n\n    // using Into\n    let origin: Point = (0, 0).into();\n    let origin: Point = [0, 0].into();\n}\n```\n\nThe impl is not symmetric, so if we'd like to convert `Point`s into tuples and arrays, we have to explicitly add those as well:\n\n```rust\nstruct Point {\n    x: i32,\n    y: i32,\n}\n\nimpl From<(i32, i32)> for Point {\n    fn from((x, y): (i32, i32)) -> Self {\n        Point { x, y }\n    }\n}\n\nimpl From<Point> for (i32, i32) {\n    fn from(Point { x, y }: Point) -> Self {\n        (x, y)\n    }\n}\n\nimpl From<[i32; 2]> for Point {\n    fn from([x, y]: [i32; 2]) -> Self {\n        Point { x, y }\n    }\n}\n\nimpl From<Point> for [i32; 2] {\n    fn from(Point { x, y }: Point) -> Self {\n        [x, y]\n    }\n}\n\nfn example() {\n    // from (i32, i32) into Point\n    let point = Point::from((0, 0));\n    let point: Point = (0, 0).into();\n\n    // from Point into (i32, i32)\n    let tuple = <(i32, i32)>::from(point);\n    let tuple: (i32, i32) = point.into();\n\n    // from [i32; 2] into Point\n    let point = Point::from([0, 0]);\n    let point: Point = [0, 0].into();\n\n    // from Point into [i32; 2]\n    let array = <[i32; 2]>::from(point);\n    let array: [i32; 2] = point.into();\n}\n```\n\nA popular use of `From<T>` is to trim down boilerplate code. Let's say we add a `Triangle` type to our program, which contains three `Point`s. Here are some of the many ways we can construct it:\n\n```rust\nstruct Point {\n    x: i32,\n    y: i32,\n}\n\nimpl Point {\n    fn new(x: i32, y: i32) -> Point {\n        Point { x, y }\n    }\n}\n\nimpl From<(i32, i32)> for Point {\n    fn from((x, y): (i32, i32)) -> Point {\n        Point { x, y }\n    }\n}\n\nstruct Triangle {\n    p1: Point,\n    p2: Point,\n    p3: Point,\n}\n\nimpl Triangle {\n    fn new(p1: Point, p2: Point, p3: Point) -> Triangle {\n        Triangle { p1, p2, p3 }\n    }\n}\n\nimpl<P> From<[P; 3]> for Triangle\nwhere\n    P: Into<Point>\n{\n    fn from([p1, p2, p3]: [P; 3]) -> Triangle {\n        Triangle {\n            p1: p1.into(),\n            p2: p2.into(),\n            p3: p3.into(),\n        }\n    }\n}\n\nfn example() {\n    // manual construction\n    let triangle = Triangle {\n        p1: Point {\n            x: 0,\n            y: 0,\n        },\n        p2: Point {\n            x: 1,\n            y: 1,\n        },\n        p3: Point {\n            x: 2,\n            y: 2,\n        },\n    };\n\n    // using Point::new\n    let triangle = Triangle {\n        p1: Point::new(0, 0),\n        p2: Point::new(1, 1),\n        p3: Point::new(2, 2),\n    };\n\n    // using From<(i32, i32)> for Point\n    let triangle = Triangle {\n        p1: (0, 0).into(),\n        p2: (1, 1).into(),\n        p3: (2, 2).into(),\n    };\n\n    // using Triangle::new + From<(i32, i32)> for Point\n    let triangle = Triangle::new(\n        (0, 0).into(),\n        (1, 1).into(),\n        (2, 2).into(),\n    );\n\n    // using From<[Into<Point>; 3]> for Triangle\n    let triangle: Triangle = [\n        (0, 0),\n        (1, 1),\n        (2, 2),\n    ].into();\n}\n```\n\nThere are no rules for when, how, or why we should impl `From<T>` for our types, so it's up to us to use our best judgement for every situation.\n\nOne popular use of `Into<T>` is to make functions that need owned values generic over whether they take owned or borrowed values:\n\n```rust\nstruct Person {\n    name: String,\n}\n\nimpl Person {\n    // accepts:\n    // - String\n    fn new1(name: String) -> Person {\n        Person { name }\n    }\n\n    // accepts:\n    // - String\n    // - &String\n    // - &str\n    // - Box<str>\n    // - Cow<'_, str>\n    // - char\n    // since all of the above types can be converted into String\n    fn new2<N: Into<String>>(name: N) -> Person {\n        Person { name: name.into() }\n    }\n}\n```\n\n\n\n## Error Handling\n\nThe best time to talk about error handling and the `Error` trait is after going over `Display`, `Debug`, `Any`, and `From`, but before getting to `TryFrom`, explaining why the **Error Handling** section awkwardly bisects the **Conversion Traits** section.\n\n\n\n### Error\n\nPrerequisites\n- [Self](#self)\n- [Methods](#methods)\n- [Default Impls](#default-impls)\n- [Generic Blanket Impls](#generic-blanket-impls)\n- [Subtraits & Supertraits](#subtraits--supertraits)\n- [Trait Objects](#trait-objects)\n- [Display & ToString](#display--tostring)\n- [Debug](#debug)\n- [Any](#any)\n- [From & Into](#from--into)\n\n```rust\ntrait Error: Debug + Display {\n    // provided default impls\n    fn source(&self) -> Option<&(dyn Error + 'static)>;\n    fn backtrace(&self) -> Option<&Backtrace>;\n    fn description(&self) -> &str;\n    fn cause(&self) -> Option<&dyn Error>;\n}\n```\n\nIn Rust, errors are returned, not thrown. Let's look at some examples.\n\nSince dividing integer types by zero panics, if we wanted to make our program safer and more explicit, we could impl a `safe_div` function that returns a `Result` instead, like this:\n\n```rust\nuse std::fmt;\nuse std::error;\n\n#[derive(Debug, PartialEq)]\nstruct DivByZero;\n\nimpl fmt::Display for DivByZero {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        write!(f, \"division by zero error\")\n    }\n}\n\nimpl error::Error for DivByZero {}\n\nfn safe_div(numerator: i32, denominator: i32) -> Result<i32, DivByZero> {\n    if denominator == 0 {\n        return Err(DivByZero);\n    }\n    Ok(numerator / denominator)\n}\n\n#[test] // ✅\nfn test_safe_div() {\n    assert_eq!(safe_div(8, 2), Ok(4));\n    assert_eq!(safe_div(5, 0), Err(DivByZero));\n}\n```\n\nSince errors are returned and not thrown, they must be explicitly handled, and if the current function cannot handle an error, it should propagate it up to the caller. The most idiomatic way to propagate errors is to use the `?` operator, which is just syntax sugar for the now deprecated `try!` macro, which simply does this:\n\n```rust\nmacro_rules! try {\n    ($expr:expr) => {\n        match $expr {\n            // if Ok just unwrap the value\n            Ok(val) => val,\n            // if Err map the err value using From and return\n            Err(err) => {\n                return Err(From::from(err));\n            }\n        }\n    };\n}\n```\n\nIf we wanted to write a function that reads a file into a `String`, we could write it like this, propagating the `io::Error`s using `?` everywhere they can appear:\n\n```rust\nuse std::io::Read;\nuse std::path::Path;\nuse std::io;\nuse std::fs::File;\n\nfn read_file_to_string(path: &Path) -> Result<String, io::Error> {\n    let mut file = File::open(path)?; // ⬆️ io::Error\n    let mut contents = String::new();\n    file.read_to_string(&mut contents)?; // ⬆️ io::Error\n    Ok(contents)\n}\n```\n\nBut let's say the file we're reading is actually a list of numbers, and we want to sum them together. Then we'd update our function like this:\n\n```rust\nuse std::io::Read;\nuse std::path::Path;\nuse std::io;\nuse std::fs::File;\n\nfn sum_file(path: &Path) -> Result<i32, /* What to put here? */> {\n    let mut file = File::open(path)?; // ⬆️ io::Error\n    let mut contents = String::new();\n    file.read_to_string(&mut contents)?; // ⬆️ io::Error\n    let mut sum = 0;\n    for line in contents.lines() {\n        sum += line.parse::<i32>()?; // ⬆️ ParseIntError\n    }\n    Ok(sum)\n}\n```\n\nBut what's the error type of our `Result` now? It can return either an `io::Error` or a `ParseIntError`. We're going to look at three approaches for solving this problem, starting with the most quick & dirty way, and finishing with the most robust way.\n\n#### String - dirty approach\n\nThe first approach is to recognize that all types which impl `Error` also impl `Display`, so we can map all the errors to `String`s and use `String` as our error type:\n\n```rust\nuse std::fs::File;\nuse std::io;\nuse std::io::Read;\nuse std::path::Path;\n\nfn sum_file(path: &Path) -> Result<i32, String> {\n    let mut file = File::open(path)\n        .map_err(|e| e.to_string())?; // ⬆️ io::Error -> String\n    let mut contents = String::new();\n    file.read_to_string(&mut contents)\n        .map_err(|e| e.to_string())?; // ⬆️ io::Error -> String\n    let mut sum = 0;\n    for line in contents.lines() {\n        sum += line.parse::<i32>()\n            .map_err(|e| e.to_string())?; // ⬆️ ParseIntError -> String\n    }\n    Ok(sum)\n}\n```\n\nThe obvious downside of stringifying every error is that we throw away type information, which makes it harder for the caller to handle the errors.\n\nOne nonobvious upside to the above approach is that we can customize the strings, to provide more context-specific information. For example, `ParseIntError` usually stringifies to `\"invalid digit found in string\"`, which is very vague and doesn't mention what the invalid string is, or what integer type it was trying to parse into. If we were debugging this problem, that error message would be almost useless. However, we can make it significantly better by providing some context-relevant information ourselves:\n\n```rust\nsum += line.parse::<i32>()\n    .map_err(|_| format!(\"failed to parse {} into i32\", line))?;\n```\n\n#### Box<dyn Error> - intermediate approach\n\nThe second approach takes advantage of this generic blanket impl from the standard library:\n\n```rust\nimpl<E: error::Error> From<E> for Box<dyn error::Error>;\n```\n\nThis means that any `Error` type can be implicitly converted into a `Box<dyn error::Error>` by the `?` operator, so we can use `Box<dyn error::Error>` as the error type of the `Result` return type of any fallible function we write, and the `?` operator will do the rest of the work for us:\n\n```rust\nuse std::fs::File;\nuse std::io::Read;\nuse std::path::Path;\nuse std::error;\n\nfn sum_file(path: &Path) -> Result<i32, Box<dyn error::Error>> {\n    let mut file = File::open(path)?; // ⬆️ io::Error -> Box<dyn error::Error>\n    let mut contents = String::new();\n    file.read_to_string(&mut contents)?; // ⬆️ io::Error -> Box<dyn error::Error>\n    let mut sum = 0;\n    for line in contents.lines() {\n        sum += line.parse::<i32>()?; // ⬆️ ParseIntError -> Box<dyn error::Error>\n    }\n    Ok(sum)\n}\n```\n\nWhile being more concise, this seems to suffer from the same downside of the previous approach, by throwing away type information. This is mostly true, but if the caller is aware of the impl details of our function, they can still handle the different errors types using the `downcast_ref()` method on `error::Error`, which works the same as it does on `dyn Any` types:\n\n```rust\nfn handle_sum_file_errors(path: &Path) {\n    match sum_file(path) {\n        Ok(sum) => println!(\"the sum is {}\", sum),\n        Err(err) => {\n            if let Some(e) = err.downcast_ref::<io::Error>() {\n                // handle io::Error\n            } else if let Some(e) = err.downcast_ref::<ParseIntError>() {\n                // handle ParseIntError\n            } else {\n                // we know sum_file can only return one of the\n                // above errors so this branch is unreachable\n                unreachable!();\n            }\n        }\n    }\n}\n```\n\n#### Custom enum - robust approach\n\nThe third approach, which is the most robust and type-safe way to aggregate these different errors, would be to build our own custom error type using an enum:\n\n```rust\nuse std::num::ParseIntError;\nuse std::fs::File;\nuse std::io;\nuse std::io::Read;\nuse std::path::Path;\nuse std::error;\nuse std::fmt;\n\n#[derive(Debug)]\nenum SumFileError {\n    Io(io::Error),\n    Parse(ParseIntError),\n}\n\nimpl From<io::Error> for SumFileError {\n    fn from(err: io::Error) -> Self {\n        SumFileError::Io(err)\n    }\n}\n\nimpl From<ParseIntError> for SumFileError {\n    fn from(err: ParseIntError) -> Self {\n        SumFileError::Parse(err)\n    }\n}\n\nimpl fmt::Display for SumFileError {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        match self {\n            SumFileError::Io(err) => write!(f, \"sum file error: {}\", err),\n            SumFileError::Parse(err) => write!(f, \"sum file error: {}\", err),\n        }\n    }\n}\n\nimpl error::Error for SumFileError {\n    // the default impl for this method always returns None\n    // but we can now override it to make it way more useful!\n    fn source(&self) -> Option<&(dyn error::Error + 'static)> {\n        Some(match self {\n            SumFileError::Io(err) => err,\n            SumFileError::Parse(err) => err,\n        })\n    }\n}\n\nfn sum_file(path: &Path) -> Result<i32, SumFileError> {\n    let mut file = File::open(path)?; // ⬆️ io::Error -> SumFileError\n    let mut contents = String::new();\n    file.read_to_string(&mut contents)?; // ⬆️ io::Error -> SumFileError\n    let mut sum = 0;\n    for line in contents.lines() {\n        sum += line.parse::<i32>()?; // ⬆️ ParseIntError -> SumFileError\n    }\n    Ok(sum)\n}\n\nfn handle_sum_file_errors(path: &Path) {\n    match sum_file(path) {\n        Ok(sum) => println!(\"the sum is {}\", sum),\n        Err(SumFileError::Io(err)) => {\n            // handle io::Error\n        },\n        Err(SumFileError::Parse(err)) => {\n            // handle ParseIntError\n        },\n    }\n}\n```\n\n\n\n## Conversion Traits Continued\n\n\n\n### TryFrom & TryInto\n\nPrerequisites\n- [Self](#self)\n- [Functions](#functions)\n- [Methods](#methods)\n- [Associated Types](#associated-types)\n- [Generic Parameters](#generic-parameters)\n- [Generic Types vs Associated Types](#generic-types-vs-associated-types)\n- [Generic Blanket Impls](#generic-blanket-impls)\n- [From & Into](#from--into)\n- [Error](#error)\n\n`TryFrom` and `TryInto` are the fallible versions of `From` and `Into`.\n\n```rust\ntrait TryFrom<T>: Sized {\n    type Error;\n    fn try_from(value: T) -> Result<Self, Self::Error>;\n}\n\ntrait TryInto<T>: Sized {\n    type Error;\n    fn try_into(self) -> Result<T, Self::Error>;\n}\n```\n\nSimilarly to `Into`, we should not impl `TryInto`, because its impl is provided by this generic blanket impl:\n\n```rust\nimpl<T, U: TryFrom<T>> TryInto<U> for T {\n    type Error = U::Error;\n\n    fn try_into(self) -> Result<U, U::Error> {\n        U::try_from(self)\n    }\n}\n```\n\nFurthermore, we cannot impl `TryFrom` for a type if it already has a `From` impl, as an infallible `TryFrom` impl is automatically provided by this generic blanket impl:\n\n```rust\nenum Inflallible {}\n\nimpl<T, U: Into<T>> TryFrom<U> for T {\n    type Error = Infallible;\n\n    fn try_from(value: U) -> Result<Self, Self::Error> {\n        Ok(U::into(value))\n    }\n}\n```\n\nSo let's say that in the context of our earlier program, it doesn't make sense for `Point`s to have `x` and `y` values that are less than `-1000` or greater than `1000`. This is how we'd rewrite our earlier `From` impls using `TryFrom` to signal to the users of our type that this conversion can now fail:\n\n```rust\nuse std::convert::TryFrom;\nuse std::error;\nuse std::fmt;\n\nstruct Point {\n    x: i32,\n    y: i32,\n}\n\n#[derive(Debug)]\nstruct OutOfBounds;\n\nimpl fmt::Display for OutOfBounds {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        write!(f, \"out of bounds\")\n    }\n}\n\nimpl error::Error for OutOfBounds {}\n\n// now fallible\nimpl TryFrom<(i32, i32)> for Point {\n    type Error = OutOfBounds;\n    fn try_from((x, y): (i32, i32)) -> Result<Point, OutOfBounds> {\n        if x.abs() > 1000 || y.abs() > 1000 {\n            return Err(OutOfBounds);\n        }\n        Ok(Point { x, y })\n    }\n}\n\n// still infallible\nimpl From<Point> for (i32, i32) {\n    fn from(Point { x, y }: Point) -> Self {\n        (x, y)\n    }\n}\n```\n\nAnd here's the refactored `TryFrom<[TryInto<Point>; 3]>` impl for `Triangle`:\n\n```rust\nuse std::convert::{TryFrom, TryInto};\nuse std::error;\nuse std::fmt;\n\nstruct Point {\n    x: i32,\n    y: i32,\n}\n\n#[derive(Debug)]\nstruct OutOfBounds;\n\nimpl fmt::Display for OutOfBounds {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        write!(f, \"out of bounds\")\n    }\n}\n\nimpl error::Error for OutOfBounds {}\n\nimpl TryFrom<(i32, i32)> for Point {\n    type Error = OutOfBounds;\n    fn try_from((x, y): (i32, i32)) -> Result<Self, Self::Error> {\n        if x.abs() > 1000 || y.abs() > 1000 {\n            return Err(OutOfBounds);\n        }\n        Ok(Point { x, y })\n    }\n}\n\nstruct Triangle {\n    p1: Point,\n    p2: Point,\n    p3: Point,\n}\n\nimpl<P> TryFrom<[P; 3]> for Triangle\nwhere\n    P: TryInto<Point>,\n{\n    type Error = P::Error;\n    fn try_from([p1, p2, p3]: [P; 3]) -> Result<Self, Self::Error> {\n        Ok(Triangle {\n            p1: p1.try_into()?,\n            p2: p2.try_into()?,\n            p3: p3.try_into()?,\n        })\n    }\n}\n\nfn example() -> Result<Triangle, OutOfBounds> {\n    let t: Triangle = [(0, 0), (1, 1), (2, 2)].try_into()?;\n    Ok(t)\n}\n```\n\n\n\n### FromStr\n\nPrerequisites\n- [Self](#self)\n- [Functions](#functions)\n- [Associated Types](#associated-types)\n- [Error](#error)\n- [TryFrom & TryInto](#tryfrom--tryinto)\n\n```rust\ntrait FromStr {\n    type Err;\n    fn from_str(s: &str) -> Result<Self, Self::Err>;\n}\n```\n\n`FromStr` types allow performing a fallible conversion from `&str` into `Self`. The idiomatic way to use `FromStr` is to call the `.parse()` method on `&str`s:\n\n```rust\nuse std::str::FromStr;\n\nfn example<T: FromStr>(s: &'static str) {\n    // these are all equivalent\n    let t: Result<T, _> = FromStr::from_str(s);\n    let t = T::from_str(s);\n    let t: Result<T, _> = s.parse();\n    let t = s.parse::<T>(); // most idiomatic\n}\n```\n\nExample impl for `Point`:\n\n```rust\nuse std::error;\nuse std::fmt;\nuse std::iter::Enumerate;\nuse std::num::ParseIntError;\nuse std::str::{Chars, FromStr};\n\n#[derive(Debug, Eq, PartialEq)]\nstruct Point {\n    x: i32,\n    y: i32,\n}\n\nimpl Point {\n    fn new(x: i32, y: i32) -> Self {\n        Point { x, y }\n    }\n}\n\n#[derive(Debug, PartialEq)]\nstruct ParsePointError;\n\nimpl fmt::Display for ParsePointError {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        write!(f, \"failed to parse point\")\n    }\n}\n\nimpl From<ParseIntError> for ParsePointError {\n    fn from(_e: ParseIntError) -> Self {\n        ParsePointError\n    }\n}\n\nimpl error::Error for ParsePointError {}\n\nimpl FromStr for Point {\n    type Err = ParsePointError;\n\n    fn from_str(s: &str) -> Result<Self, Self::Err> {\n        let is_num = |(_, c): &(usize, char)| matches!(c, '0'..='9' | '-');\n        let isnt_num = |t: &(_, _)| !is_num(t);\n\n        let get_num =\n            |char_idxs: &mut Enumerate<Chars<'_>>| -> Result<(usize, usize), ParsePointError> {\n                let (start, _) = char_idxs\n                    .skip_while(isnt_num)\n                    .next()\n                    .ok_or(ParsePointError)?;\n                let (end, _) = char_idxs\n                    .skip_while(is_num)\n                    .next()\n                    .ok_or(ParsePointError)?;\n                Ok((start, end))\n            };\n\n        let mut char_idxs = s.chars().enumerate();\n        let (x_start, x_end) = get_num(&mut char_idxs)?;\n        let (y_start, y_end) = get_num(&mut char_idxs)?;\n\n        let x = s[x_start..x_end].parse::<i32>()?;\n        let y = s[y_start..y_end].parse::<i32>()?;\n\n        Ok(Point { x, y })\n    }\n}\n\n#[test] // ✅\nfn pos_x_y() {\n    let p = \"(4, 5)\".parse::<Point>();\n    assert_eq!(p, Ok(Point::new(4, 5)));\n}\n\n#[test] // ✅\nfn neg_x_y() {\n    let p = \"(-6, -2)\".parse::<Point>();\n    assert_eq!(p, Ok(Point::new(-6, -2)));\n}\n\n#[test] // ✅\nfn not_a_point() {\n    let p = \"not a point\".parse::<Point>();\n    assert_eq!(p, Err(ParsePointError));\n}\n```\n\n`FromStr` has the same signature as `TryFrom<&str>`. It doesn't matter which one we impl for a type first, as long as we forward the impl to the other one. Here's a `TryFrom<&str>` impl for `Point`, assuming it already has a `FromStr` impl:\n\n```rust\nimpl TryFrom<&str> for Point {\n    type Error = <Point as FromStr>::Err;\n    fn try_from(s: &str) -> Result<Point, Self::Error> {\n        <Point as FromStr>::from_str(s)\n    }\n}\n```\n\n\n### AsRef & AsMut\n\nPrerequisites\n- [Self](#self)\n- [Methods](#methods)\n- [Sized](#sized)\n- [Generic Parameters](#generic-parameters)\n- [Deref & DerefMut](#deref--derefmut)\n\n```rust\ntrait AsRef<T: ?Sized> {\n    fn as_ref(&self) -> &T;\n}\n\ntrait AsMut<T: ?Sized> {\n    fn as_mut(&mut self) -> &mut T;\n}\n```\n\n`AsRef` is for cheap reference to reference conversions. However, one of the most common ways it's used is to make functions generic over whether they take ownership or not:\n\n```rust\n// accepts:\n//  - &str\n//  - &String\nfn takes_str(s: &str) {\n    // use &str\n}\n\n// accepts:\n//  - &str\n//  - &String\n//  - String\nfn takes_asref_str<S: AsRef<str>>(s: S) {\n    let s: &str = s.as_ref();\n    // use &str\n}\n\nfn example(slice: &str, borrow: &String, owned: String) {\n    takes_str(slice);\n    takes_str(borrow);\n    takes_str(owned); // ❌\n    takes_asref_str(slice);\n    takes_asref_str(borrow);\n    takes_asref_str(owned); // ✅\n}\n```\n\nThe other most common use-case is returning a reference to inner private data, wrapped by a type that protects some invariant. A good example from the standard library is `String`, which is just a wrapper around `Vec<u8>`:\n\n```rust\nstruct String {\n    vec: Vec<u8>,\n}\n```\n\nThis inner `Vec` cannot be made public, because if it was, people could mutate any byte and break the `String`'s valid UTF-8 encoding. However, it's safe to expose an immutable read-only reference to the inner byte array, hence this impl:\n\n```rust\nimpl AsRef<[u8]> for String;\n```\n\nGenerally, it often only makes sense to impl `AsRef` for a type if it wraps some other type, to either provide additional functionality around the inner type, or to protect some invariant on the inner type.\n\nLet's examine a example of bad `AsRef` impls:\n\n```rust\nstruct User {\n    name: String,\n    age: u32,\n}\n\nimpl AsRef<String> for User {\n    fn as_ref(&self) -> &String {\n        &self.name\n    }\n}\n\nimpl AsRef<u32> for User {\n    fn as_ref(&self) -> &u32 {\n        &self.age\n    }\n}\n```\n\nThis works and kinda makes sense at first, but quickly falls apart if we add more members to `User`:\n\n```rust\nstruct User {\n    name: String,\n    email: String,\n    age: u32,\n    height: u32,\n}\n\nimpl AsRef<String> for User {\n    fn as_ref(&self) -> &String {\n        // uh, do we return name or email here?\n    }\n}\n\nimpl AsRef<u32> for User {\n    fn as_ref(&self) -> &u32 {\n        // uh, do we return age or height here?\n    }\n}\n```\n\nA `User` is composed of `String`s and `u32`s, but it's not really the same thing as a `String` or a `u32`. Even if we had much more specific types:\n\n```rust\nstruct User {\n    name: Name,\n    email: Email,\n    age: Age,\n    height: Height,\n}\n```\n\nIt still wouldn't make much sense to impl `AsRef` for any of those because `AsRef` is for cheap reference to reference conversions between semantically equivalent things, and `Name`, `Email`, `Age`, and `Height` by themselves are not the same thing as a `User`.\n\nA good example where we would impl `AsRef` would be if we introduced a new type `Moderator`, which just wrapped a `User` and added some moderation specific privileges:\n\n```rust\nstruct User {\n    name: String,\n    age: u32,\n}\n\n// unfortunately, the standard library cannot provide\n// a generic blanket impl to save us from this boilerplate\nimpl AsRef<User> for User {\n    fn as_ref(&self) -> &User {\n        self\n    }\n}\n\nenum Privilege {\n    BanUsers,\n    EditPosts,\n    DeletePosts,\n}\n\n// although Moderators have some special\n// privileges, they are still regular Users\n// and should be able to do all the same stuff\nstruct Moderator {\n    user: User,\n    privileges: Vec<Privilege>\n}\n\nimpl AsRef<Moderator> for Moderator {\n    fn as_ref(&self) -> &Moderator {\n        self\n    }\n}\n\nimpl AsRef<User> for Moderator {\n    fn as_ref(&self) -> &User {\n        &self.user\n    }\n}\n\n// this should be callable with Users\n// and Moderators (who are also Users)\nfn create_post<U: AsRef<User>>(u: U) {\n    let user = u.as_ref();\n    // etc\n}\n\nfn example(user: User, moderator: Moderator) {\n    create_post(&user);\n    create_post(&moderator); // ✅\n}\n```\n\nThis works because `Moderator`s are just `User`s. Here's the example from the `Deref` section, but uses `AsRef` instead:\n\n```rust\nuse std::convert::AsRef;\n\nstruct Human {\n    health_points: u32,\n}\n\nimpl AsRef<Human> for Human {\n    fn as_ref(&self) -> &Human {\n        self\n    }\n}\n\nenum Weapon {\n    Spear,\n    Axe,\n    Sword,\n}\n\n// a Soldier is just a Human with a Weapon\nstruct Soldier {\n    human: Human,\n    weapon: Weapon,\n}\n\nimpl AsRef<Soldier> for Soldier {\n    fn as_ref(&self) -> &Soldier {\n        self\n    }\n}\n\nimpl AsRef<Human> for Soldier {\n    fn as_ref(&self) -> &Human {\n        &self.human\n    }\n}\n\nenum Mount {\n    Horse,\n    Donkey,\n    Cow,\n}\n\n// a Knight is just a Soldier with a Mount\nstruct Knight {\n    soldier: Soldier,\n    mount: Mount,\n}\n\nimpl AsRef<Knight> for Knight {\n    fn as_ref(&self) -> &Knight {\n        self\n    }\n}\n\nimpl AsRef<Soldier> for Knight {\n    fn as_ref(&self) -> &Soldier {\n        &self.soldier\n    }\n}\n\nimpl AsRef<Human> for Knight {\n    fn as_ref(&self) -> &Human {\n        &self.soldier.human\n    }\n}\n\nenum Spell {\n    MagicMissile,\n    FireBolt,\n    ThornWhip,\n}\n\n// a Mage is just a Human who can cast Spells\nstruct Mage {\n    human: Human,\n    spells: Vec<Spell>,\n}\n\nimpl AsRef<Mage> for Mage {\n    fn as_ref(&self) -> &Mage {\n        self\n    }\n}\n\nimpl AsRef<Human> for Mage {\n    fn as_ref(&self) -> &Human {\n        &self.human\n    }\n}\n\nenum Staff {\n    Wooden,\n    Metallic,\n    Plastic,\n}\n\n// a Wizard is just a Mage with a Staff\nstruct Wizard {\n    mage: Mage,\n    staff: Staff,\n}\n\nimpl AsRef<Wizard> for Wizard {\n    fn as_ref(&self) -> &Wizard {\n        self\n    }\n}\n\nimpl AsRef<Mage> for Wizard {\n    fn as_ref(&self) -> &Mage {\n        &self.mage\n    }\n}\n\nimpl AsRef<Human> for Wizard {\n    fn as_ref(&self) -> &Human {\n        &self.mage.human\n    }\n}\n\nfn borrows_human<H: AsRef<Human>>(human: H) {}\nfn borrows_soldier<S: AsRef<Soldier>>(soldier: S) {}\nfn borrows_knight<K: AsRef<Knight>>(knight: K) {}\nfn borrows_mage<M: AsRef<Mage>>(mage: M) {}\nfn borrows_wizard<W: AsRef<Wizard>>(wizard: W) {}\n\nfn example(human: Human, soldier: Soldier, knight: Knight, mage: Mage, wizard: Wizard) {\n    // all types can be used as Humans\n    borrows_human(&human);\n    borrows_human(&soldier);\n    borrows_human(&knight);\n    borrows_human(&mage);\n    borrows_human(&wizard);\n    // Knights can be used as Soldiers\n    borrows_soldier(&soldier);\n    borrows_soldier(&knight);\n    // Wizards can be used as Mages\n    borrows_mage(&mage);\n    borrows_mage(&wizard);\n    // Knights & Wizards passed as themselves\n    borrows_knight(&knight);\n    borrows_wizard(&wizard);\n}\n```\n\n`Deref` didn't work in the prior version of the example above, because deref coercion is an implicit conversion between types, which leaves room for people to mistakenly formulate the wrong ideas and expectations for how it will behave. `AsRef` works above, because it makes the conversion between types explicit, and there's no room left over to develop any wrong ideas or expectations.\n\n\n\n### Borrow & BorrowMut\n\nPrerequisites\n- [Self](#self)\n- [Methods](#methods)\n- [Generic Parameters](#generic-parameters)\n- [Subtraits & Supertraits](#subtraits--supertraits)\n- [Sized](#sized)\n- [AsRef & AsMut](#asref--asmut)\n- [PartialEq & Eq](#partialeq--eq)\n- [Hash](#hash)\n- [PartialOrd & Ord](#partialord--ord)\n\n```rust\ntrait Borrow<Borrowed> \nwhere\n    Borrowed: ?Sized, \n{\n    fn borrow(&self) -> &Borrowed;\n}\n\ntrait BorrowMut<Borrowed>: Borrow<Borrowed> \nwhere\n    Borrowed: ?Sized, \n{\n    fn borrow_mut(&mut self) -> &mut Borrowed;\n}\n```\n\nThese traits were invented to solve the very specific problem of looking up `String` keys in `HashSet`s, `HashMap`s, `BTreeSet`s, and `BTreeMap`s using `&str` values.\n\nWe can view `Borrow<T>` and `BorrowMut<T>` as stricter versions of `AsRef<T>` and `AsMut<T>`, where the returned reference `&T` has equivalent `Eq`, `Hash`, and `Ord` impls to `Self`. This is more easily explained with a commented example:\n\n```rust\nuse std::borrow::Borrow;\nuse std::hash::Hasher;\nuse std::collections::hash_map::DefaultHasher;\nuse std::hash::Hash;\n\nfn get_hash<T: Hash>(t: T) -> u64 {\n    let mut hasher = DefaultHasher::new();\n    t.hash(&mut hasher);\n    hasher.finish()\n}\n\nfn asref_example<Owned, Ref>(owned1: Owned, owned2: Owned)\nwhere\n    Owned: Eq + Ord + Hash + AsRef<Ref>,\n    Ref: Eq + Ord + Hash\n{\n    let ref1: &Ref = owned1.as_ref();\n    let ref2: &Ref = owned2.as_ref();\n    \n    // refs aren't required to be equal if owned types are equal\n    assert_eq!(owned1 == owned2, ref1 == ref2); // ❌\n    \n    let owned1_hash = get_hash(&owned1);\n    let owned2_hash = get_hash(&owned2);\n    let ref1_hash = get_hash(&ref1);\n    let ref2_hash = get_hash(&ref2);\n    \n    // ref hashes aren't required to be equal if owned type hashes are equal\n    assert_eq!(owned1_hash == owned2_hash, ref1_hash == ref2_hash); // ❌\n    \n    // ref comparisons aren't required to match owned type comparisons\n    assert_eq!(owned1.cmp(&owned2), ref1.cmp(&ref2)); // ❌\n}\n\nfn borrow_example<Owned, Borrowed>(owned1: Owned, owned2: Owned)\nwhere\n    Owned: Eq + Ord + Hash + Borrow<Borrowed>,\n    Borrowed: Eq + Ord + Hash\n{\n    let borrow1: &Borrowed = owned1.borrow();\n    let borrow2: &Borrowed = owned2.borrow();\n    \n    // borrows are required to be equal if owned types are equal\n    assert_eq!(owned1 == owned2, borrow1 == borrow2); // ✅\n    \n    let owned1_hash = get_hash(&owned1);\n    let owned2_hash = get_hash(&owned2);\n    let borrow1_hash = get_hash(&borrow1);\n    let borrow2_hash = get_hash(&borrow2);\n    \n    // borrow hashes are required to be equal if owned type hashes are equal\n    assert_eq!(owned1_hash == owned2_hash, borrow1_hash == borrow2_hash); // ✅\n    \n    // borrow comparisons are required to match owned type comparisons\n    assert_eq!(owned1.cmp(&owned2), borrow1.cmp(&borrow2)); // ✅\n}\n```\n\nIt's good to be aware of these traits and understand why they exist, since it helps demystify some of the methods on `HashSet`, `HashMap`, `BTreeSet`, and `BTreeMap`, but it's very rare that we would ever need to impl these traits for any of our types, because it's very rare that we would ever need create a pair of types where one is the \"borrowed\" version of the other in the first place. If we have some `T` then `&T` will get the job done 99.99% of the time, and `T: Borrow<T>` is already implemented for all `T` because of a generic blanket impl, so we don't need to manually impl it, and we don't need to create some `U` such that `T: Borrow<U>`.\n\n\n\n### ToOwned\n\nPrerequisites\n- [Self](#self)\n- [Methods](#methods)\n- [Default Impls](#default-impls)\n- [Clone](#clone)\n- [Borrow & BorrowMut](#borrow--borrowmut)\n\n```rust\ntrait ToOwned {\n    type Owned: Borrow<Self>;\n    fn to_owned(&self) -> Self::Owned;\n    \n    // provided default impls\n    fn clone_into(&self, target: &mut Self::Owned);\n}\n```\n\n`ToOwned` is a more generic version of `Clone`. `Clone` allows us to take a `&T` and turn it into a `T`, but `ToOwned` allows us to take a `&Borrowed` and turn it into an `Owned` where `Owned: Borrow<Borrowed>`.\n\nIn other words, we can't \"clone\" a `&str` into a `String`, or a `&Path` into a `PathBuf`, or an `&OsStr` into an `OsString`, since the `clone` method signature doesn't support this kind of cross-type cloning, and that's what `ToOwned` was made for.\n\nFor similar reasons as `Borrow` and `BorrowMut`, it's good to be aware of this trait and understand why it exists, but it's very rare that we'll ever need to impl it for any of our types.\n\n\n\n## Iteration Traits\n\n\n\n### Iterator\n\nPrerequisites\n- [Self](#self)\n- [Methods](#methods)\n- [Associated Types](#associated-types)\n- [Default Impls](#default-impls)\n\n```rust\ntrait Iterator {\n    type Item;\n    fn next(&mut self) -> Option<Self::Item>;\n\n    // provides default impls for 75 functions\n    // which are omitted here for brevity's sake\n}\n```\n\n`Iterator<Item = T>` types can be iterated and will produce `T` types. There's no `IteratorMut` trait. Each `Iterator` impl can specify whether it returns immutable references, mutable references, or owned values via the `Item` associated type.\n\n| `Vec<T>` method | Returns |\n|-----------------|-------------------|\n| `.iter()` | `Iterator<Item = &T>` |\n| `.iter_mut()` | `Iterator<Item = &mut T>` |\n| `.into_iter()` | `Iterator<Item = T>` |\n\nSomething that is not immediately obvious to beginner Rustaceans, but that intermediate Rustaceans take for granted, is that most types are not their own iterators. If a type is iterable, we almost always impl some other custom iterator type to iterate over it, rather than trying to make it iterate over itself:\n\n```rust\nstruct MyType {\n    items: Vec<String>\n}\n\nimpl MyType {\n    fn iter(&self) -> impl Iterator<Item = &String> {\n        MyTypeIterator {\n            index: 0,\n            items: &self.items\n        }\n    }\n}\n\nstruct MyTypeIterator<'a> {\n    index: usize,\n    items: &'a Vec<String>\n}\n\nimpl<'a> Iterator for MyTypeIterator<'a> {\n    type Item = &'a String;\n    fn next(&mut self) -> Option<Self::Item> {\n        if self.index >= self.items.len() {\n            None\n        } else {\n            let item = &self.items[self.index];\n            self.index += 1;\n            Some(item)\n        }\n    }\n}\n```\n\nThe above example shows how to impl an `Iterator` from scratch for educational value, but the idiomatic solution in this situation would be to just defer to `Vec`'s `iter` method:\n\n```rust\nstruct MyType {\n    items: Vec<String>\n}\n\nimpl MyType {\n    fn iter(&self) -> impl Iterator<Item = &String> {\n        self.items.iter()\n    }\n}\n```\n\nAlso, this is a good generic blanket impl to be aware of:\n\n```rust\nimpl<I: Iterator + ?Sized> Iterator for &mut I;\n```\n\nIt says that any mutable reference to an iterator is also an iterator. This is useful to know, because it allows us to use iterator methods with `self` receivers as if they had `&mut self` receivers.\n\nAs an example, imagine we have a function that processes an iterator of more than three items, but the first step of the function is to take out the first three items of the iterator and process them separately, before iterating over the remaining items. Here's how a beginner might attempt to write this function:\n\n```rust\nfn example<I: Iterator<Item = i32>>(mut iter: I) {\n    let first3: Vec<i32> = iter.take(3).collect();\n    for item in iter { // ❌ iter consumed in line above\n        // process remaining items\n    }\n}\n```\n\nWell that's annoying. The `take` method has a `self` receiver so it seems like we cannot call it without consuming the whole iterator! Here's what a naive refactor of the above code might look like:\n\n```rust\nfn example<I: Iterator<Item = i32>>(mut iter: I) {\n    let first3: Vec<i32> = vec![\n        iter.next().unwrap(),\n        iter.next().unwrap(),\n        iter.next().unwrap(),\n    ];\n    for item in iter { // ✅\n        // process remaining items\n    }\n}\n```\n\nWhich is okay. However, the idiomatic refactor is actually:\n\n```rust\nfn example<I: Iterator<Item = i32>>(mut iter: I) {\n    let first3: Vec<i32> = iter.by_ref().take(3).collect();\n    for item in iter { // ✅\n        // process remaining items\n    }\n}\n```\n\nNot very easy to discover. But anyway, now we know.\n\nAlso, there are no rules or conventions on what can or cannot be an iterator. If the type impls `Iterator` then it's an iterator. Some creative examples from the standard library:\n\n```rust\nuse std::sync::mpsc::channel;\nuse std::thread;\n\nfn paths_can_be_iterated(path: &Path) {\n    for part in path {\n        // iterate over parts of a path\n    }\n}\n\nfn receivers_can_be_iterated() {\n    let (send, recv) = channel();\n\n    thread::spawn(move || {\n        send.send(1).unwrap();\n        send.send(2).unwrap();\n        send.send(3).unwrap();\n    });\n\n    for received in recv {\n        // iterate over received values\n    }\n}\n```\n\n\n\n### ExactSizeIterator\n\nPrerequisites\n- [Self](#self)\n- [Methods](#methods)\n- [Associated Types](#associated-types)\n- [Marker Traits](#marker-traits)\n- [Subtraits & Supertraits](#subtraits--supertraits)\n- [Iterator](#iterator)\n\n```rust\ntrait ExactSizeIterator: Iterator {\n    // provided default impls\n    fn len(&self) -> usize;\n    fn is_empty(&self) -> bool;\n}\n```\n\nThe default impls provided by the `Iterator` trait for the methods `size_hint`, `count`,  `last`, and `nth` are suboptimal if we know the exact size of the data we're iterating over and have have fast random access into it.\n\nTo illustrate this point, let's start by defining a type called `Range`, which impls an `Iterator` that we can calculate the exact size of:\n\n```rust\nstruct Range {\n    start: usize,\n    end: usize,\n}\n\nimpl Iterator for Range {\n    type Item = usize;\n    fn next(&mut self) -> Option<Self::Item> {\n        let current = self.start;\n        self.start += 1;\n        if current < self.end {\n            Some(current)\n        } else {\n            None\n        }\n    }\n}\n```\n\nHere's the default `size_hint` impl that `Range` would get from the `Iterator` trait:\n\n```rust\nfn size_hint(&self) -> (usize, Option<usize>) {\n    (0, None)\n}\n```\n\nIt's not useful at all! The lower bound is hardcoded to `0` and the upper bound is hardcoded to `None`, which is the same as saying _\"I have no clue how big this iterator is. It can have anywhere from zero to infinity remaining items in it.\"_\n\nYet we can precisely calculate how many items are remaining in `Range` and provide an actually useful `size_hint` impl:\n\n```rust\nimpl Iterator for Range {\n    // ...\n    fn size_hint(&self) -> (usize, Option<usize>) {\n        let size = self.end - self.start;\n        (size, Some(size))\n    }\n}\n```\n\nWe can also now impl `ExactSizeIterator` for `Range`, because it's a marker trait that marks the type as having an accurate `size_hint` impl:\n\n```rust\nimpl ExactSizeIterator for Range {}\n```\n\nWe should also provide our own impls for `count`, `last`, and `nth`, as their default impls assume the size of the iterator is unknown and rely on repeatedly calling `next`. Here's a simplified version of the default `count` impl as an example:\n\n```rust\nfn count(self) -> usize {\n    let mut accum = 0;\n    while let Some(x) = self.next() {\n        accum += 1;\n    }\n    accum\n}\n```\n\nIf we had a `Range` of size one million, that's one million times the `next` function would have to be called to `count` it! We can do much better:\n\n```rust\nimpl Iterator for Range {\n    // ...\n    fn count(self) -> usize {\n        self.end - self.start\n    }\n}\n```\n\nAnd efficient impls for `last` and `nth`:\n\n```rust\nimpl Iterator for Range {\n    type Item = usize;\n    fn last(self) -> Option<Self::Item> {\n        if self.start == self.end {\n            None\n        } else {\n            Some(self.end - 1)\n        }\n    }\n    fn nth(&mut self, n: usize) -> Option<Self::Item> {\n        if self.start + n > self.end {\n            None\n        } else {\n            self.start += n;\n            self.next()\n        }\n    }\n}\n```\n\n\n\n### IntoIterator\n\nPrerequisites\n- [Self](#self)\n- [Methods](#methods)\n- [Associated Types](#associated-types)\n- [Iterator](#iterator)\n\n```rust\ntrait IntoIterator \nwhere\n    <Self::IntoIter as Iterator>::Item == Self::Item, \n{\n    type Item;\n    type IntoIter: Iterator;\n    fn into_iter(self) -> Self::IntoIter;\n}\n```\n\n`IntoIterator` types can be converted into iterators, hence the name. The `into_iter` method is called on a type when it's used within a `for-in` loop:\n\n```rust\n// vec = Vec<T>\nfor v in vec {} // v = T\n\n// above line desugared\nfor v in vec.into_iter() {}\n```\n\nNot only does `Vec` impl `IntoIterator`, but so does `&Vec` and `&mut Vec`, which iterate over immutable or mutable references to items in the vec, respectively, instead of iterating over owned values and consuming the container.\n\n```rust\n// vec = Vec<T>\nfor v in &vec {} // v = &T\n\n// above example desugared\nfor v in (&vec).into_iter() {}\n\n// vec = Vec<T>\nfor v in &mut vec {} // v = &mut T\n\n// above example desugared\nfor v in (&mut vec).into_iter() {}\n```\n\n\n\n### Extend\n\nPrerequisites\n- [Self](#self)\n- [Methods](#methods)\n- [Generic Parameters](#generic-parameters)\n- [Iterator](#iterator)\n- [IntoIterator](#intoiterator)\n\n\n```rust\ntrait Extend<A> {\n    fn extend<T>(&mut self, iter: T)\n       where T: IntoIterator<Item = A>;\n\n    // provided default impls\n    fn extend_one(&mut self, item: A);\n    fn extend_reserve(&mut self, additional: usize);\n}\n```\n\n`Extend` types can be extended from an iterator. They're usually collections. Using `MyType` from before:\n\n```rust\nstruct MyType {\n    items: Vec<String>\n}\n\nimpl Extend<String> for MyType {\n    // add Strings from iter into MyType\n    fn extend<T: IntoIterator<Item = String>>(&mut self, iter: T) {\n        for i in iter {\n            self.items.push(i);\n        }\n    }\n}\n```\n\nThe above example is meant to be illustrative, the idiomatic solution would be to defer to the inner `Vec`'s `extend` impl:\n\n```rust\nimpl Extend<String> for MyType {\n    // add Strings from iter into MyType\n    fn extend<T: IntoIterator<Item = String>>(&mut self, iter: T) {\n        self.items.extend(iter)\n    }\n}\n```\n\n\n\n### FromIterator\n\nPrerequisites\n- [Self](#self)\n- [Functions](#functions)\n- [Generic Parameters](#generic-parameters)\n- [Sized](#sized)\n- [Iterator](#iterator)\n- [IntoIterator](#intoiterator)\n- [Extend](#extend)\n\n```rust\ntrait FromIterator<A>: Sized {\n    fn from_iter<T>(iter: T) -> Self\n    where\n        T: IntoIterator<Item = A>;\n}\n```\n\n`FromIterator` types can be created from an iterator, hence the name. `FromIterator` is most commonly and idiomatically used by calling the `collect` method on `Iterator`:\n\n```rust\nfn collect<B>(self) -> B\nwhere\n    B: FromIterator<Self::Item>;\n```\n\nExample of collecting an `Iterator<Item = char>` into a `String`:\n\n```rust\nfn filter_letters(string: &str) -> String {\n    string.chars().filter(|c| c.is_alphabetic()).collect()\n}\n```\n\nAll the collections in the standard library impl `IntoIterator` and `FromIterator`, so that makes it easier to convert between them:\n\n```rust\nuse std::collections::{BTreeSet, HashMap, HashSet, LinkedList};\n\n// String -> HashSet<char>\nfn unique_chars(string: &str) -> HashSet<char> {\n    string.chars().collect()\n}\n\n// Vec<T> -> BTreeSet<T>\nfn ordered_unique_items<T: Ord>(vec: Vec<T>) -> BTreeSet<T> {\n    vec.into_iter().collect()\n}\n\n// HashMap<K, V> -> LinkedList<(K, V)>\nfn entry_list<K, V>(map: HashMap<K, V>) -> LinkedList<(K, V)> {\n    map.into_iter().collect()\n}\n\n// and countless more possible examples\n```\n\nIf we're going to impl `FromIterator` for our own type, it's best to reuse an `Extend` impl if one exists:\n\n```rust\nstruct MyType {\n    items: Vec<String>,\n}\n\nimpl MyType {\n    fn new() -> Self {\n        MyType {\n            items: Vec::new()\n        }\n    }\n}\n\nimpl Extend<String> for MyType {\n    fn extend<T: IntoIterator<Item = String>>(&mut self, iter: T) {\n        self.items.extend(iter)\n    }\n}\n\nimpl FromIterator<String> for MyType {\n    fn from_iter<T: IntoIterator<Item = String>>(iter: T) -> Self {\n        let mut my_type = MyType::new();\n        my_type.extend(iter);\n        my_type\n    }\n}\n```\n\n\n\n## I/O Traits\n\n\n\n### Read & Write\n\nPrerequisites\n- [Self](#self)\n- [Methods](#methods)\n- [Scope](#scope)\n- [Generic Blanket Impls](#generic-blanket-impls)\n\n```rust\ntrait Read {\n    fn read(&mut self, buf: &mut [u8]) -> Result<usize>;\n\n    // provided default impls\n    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> Result<usize>;\n    fn is_read_vectored(&self) -> bool;\n    unsafe fn initializer(&self) -> Initializer;\n    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize>;\n    fn read_to_string(&mut self, buf: &mut String) -> Result<usize>;\n    fn read_exact(&mut self, buf: &mut [u8]) -> Result<()>;\n    fn by_ref(&mut self) -> &mut Self\n    where\n        Self: Sized;\n    fn bytes(self) -> Bytes<Self>\n    where\n        Self: Sized;\n    fn chain<R: Read>(self, next: R) -> Chain<Self, R>\n    where\n        Self: Sized;\n    fn take(self, limit: u64) -> Take<Self>\n    where\n        Self: Sized;\n}\n\ntrait Write {\n    fn write(&mut self, buf: &[u8]) -> Result<usize>;\n    fn flush(&mut self) -> Result<()>;\n\n    // provided default impls\n    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> Result<usize>;\n    fn is_write_vectored(&self) -> bool;\n    fn write_all(&mut self, buf: &[u8]) -> Result<()>;\n    fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> Result<()>;\n    fn write_fmt(&mut self, fmt: Arguments<'_>) -> Result<()>;\n    fn by_ref(&mut self) -> &mut Self\n    where\n        Self: Sized;\n}\n```\n\nGeneric blanket impls worth knowing:\n\n```rust\nimpl<R: Read + ?Sized> Read for &mut R;\nimpl<W: Write + ?Sized> Write for &mut W;\n```\n\nThese say that any mutable reference to a `Read` type is also `Read`, and same with `Write`. This is useful to know because it allows us to use any method with a `self` receiver as if it had a `&mut self` receiver. We already went over how to do this and why it's useful in the `Iterator` trait section, so I'm not going to repeat it again here.\n\nI'd like to point out that `&[u8]` impls `Read`, and that `Vec<u8>` impls `Write`, so we can easily unit test our file handling functions using `String`s, which are trivial to convert to `&[u8]` and from `Vec<u8>`:\n\n```rust\nuse std::path::Path;\nuse std::fs::File;\nuse std::io::Read;\nuse std::io::Write;\nuse std::io;\n\n// function we want to test\nfn uppercase<R: Read, W: Write>(mut read: R, mut write: W) -> Result<(), io::Error> {\n    let mut buffer = String::new();\n    read.read_to_string(&mut buffer)?;\n    let uppercase = buffer.to_uppercase();\n    write.write_all(uppercase.as_bytes())?;\n    write.flush()?;\n    Ok(())\n}\n\n// in actual program we'd pass Files\nfn example(in_path: &Path, out_path: &Path) -> Result<(), io::Error> {\n    let in_file = File::open(in_path)?;\n    let out_file = File::open(out_path)?;\n    uppercase(in_file, out_file)\n}\n\n// however in unit tests we can use Strings!\n#[test] // ✅\nfn example_test() {\n    let in_file: String = \"i am screaming\".into();\n    let mut out_file: Vec<u8> = Vec::new();\n    uppercase(in_file.as_bytes(), &mut out_file).unwrap();\n    let out_result = String::from_utf8(out_file).unwrap();\n    assert_eq!(out_result, \"I AM SCREAMING\");\n}\n```\n\n\n\n## Conclusion\n\nWe learned a lot together! Too much in fact. This is us now:\n\n![rust standard library traits](../assets/jason-jarvis-stdlib-traits.png)\n\n_Artist credit: [The Jenkins Comic](https://thejenkinscomic.wordpress.com/2020/05/06/memory/)_\n\n\n\n## Discuss\n\nDiscuss this article on\n- [Github](https://github.com/pretzelhammer/rust-blog/discussions)\n- [learnrust subreddit](https://www.reddit.com/r/learnrust/comments/ml9shl/tour_of_rusts_standard_library_traits/)\n- [official Rust users forum](https://users.rust-lang.org/t/blog-post-tour-of-rusts-standard-library-traits/57974)\n- [lobste.rs](https://lobste.rs/s/g27ezp/tour_rust_s_standard_library_traits)\n- [rust subreddit](https://www.reddit.com/r/rust/comments/mmrao0/tour_of_rusts_standard_library_traits/)\n\n\n\n## Further Reading\n\n- [Common Rust Lifetime Misconceptions](./common-rust-lifetime-misconceptions.md)\n- [Beginner's Guide to Concurrent Programming: Coding a Multithreaded Chat Server using Tokio](./chat-server.md)\n- [Learning Rust in 2024](./learning-rust-in-2024.md)\n- [Using Rust in Non-Rust Servers to Improve Performance](./rust-in-non-rust-servers.md)\n- [Sizedness in Rust](./sizedness-in-rust.md)\n- [RESTful API in Sync & Async Rust](./restful-api-in-sync-and-async-rust.md)\n- [Learn Assembly with Entirely Too Many Brainfuck Compilers](./too-many-brainfuck-compilers.md)\n\n\n\n## Notifications\n\nGet notified when a new blog post gets published by\n- Subscribing to this repo's [releases RSS feed](https://github.com/pretzelhammer/rust-blog/releases.atom) or\n- Watching this repo's releases (click `Watch` → click `Custom` → select `Releases` → click `Apply`)\n"
  },
  {
    "path": "posts/translations/jp/common-rust-lifetime-misconceptions.md",
    "content": "# Rustのライフタイムについてのよくある誤解\n\n2020年5月19日 · 読了時間 30分 · #rust · #lifetimes\n\nTranslated by [Yusuke Kominami](https://github.com/komi1230)\n\n## 目次\n\n- [はじめに](#はじめに)\n- [誤解](#誤解)\n  - [1) `T` は所有型のみ取りうる](#1-t-は所有型のみ取りうる)\n  - [2) `T: 'static`ならば`T`はプログラム全体で有効でなければならない](#2-t-staticならばtはプログラム全体で有効でなければならない)\n  - [3) `&'a T`と`T: 'a`は同じ](#3-a-tとt-aは同じ)\n  - [4) 自分のコードはジェネリックではなくライフタイムを持たない](#4-自分のコードはジェネリックではなくライフタイムを持たない)\n  - [5) コンパイルされたならライフタイムの記述は正しい](#5-コンパイルされたならライフタイムの記述は正しい)\n  - [6) Boxトレイトオブジェクトはライフタイムを持たない](#6-boxトレイトオブジェクトはライフタイムを持たない)\n  - [7) コンパイラのエラーメッセージはプログラムの直し方を教えてくれる](#7-コンパイラのエラーメッセージはプログラムの直し方を教えてくれる)\n  - [8) ライフタイムは実行時に伸び縮みする](#8-ライフタイムは実行時に伸び縮みする)\n  - [9) 可変参照から共有参照へ降格することは安全](#9-可変参照から共有参照へ降格することは安全)\n  - [10) クロージャは関数と同じライフタイム省略ルールに従う](#10-クロージャは関数と同じライフタイム省略ルールに従う)\n  - [11) `'static`な参照は`'a`な参照になることを常に強制される](#11-staticな参照はaな参照になることを常に強制される)\n- [まとめ](#まとめ)\n- [ディスカッション](#ディスカッション)\n- [参考](#参考)\n\n## はじめに\n\n私は何らかのタイミングでこのような誤解をしたことがあり、今日多くの初心者がこうした誤解に苦戦しています。私が使っている用語の中には普通ではないものもあるかもしれませんので、ここでは私が使っている略語とその意味を表にしてみました。\n\n| 用語 | 意味 |\n|-|-|\n| `T` | 1) 成りうる型を要素として持つ集合 _または_ <br> 2) その集合の要素となる型 |\n| 所有型 | 何らかの参照ではない型 <br>例) `i32`, `String`, `Vec`, など |\n| 1) 借用型 _または_<br>2) 参照型 | 可変性を問わない何らかの参照型 <br>例) `&i32`, `&mut i32`, など |\n| 1) 可変参照 _または_<br>2) 排他的参照 | 排他的で可変性のある参照、つまり `&mut T` |\n| 1) 不可変参照 _または_<br>2) 共有参照 | 不可変で共有された参照、つまり `&T` |\n\n## 誤解\n\n結局のところ、変数のライフタイムとはその変数が指すデータが現在のメモリアドレスで有効であることをコンパイラが静的に検証することができる期間です。以降では、どこで困惑してしまうのかについて詳しく述べていこうと思います。\n\n### 1) `T` は所有型のみ取りうる\n\nこの誤解はライフタイムに関するというよりジェネリクスについての話ですが、ジェネリクスとライフタイムはRustでは密接に絡み合ったもので、なので一方について言及せず他方について言及することは不可能なのです。\n\n私がRustを学び始めたとき、`i32`と`&i32`、`&mut i32`は異なる型だと知りました。また、あるジェネリックな型変数`T`は可能性のあるあらゆる型を内包した集合を表現していると知りました。しかし、これらを別々に理解しているとはいえ、これらを一緒に理解するのは不可能でした。Rust初心者だった私の頭の中ではジェネリクスはこのようなものだと理解していました。\n\n| | | | |\n|-|-|-|-|\n| **型変数** | `T` | `&T` | `&mut T` |\n| **例** | `i32` | `&i32` | `&mut i32` |\n\n`T`はあらゆる所有型を持つ。`&T`はあらゆる不可変な借用型を持つ。`&mut T`はあらゆる可変な借用型を持つ。`T`と`&T`、`&mut T`は共通部分を持たない有限集合なのです。素晴らしい、シンプルで綺麗、簡単で直感的、そして完全に間違っていた。Rustではジェネリクスが実際にこのように動いているのだ;\n\n| | | | |\n|-|-|-|-|\n| **型変数** | `T` | `&T` | `&mut T` |\n| **例** | `i32`, `&i32`, `&mut i32`, `&&i32`, `&mut &mut i32`, ... | `&i32`, `&&i32`, `&&mut i32`, ... | `&mut i32`, `&mut &mut i32`, `&mut &i32`, ... |\n\n`T`と`&T`、`&mut T`は全て無限集合で、それゆえに無限に型を借用できるのです。`T`は`&T`と`&mut T`を含む集合で、`&T`と`&mut T`は共通部分を持たない集合なのです。こうした概念を検証するためにいくつか例を見てみましょう。\n\n```rust\ntrait Trait {}\n\nimpl<T> Trait for T {}\n\nimpl<T> Trait for &T {} // コンパイルエラー\n\nimpl<T> Trait for &mut T {} // コンパイルエラー\n```\n\n上記のプログラムは期待した通りにはコンパイルされません。\n\n```rust\nerror[E0119]: conflicting implementations of trait `Trait` for type `&_`:\n --> src/lib.rs:5:1\n  |\n3 | impl<T> Trait for T {}\n  | ------------------- first implementation here\n4 |\n5 | impl<T> Trait for &T {}\n  | ^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_`\n\nerror[E0119]: conflicting implementations of trait `Trait` for type `&mut _`:\n --> src/lib.rs:7:1\n  |\n3 | impl<T> Trait for T {}\n  | ------------------- first implementation here\n...\n7 | impl<T> Trait for &mut T {}\n  | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&mut _`\n```\n\nコンパイラは`&T`や`&mut T`に対しての`Trait`を実装させません。これはすでに`&T`や`&mut T`などを含んだ`T`への`Trait`の実装と衝突が起こるかもしれないからです。以下のプログラムは期待した通りにコンパイルされます。これは`&T`と`&mut T`は互いに独立だからです。\n\n```rust\ntrait Trait {}\n\nimpl<T> Trait for &T {} // コンパイルされる\n\nimpl<T> Trait for &mut T {} // コンパイルされる\n```\n\n**キーポイント**\n\n- `T`は`&T`と`&mut T`を含む集合\n- `&T`と`&mut T`は共通部分を持たない\n\n\n### 2) `T: 'static`ならば`T`はプログラム全体で有効でなければならない\n\n**誤解の流れ**\n\n- `T: 'static`は _\"`T`はライフタイム`'static`を持っている\"_ と読まれるべき。\n- `&'static T` と `T: 'static` は同じもの\n- `T: 'static` ならば `T` は不可変でなければならない\n- `T: 'static` ならば `T` はコンパイル時にのみ作られる\n\nRust初心者の多くは初めてライフタイム`'static`を学ぶ際、このような感じのコードの例から入ります。\n\n```rust\nfn main() {\n    let str_literal: &'static str = \"str literal\";\n}\n```\n\n`\"str literal\"`はコンパイルされたバイナリにハードコーディングされ、実行時には読み込み専用のメモリへ積まれ、そうしてプログラム全体で不可変で有効で、それが`'static`だと教わる。こうした概念は、キーワード`static`を用いて定義される`static`変数に関するルールによってさらに強まります。\n\n```rust\nstatic BYTES: [u8; 3] = [1, 2, 3];\nstatic mut MUT_BYTES: [u8; 3] = [1, 2, 3];\n\nfn main() {\n   MUT_BYTES[0] = 99; // コンパイルエラー、static変数を変更するのはunsafe\n\n    unsafe {\n        MUT_BYTES[0] = 99;\n        assert_eq!(99, MUT_BYTES[0]);\n    }\n}\n```\n\n`static`変数について\n\n- コンパイル時にのみ作られる\n- 不可変であるべきで、変更するのはunsafe\n- プログラム全体で有効\n\nライフタイム`'static`はひょっとしたら`static`変数のデフォルトのライフタイムにちなんで名付けられたのではないでしょうか？なのでライフタイム`'static`は全く同じルールに従う必要があるのではないでしょうか？\n\nええ、しかしライフタイム`'static`のある型はライフタイム`'static`で _境界付けられた_ 型とは異なるのです。後者は実行時に動的に確保され、安全に、かつ自由に変化させられ、ドロップでき、意図した通りの期間で有効なのです。\n\nここで`&'static T`と`T: 'static`を区別しておくことは大切です。\n\n`&'static T`はプログラムの最後までを含んだ限りなく長い間安全に保持される`T`への不可変な参照なのです。これは`T`自身が不可変で _参照が作られた後に_ moveしない場合にのみ可能です。`T`はコンパイル時に作られる必要はないのです。メモリがリークするコストの元で、実行時にランダムに動的に確保されたデータを作り、それへの`'static`な参照を返すことが可能です。例えば\n\n```rust\nuse rand;\n\n// 実行時にランダムな'staticなstrへの参照を作成\nfn rand_str_generator() -> &'static str {\n    let rand_string = rand::random::<u64>().to_string();\n    Box::leak(rand_string.into_boxed_str())\n}\n```\n\n`T: 'static`はプログラム終了までを含んだ限りなく長い間で安全に保持される`T`なのです。`T: 'static`は`&'static T`を含みますが、同時に`String`や`Vec`などの所有型も含むのです。データの所有者は、データを保持している限りデータが無効になることがないことが保証されているので、プログラム終了までを含めて無期限にデータを保持することができ、安全にデータを保持することができます。`T: 'static`は _\"`T`はライフタイム`'static`によって境界付けられている\"_ と読むべきなのです。以下にこうした概念を説明するためのプログラムを示します。\n\n```rust\nuse rand;\n\nfn drop_static<T: 'static>(t: T) {\n    std::mem::drop(t);\n}\n\nfn main() {\n    let mut strings: Vec<String> = Vec::new();\n    for _ in 0..10 {\n        if rand::random() {\n            // 文字列はランダムに生成され実行時に動的に確保される\n            let string = rand::random::<u64>().to_string();\n            strings.push(string);\n        }\n    }\n\n    // 文字列は所有型なので'staticで境界付けられる\n    for mut string in strings {\n        // 文字列は可変\n        string.push_str(\"a mutation\");\n        // 文字列はドロップ可能\n        drop_static(string); // コンパイル可能\n    }\n\n    // 文字列はプログラム終了前に無効になっている\n    println!(\"i am the end of the program\");\n}\n```\n\n**キーポイント**\n\n- `T: 'static`は _\"`T`はライフタイム`'static`で境界づけられている\"_ と読むべき\n- `T: 'static`ならば`T`はライフタイム`'static` _または_ 所有型を持った借用型でありうる。\n- `T: 'static`は所有型を含み、これの意味するところとして`T`は\n  - 実行時に動的に確保される\n  - プログラム全体で有効である必要はない\n  - 安全かつ自由に変更可能\n  - 実行時に動的にドロップされる\n  - 異なる期間のライフタイムを持つ\n\n### 3) `&'a T`と`T: 'a`は同じ\n\nこの誤解は一つ前のものの一般化されたものです。\n\n`&'a T`は`T: 'a`を要求し、そして示唆しています。これは`T`自身が`'a`に対して有効でない場合ライフタイム`'a`の`T`への参照は有効となり得ないからです。例えば`Ref`は`'a`に対してのみ有効である場合それへの`'static`な参照を作ることができないので、Rustコンパイラは`&'static Ref<'a, T>`型を許さないでしょう。\n\n`T: 'a`は`&'a T`を含みますがその逆は成り立ちません。\n\n```rust\n// 'aによって境界づけられた参照型のみ取る\nfn t_ref<'a, T: 'a>(t: &'a T) {}\n\n// 'aによって境界づけられた任意の型を取る\nfn t_bound<'a, T: 'a>(t: T) {}\n\n// 参照を含んだ所有型\nstruct Ref<'a, T: 'a>(&'a T);\n\nfn main() {\n    let string = String::from(\"string\");\n\n    t_bound(&string); // コンパイル可能\n    t_bound(Ref(&string)); // コンパイル可能\n    t_bound(&Ref(&string)); // コンパイル可能\n\n    t_ref(&string); // コンパイル可能\n    t_ref(Ref(&string)); // コンパイルエラー, expected ref, found struct\n    t_ref(&Ref(&string)); // コンパイル可能\n\n    // 文字列の変数は'aで境界づけられた'staticで境界づけられている\n    t_bound(string); // コンパイル可能\n}\n```\n\n**キーポイント**\n\n- `T: 'a`は`&'a T`よりも一般的で柔軟\n- `T: 'a`は所有型と参照を含んだ所有型、参照を受け付ける\n- `&'a T`は参照のみ受け付ける\n- 任意の`'a`に対して`'static` >= `'a`なので`T: 'static`ならば`T: 'a`\n\n### 4) 自分のコードはジェネリックではなくライフタイムを持たない\n\n**誤解の流れ**\n\n- ジェネリクスとライフタイムを使わないことは可能\n\nこの心地よい誤解はRustのライフタイムの省略ルールのおかげで起きていて、Rustの借用チェックが以下の規則を推論しているため関数でライフタイムの記述を省くことができるのです。\n- 関数への全ての引数の参照は別々のライフタイムを得る\n- 引数のライフタイムが正確に1つであれば、全ての返り値の参照に適用される\n- 複数の引数のライフタイムがあるがそれらのうち1つが`&self`か`&mut self`である場合は`self`のライフタイムは全ての返り値の参照に適用される\n- それ以外の場合は返り値のライフタイムは明示的でなければならない\n\nたくさん出てきたのでいくつか例を見てみましょう。\n\n```rust\n// 省略された記法\nfn print(s: &str);\n\n// 元々の記法\nfn print<'a>(s: &'a str);\n\n// 省略された記法\nfn trim(s: &str) -> &str;\n\n// 元々の記法\nfn trim<'a>(s: &'a str) -> &'a str;\n\n// エラー、引数がないため返り値のライフタイムが決定できない\nfn get_str() -> &str;\n\n// 明示的な記法\nfn get_str<'a>() -> &'a str; // ジェネリックなバージョン\nfn get_str() -> &'static str; // 'staticなバージョン\n\n// エラー、複数の引数があるので返り値のライフタイムが決定できない\nfn overlap(s: &str, t: &str) -> &str;\n\n// 元々の記法(部分的には省略記法)\nfn overlap<'a>(s: &'a str, t: &str) -> &'a str; // 返り値はsより長持ちしない\nfn overlap<'a>(s: &str, t: &'a str) -> &'a str; // 返り値はtより長持ちしない\nfn overlap<'a>(s: &'a str, t: &'a str) -> &'a str; // 返り値はsとtより長持ちしない\nfn overlap(s: &str, t: &str) -> &'static str; // // 返り値はsとtより長持ちしない\nfn overlap<'a>(s: &str, t: &str) -> &'a str; // 引数と返り値のライフタイムとは関係ない\n\n// 元々の記法\nfn overlap<'a, 'b>(s: &'a str, t: &'b str) -> &'a str;\nfn overlap<'a, 'b>(s: &'a str, t: &'b str) -> &'b str;\nfn overlap<'a>(s: &'a str, t: &'a str) -> &'a str;\nfn overlap<'a, 'b>(s: &'a str, t: &'b str) -> &'static str;\nfn overlap<'a, 'b, 'c>(s: &'a str, t: &'b str) -> &'c str;\n\n// 省略された記法\nfn compare(&self, s: &str) -> &str;\n\n// 元々の記法\nfn compare<'a, 'b>(&'a self, &'b str) -> &'a str;\n```\n\nもし以下のものを書いたことがあるなら、ジェネリックなライフタイムの省略がなされています。\n\n- 構造体\n- 参照をとる関数\n- 参照を返す関数\n- ジェネリックな関数\n- トレイトオブジェクト (これについては後ほど)\n- クロージャ (これについては後ほど)\n\n**キーポイント**\n\n- Rustのコードのほとんどはジェネリックなコードで、どこにでも省略されたライフタイムが存在する\n\n### 5) コンパイルされたならライフタイムの記述は正しい\n\n**誤解の流れ**\n\n- Rustの関数へのライフタイムの省略ルールは常に正しい\n- Rustの借用チェックは技術的に、そして _意味的に_ 常に正しい\n- Rustはプログラマー以上にプログラムの意味について把握している\n\nRustのプログラムは技術的にコンパイル可能でも意味論的には間違っていることはありえます。この例を見てみましょう。\n\n```rust\nstruct ByteIter<'a> {\n    remainder: &'a [u8]\n}\n\nimpl<'a> ByteIter<'a> {\n    fn next(&mut self) -> Option<&u8> {\n        if self.remainder.is_empty() {\n            None\n        } else {\n            let byte = &self.remainder[0];\n            self.remainder = &self.remainder[1..];\n            Some(byte)\n        }\n    }\n}\n\nfn main() {\n    let mut bytes = ByteIter { remainder: b\"1\" };\n    assert_eq!(Some(&b'1'), bytes.next());\n    assert_eq!(None, bytes.next());\n}\n```\n\n`ByteIter`はバイトのスライスを繰り返すイテレータです。ここでは簡潔さのために`Iterator`トレイトの実装を省いています。これはちゃんと動くようですが、一度に何バイトかチェックしたいときはどうなるでしょう？\n\n```rust\nfn main() {\n    let mut bytes = ByteIter { remainder: b\"1123\" };\n    let byte_1 = bytes.next();\n    let byte_2 = bytes.next();\n    if byte_1 == byte_2 {\n        // 何かしらの処理\n    }\n}\n```\n\nおやおや、コンパイルエラーです。\n\n```rust\nerror[E0499]: cannot borrow `bytes` as mutable more than once at a time\n  --> src/main.rs:20:18\n   |\n19 |     let byte_1 = bytes.next();\n   |                  ----- first mutable borrow occurs here\n20 |     let byte_2 = bytes.next();\n   |                  ^^^^^ second mutable borrow occurs here\n21 |     if byte_1 == byte_2 {\n   |        ------ first borrow later used here\n```\n\nそれぞれのバイトをコピーすることは可能っぽいです。バイト列の処理をするときはコピーは大丈夫ですが、`ByteIter`を`&'a [T]`を繰り返すことができるジェネリックなスライスのイテレータにしたとき、それを将来的にはコピーやクローンをするのが高コストだったり不可能な型と一緒に使いたくなるでしょう。ええ、これについてできることは無さそうです。コードはコンパイルされライフタイムの記述は正しいでしょう。ね？\n\nいいえ、実は現在のライフタイムの記述はバグの原因なのです。そのバグとなりがちなライフタイムの記述は省略されるため、特に見分けがつきにくいのです。それでは省略されたライフタイムを広げてみて問題の原因を明確にしてみましょう。\n\n```rust\nstruct ByteIter<'a> {\n    remainder: &'a [u8]\n}\n\nimpl<'a> ByteIter<'a> {\n    fn next<'b>(&'b mut self) -> Option<&'b u8> {\n        if self.remainder.is_empty() {\n            None\n        } else {\n            let byte = &self.remainder[0];\n            self.remainder = &self.remainder[1..];\n            Some(byte)\n        }\n    }\n}\n```\n\n全く役に立ちそうにないです。私はまだ混乱してます。これはRustのプロだけが知っているコツなのですが、ライフタイムの記述を説明的な名前にしてみましょう。それではもう一度見てみます。\n\n```rust\nstruct ByteIter<'remainder> {\n    remainder: &'remainder [u8]\n}\n\nimpl<'remainder> ByteIter<'remainder> {\n    fn next<'mut_self>(&'mut_self mut self) -> Option<&'mut_self u8> {\n        if self.remainder.is_empty() {\n            None\n        } else {\n            let byte = &self.remainder[0];\n            self.remainder = &self.remainder[1..];\n            Some(byte)\n        }\n    }\n}\n```\n\nそれぞれ返り値のバイトは`'mut_self`と注釈づけられていますが、バイトは明らかに`'remainder`から来ています！それでは直してみましょう。\n\n```rust\nstruct ByteIter<'remainder> {\n    remainder: &'remainder [u8]\n}\n\nimpl<'remainder> ByteIter<'remainder> {\n    fn next(&mut self) -> Option<&'remainder u8> {\n        if self.remainder.is_empty() {\n            None\n        } else {\n            let byte = &self.remainder[0];\n            self.remainder = &self.remainder[1..];\n            Some(byte)\n        }\n    }\n}\n\nfn main() {\n    let mut bytes = ByteIter { remainder: b\"1123\" };\n    let byte_1 = bytes.next();\n    let byte_2 = bytes.next();\n    std::mem::drop(bytes); // イテレータをドロップすることができます！\n    if byte_1 == byte_2 { // コンパイル可能\n        // 何らかの処理\n    }\n}\n```\n\n今こうして前のプログラムを見返してみると、明らかに間違っていましたね。どうしてRustはコンパイルできたんでしょう？その答えはシンプルで、メモリ安全だったからです。\n\nRustの借用チェッカはメモリ安全かどうかを静的に検証できる範囲でのみプログラム内のライフタイム注釈を見ています。Rustは幸いなことに、ライフタイム注釈が意味的に間違っていてもコンパイル可能ですが、その結果プログラムは不必要に制限されるのです。\n\nここで先ほどの例とは反対の簡単な例を見てみましょう。Rustのライフタイム省略ルールはこの場では意味的に正しくても、意図せず不要な明示的ライフタイム注釈を使って制限的なメソッドを書いているのです。\n\n```rust\n#[derive(Debug)]\nstruct NumRef<'a>(&'a i32);\n\nimpl<'a> NumRef<'a> {\n    // この構造体は'aにおいてジェネリックなので注釈をつける必要がある\n    // 'aがついたselfパラメータもそうでしょう？ (答え: 間違い)\n    fn some_method(&'a mut self) {}\n}\n\nfn main() {\n    let mut num_ref = NumRef(&5);\n    num_ref.some_method(); // mutably borrows num_ref for the rest of its lifetime\n    num_ref.some_method(); // コンパイルエラー\n    println!(\"{:?}\", num_ref); // 同様にコンパイルエラー\n}\n```\n\n`'a`でジェネリックな構造体があったとき`&'a mut self`を受け取るようなメソッドを書きたいことはほぼないでしょう。Rustに伝えていることは _\"このメソッドは構造体のライフタイムの中で構造体を可変に借用する\"_ ということなのです。実際、これは構造体が永久に可変借用されて利用不可になる前に、Rustの借用チェッカは最大でも1回しか`some_method`の呼び出しを許可しないのです。このユースケースは究極的にはほとんど無いのですが、上記のコードは混乱していた初心者が書いてコンパイルするにはとても簡単です。修正点としては、不必要に明示的なライフタイム注釈をつけることではなくRustのライフタイム省略ルールに任せるのです。\n\n```rust\n#[derive(Debug)]\nstruct NumRef<'a>(&'a i32);\n\nimpl<'a> NumRef<'a> {\n    // mut selfには'aをつけない\n    fn some_method(&mut self) {}\n\n    // 上記の糖衣を外した版\n    fn some_method_desugared<'b>(&'b mut self){}\n}\n\nfn main() {\n    let mut num_ref = NumRef(&5);\n    num_ref.some_method();\n    num_ref.some_method(); // コンパイル可能\n    println!(\"{:?}\", num_ref); // コンパイル可能\n}\n```\n\n**キーポイント**\n\n- Rustの関数のライフタイム省略ルールはあらゆる状況で常に正しいわけではない\n- Rustはプログラムの意味についてはプログラマ以上に知っているわけではない\n- ライフタイム注釈には説明的な名前をつけよう\n- どこに、そしてなぜ明示的なライフタイム注釈をつけるかについて気にかけよう\n\n### 6) Boxトレイトオブジェクトはライフタイムを持たない\n\n先ほどRustの _関数の_ ライフタイムの省略ルールについて見ました。Rustは同様にトレイトオブジェクトについてもライフタイムの省略ルールがあり、それは\n\n- トレイトオブジェクトがジェネリックな型への型引数として使われた場合、そのライフタイム境界は保持している型から推論される\n  - 保持しているのが一意であればそれが使われる\n  - 保持しているのが複数あれば明示的な境界がなければならない\n- もし上記が適用されない場合\n  - トレイトが一つのライフタイム境界で定義されているならばそれが使われる\n  - ライフタイム境界に`'static`が使われている場合、`'static`となる\n  - 何もライフタイム境界が無い場合、式から推論され、式の外では`'static`となる\n\nこれらは非常に複雑に思えますが、 _トレイトオブジェクトのライフタイム境界は文脈から推論される_ とシンプルにまとめられます。いくつか手軽な例を見ればライフタイム境界の推論が極めて直感的で形式的なルールを覚える必要がないとわかるでしょう。\n\n```rust\nuse std::cell::Ref;\n\ntrait Trait {}\n\n// 省略された記法\ntype T1 = Box<dyn Trait>;\n// 元々の記法、Box<T> は T については何もライフタイム境界を持っていないので 'static と推論される\ntype T2 = Box<dyn Trait + 'static>;\n\n// 省略された記法\nimpl dyn Trait {}\n// 元々の記法\nimpl dyn Trait + 'static {}\n\n// 省略された記法\ntype T3<'a> = &'a dyn Trait;\n// 元々の記法、&'a T は T: 'a を要求するので 'a と推論される\ntype T4<'a> = &'a (dyn Trait + 'a);\n\n// 省略された記法\ntype T5<'a> = Ref<'a, dyn Trait>;\n// 元々の記法、Ref<'a, T> は T: 'a を要求するので 'a と推論される\ntype T6<'a> = Ref<'a, dyn Trait + 'a>;\n\ntrait GenericTrait<'a>: 'a {}\n\n// 省略された記法\ntype T7<'a> = Box<dyn GenericTrait<'a>>;\n// 元々の記法\ntype T8<'a> = Box<dyn GenericTrait<'a> + 'a>;\n\n// 省略された記法\nimpl<'a> dyn GenericTrait<'a> {}\n// 元々の記法\nimpl<'a> dyn GenericTrait<'a> + 'a {}\n```\n\nトレイトを実装した具体的な型は参照を持ち、またライフタイム境界を持っていて、対応するトレイトオブジェクトはライフタイム境界を持ちます。同様に明らかにライフタイム境界を持つ参照に対してトレイトを直接実装することもできます。\n\n```rust\ntrait Trait {}\n\nstruct Struct {}\nstruct Ref<'a, T>(&'a T);\n\nimpl Trait for Struct {}\nimpl Trait for &Struct {} // 参照型への直接的なimpl Trait\nimpl<'a, T> Trait for Ref<'a, T> {} // 参照を保持した型へのimpl Trait\n```\n\n何にせよ、初心者が関数をトレイトオブジェクトを使ったものからジェネリクスを使ったものへリファクタリングする際、またはその逆を行うとしばしば混乱するため、この点については説明する価値があります。例として以下のプログラムを見てみましょう。\n\n```rust\nuse std::fmt::Display;\n\nfn dynamic_thread_print(t: Box<dyn Display + Send>) {\n    std::thread::spawn(move || {\n        println!(\"{}\", t);\n    }).join();\n}\n\nfn static_thread_print<T: Display + Send>(t: T) {\n    std::thread::spawn(move || {\n        println!(\"{}\", t);\n    }).join();\n}\n```\n\nこれはコンパイルエラーを吐きます。\n\n```rust\nerror[E0310]: the parameter type `T` may not live long enough\n  --> src/lib.rs:10:5\n   |\n9  | fn static_thread_print<T: Display + Send>(t: T) {\n   |                        -- help: consider adding an explicit lifetime bound...: `T: 'static +`\n10 |     std::thread::spawn(move || {\n   |     ^^^^^^^^^^^^^^^^^^\n   |\nnote: ...so that the type `[closure@src/lib.rs:10:24: 12:6 t:T]` will meet its required lifetime bounds\n  --> src/lib.rs:10:5\n   |\n10 |     std::thread::spawn(move || {\n   |     ^^^^^^^^^^^^^^^^^^\n```\n\nよし、素晴らしい。コンパイラはどのように修正すれば良いかを教えてくれているので早速問題になっている箇所を直しましょう。\n\n```rust\nuse std::fmt::Display;\n\nfn dynamic_thread_print(t: Box<dyn Display + Send>) {\n    std::thread::spawn(move || {\n        println!(\"{}\", t);\n    }).join();\n}\n\nfn static_thread_print<T: Display + Send + 'static>(t: T) {\n    std::thread::spawn(move || {\n        println!(\"{}\", t);\n    }).join();\n}\n```\n\n今はこれでコンパイルされますが、この2つの関数は両者を比べるとおかしく見えます。どうして2番目の関数は`T`に対して1番目の関数が要求していない`'static`を要求しているのでしょうか？トリッキーな質問です。ライフタイムの省略ルールを適用することでRustは自動で1番目の関数では`'static`境界を推論しており、実際は両方とも`'static`境界を持っているのです。これがRustコンパイラが見ているものです。\n\n```rust\nuse std::fmt::Display;\n\nfn dynamic_thread_print(t: Box<dyn Display + Send + 'static>) {\n    std::thread::spawn(move || {\n        println!(\"{}\", t);\n    }).join();\n}\n\nfn static_thread_print<T: Display + Send + 'static>(t: T) {\n    std::thread::spawn(move || {\n        println!(\"{}\", t);\n    }).join();\n}\n```\n\n**キーポイント**\n\n- 全てのトレイトオブジェクトは推論されたデフォルトのライフタイム境界を持っている\n\n### 7) コンパイラのエラーメッセージはプログラムの直し方を教えてくれる\n\n**誤解の流れ**\n\n- Rustのトレイトオブジェクトへのライフタイム省略ルールは常に正しい\n- Rustはプログラムの意味についてプログラマよりも知っている\n\nこの誤解は前の2つのものが合わさったもので、例として\n\n```rust\nuse std::fmt::Display;\n\nfn box_displayable<T: Display>(t: T) -> Box<dyn Display> {\n    Box::new(t)\n}\n```\n\nこれはエラーを吐きます。\n\n```rust\nerror[E0310]: the parameter type `T` may not live long enough\n --> src/lib.rs:4:5\n  |\n3 | fn box_displayable<T: Display>(t: T) -> Box<dyn Display> {\n  |                    -- help: consider adding an explicit lifetime bound...: `T: 'static +`\n4 |     Box::new(t)\n  |     ^^^^^^^^^^^\n  |\nnote: ...so that the type `T` will meet its required lifetime bounds\n --> src/lib.rs:4:5\n  |\n4 |     Box::new(t)\n  |     ^^^^^^^^^^^\n```\n\nよし、Boxトレイトオブジェクトにはライフタイム`'static`境界が自動で推論されて、推奨されている修正はその不文律に基づいていることを心に留めつつ早速コンパイラが教えてくれている通りに直してみよう。\n\n```rust\nuse std::fmt::Display;\n\nfn box_displayable<T: Display + 'static>(t: T) -> Box<dyn Display> {\n    Box::new(t)\n}\n```\n\nプログラムはコンパイルされます... しかしこれは本当にやりたかったことなんでしょうか？ひょっとしたら、いやもしかしたらそうではないのかもだけど。コンパイラは他の修正については言及してませんが、こちらもまた良さそうです。\n\n```rust\nuse std::fmt::Display;\n\nfn box_displayable<'a, T: Display + 'a>(t: T) -> Box<dyn Display + 'a> {\n    Box::new(t)\n}\n```\n\nこの関数は前のものと全く同じ引数を受け付けるのに加え、それ以上です！改善したのでしょうか？いえ、必ずしもそうとは限らず、プログラムの要求と制約次第です。この例は少々抽象的なので、もっとシンプルで明らかなケースを見てみましょう。\n\n```rust\nfn return_first(a: &str, b: &str) -> &str {\n    a\n}\n```\n\nこれは以下のようになります。\n\n```rust\nerror[E0106]: missing lifetime specifier\n --> src/lib.rs:1:38\n  |\n1 | fn return_first(a: &str, b: &str) -> &str {\n  |                    ----     ----     ^ expected named lifetime parameter\n  |\n  = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `a` or `b`\nhelp: consider introducing a named lifetime parameter\n  |\n1 | fn return_first<'a>(a: &'a str, b: &'a str) -> &'a str {\n  |                ^^^^    ^^^^^^^     ^^^^^^^     ^^^\n```\n\nエラーメッセージは引数と返り値の両方に同じライフタイムをつけるように推奨しています。もしこうすると、プログラムはコンパイルは通りますが、この関数の返り値の型は制約が強くなりすぎます。実際にやりたいのはこういうことでしょう。\n\n```rust\nfn return_first<'a>(a: &'a str, b: &str) -> &'a str {\n    a\n}\n```\n\n**キーポイント**\n\n- Rustのトレイトオブジェクトへのライフタイム省略ルールはどんな状況でも正しいというわけではない\n- Rustはプログラムの意味についてプログラマよりも知っているわけではない\n- Rustのコンパイラが吐くエラーメッセージでおすすめされる修正はコンパイルが通るようにするが、コンパイルが通り、 _かつ_ プログラムへの要求をちゃんと満たしたものするわけではない\n\n### 8) ライフタイムは実行時に伸び縮みする\n\n**誤解の流れ**\n\n- 保有者の型は実行時に参照をスワップしてライフタイムを変える\n- Rustの借用チェッカは高度な制御フロー解析を行う\n\nこれはコンパイルされません。\n\n```rust\nstruct Has<'lifetime> {\n    lifetime: &'lifetime str,\n}\n\nfn main() {\n    let long = String::from(\"long\");\n    let mut has = Has { lifetime: &long };\n    assert_eq!(has.lifetime, \"long\");\n\n    {\n        let short = String::from(\"short\");\n        // 短いライフタイムへ\"切り替える\"\n        has.lifetime = &short;\n        assert_eq!(has.lifetime, \"short\");\n\n        // 長いライフタイムへ\"切り戻す\" (しかし実際はそうではない)\n        has.lifetime = &long;\n        assert_eq!(has.lifetime, \"long\");\n        // 短い方はここでドロップされる\n    }\n\n    // コンパイルエラー、短い方はドロップの後もまだ\"借用されている\"\n    assert_eq!(has.lifetime, \"long\");\n}\n```\n\nこれは以下のようになります。\n\n```rust\nerror[E0597]: `short` does not live long enough\n  --> src/main.rs:11:24\n   |\n11 |         has.lifetime = &short;\n   |                        ^^^^^^ borrowed value does not live long enough\n...\n15 |     }\n   |     - `short` dropped here while still borrowed\n16 |     assert_eq!(has.lifetime, \"long\");\n   |     --------------------------------- borrow later used here\n```\n\nこれも同様にコンパイルが通らず、上記と全く同様のエラーとなります。\n\n```rust\nstruct Has<'lifetime> {\n    lifetime: &'lifetime str,\n}\n\nfn main() {\n    let long = String::from(\"long\");\n    let mut has = Has { lifetime: &long };\n    assert_eq!(has.lifetime, \"long\");\n\n    // このブロックは実行されない\n    if false {\n        let short = String::from(\"short\");\n        // 短いライフタイムへ\"切り替える\"\n        has.lifetime = &short;\n        assert_eq!(has.lifetime, \"short\");\n\n        // 長いライフタイムへ\"切り戻す\" (しかし実際はそうではない)\n        has.lifetime = &long;\n        assert_eq!(has.lifetime, \"long\");\n        // 短い方はここでドロップされる\n    }\n\n    // コンパイルエラー、短い方はドロップの後もまだ\"借用されている\"\n    assert_eq!(has.lifetime, \"long\");\n}\n```\n\nライフタイムはコンパイル時に静的に検証される必要があり、Rustの借用チェッカはとても基礎的な制御フロー解析のみを行います。そのため`if-else`節のブロックや`match`節では変数にとって最短で可能性のあるライフタイムが取られます。変数は一度ライフタイムに境界づけられると _永遠に_ そのライフタイムに境界づけられます。変数のライフタイムは縮小はしますが、その縮小はコンパイル時に決定されるのです。\n\n**キーポイント**\n\n- ライフタイムはコンパイル時に静的に検証される\n- ライフタイムは実行時には決して伸び縮みしない\n- Rustの借用チェッカは、あらゆるコードパスは通りうるものという前提で常に変数の最短のライフタイムをとる\n\n### 9) 可変参照から共有参照へ降格することは安全\n\n**誤解の流れ**\n\n- 参照を再借用するとそのライフタイムは終わって新しいライフタイムが始まる\n\nRustは暗黙的に可変借用を不可変なものとして再借用するため共有借用を期待して関数に可変借用を渡すことができます。\n\n```rust\nfn takes_shared_ref(n: &i32) {}\n\nfn main() {\n    let mut a = 10;\n    takes_shared_ref(&mut a); // コンパイル可能\n    takes_shared_ref(&*(&mut a)); // 上記の糖衣を外したもの\n}\n```\n\n直感的には筋が通っていて、可変借用を不可変なものとして再借用するのは問題がないからです、ね？驚いたことにこれは違っていて、以下のプログラムはコンパイルが通りません。\n\n```rust\nfn main() {\n    let mut a = 10;\n    let b: &i32 = &*(&mut a); // 不可変として再借用\n    let c: &i32 = &a;\n    dbg!(b, c); // コンパイルエラー\n}\n```\n\n以下のようなエラーを吐きます。\n\n```rust\nerror[E0502]: cannot borrow `a` as immutable because it is also borrowed as mutable\n --> src/main.rs:4:19\n  |\n3 |     let b: &i32 = &*(&mut a);\n  |                     -------- mutable borrow occurs here\n4 |     let c: &i32 = &a;\n  |                   ^^ immutable borrow occurs here\n5 |     dbg!(b, c);\n  |          - mutable borrow later used here\n```\n\n可変借用は起きていますが、すぐに不可変として再借用され、そしてドロップされます。どうしてRustは不可変な再借用をまだ可変参照の排他的なライフタイムを持っているかのように扱うのでしょう？特に上記の例は何も問題がないのですが、実際には可変参照を共有参照へ降格することを可能とすることでメモリ安全の問題が起きているのです。\n\n```rust\nuse std::sync::Mutex;\n\nstruct Struct {\n    mutex: Mutex<String>\n}\n\nimpl Struct {\n    // 可変参照を共有参照へ降格\n    fn get_string(&mut self) -> &str {\n        self.mutex.get_mut().unwrap()\n    }\n    fn mutate_string(&self) {\n        // 可変参照を共有参照へ降格を可能にしてしまうと\n        // 以下の行ではget_stringメソッドから得られる共有参照を\n        // 無効にしてしまうのです\n        *self.mutex.lock().unwrap() = \"surprise!\".to_owned();\n    }\n}\n\nfn main() {\n    let mut s = Struct {\n        mutex: Mutex::new(\"string\".to_owned())\n    };\n    let str_ref = s.get_string(); // 共有参照へ降格された可変参照\n    s.mutate_string(); // str_refは無効化され、ダングリングポインタになっているg!(str_ref); // 予想通りコンパイルエラー\n}\n```\n\nここでのポイントは、可変参照を共有参照として再借用したとき、覚悟がないと共有参照は使えません。共有参照自体がドロップされていても再借用の期間だけ共有参照のライフタイムを延長するのです。再借用された共有参照を使用するのはとても難しく、これは不可変でありつつも他のどの共有参照とも重複してはいけないからなのです。再借用された共有参照は可変参照の短所と共有参照の短所を全て持っており、どちらの長所も持っていません。可変参照を共有参照として再借用することはRustのアンチパターンであるべきだと私は考えています。以下のようなコードを見たとき簡単にわかるよう、このアンチパターンを意識しておくことは重要です。\n\n```rust\n// 可変なTを共有なTへ降格\nfn some_function<T>(some_arg: &mut T) -> &T;\n\nstruct Struct;\n\nimpl Struct {\n    // 可変なselfを共有なselfへ降格\n    fn some_method(&mut self) -> &self;\n\n    // 可変なselfを共有なTへ降格\n    fn other_method(&mut self) -> &T;\n}\n```\n\n関数やメソッドのシグネチャで再借用を回避してもRustは自動的に暗黙の再借用が行われるため、気づかないうちにこの問題にぶつかってしまうことがあります。\n\n```rust\nuse std::collections::HashMap;\n\ntype PlayerID = i32;\n\n#[derive(Debug, Default)]\nstruct Player {\n    score: i32,\n}\n\nfn start_game(player_a: PlayerID, player_b: PlayerID, server: &mut HashMap<PlayerID, Player>) {\n    // サーバーからプレーヤーをもらい、まだ存在しなければ作成と挿入を行う\n    let player_a: &Player = server.entry(player_a).or_default();\n    let player_b: &Player = server.entry(player_b).or_default();\n\n    // プレーヤーで何かしらの処理\n    dbg!(player_a, player_b); // コンパイルエラー\n}\n```\n\n上記の例はコンパイルが通りません。明示的な型注釈をつけているので`or_default()`は暗黙的に`&Player`として再借用した`&mut Player`を返します。やりたいことを実現するには以下のようにする必要があります。\n\n```rust\nuse std::collections::HashMap;\n\ntype PlayerID = i32;\n\n#[derive(Debug, Default)]\nstruct Player {\n    score: i32,\n}\n\nfn start_game(player_a: PlayerID, player_b: PlayerID, server: &mut HashMap<PlayerID, Player>) {\n    // 返ってきた可変なPlayerをドロップ、これは同時に扱うことができないため\n    server.entry(player_a).or_default();\n    server.entry(player_b).or_default();\n\n    // 再びプレーヤーを取り寄せ、暗黙の再借用をすることなくここで不可変に取得\n    let player_a = server.get(&player_a);\n    let player_b = server.get(&player_b);\n\n    // プレーヤーで何かしらの処理\n    dbg!(player_a, player_b); // compiles\n}\n```\n\nどこか変な感じがしますが、メモリ安全のためには必要な儀式なのです。\n\n**キーポイント**\n\n- 可変参照を共有参照として再借用しないようにしよう、さもなくば嫌なことになります\n- 可変参照を再借用しても、例えその参照がドロップされていたとしてもそのライフタイムは終わらない\n\n### 10) クロージャは関数と同じライフタイム省略ルールに従う\n\nこれは誤解というよりRustの嬉しいところです。\n\nクロージャは関数であるにも関わらず、関数と同じライフタイム省略ルールに従わないのです。\n\n```rust\nfn function(x: &i32) -> &i32 {\n    x\n}\n\nfn main() {\n    let closure = |x: &i32| x;\n}\n```\n\nこれは以下の通りとなります。\n\n```rust\nerror: lifetime may not live long enough\n --> src/main.rs:6:29\n  |\n6 |     let closure = |x: &i32| x;\n  |                       -   - ^ returning this value requires that `'1` must outlive `'2`\n  |                       |   |\n  |                       |   return type of closure is &'2 i32\n  |                       let's call the lifetime of this reference `'1`\n```\n\n糖衣を外すと以下のようになります。\n\n```rust\n// 引数のライフタイムが返り値に適用される\nfn function<'a>(x: &'a i32) -> &'a i32 {\n    x\n}\n\nfn main() {\n    // 引数と返り値は別々のライフタイムを持つ\n    let closure = for<'a, 'b> |x: &'a i32| -> &'b i32 { x };\n    // メモ: この行は有効な構文ではないが説明のためにこうしている\n}\n```\n\nこの不一致には何の理由もありません。クロージャは最初は関数とは異なる型推論のセマンティクスで実装されていましたが、ここでクロージャと関数を統一してしまうのは破壊的な変更になってしまうのでずっと行き詰まっているのです。そのため、どうしたらクロージャの型を明示的に注釈できるでしょう？選択肢としては以下の通りです。\n\n```rust\nfn main() {\n    // トレイトオブジェクトへキャスト、そうするとunsizedになり、あらら、コンパイルエラーだ\n    let identity: dyn Fn(&i32) -> &i32 = |x: &i32| x;\n\n    // ワークアラウンドとしてヒープに確保、しかし変な感じだ\n    let identity: Box<dyn Fn(&i32) -> &i32> = Box::new(|x: &i32| x);\n\n    // 確保をスキップしてただ静的な参照を作る\n    let identity: &dyn Fn(&i32) -> &i32 = &|x: &i32| x;\n\n    // 上のものの構文糖衣を外したもの :)\n    let identity: &'static (dyn for<'a> Fn(&'a i32) -> &'a i32 + 'static) = &|x: &i32| -> &i32 { x };\n\n    // これが理想的なのだけれど無効な構文\n    let identity: impl Fn(&i32) -> &i32 = |x: &i32| x;\n\n    // これもまた良いのだけれど、これも無効な構文\n    let identity = for<'a> |x: &'a i32| -> &'a i32 { x };\n\n    // \"impl trait\"は関数の返り値の位置で動くため\n    fn return_identity() -> impl Fn(&i32) -> &i32 {\n        |x| x\n    }\n    let identity = return_identity();\n\n    // 前のものの更にジェネリックなもの\n    fn annotate<T, F>(f: F) -> F where F: Fn(&T) -> &T {\n        f\n    }\n    let identity = annotate(|x: &i32| x);\n}\n```\n\n上記の例から既に気付いてると思いますが、クロージャの型がトレイト境界として使われたとき普通の関数のライフタイム省略ルールに従うのです。\n\n実際はここから得られる学びや発見は何もなくて、ただそうなのです。\n\n**キーポイント**\n\n- どの言語にもあららってなる部分があるんです 🤷\n\n\n### 11) `'static`な参照は`'a`な参照になることを常に強制される\n\n私は先ほどこんなコード例を出しました。\n\n```rust\nfn get_str<'a>() -> &'a str; // ジェネリックなもの\nfn get_str() -> &'static str; // 'static のもの\n```\n\n何人かの読者からこの2つに実用的な違いはあるのかという質問がありました。最初はわからなかったのですが、少し調べたところ残念なことにその答えはYesで、これら2つの関数には実用的な違いがあります。\n\n普通、値を扱うとき`'a`の参照の代わりに`'static`の参照が使えます。これはRustは自動的に`'static`な参照を`'a`の参照へと自動で強制するからです。直感的にはこれは筋が通っていて、短いライフタイムが必要なところで長いライフタイムを持つ参照を用いても何のメモリ安全の問題にならないからです。以下のプログラムは期待通りコンパイルされます。\n\n```rust\nuse rand;\n\nfn generic_str_fn<'a>() -> &'a str {\n    \"str\"\n}\n\nfn static_str_fn() -> &'static str {\n    \"str\"\n}\n\nfn a_or_b<T>(a: T, b: T) -> T {\n    if rand::random() {\n        a\n    } else {\n        b\n    }\n}\n\nfn main() {\n    let some_string = \"string\".to_owned();\n    let some_str = &some_string[..];\n    let str_ref = a_or_b(some_str, generic_str_fn()); // compiles\n    let str_ref = a_or_b(some_str, static_str_fn()); // compiles\n}\n```\n\nしかしこの強制は参照が関数の型シグネチャの一部のときは起きず、そのため以下のものはコンパイルされません。\n\n```rust\nuse rand;\n\nfn generic_str_fn<'a>() -> &'a str {\n    \"str\"\n}\n\nfn static_str_fn() -> &'static str {\n    \"str\"\n}\n\nfn a_or_b_fn<T, F>(a: T, b_fn: F) -> T\n    where F: Fn() -> T\n{\n    if rand::random() {\n        a\n    } else {\n        b_fn()\n    }\n}\n\nfn main() {\n    let some_string = \"string\".to_owned();\n    let some_str = &some_string[..];\n    let str_ref = a_or_b_fn(some_str, generic_str_fn); // compiles\n    let str_ref = a_or_b_fn(some_str, static_str_fn); // compile error\n}\n```\n\nこれは以下のようなエラーになります。\n\n```rust\nerror[E0597]: `some_string` does not live long enough\n  --> src/main.rs:23:21\n   |\n23 |     let some_str = &some_string[..];\n   |                     ^^^^^^^^^^^ borrowed value does not live long enough\n...\n25 |     let str_ref = a_or_b_fn(some_str, static_str_fn);\n   |                   ---------------------------------- argument requires that `some_string` is borrowed for `'static`\n26 | }\n   | - `some_string` dropped here while still borrowed\n```\n\nこれがRustのあららってなってしまうとこなのかは議論を呼ぶところです。なぜならこれは`&'static str`を`&'a str`と強制する簡単な場合ではなく、`for<T> Fn() -> &'static T`を`for<'a, T> Fn() -> &'a T`に強制するものだからです。前者は値同士の強制であり、後者は型同士の強制なのです。\n\n**キーポイント**\n\n- `for<'a, T> fn() -> &'a T`のシグネチャのある関数は`for<T> fn() -> &'static T`のシグネチャのある関数よりも柔軟で色々なケースで動く\n\n## まとめ\n\n- `T`は`&T`と`&mut T`の上位集合\n- `&T`と`&mut T`は互いに独立\n- `T: 'static`は _\"`T`はライフタイム`'static`で境界づけられている\"_ と読むべき\n- `T: 'static`ならば`T`はライフタイム`'static` _または_ 所有型を持った借用型でありうる。\n- `T: 'static`は所有型を含み、これの意味するところとして`T`は\n  - 実行時に動的に確保される\n  - プログラム全体で有効である必要はない\n  - 安全かつ自由に変更可能\n  - 実行時に動的にドロップされる\n  - 異なる期間のライフタイムを持つ\n- `T: 'a`は`&'a T`よりも一般的で柔軟\n- `T: 'a`は所有型と参照を含んだ所有型、参照を受け付ける\n- `&'a T`は参照のみ受け付ける\n- 任意の`'a`に対して`'static` >= `'a`なので`T: 'static`ならば`T: 'a`\n- Rustのコードのほとんどはジェネリックなコードで、どこにでも省略されたライフタイムが存在する\n- Rustの関数のライフタイム省略ルールはあらゆる状況で常に正しいわけではない\n- Rustはプログラムの意味についてはプログラマ以上に知っているわけではない\n- ライフタイム注釈には説明的な名前をつけよう\n- どこに、そしてなぜ明示的なライフタイム注釈をつけるかについて気にかけよう\n- 全てのトレイトオブジェクトは推論されたデフォルトのライフタイム境界を持っている\n- Rustのトレイトオブジェクトへのライフタイム省略ルールはどんな状況でも正しいというわけではない\n- Rustはプログラムの意味についてプログラマよりも知っているわけではない\n- Rustのコンパイラが吐くエラーメッセージでおすすめされる修正はコンパイルが通るようにするが、コンパイルが通り、 _かつ_ プログラムへの要求をちゃんと満たしたものするわけではない\n- 可変参照を共有参照として再借用しないようにしよう、さもなくば嫌なことになります\n- 可変参照を再借用しても、例えその参照がドロップされていたとしてもそのライフタイムは終わらない\n- どの言語にもあららってなる部分があるんです 🤷\n- `for<'a, T> fn() -> &'a T`のシグネチャのある関数は`for<T> fn() -> &'static T`のシグネチャのある関数よりも柔軟で色々なケースで動く\n\n\n\n## ディスカッション\n\nこの記事については以下でディスカッションされています。\n\n- [learnrust subreddit](https://www.reddit.com/r/learnrust/comments/gmrcrq/common_rust_lifetime_misconceptions/)\n- [official Rust users forum](https://users.rust-lang.org/t/blog-post-common-rust-lifetime-misconceptions/42950)\n- [Twitter](https://twitter.com/pretzelhammer/status/1263505856903163910)\n- [rust subreddit](https://www.reddit.com/r/rust/comments/golrsx/common_rust_lifetime_misconceptions/)\n- [Hackernews](https://news.ycombinator.com/item?id=23279731)\n\n## 参考\n\n- [Sizedness in Rust](./../../sizedness-in-rust.md)\n- [Learning Rust in 2020](./../../learning-rust-in-2020.md)\n"
  },
  {
    "path": "posts/translations/rus/common-rust-lifetime-misconceptions.md",
    "content": "# Распространенные заблуждения о временах жизни в Rust\n\n*19 мая 2020 г. · 37 минут · #rust · #lifetimes*\n\n**Оглавление**\n\n- [Вступление](#вступление)\n- [Заблуждения](#заблуждения)\n    - [1) `T` содержит только владеющие типы](#1-t-содержит-только-владеющие-типы)\n    - [2) если `T: 'static`, то `T` должно жить на протяжении всего времени работы программы](#2-если-t-static-то-t-должно-жить-на-протяжении-всего-времени-работы-программы)\n    - [3) `&'a T` и `T: 'a` — это одно и то же](#3-a-t-и-t-a--это-одно-и-то-же)\n    - [4) мой код не является обобщённым и не имеет времён жизни](#4-мой-код-не-является-обобщённым-и-не-имеет-времён-жизни)\n    - [5) если оно компилируется, то мои аннотации времён жизни верны](#5-если-мой-код-компилируется-то-мои-аннотации-времён-жизни-верны)\n    - [6) трейт-объекты за владеющими указателями не имеют времён жизни](#6-трейт-объекты-за-владеющими-указателями-не-имеют-времён-жизни)\n    - [7) сообщения об ошибках компиляции скажут мне, как исправить мою программу](#7-сообщения-об-ошибках-компиляции-скажут-мне-как-исправить-мою-программу)\n    - [8) времена жизни могут расти и сокращаться в рантайме](#8-время-жизни-может-расти-и-сокращаться-во-время-исполнения)\n    - [9) ослабление mut-ссылок до разделяемых безопасно](#9-ослабление-мутабельных-ссылок-до-разделяемых-безопасно)\n    - [10) замыкания следуют тем же правилам вывода времён жизни, что и функции](#10-замыкания-следуют-тем-же-правилам-вывода-времён-жизни-что-и-функции)\n    - [11) `'static` ссылки всегда можно привести к `'a`](#11-static-ссылки-всегда-можно-привести-к-a-ссылкам)\n- [Заключение](#заключение)\n- [Обсуждение](#обсуждение)\n- [Дальнейшее чтение](#дальнейшее-чтение)\n\n## Вступление\n\nКогда-то я был подвержен всем этим заблуждениям, сейчас же вижу, как многие новички борются с ними. Некоторые используемые мной термины могут быть нестандартными, поэтому для обозначения вкладываемого в них смысла я привожу таблицу со значениями.\n\n| Термин | Значение |\n| --- | --- |\n| `T` | 1) множество всех возможных типов *или* <br> 2) некоторый тип из этого множества |\n| владеющий тип | некоторый тип, не являющийся ссылкой, например, `i32`, `String`, `Vec` и т. д. |\n| 1) заимствованный тип *или* <br> 2) ссылочный тип | некоторый ссылочный тип, вне зависимости от его изменяемости, например `&i32` , `&mut i32` и т. д. |\n| 1) mut-ссылка *или* <br> 2) эксклюзивная ссылка | эксклюзивная изменяемая ссылка, т.е. `&mut T` |\n| 1) immut-ссылка *или* <br> 2) разделяемая ссылка | разделяемая неизменяемая ссылка, т.е. `&T` |\n\n## Заблуждения\n\nВ двух словах: время жизни переменной — это статически проверяемый компилятором промежуток времени, в течение которого валидны обращения к данным, лежащим по адресу, сохранённому в переменной. Следующие ~6500 слов я потрачу на более подробный рассказ о том, где обычно возникает путаница.\n\n### 1) `T` содержит только владеющие типы\n\nЭто заблуждение больше относится к обобщённым типам, чем к временам жизни, но обобщённые типы и времена жизни тесно связаны в Rust, поэтому невозможно говорить об одном, не говоря о другом. В любом случае:\n\nКогда я впервые начал изучать Rust, я понял, что `i32` , `&i32` и `&mut i32` — это разные типы. Я также понял, что некоторая переменная типа `T` представляет собой множество, которое содержит все возможные типы. Однако, несмотря на то, что я понимал обе эти вещи по отдельности, я не мог понять их в совокупности. Я наивно полагал, что в Rust обобщённые типы работают так:\n\n|  |  |  |  |\n| --- | --- | --- | --- |\n| **Переменная типа** | `T` | `&T` | `&mut T` |\n| **Примеры** | `i32` | `&i32` | `&mut i32` |\n\n`T` содержит все владеющие типы. `&T` содержит все неизменяемо заимствованные типы. `&mut T` содержит все изменяемо заимствованные типы. `T` , `&T` и `&mut T` — непересекающиеся конечные множества. Красиво, просто, кратко, легко, интуитивно понятно и совершенно неправильно. Вот как в Rust обобщённые типы работают по-настоящему:\n\n|  |  |  |  |\n| --- | --- | --- | --- |\n| **Переменная типа** | `T` | `&T` | `&mut T` |\n| **Примеры** | `i32` , `&i32` , `&mut i32` , `&&i32` , `&mut &mut i32` , ... | `&i32` , `&&i32` , `&&mut i32` , ... | `&mut i32` , `&mut &mut i32` , `&mut &i32` , ... |\n\n`T` , `&T` и `&mut T` — бесконечные множества, так как тип можно заимствовать до бесконечности. `T` является надмножеством обоих `&T` и `&mut T`, а `&T` и `&mut T` — непересекающиеся множества. Вот пара примеров, подтверждающих эти представления:\n\n```rust\ntrait Trait {}\n\nimpl<T> Trait for T {}\n\nimpl<T> Trait for &T {} // ошибка компиляции\n\nimpl<T> Trait for &mut T {} // ошибка компиляции\n```\n\nПрограмма выше не компилируется, как и ожидалось:\n\n```rust\nerror[E0119]: conflicting implementations of trait `Trait` for type `&_`:\n --> src/lib.rs:5:1\n  |\n3 | impl<T> Trait for T {}\n  | ------------------- first implementation here\n4 |\n5 | impl<T> Trait for &T {}\n  | ^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_`\n\nerror[E0119]: conflicting implementations of trait `Trait` for type `&mut _`:\n --> src/lib.rs:7:1\n  |\n3 | impl<T> Trait for T {}\n  | ------------------- first implementation here\n...\n7 | impl<T> Trait for &mut T {}\n  | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&mut _`\n```\n\nКомпилятор не позволяет нам определять реализацию `Trait` для `&T` и `&mut T`, потому что она будет конфликтовать с реализацией `Trait` для `T`, которая уже включает в себя все `&T` и `&mut T`. Программа ниже компилируется, как и ожидалось, так как `&T` и `&mut T` не пересекаются:\n\n```rust\ntrait Trait {}\n\nimpl<T> Trait for &T {} // компилируется\n\nimpl<T> Trait for &mut T {} // компилируется\n```\n\n**Ключевые выводы**\n\n- `T` является надмножеством как `&T`, так и `&mut T`\n- `&T` и `&mut T` являются непересекающимися множествами\n\n### 2) если `T: 'static`, то `T` должно жить на протяжении всего времени работы программы\n\n**Ошибочные выводы**\n\n- `T: 'static` должно читаться как *«`T` имеет время жизни `'static`»*\n- `&'static T` и `T: 'static` — это одно и то же\n- если `T: 'static`, то `T` должен быть неизменяемым\n- если `T: 'static`, то `T` может быть создан только на этапе компиляции\n\nБольшинство новичков в Rust впервые знакомятся со временем жизни `'static`, используя код, выглядящий примерно так:\n\n```rust\nfn main() {\n    let str_literal: &'static str = \"str literal\";\n}\n```\n\nИм говорят, что `\"str literal\"` хранится в сегменте данных в скомпилированном двоичном файле и загружается в доступную только для чтения память во время исполнения, поэтому он неизменяем и действителен на протяжении всего времени работы программы, что и делает его `'static`. Эти понятия дополнительно подкрепляются правилами определения `static` переменных с использованием ключевого слова `static` .\n\n```rust\nstatic BYTES: [u8; 3] = [1, 2, 3];\nstatic mut MUT_BYTES: [u8; 3] = [1, 2, 3];\n\nfn main() {\n   MUT_BYTES[0] = 99; // ошибка компиляции, изменение статической переменной является небезопасной операцией\n\n    unsafe {\n        MUT_BYTES[0] = 99;\n        assert_eq!(99, MUT_BYTES[0]);\n    }\n}\n```\n\nЧто справедливо по отношению к `static` переменным:\n\n- они могут быть созданы только во время компиляции\n- они должны быть неизменяемыми, модифицировать их небезопасно\n- они доступны на протяжении всего времени работы программы\n\n`'static` время жизни, вероятно, было названо так из-за времён жизни по умолчанию `static` переменных, ведь так? Так что логично, что время жизни `'static` должно следовать тем же правилам, не так ли?\n\nНу, да, но тип, *содержащий* время жизни `'static`, отличается от типа, *ограниченного* временем жизни `'static`. Последний может быть динамически создан во время исполнения, безопасно и беспрепятственно изменён и удалён, а также может существовать в течение произвольных промежутков времени.\n\nВажно различать `&'static T` и `T: 'static`.\n\n`&'static T` - это неизменяемая ссылка на некоторый `T`, которую можно хранить безопасно неопределенно долгое время, в том числе вплоть до конца работы программы. Это возможно только в том случае, если сам `T` является неизменяемым и не перемещается *после создания ссылки*. `T` не обязательно должен быть создан на этапе компиляции. Вполне возможно генерировать произвольные динамически выделяемые значения во время исполнения и возвращать `'static` ссылки на них ценой утечки памяти, например:\n\n```rust\nuse rand;\n\n// генерирует во время исполнения случайные 'static str ссылки\nfn rand_str_generator() -> &'static str {\n    let rand_string = rand::random::<u64>().to_string();\n    Box::leak(rand_string.into_boxed_str())\n}\n```\n\n`T: 'static` — это некий `T`, который можно хранить безопасно бесконечно долго, в том числе вплоть до конца работы программы. `T: 'static` включает в себя все `&'static T`, однако оно также включает в себя все владеющие типы, такие как `String`, `Vec` и т. д. Владелец некоторых данных является гарантом того, что данные никогда не будут инвалидированы, пока владелец их удерживает, следовательно, владелец может безопасно хранить данные сколь угодно долго, в том числе вплоть до конца работы программы. `T: 'static` должно читаться, как _«`T` ограничен временем жизни `'static`»_, а не _«`T` имеет время жизни `'static`»_. Вот программа для иллюстрации этих концепций:\n\n```rust\nuse rand;\n\nfn drop_static<T: 'static>(t: T) {\n    std::mem::drop(t);\n}\n\nfn main() {\n    let mut strings: Vec<String> = Vec::new();\n    for _ in 0..10 {\n        if rand::random() {\n            // все строки сгенерированны случайным образом\n            // и динамически созданы в куче во время исполнения\n            let string = rand::random::<u64>().to_string();\n            strings.push(string);\n        }\n    }\n\n    // строки являются владеющими типами,\n    // поэтому они удовлетворяют ограничению 'static\n    for mut string in strings {\n        // все строки изменяемы\n        string.push_str(\"a mutation\");\n        // все строки динамически уничтожаемы\n        drop_static(string); // компилируется\n    }\n\n    // все строки были инвалидированы до окончания работы программы\n    println!(\"i am the end of the program\");\n}\n```\n\n**Ключевые выводы**\n\n- `T: 'static` должно читаться, как *«`T` ограничен временем жизни `'static`»*\n- если `T: 'static`, то `T` может быть заимствованным типом с временем жизни `'static` *или* владеющим типом.\n- поскольку `T: 'static` включает в себя владеющие типы, это означает, что `T`\n    - может быть динамически создан в рантайме\n    - не обязан существовать на протяжении всего времени работы программы\n    - может быть безопасно и беспрепятственно изменён\n    - может быть динамически уничтожен во время исполнения\n    - может иметь время жизни произвольной продолжительности\n\n### 3) `&'a T` и `T: 'a` — это одно и то же\n\nЭто заблуждение является обобщением заблуждения выше.\n\n`&'a T` требует и подразумевает `T: 'a`, поскольку ссылка на `T`, имеющая время жизни `'a`, не может быть действительной для `'a`, если сам `T` недействителен для `'a` . Например, компилятор Rust никогда не разрешит конструкцию типа `&'static Ref<'a, T>` потому что если `Ref` действителен только для `'a`, то мы не можем сделать `'static` ссылку на него.\n\n`T: 'a` включает в себя все `&'a T`, но обратное неверно.\n\n```rust\n// принимает только ссылки, ограниченные 'a\nfn t_ref<'a, T: 'a>(t: &'a T) {}\n\n// принимает любые типы, ограниченные 'a\nfn t_bound<'a, T: 'a>(t: T) {}\n\n// владеющий тип, содержащий ссылку\nstruct Ref<'a, T: 'a>(&'a T);\n\nfn main() {\n    let string = String::from(\"string\");\n\n    t_bound(&string); // компилируется\n    t_bound(Ref(&string)); // компилируется\n    t_bound(&Ref(&string)); // компилируется\n\n    t_ref(&string); // компилируется\n    t_ref(Ref(&string)); // ошибка компиляции, ожидалась ссылка, обнаружена структура\n    t_ref(&Ref(&string)); // компилируется\n\n    // строковая переменная ограничена 'static, которое, в свою очередь, ограничено 'a\n    t_bound(string); // компилируется\n}\n```\n\n**Ключевые выводы**\n\n- `T: 'a` является более общим и более гибким типом, чем `&'a T`\n- `T: 'a` принимает владеющие типы, владеющие типы, которые содержат ссылки, и ссылки\n- `&'a T` принимает только ссылки\n- если `T: 'static`, то `T: 'a`, так как `'static` >= `'a` для всех `'a`\n\n### 4) мой код не является обобщённым и не имеет времён жизни\n\n**Ошибочные выводы**\n\n- можно избежать использования обобщённых типов и времён жизни\n\nЭто удобное заблуждение сохраняется из-за правил вывода времён жизни (lifetime elision), позволяющих опустить аннотации времён жизни в функциях, поскольку компилятор Rust выведет их согласно следующим правилам:\n\n- каждая ссылка-аргумент функции получает отдельное время жизни\n- если есть ровно одно входное время жизни, то оно приписывается всем возвращаемым ссылкам (прим. переводчика: не только ссылкам, но и вообще всем обобщённым типам, параметризованным временем жизни)\n- если есть несколько входных времён жизни, но одно из них — это время жизни `&self` или `&mut self`, то  время жизни `self` приписывается всем возвращаемым ссылкам\n- в противном случае времена жизни возвращаемых значений должны быть указаны явно\n\nЭто довольно много, поэтому давайте рассмотрим несколько примеров:\n\n```rust\n// неявно\nfn print(s: &str);\n\n// выведено\nfn print<'a>(s: &'a str);\n\n// неявно\nfn trim(s: &str) -> &str;\n\n// выведено\nfn trim<'a>(s: &'a str) -> &'a str;\n\n// правила вывода неприменимы, нельзя вывести время жизни возвращаемого значения,\n// т. к. нет входных времён жизни\nfn get_str() -> &str;\n\n// возможные варианты явных аннотаций\nfn get_str<'a>() -> &'a str; // обобщённая версия\nfn get_str() -> &'static str; // 'static версия\n\n// правила вывода неприменимы, нельзя вывести время жизни возвращаемого значения,\n// т. к. есть несколько входных времён жизни\nfn overlap(s: &str, t: &str) -> &str;\n\n// возможные варианты с явным указанием времён жизни\n// (но всё равно с частичным выводом)\nfn overlap<'a>(s: &'a str, t: &str) -> &'a str; // возвращаемое значение не может прожить дольше s\nfn overlap<'a>(s: &str, t: &'a str) -> &'a str; // возвращаемое значение не может прожить дольше t\nfn overlap<'a>(s: &'a str, t: &'a str) -> &'a str; // возвращаемое значение не может прожить дольше s и t\nfn overlap(s: &str, t: &str) -> &'static str; // возвращаемое значение может прожить дольше s и t\nfn overlap<'a>(s: &str, t: &str) -> &'a str; // никакой связи между входными и выходными временами жизни\n\n// выведено\nfn overlap<'a, 'b>(s: &'a str, t: &'b str) -> &'a str;\nfn overlap<'a, 'b>(s: &'a str, t: &'b str) -> &'b str;\nfn overlap<'a>(s: &'a str, t: &'a str) -> &'a str;\nfn overlap<'a, 'b>(s: &'a str, t: &'b str) -> &'static str;\nfn overlap<'a, 'b, 'c>(s: &'a str, t: &'b str) -> &'c str;\n\n// неявно\nfn compare(&self, s: &str) -> &str;\n\n// выведено\nfn compare<'a, 'b>(&'a self, &'b str) -> &'a str;\n```\n\nЕсли вы когда-нибудь писали:\n\n- метод структуры\n- функцию, принимающую ссылки\n- функцию, возвращающую ссылки\n- обобщённую функцию\n- трейт-объект (подробнее об этом позже)\n- замыкание (подробнее об этом позже)\n\nто тогда повсюду в вашем коде есть выведенные аннотации времён жизни.\n\n**Ключевые выводы**\n\n- почти весь код Rust является обобщённым кодом, и везде есть выведенные аннотации времён жизни\n\n### 5) если мой код компилируется, то мои аннотации времён жизни верны\n\n**Ошибочные выводы**\n\n- Правила вывода времён жизни для функций всегда верны\n- Анализатор заимствований (borrow checker) в Rust всегда прав, и технически, *и семантически*\n- Rust знает о семантике моей программы больше меня\n\nПрограмма на Rust может быть технически компилируемой, но в то же время семантически неверной. Рассмотрим пример:\n\n```rust\nstruct ByteIter<'a> {\n    remainder: &'a [u8]\n}\n\nimpl<'a> ByteIter<'a> {\n    fn next(&mut self) -> Option<&u8> {\n        if self.remainder.is_empty() {\n            None\n        } else {\n            let byte = &self.remainder[0];\n            self.remainder = &self.remainder[1..];\n            Some(byte)\n        }\n    }\n}\n\nfn main() {\n    let mut bytes = ByteIter { remainder: b\"1\" };\n    assert_eq!(Some(&b'1'), bytes.next());\n    assert_eq!(None, bytes.next());\n}\n```\n\n`ByteIter` - это итератор, который перебирает срез байтов. Для краткости мы пропустили реализацию трейта `Iterator`. Кажется, всё работает нормально, но что, если мы хотим проверить пару байтов за раз?\n\n```rust\nfn main() {\n    let mut bytes = ByteIter { remainder: b\"1123\" };\n    let byte_1 = bytes.next();\n    let byte_2 = bytes.next();\n    if byte_1 == byte_2 {\n        // что-то делаем\n    }\n}\n```\n\nОй! Ошибка компиляции:\n\n```rust\nerror[E0499]: cannot borrow `bytes` as mutable more than once at a time\n  --> src/main.rs:20:18\n   |\n19 |     let byte_1 = bytes.next();\n   |                  ----- first mutable borrow occurs here\n20 |     let byte_2 = bytes.next();\n   |                  ^^^^^ second mutable borrow occurs here\n21 |     if byte_1 == byte_2 {\n   |        ------ first borrow later used here\n```\n\nДумаю, мы можем позволить себе скопировать каждый байт. Копирование — это нормально, когда мы работаем с байтами, но если мы превратим `ByteIter` в обобщённый итератор среза, который может перебирать любой `&'a [T]`, то мы могли бы захотеть использовать его в будущем с типами, которые дорого или вовсе невозможно копировать/клонировать. Что ж, я думаю, мы ничего не можем с этим поделать, ведь код компилируется, а значит, аннотации времён жизни должны быть правильными, ведь так?\n\nОтнюдь, текущие аннотации времён жизни на самом деле являются источником ошибки! Это особенно трудно заметить, потому что ошибочные аннотации жизни опущены. Давайте выпишем развёрнутые аннотации времён жизни, чтобы получить более чёткое представление о проблеме:\n\n```rust\nstruct ByteIter<'a> {\n    remainder: &'a [u8]\n}\n\nimpl<'a> ByteIter<'a> {\n    fn next<'b>(&'b mut self) -> Option<&'b u8> {\n        if self.remainder.is_empty() {\n            None\n        } else {\n            let byte = &self.remainder[0];\n            self.remainder = &self.remainder[1..];\n            Some(byte)\n        }\n    }\n}\n```\n\nЭто совсем не помогло. Я всё ещё в замешательстве. Вот хорошая уловка, которую знают только профессионалы Rust: давайте аннотациям времён жизни осмысленные имена. Попробуем ещё раз:\n\n```rust\nstruct ByteIter<'remainder> {\n    remainder: &'remainder [u8]\n}\n\nimpl<'remainder> ByteIter<'remainder> {\n    fn next<'mut_self>(&'mut_self mut self) -> Option<&'mut_self u8> {\n        if self.remainder.is_empty() {\n            None\n        } else {\n            let byte = &self.remainder[0];\n            self.remainder = &self.remainder[1..];\n            Some(byte)\n        }\n    }\n}\n```\n\nКаждый возвращаемый байт аннотирован `'mut_self`, но байты явно поступают из `'remainder` ! Давайте исправим это.\n\n```rust\nstruct ByteIter<'remainder> {\n    remainder: &'remainder [u8]\n}\n\nimpl<'remainder> ByteIter<'remainder> {\n    fn next(&mut self) -> Option<&'remainder u8> {\n        if self.remainder.is_empty() {\n            None\n        } else {\n            let byte = &self.remainder[0];\n            self.remainder = &self.remainder[1..];\n            Some(byte)\n        }\n    }\n}\n\nfn main() {\n    let mut bytes = ByteIter { remainder: b\"1123\" };\n    let byte_1 = bytes.next();\n    let byte_2 = bytes.next();\n    std::mem::drop(bytes); // теперь мы даже можем удалить итератор!\n    if byte_1 == byte_2 { // компилируется\n        // что-то делаем\n    }\n}\n```\n\nТеперь, рассматривая предыдущую версию нашей программы, мы видим, что она явно была ошибочной. Так почему же Rust скомпилировал ее? Ответ прост: это было безопасным использованием памяти (memory safe).\n\nАнализатор заимствований (borrow checker) Rust-а заботится о аннотациях времён жизни в программе только до той степени, до которой он может использовать их для статической проверки безопасности работы с памятью. Rust с радостью скомпилирует программы, даже если аннотации времён жизни содержат семантические ошибки и из-за этого программа становится излишне строгой.\n\nВот простой пример, который противоположен предыдущему: правила вывода времён жизни Rust в данном случае семантически корректны, но мы непреднамеренно пишем очень ограниченный метод с нашими собственными ненужными явными аннотациями времён жизни.\n\n```rust\n#[derive(Debug)]\nstruct NumRef<'a>(&'a i32);\n\nimpl<'a> NumRef<'a> {\n    // моя структура параметризована 'a, так что мне нужно\n    // также аннотировать self 'a, верно? (ответ: нет, не верно)\n    fn some_method(&'a mut self) {}\n}\n\nfn main() {\n    let mut num_ref = NumRef(&5);\n    num_ref.some_method(); // изменяемо заимствует num_ref до конца её времени жизни\n    num_ref.some_method(); // ошибка компиляции\n    println!(\"{:?}\", num_ref); // также ошибка компиляции\n}\n```\n\nЕсли у нас есть какая-то обобщённая структура, параметризованная `'a`, то мы почти никогда не хотим писать метод с аргументом `&'a mut self` . Мы таким образом сообщаем Rust, что «этот метод будет изменяемо заимствовать структуру на всё её время жизни». На практике это означает, что анализатор заимствований Rust разрешит не более одного вызова `some_method`, после которого структура станет перманентно изменяемо заимствованной и, таким образом, непригодной к использованию. Случаи, в которых это требуется, крайне редки, но приведенный выше код новички очень легко могут написать по ошибке, и он компилируется. Исправление ошибки состоит в том, чтобы не добавлять ненужные явные аннотации времён жизни и положиться на правила вывода времён жизни Rust:\n\n```rust\n#[derive(Debug)]\nstruct NumRef<'a>(&'a i32);\n\nimpl<'a> NumRef<'a> {\n    // на mut self больше нет 'a\n    fn some_method(&mut self) {}\n\n    // строчка выше рассахаривается таким образом\n    fn some_method_desugared<'b>(&'b mut self){}\n}\n\nfn main() {\n    let mut num_ref = NumRef(&5);\n    num_ref.some_method();\n    num_ref.some_method(); // компилируется\n    println!(\"{:?}\", num_ref); // компилируется\n}\n```\n\n**Ключевые выводы**\n\n- правила вывода времён жизни Rust не всегда подходят к конкретной ситуации\n- Rust не знает о семантике вашей программы больше, чем вы\n- давайте вашим аннотациям времён жизни осмысленные имена\n- старайтесь понимать, где вы размещаете явные аннотации времён жизни и почему\n\n### 6) трейт-объекты за владеющими указателями не имеют времён жизни\n\nРанее мы обсуждали правила Rust для вывода времён жизни применительно к *функциям* . У Rust также есть подобные правила для трейт-объектов:\n\n- если трейт-объект используется в качестве ти́пового параметра обобщённого типа, то время жизни трейт-объекта выводится из этого внешнего обобщённого типа\n    - если есть только одно ограничение, следующее из внешнего типа, то оно и используется\n    - если ограничений, следующих из внешнего типа, больше одного, то ограничение должно быть указано явно\n- если правила выше не применимы, то\n    - если трейт определён с единственным ограничением времени жизни, то оно и используется\n    - если для любого ограничения времени жизни используется `'static`, то используется `'static`\n    - если трейт не имеет ограничений времён жизни, то в выражениях его время жизни выводится, а вне выражений имеет ограничение `'static`\n\nВсё это звучит очень сложно, но это можно выразить коротко как *«ограничения времени жизни трейт-объекта выводятся из контекста».* Изучив несколько примеров, мы увидим, что выведенные времена жизни довольно интуитивны, поэтому нам не нужно запоминать формальные правила:\n\n```rust\nuse std::cell::Ref;\n\ntrait Trait {}\n\n// неявно\ntype T1 = Box<dyn Trait>;\n// выведено, Box<T> не налагает ограничений времён жизни на T,\n// поэтому выводится 'static\ntype T2 = Box<dyn Trait + 'static>;\n\n// неявно\nimpl dyn Trait {}\n// выведено\nimpl dyn Trait + 'static {}\n\n// неявно\ntype T3<'a> = &'a dyn Trait;\n// выведено, &'a T требует T: 'a, поэтому выводится 'a\ntype T4<'a> = &'a (dyn Trait + 'a);\n\n// неявно\ntype T5<'a> = Ref<'a, dyn Trait>;\n// выведено, Ref<'a, T> требует T: 'a, поэтому выводится 'a\ntype T6<'a> = Ref<'a, dyn Trait + 'a>;\n\ntrait GenericTrait<'a>: 'a {}\n\n// неявно\ntype T7<'a> = Box<dyn GenericTrait<'a>>;\n// выведено\ntype T8<'a> = Box<dyn GenericTrait<'a> + 'a>;\n\n// неявно\nimpl<'a> dyn GenericTrait<'a> {}\n// выведено\nimpl<'a> dyn GenericTrait<'a> + 'a {}\n```\n\nКонкретные типы, которые реализуют трейты, могут иметь ссылки, и, таким образом, иметь ограничения времён жизни, поэтому созданные из них трейт-объекты имеют соответствующие времена жизни. Также вы можете реализовать трейты непосредственно для ссылок, которые, очевидно, имеют ограничения времён жизни:\n\n```rust\ntrait Trait {}\n\nstruct Struct {}\nstruct Ref<'a, T>(&'a T);\n\nimpl Trait for Struct {}\nimpl Trait for &Struct {} // реализация трейта напрямую на ссылке\nimpl<'a, T> Trait for Ref<'a, T> {} // реализация трейта для типа, содержащего ссылку\n```\n\nВ любом случае, это стоит повторить, поскольку это часто сбивает с толку новичков, когда они преобразуют функцию из использующей трейт-объекты в обобщённую или наоборот. Рассмотрим пример:\n\n```rust\nuse std::fmt::Display;\n\nfn dynamic_thread_print(t: Box<dyn Display + Send>) {\n    std::thread::spawn(move || {\n        println!(\"{}\", t);\n    }).join();\n}\n\nfn static_thread_print<T: Display + Send>(t: T) {\n    std::thread::spawn(move || {\n        println!(\"{}\", t);\n    }).join();\n}\n```\n\nОно выдаёт ошибку компиляции:\n\n```rust\nerror[E0310]: the parameter type `T` may not live long enough\n  --> src/lib.rs:10:5\n   |\n9  | fn static_thread_print<T: Display + Send>(t: T) {\n   |                        -- help: consider adding an explicit lifetime bound...: `T: 'static +`\n10 |     std::thread::spawn(move || {\n   |     ^^^^^^^^^^^^^^^^^^\n   |\nnote: ...so that the type `[closure@src/lib.rs:10:24: 12:6 t:T]` will meet its required lifetime bounds\n  --> src/lib.rs:10:5\n   |\n10 |     std::thread::spawn(move || {\n   |     ^^^^^^^^^^^^^^^^^^\n```\n\nОтлично, компилятор говорит нам, как решить проблему. Давайте исправим её.\n\n```rust\nuse std::fmt::Display;\n\nfn dynamic_thread_print(t: Box<dyn Display + Send>) {\n    std::thread::spawn(move || {\n        println!(\"{}\", t);\n    }).join();\n}\n\nfn static_thread_print<T: Display + Send + 'static>(t: T) {\n    std::thread::spawn(move || {\n        println!(\"{}\", t);\n    }).join();\n}\n```\n\nТеперь код компилируется, но эти две функции в сравнении выглядят несколько странно. Почему вторая функция требует ограничение `'static` на `T`, а первая функция — нет? Это вопрос с подвохом. Используя правила вывода времён жизни, Rust автоматически выводит ограничение `'static` в первой функции, поэтому у них обеих фактически есть ограничение `'static`. Вот что видит компилятор Rust:\n\n```rust\nuse std::fmt::Display;\n\nfn dynamic_thread_print(t: Box<dyn Display + Send + 'static>) {\n    std::thread::spawn(move || {\n        println!(\"{}\", t);\n    }).join();\n}\n\nfn static_thread_print<T: Display + Send + 'static>(t: T) {\n    std::thread::spawn(move || {\n        println!(\"{}\", t);\n    }).join();\n}\n```\n\n**Ключевые выводы**\n\n- все трейт-объекты имеют определенные выведенные ограничения времён жизни по умолчанию\n\n### 7) сообщения об ошибках компиляции скажут мне, как исправить мою программу\n\n**Ошибочные выводы**\n\n- правила вывода времён жизни для трейт-объектов всегда верны\n- Rust знает о семантике моей программы больше меня\n\nДанное заблуждение — это предыдущие два, объединённые в один пример:\n\n```rust\nuse std::fmt::Display;\n\nfn box_displayable<T: Display>(t: T) -> Box<dyn Display> {\n    Box::new(t)\n}\n```\n\nЭта программа выдаёт следующую ошибку:\n\n```rust\nerror[E0310]: the parameter type `T` may not live long enough\n --> src/lib.rs:4:5\n  |\n3 | fn box_displayable<T: Display>(t: T) -> Box<dyn Display> {\n  |                    -- help: consider adding an explicit lifetime bound...: `T: 'static +`\n4 |     Box::new(t)\n  |     ^^^^^^^^^^^\n  |\nnote: ...so that the type `T` will meet its required lifetime bounds\n --> src/lib.rs:4:5\n  |\n4 |     Box::new(t)\n  |     ^^^^^^^^^^^\n```\n\nХорошо, давайте исправим проблему так, как говорит нам компилятор. Не будем обращать внимание на тот факт, что он, не говоря нам, автоматически выводит для нашего трейт-объекта ограничение времени жизни `'static` и что его рекомендуемое исправление основано на этом предположении:\n\n```rust\nuse std::fmt::Display;\n\nfn box_displayable<T: Display + 'static>(t: T) -> Box<dyn Display> {\n    Box::new(t)\n}\n```\n\nИтак, теперь программа компилируется... Но действительно ли это то, чего мы хотим? Возможно, да, но возможно, что и нет. Компилятор не предложил никаких других исправлений, но этот вариант также применим:\n\n```rust\nuse std::fmt::Display;\n\nfn box_displayable<'a, T: Display + 'a>(t: T) -> Box<dyn Display + 'a> {\n    Box::new(t)\n}\n```\n\nЭта функция принимает все те же аргументы, что и в предыдущая версии, и даже сверх этого! Делает ли это её лучше? Необязательно, это зависит от требований к нашей программе. Данный пример несколько абстрактный, поэтому давайте рассмотрим более простой и очевидный случай:\n\n```rust\nfn return_first(a: &str, b: &str) -> &str {\n    a\n}\n```\n\nВыдаёт ошибку:\n\n```rust\nerror[E0106]: missing lifetime specifier\n --> src/lib.rs:1:38\n  |\n1 | fn return_first(a: &str, b: &str) -> &str {\n  |                    ----     ----     ^ expected named lifetime parameter\n  |\n  = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `a` or `b`\nhelp: consider introducing a named lifetime parameter\n  |\n1 | fn return_first<'a>(a: &'a str, b: &'a str) -> &'a str {\n  |                ^^^^    ^^^^^^^     ^^^^^^^     ^^^\n```\n\nСообщение об ошибке рекомендует аннотировать оба аргумента и возвращаемое значение одинаковым временем жизни. Если бы мы так сделали, наша программа бы скомпилировалась, но эта функция чрезмерно ограничила бы тип возвращаемого значения. На самом деле мы хотим этого:\n\n```rust\nfn return_first<'a>(a: &'a str, b: &str) -> &'a str {\n    a\n}\n```\n\n**Ключевые выводы**\n\n- правила вывода времени жизни для трейт-объектов подходят не к любой ситуации\n- Rust не знает о семантике вашей программы больше, чем вы\n- Сообщения об ошибках компиляции Rust предлагают исправления, которые приведут к успешной компиляции вашей программы, но это не то же самое, что и исправления, которые заставят вашу программу успешно компилироваться *и одновременно* наилучшим образом соответствуют требованиям вашей программы.\n\n### 8) время жизни может расти и сокращаться во время исполнения\n\n**Ошибочные выводы**\n\n- контейнерные типы могут менять ссылки во время выполнения, чтобы изменять их времена жизни\n- анализатор заимствований Rust использует продвинутый анализ потока управления\n\nЭтот код не компилируется:\n\n```rust\nstruct Has<'lifetime> {\n    lifetime: &'lifetime str,\n}\n\nfn main() {\n    let long = String::from(\"long\");\n    let mut has = Has { lifetime: &long };\n    assert_eq!(has.lifetime, \"long\");\n\n    {\n        let short = String::from(\"short\");\n        // \"переключиться\" на более короткое время жизни\n        has.lifetime = &short;\n        assert_eq!(has.lifetime, \"short\");\n\n        // \"переключиться обратно\" на более длинное время жизни (на самом деле нет)\n        has.lifetime = &long;\n        assert_eq!(has.lifetime, \"long\");\n        // здесь `short` удаляется\n    }\n\n    // ошибка компиляции, `short` все ещё \"заимствовано\" после удаления\n    assert_eq!(has.lifetime, \"long\");\n}\n```\n\nОн выдаёт ошибку:\n\n```rust\nerror[E0597]: `short` does not live long enough\n  --> src/main.rs:11:24\n   |\n11 |         has.lifetime = &short;\n   |                        ^^^^^^ borrowed value does not live long enough\n...\n15 |     }\n   |     - `short` dropped here while still borrowed\n16 |     assert_eq!(has.lifetime, \"long\");\n   |     --------------------------------- borrow later used here\n```\n\nЭтот код также не компилируется и выдает ту же ошибку, что и пример выше:\n\n```rust\nstruct Has<'lifetime> {\n    lifetime: &'lifetime str,\n}\n\nfn main() {\n    let long = String::from(\"long\");\n    let mut has = Has { lifetime: &long };\n    assert_eq!(has.lifetime, \"long\");\n\n    // этот блок никогда не будет выполнен\n    if false {\n        let short = String::from(\"short\");\n        // \"переключиться\" на более короткое время жизни\n        has.lifetime = &short;\n        assert_eq!(has.lifetime, \"short\");\n\n        // \"переключится обратно\" на более длинное время жизни (на самом деле нет)\n        has.lifetime = &long;\n        assert_eq!(has.lifetime, \"long\");\n        // здесь `short` удаляется\n    }\n\n    // все ещё ошибка компиляции, `short` все ещё \"заимствовано\" после удаления\n    assert_eq!(has.lifetime, \"long\");\n}\n```\n\nВремена жизни должны быть статически проверены во время компиляции, и анализатор заимствований выполняет только очень ограниченный анализ потока управления, поэтому он предполагает, что каждый блок в операторе `if-else` и каждая ветвь выражения `match` могут быть выполнены, а затем выбирает самое короткое из возможных времён жизни для переменной. Как только переменная ограничена временем жизни, она ограничена этим временем жизни *навсегда*. Время жизни переменной может только сокращаться, и это сокращение полностью определяется на этапе компиляции.\n\n**Ключевые выводы**\n\n- времена жизни проверяется статически на этапе компиляции\n- времена жизни не могут расти, уменьшаться или как-то изменяться во время исполнения\n- компилятор Rust всегда выбирает наименьшее возможное время жизни для переменной, предполагая, что возможны все пути исполнения кода\n\n### 9) ослабление мутабельных ссылок до разделяемых безопасно\n\n**Ошибочные выводы**\n\n- перезаимствование (re-borrowing) ссылки заканчивает её время жизни и начинает новое\n\nВы можете передать mut-ссылку в функцию, ожидающую разделяемую ссылку, потому что Rust неявно перезаимствует mut-ссылку как неизменяемую:\n\n```rust\nfn takes_shared_ref(n: &i32) {}\n\nfn main() {\n    let mut a = 10;\n    takes_shared_ref(&mut a); // компилируется\n    takes_shared_ref(&*(&mut a)); // рассахаренная строка выше\n}\n```\n\nИнтуитивно это понятно, поскольку в повторном заимствовании mut-ссылки как иммутабельной нет ничего страшного, ведь так? На удивление — нет, так как программа ниже не компилируется:\n\n```rust\nfn main() {\n    let mut a = 10;\n    let b: &i32 = &*(&mut a); // перезаимствована как иммутабельная\n    let c: &i32 = &a;\n    dbg!(b, c); // ошибка компиляции\n}\n```\n\nВыдаёт следующую ошибку:\n\n```rust\nerror[E0502]: cannot borrow `a` as immutable because it is also borrowed as mutable\n --> src/main.rs:4:19\n  |\n3 |     let b: &i32 = &*(&mut a);\n  |                     -------- mutable borrow occurs here\n4 |     let c: &i32 = &a;\n  |                   ^^ immutable borrow occurs here\n5 |     dbg!(b, c);\n  |          - mutable borrow later used here\n```\n\nПеременная изменяемо заимствуется, но затем немедленно и безоговорочно перезаимствуется как неизменяемая, а затем ссылка отбрасывается. Почему Rust обращается с неизменяемым повторным заимствованием так, как будто у него все еще есть исключительное время жизни mut-ссылки? Хотя конкретно в приведенном выше примере проблем нет, предоставление возможности ослабления всех mut-ссылок до разделяемых действительно создает потенциальные проблемы безопасного доступа к памяти:\n\n```rust\nuse std::sync::Mutex;\n\nstruct Struct {\n    mutex: Mutex<String>\n}\n\nimpl Struct {\n    // ослабляет мутабельную ссылку на self до разделяемой\n    fn get_string(&mut self) -> &str {\n        self.mutex.get_mut().unwrap()\n    }\n    fn mutate_string(&self) {\n        // если бы Rust разрешал ослабление мутабельных ссылок до разделяемых,\n        // то следующая строка делала бы недействительной все\n        // разделяемые ссылки, возвращённые get_string\n        *self.mutex.lock().unwrap() = \"surprise!\".to_owned();\n    }\n}\n\nfn main() {\n    let mut s = Struct {\n        mutex: Mutex::new(\"string\".to_owned())\n    };\n    let str_ref = s.get_string(); // мутабельная ссылка ослаблена до разделяемой\n    s.mutate_string(); // str_ref инвалидирована, теперь это висячий указатель\n    dbg!(str_ref); // ошибка компиляции, как и ожидалось\n}\n```\n\nДело в том, что когда вы повторно заимствуете mut-ссылку как разделяемую, вы получаете ссылку, но с некоторым подвохом: она продлевает время жизни изначальной ссылки на время перезаимствования, даже если та уже не используется. Использовать перезаимствованную разделяемую ссылку очень сложно, потому что она неизменяемая, но при этом не может пересекаться с другими разделяемыми ссылками. Перезаимствованная разделяемая ссылка имеет все минусы и разделяемой ссылки, и изменяемой, и не имеет плюсов ни той, ни другой. Я считаю, что повторное заимствование мутабельной ссылки как разделяемой должно считаться в Rust анти-паттерном. Знать этот анти-паттерн важно, чтобы вы могли легко заметить его в коде, подобном этому:\n\n```rust\n// ослабляет изменяемый T до разделяемого T\nfn some_function<T>(some_arg: &mut T) -> &T;\n\nstruct Struct;\n\nimpl Struct {\n    // ослабляет мутабельную ссылку на self до разделяемой\n    fn some_method(&mut self) -> &Self;\n\n    // ослабляет мутабельную ссылку на self до разделяемой ссылки на T\n    fn other_method(&mut self) -> &T;\n}\n```\n\nДаже если вы избегаете повторных заимствований в сигнатурах функций и методов, Rust по-прежнему выполняет автоматические неявные повторные заимствования, поэтому с этой проблемой легко можно столкнуться, не распознав её:\n\n```rust\nuse std::collections::HashMap;\n\ntype PlayerID = i32;\n\n#[derive(Debug, Default)]\nstruct Player {\n    score: i32,\n}\n\nfn start_game(player_a: PlayerID, player_b: PlayerID, server: &mut HashMap<PlayerID, Player>) {\n    // получить от сервера игроков или создать и сохранить новых, если их ещё нет\n    let player_a: &Player = server.entry(player_a).or_default();\n    let player_b: &Player = server.entry(player_b).or_default();\n\n    // делаем что-то с игроками\n    dbg!(player_a, player_b); // ошибка компиляции\n}\n```\n\nПример выше не удаётся скомпилировать. `or_default()` возвращает `&mut Player`, который мы неявно повторно заимствуем как `&Player` из-за наших явных аннотаций типов. Чтобы сделать то, что мы хотим, нам приходится делать следующее:\n\n```rust\nuse std::collections::HashMap;\n\ntype PlayerID = i32;\n\n#[derive(Debug, Default)]\nstruct Player {\n    score: i32,\n}\n\nfn start_game(player_a: PlayerID, player_b: PlayerID, server: &mut HashMap<PlayerID, Player>) {\n    // избавляемся от изменяемых ссылок на Player, так как мы всё равно не можем использовать их вместе\n    server.entry(player_a).or_default();\n    server.entry(player_b).or_default();\n\n    // снова получаем доступ к игрокам, на этот раз по неизменяемым ссылкам, без неявных перезаимствований\n    let player_a = server.get(&player_a);\n    let player_b = server.get(&player_b);\n\n    // что-то делаем с игроками\n    dbg!(player_a, player_b); // компилируется\n}\n```\n\nДа, это несколько неловко и неуклюже, но это — жертва, которую мы приносим на Алтарь Безопасной Работы С Памятью.\n\n**Ключевые выводы**\n\n- старайтесь не перезаимствовать mut-ссылки как разделяемые, иначе вы об этом пожалеете\n- повторное заимствование mut-ссылки не заканчивает её время жизни, даже если сама ссылка отброшена\n\n### 10) замыкания следуют тем же правилам вывода времён жизни, что и функции\n\nЭто скорее подвох, нежели заблуждение.\n\nЗамыкания, несмотря на то, что они являются функциями, не следуют тем же правилам вывода времён жизни, что и функции.\n\n```rust\nfn function(x: &i32) -> &i32 {\n    x\n}\n\nfn main() {\n    let closure = |x: &i32| x;\n}\n```\n\nВыдаёт ошибку:\n\n```rust\nerror: lifetime may not live long enough\n --> src/main.rs:6:29\n  |\n6 |     let closure = |x: &i32| x;\n  |                       -   - ^ returning this value requires that `'1` must outlive `'2`\n  |                       |   |\n  |                       |   return type of closure is &'2 i32\n  |                       let's call the lifetime of this reference `'1`\n```\n\nПосле рассахаривания мы получаем:\n\n```rust\n// время жизни аргумента применяется к возвращаемому значению\nfn function<'a>(x: &'a i32) -> &'a i32 {\n    x\n}\n\nfn main() {\n    // аргумент и возвращаемое значение получают разные времена жизни\n    let closure = for<'a, 'b> |x: &'a i32| -> &'b i32 { x };\n    // внимание, строка выше не является корректным синтаксисом Rust, но она требуется для пояснения\n}\n```\n\nДля этого несоответствия нет удовлетворительной причины. Сначала замыкания были реализованы с выводом типов, отличным от функций, и теперь мы застряли с этим навсегда, потому что в наше время унификация их поведения стало бы изменением, ломающим обратную совместимость. Так как же мы можем явно аннотировать тип замыкания? Вот доступные нам варианты:\n\n```rust\nfn main() {\n    // кастуем к трейт-объекту, значение становится безразмерным, упс, ошибка компиляции\n    let identity: dyn Fn(&i32) -> &i32 = |x: &i32| x;\n\n    // можем выделить в куче, но это как-то неуклюже\n    let identity: Box<dyn Fn(&i32) -> &i32> = Box::new(|x: &i32| x);\n\n    // можем не аллоцировать вовсе, а создать статическую ссылку\n    let identity: &dyn Fn(&i32) -> &i32 = &|x: &i32| x;\n\n    // рассахаренная строка выше :)\n    let identity: &'static (dyn for<'a> Fn(&'a i32) -> &'a i32 + 'static) = &|x: &i32| -> &i32 { x };\n\n    // в идеале нам хотелось бы написать так, но это некорректный синтаксис\n    let identity: impl Fn(&i32) -> &i32 = |x: &i32| x;\n\n    // это тоже было бы хорошо, но это также некорректный синтаксис\n    let identity = for<'a> |x: &'a i32| -> &'a i32 { x };\n\n    // так как \"impl trait\" работает в позиции возвращаемого значения\n    fn return_identity() -> impl Fn(&i32) -> &i32 {\n        |x| x\n    }\n    let identity = return_identity();\n\n    // более общая версия предыдущего решения\n    fn annotate<T, F>(f: F) -> F where F: Fn(&T) -> &T {\n        f\n    }\n    let identity = annotate(|x: &i32| x);\n}\n```\n\nУверен, вы уже заметили в приведенных выше примерах, что когда на типы замыканий накладываются ограничения трейтов замыканий, они следуют обычным правилам вывода времён жизни для функций.\n\nТут нет какого-то урока или озарения, оно просто есть.\n\n**Ключевые выводы**\n\n- у каждого языка есть свои проблемы 🤷\n\n### 11) `'static`-ссылки всегда можно привести к `'a`-ссылкам\n\nРанее я показал следующий пример:\n\n```rust\nfn get_str<'a>() -> &'a str; // обобщённая версия\nfn get_str() -> &'static str; // версия со 'static\n```\n\nНекоторые читатели связались со мной, чтобы спросить, существует ли на практике какая-то разница между этими двумя вариантами. Сначала я не был уверен, но после некоторого расследования я могу заявить, что, к сожалению, ответ на это вопрос утвердительный, разница есть.\n\nОбычно, когда мы работаем со значениями, мы можем использовать `'static`-ссылки там, где ожидаются `'a`-ссылки, потому что Rust автоматически приводит `'static`-ссылки к `'a`-ссылкам за нас. Это соответствует нашей интуиции: мы можем использовать долгоживущую ссылку там, где ожидается ссылка с более коротким временем жизни, и это не приведёт ни к каким проблемам. Программа ниже, как и ожидалось, компилируется.\n\n```rust\nuse rand;\n\nfn generic_str_fn<'a>() -> &'a str {\n    \"str\"\n}\n\nfn static_str_fn() -> &'static str {\n    \"str\"\n}\n\nfn a_or_b<T>(a: T, b: T) -> T {\n    if rand::random() {\n        a\n    } else {\n        b\n    }\n}\n\nfn main() {\n    let some_string = \"string\".to_owned();\n    let some_str = &some_string[..];\n    let str_ref = a_or_b(some_str, generic_str_fn()); // компилируется\n    let str_ref = a_or_b(some_str, static_str_fn()); // компилируется\n}\n```\n\nОднако это приведение не работает, когда ссылки являются частью сигнатуры функции, поэтому этот код не компилируется:\n\n```rust\nuse rand;\n\nfn generic_str_fn<'a>() -> &'a str {\n    \"str\"\n}\n\nfn static_str_fn() -> &'static str {\n    \"str\"\n}\n\nfn a_or_b_fn<T, F>(a: T, b_fn: F) -> T\n    where F: Fn() -> T\n{\n    if rand::random() {\n        a\n    } else {\n        b_fn()\n    }\n}\n\nfn main() {\n    let some_string = \"string\".to_owned();\n    let some_str = &some_string[..];\n    let str_ref = a_or_b_fn(some_str, generic_str_fn); // компилируется\n    let str_ref = a_or_b_fn(some_str, static_str_fn); // ошибка компиляции\n}\n```\n\nИ выдаёт эту ошибку компиляции:\n\n```rust\nerror[E0597]: `some_string` does not live long enough\n  --> src/main.rs:23:21\n   |\n23 |     let some_str = &some_string[..];\n   |                     ^^^^^^^^^^^ borrowed value does not live long enough\n...\n25 |     let str_ref = a_or_b_fn(some_str, static_str_fn);\n   |                   ---------------------------------- argument requires that `some_string` is borrowed for `'static`\n26 | }\n   | - `some_string` dropped here while still borrowed\n```\n\nЯвляется ли это подвохом или нет — вопрос спорный, так как это не простой прямолинейный случай приведения `&'static str` к `&'a str`, а приведение `for<T> Fn() -> &'static T` к `for<'a, T> Fn() -> &'a T`. Первое — это приведение между значениями, а второе — это приведение между типами.\n\n**Ключевые выводы**\n\n- функции с сигнатурами вида `for<'a, T> fn() -> &'a T` являются более гибкими и работают в большем числе случаев, чем функции с сигнатурами вида `for<T> fn() -> &'static T`\n\n## Заключение\n\n- `T` является надмножеством как `&T`, так и `&mut T`\n- `&T` и `&mut T` являются непересекающимися множествами\n- `T: 'static` должно читаться, как *« `T` ограничен временем жизни `'static`»*\n- если `T: 'static`, то `T` может быть заимствованным типом с временем жизни `'static` *или* владеющим типом.\n- поскольку `T: 'static` включает в себя владеющие типы, это означает, что `T`\n    - может быть динамически создан во время исполнения\n    - не обязан существовать на протяжении всего времени работы программы\n    - может быть безопасно изменён без каких-либо ограничений\n    - может быть динамически уничтожен во время исполнения\n    - может иметь время жизни произвольной продолжительности\n- `T: 'a` является более общим и более гибким типом, чем `&'a T`\n- `T: 'a` принимает владеющие типы, владеющие типы, которые содержат ссылки, и ссылки\n- `&'a T` принимает только ссылки\n- если `T: 'static`, то `T: 'a`, так как `'static` >= `'a` для всех `'a`\n- почти весь код на Rust является обобщённым кодом, и повсюду есть выведенные аннотации времён жизни\n- правила вывода времён жизни Rust не всегда подходят к конкретной ситуации\n- Rust не знает о семантике вашей программы больше, чем вы\n- давайте вашим аннотациям времён жизни осмысленные имена\n- старайтесь понимать, где вы размещаете явные аннотации времён жизни и почему\n- все трейт-объекты имеют определенные выведенные ограничения времён жизни по умолчанию\n- сообщения об ошибках компиляции Rust предлагают исправления, которые приведут к успешной компиляции вашей программы, но это не то же самое, что и исправления, которые заставят вашу программу успешно компилироваться *и одновременно* наилучшим образом соответствуют требованиям вашей программы.\n- времена жизни проверяется статически на этапе компиляции\n- времена жизни не могут расти, уменьшаться или изменяться каким-либо образом в рантайме\n- анализатор заимствований Rust всегда выбирает наименьшее возможное время жизни для переменной, предполагая, что все пути исполнения кода возможны\n- старайтесь не перезаимствовать изменяемые ссылки как разделяемые, иначе вы об этом пожалеете\n- повторное заимствование mut-ссылки не заканчивает её время жизни, даже если сама ссылка уничтожена\n- у каждого языка есть свои проблемы 🤷\n- функции с сигнатурами вида `for<'a, T> fn() -> &'a T` являются более гибкими и работают в большем числе случаев, чем функции с сигнатурами вида `for<T> fn() -> &'static T`\n\n## Обсуждение\n\nОбсудите эту статью на\n\n- [субреддите learnrust](https://www.reddit.com/r/learnrust/comments/gmrcrq/common_rust_lifetime_misconceptions/)\n- [официальном форуме пользователей Rust](https://users.rust-lang.org/t/blog-post-common-rust-lifetime-misconceptions/42950)\n- [Twitter](https://twitter.com/pretzelhammer/status/1263505856903163910)\n- [субреддите Rust](https://www.reddit.com/r/rust/comments/golrsx/common_rust_lifetime_misconceptions/)\n- [Hackernews](https://news.ycombinator.com/item?id=23279731)\n\n## Дальнейшее чтение\n\n- [Размерность в Rust](./../../sizedness-in-rust.md)\n- [Изучение Rust в 2020 году](./../../learning-rust-in-2020.md)\n"
  },
  {
    "path": "posts/translations/tr/why-blog.md",
    "content": "# Neden Blog?\n\n_02 May 2020 · #blogging_\n\nRust'ı öğrenme sürecinde kavramları anlamlandırmaya ve düzene sokmaya çalışıyordum bu yüzden bilgilerimi markdown dosyalarına yazazarak düzenlemeye çalıştım. Az zamanda birkaç markdown dosyası oldu. Aklımda _\"Belki blog yazmalıyım\"_ fikri oluştu fakat düşündüm ki _\"Belki de yazmamalıyım, yazdıklarım hiçbir zaman Niko Matsakis, Saoirse Shipwreckt, Huon Wilson, David Tolnay, Alexis Beingessner, Daniel Keep, Carl Fredrik Samson, Aleksey Kladov, Amos Wegner, Pascal Hertleif, Dimitri Sabadie, Daniel Henry-Mantilla, Steve Klabnik, Jake Goulding, veya Carol Nichols gibi isimlerin Rust hakkında yazdıkları herhangi bir şey kadar iyi olmayacak\"_. Bu isimler tamamı bile değil, bunların dışında daha saymadığım bir düzine insan var. Zaten Rust hakkında yazmış bir sürü süper zeka adam var. Neyse ki bende bu insanların sahip olmadığı bir avantaj var: Ben aptalım! Süper zeki adamlar sadece süper zeki adamların anlayabileceği makaleler yazıyor. Biz aptallar için piyasada boşluk var ve bu boşluğu yazılarımla doldurmaya niyet ettim.\n\nAyrıca oldukça cesaretlendirici bu karikatürü gördüm:\n\n![holy shit two cakes](../assets/holy-shit-two-cakes.png)\n\n_Artist credit: [stuffman](https://stuffman.tumblr.com/)_\n\n## Tamam ama senin blogun neden websitede değil de Github'da?\n\nMesleğim full-stack webdev bu yüzden söz konusu website olduğunda _aşırı titiz_ olurum. Teknik detaylarda boğulurum ve _mükemmel bir website_ oluşturmaya çalışırken asıl yazmam gerekeni yazamam. Teknik meseleleri %90 halleden [yüzlerce, site oluşturucusu](https://www.staticgen.com/) olduğunu biliyorum fakat önceden denedim ve memnun kalmadım. Bu, araçların kötü olduğundan değil hatta bir çoğu mükemmel araçlar. Ben bir sanatçıyım ve kendi yapmadığım bir iş içime sinmiyor. Biliyorum, bu bir problem. \n\nNeredeyse blog yazma fikrimden vazgeçecektim ta ki bunla karşılaşıncaya dek [Frank McSherry's blog](https://github.com/frankmcsherry/blog). Bunu yapmayı daha önce nasıl akıl edemedim. Herhangi bir şeyi build, deploy ya da render etmeye gerek yok! Markdown dosyalarını Github'a yüklüyorsun ve insanlar Github üzerinden sadece okuyor onları. Çok basit, bunu sevdim. Bunu kendi blogumu yazarken kullanmaya karar verdim böylece bütün enerjimi asıl yazmam gereken konuya verebilirdim.\n\nSon bir not: Blog tamamen Rust hakkında olacak. Bu başlangıç yazısı hariç blog boyunca kişisel bir yazı görmeyeceksiniz.\n\n## Further Reading\n\n- [Common Rust Lifetime Misconceptions](./common-rust-lifetime-misconceptions.md)\n- [Tour of Rust's Standard Library Traits](./tour-of-rusts-standard-library-traits.md)\n- [Sizedness in Rust](./sizedness-in-rust.md)\n- [RESTful API in Sync & Async Rust](./restful-api-in-sync-and-async-rust.md)\n- [Learning Rust in 2020](./learning-rust-in-2020.md)\n- [Learn Assembly with Entirely Too Many Brainfuck Compilers](./too-many-brainfuck-compilers.md)\n"
  },
  {
    "path": "posts/translations/zh-hans/chat-server.md",
    "content": "# 并发编程新手指南: 使用Tokio实现多线程聊天服务器\n\n_2024年5月4日 · #rust · #async · #concurrency · #tokio_\n\n![聊天服务器演示](../../../assets/chat-server-demo.gif)\n\n<details>\n<summary><b>目录</b></summary>\n\n[导读](#introduction)<br>\n[01\\) 最简单的回显服务器](#01-最简单的回显服务器)<br>\n[02\\) 串行处理多个连接](#02-串行处理多个连接)<br>\n[03\\) 修改消息](#03-修改消息)<br>\n[04\\) 将字节流解析为行](#04-将字节流解析为行)<br>\n[05\\) 服务器增加`/help`和`/quit`命令](#05-服务器增加help和quit命令)<br>\n[06\\) 并发处理多个连接](#06-并发处理多个连接)<br>\n[07\\) 让用户聊天](#07-让用户聊天)<br>\n[08\\) 让用户真正的聊天](#08-让用户真正的聊天)<br>\n[09\\) 为用户分配名称](#09-为用户分配名称)<br>\n[10\\) 使用`/name`命令编辑自己的名字](#10-使用name命令编辑自己的名字)<br>\n[11\\) 在客户端断开连接时释放用户名](#11-在客户端断开连接时释放用户名)<br>\n[12\\) 增加`main`聊天室](#12-增加main聊天室)<br>\n[13\\) 使用`/join`加入或创建聊天室](#13-使用join加入或创建聊天室)<br>\n[14\\) 使用`/rooms`列出所有聊天室](#14-使用rooms列出所有聊天室)<br>\n[15\\) 删除空聊天室](#15-删除空聊天室)<br>\n[16\\) 使用`/users`命令列出当前聊天室的用户](#16-使用users命令列出当前聊天室的用户)<br>\n[17\\) 性能优化](#17-性能优化)<br>\n[18\\) 收尾工作](#18-收尾工作)<br>\n[结论](#结论)<br>\n[讨论](#讨论)<br>\n[进一步阅读](#进一步阅读)<br>\n\n</details>\n\n## Introduction\n\n我最近使用 `tokio` 编写了一个多线程聊天服务器，我对此很满意。我想通过这篇易于理解、循序渐进的教程分享我学到的东西，让我们开始吧。\n\n> [!NOTE]\n> 每一步的源代码都在 [这个仓库](https://github.com/pretzelhammer/chat-server) 的 [examples 目录](https://github.com/pretzelhammer/chat-server/tree/main/examples) 找到。\n\n## 01\\) 最简单的回显服务器\n\n让我们开始写一个最简单的回显服务器。\n\n```rust\nuse tokio::{io::{AsyncReadExt, AsyncWriteExt}, net::TcpListener};\n\n#[tokio::main]\nasync fn main() -> anyhow::Result<()> {\n    let server = TcpListener::bind(\"127.0.0.1:42069\").await?;\n    let (mut tcp, _) = server.accept().await?;\n    let mut buffer = [0u8; 16];\n    loop {\n        let n = tcp.read(&mut buffer).await?;\n        if n == 0 {\n            break;\n        }\n        let _ = tcp.write(&buffer[..n]).await?;\n    }\n    Ok(())\n}\n```\n\n`#[tokio::main]` 是一个过程宏，它可以自动生成 `tokio` 运行时所需的重复性代码, 如下的代码:\n\n```rust\n#[tokio::main]\nasync fn my_async_fn() {\n    todo!()\n}\n```\n\n大致等同于转换成这样:\n\n```rust\nfn main() {\n    tokio::runtime::Builder::new_multi_thread()\n        .enable_all()\n        .build()\n        .unwrap()\n        .block_on(my_async_fn)\n}\n\nasync fn my_async_fn() {\n    todo!()\n}\n```\n\n快速回顾一下，如果我们有一个如下的异步函数:\n\n```rust\nasync fn my_async_fn<T>(t: T) -> T {\n    todo!()\n}\n```\n\n可以转换为:\n\n```rust\nfn my_async_fn<T>(t: T) -> impl Future<Output = T> {\n    todo!()\n}\n```\n\n`Future` 表示某种形式的异步计算，我们可以使用 `await` 获取其结果。\n\n我们使用 `anyhow` 模块进行优雅的错误传播。在任何想要返回 `Result<T, Box<dyn std::err::Error>>` 的地方，我们可以使用 `anyhow::Result<T>` 优雅替代。\n\n下面这一行代码我们绑定了一个IP地址，创建了一个TCP监听器：\n\n```rust\nlet server = TcpListener::bind(\"127.0.0.1:42069\").await?;\n```\n\n> [!IMPORTANT]\n> 这里使用 `tokio::net::TcpListener` 而不是 `std::net::TcpListener`。前者是异步，后者是同步。调用异步 `bind` 返回一个 `Future` ，因为在Rust中 `Future` 是惰性的，所以我们 **必须调用** `await` ，否则该代码不会执行!\n\n一个经验法则，如果在 `tokio` 和 `std` 中都有相同名称的处理 IO 的类型，我们应该使用 `tokio` 中的。\n\n其余的代码简单明了:\n\n```rust\nlet (mut tcp, _) = server.accept().await?;\nlet mut buffer = [0u8; 16];\nloop {\n    let n = tcp.read(&mut buffer).await?;\n    if n == 0 {\n        break;\n    }\n    let _ = tcp.write(&buffer[..n]).await?;\n}\n```\n\n我们接受一个连接，创建一个缓冲区，然后循环从连接中读取数据到缓存后再将缓存数据写回连接，直至连接关闭。\n\n我们可以使用类似 `telnet` 工具连接服务器，查看服务器回显我们输入的数据：\n\n```console\n$ telnet 127.0.0.1 42069\n> my first e c h o server!\nmy first e c h o server!\n> hooray!\nhooray!\n```\n\n> [!TIP]\n> 退出 `telnet` 需要按下 `^]` (Ctrl + 右方括号) 进入命令模式，然后输入 `quit` 回车即可.\n\n如果你想要探索代码可以 `git clone` [这个仓库](https://github.com/pretzelhammer/chat-server) ，然后通过 `just example {number}` 命令运行指定的例子。 你也可以修改 `examples/server-{number}.rs` 中的源代码。一旦例子运行后，可以使用 `just telnet` 命令和例子进行交互。\n\n译注：要使用just命令，先要 [安装just](https://github.com/casey/just/blob/master/README.%E4%B8%AD%E6%96%87.md) 。\n\n## 02\\) 串行处理多个连接\n\n上面的代码中有一个烦人的bug，一旦处理完一个连接后服务器就退出了！接下来我们执行 `just telnet` 将会得到 `telnet: Unable to connect to remote host: Connection refused` 的错误，这时候我们需要执行 `just example 01` 命令手动重启服务器程序。 🤦\n\n下面我们将修复这个bug:\n\n```rust\nuse tokio::{io::{AsyncReadExt, AsyncWriteExt}, net::TcpListener};\n\n#[tokio::main]\nasync fn main() -> anyhow::Result<()> {\n    let server = TcpListener::bind(\"127.0.0.1:42069\").await?;\n    loop {\n        let (mut tcp, _) = server.accept().await?;\n        let mut buffer = [0u8; 16];\n        loop {\n            let n = tcp.read(&mut buffer).await?;\n            if n == 0 {\n                break;\n            }\n            let _ = tcp.write(&buffer[..n]).await?;\n        }\n    }\n}\n```\n\n非常简单，我们只需要加一个 `loop` 包裹 `server.accept()` 行！现在我们执行 `just example 02` 运行更新后的服务器程序，无论我们连续执行多少次 `just telnet` ，服务器都会保持正常运行。\n\n## 03\\) 修改消息\n\n当前回显服务器很好了，但是能以某种方式修改消息那就更棒了。我们尝试在每一条回显消息行尾增加一个 ❤️ 表情怎么样？ 代码如下:\n\n```rust\nuse tokio::{io::{AsyncReadExt, AsyncWriteExt}, net::TcpListener};\n\n#[tokio::main]\nasync fn main() -> anyhow::Result<()> {\n    let server = TcpListener::bind(\"127.0.0.1:42069\").await?;\n    loop {\n        let (mut tcp, _) = server.accept().await?;\n        let mut buffer = [0u8; 16];\n        loop {\n            let n = tcp.read(&mut buffer).await?;\n            if n == 0 {\n                break;\n            }\n            // convert byte slice to a String\n            let mut line = String::from_utf8(buffer[..n].to_vec())?;\n            // remove line terminating chars added by telnet\n            line.pop(); // remove \\n char\n            line.pop(); // remove \\r char\n            // add our own line terminator :)\n            line.push_str(\" ❤️\\n\");\n            let _ = tcp.write(line.as_bytes()).await?;\n        }\n    }\n}\n```\n\n令人激动的回显服务器演示:\n\n```console\n$ just telnet\n> hello\nhello ❤️\n> it works!\nit works! ❤️\n```\n\n但是，当我们写一个长的消息，我们就会发现bug：\n\n```console\n> this is the best day ever!\nthis is the be ❤️\n day ever ❤️\n```\n\n啊哈! 可能有人会说这个很容易，我们可以增加缓冲区的大小，但是增加多少呢？我们可以使用像 `Vec` 这样动态增长的缓冲区，但是如果客户端发送了一个**非常非常长的行**怎么办？我们需要解决这些问题，由于这是一个通用性问题，所以可以从其他人那里找到对应的解决方案。\n\n## 04\\) 将字节流解析为行\n\nTokio在 `tokio-util` 模块提供的方便可靠的解决方案，我们可以这样使用：\n\n```rust\nuse futures::{SinkExt, StreamExt};\nuse tokio::net::TcpListener;\nuse tokio_util::codec::{FramedRead, FramedWrite, LinesCodec};\n\n#[tokio::main]\nasync fn main() -> anyhow::Result<()> {\n    let server = TcpListener::bind(\"127.0.0.1:42069\").await?;\n    loop {\n        let (mut tcp, _) = server.accept().await?;\n        let (reader, writer) = tcp.split();\n        let mut stream = FramedRead::new(reader, LinesCodec::new());\n        let mut sink = FramedWrite::new(writer, LinesCodec::new());\n        while let Some(Ok(mut msg)) = stream.next().await {\n            msg.push_str(\" ❤️\");\n            sink.send(msg).await?;\n        }\n    }\n}\n```\n\n这个例子中有很多新东西。 `split` 方法将 `TcpStream` 拆分为 `ReadHalf` 和 `WriteHalf`。 这对想要把读写两个部分添加到不同的结构、或者发送给不同线程、或者并发的读写 `TcpStream` 的情况将非常有用（我们后面将要做的）。\n\n`ReadHalf` 实现了 `AsyncRead` ， `WriteHalf` 实现了 `AsyncWrite`, 然而正如之前所述，直接使用这些方法会比较繁琐且容易出错，所以这里使用了编解码中的 `LinesCodec`、 `FramedRead` 和 `FramedWrite`。\n\n`LinesCodec` 处理底层细节将字节流转换为换行分隔的 `UTF-8` 的字符串，并与 `FramedRead` 一起使用，我们可以包装 `ReadHalf` 实现 `Stream<Item = Result<String, _>>`，这比 `AsyncRead` 更容易使用。`Stream` 就像是 `Iterator` 的异步版本。举个例子，假如我们有一个如下同步的函数：\n\n```rust\nfn iterate<T>(items: impl Iterator<Item = T>) {\n    for item in items {\n        todo!()\n    }\n}\n```\n\n重构后的异步版本是：\n\n```rust\nuse futures::{Stream, StreamExt};\n\nasync fn iterate<T>(mut items: impl Stream<Item = T> + Unpin) {\n    while let Some(item) = items.next().await {\n        todo!()\n    }\n}\n```\n\n同样，我们使用 `LinesCodec` 和 `FramedWrite` 包装 `WriteHalf` 获得 `Sink<String, Error = _>` 的实现，它比 `AsyncWrite` 更易使用。正如你猜测的那样， `Sink` 是 `Stream` 的反操作, 它消耗数据而不是生产数据。\n\n剩余的代码非常简单：\n\n```rust\nwhile let Some(Ok(mut msg)) = stream.next().await {\n    msg.push_str(\" ❤️\");\n    sink.send(msg).await?;\n}\n```\n\n我们从流中获取消息，然后在行末增加一个❤️表情，最后发送到接收端。如果我们要更花哨一点，可以将流映射并将其转发到接收端，就像这样：\n\n```rust\nstream.map(|msg| {\n    let mut msg = msg?;\n    msg.push_str(\" ❤️\");\n    Ok(msg)\n}).forward(sink).await?\n```\n\n`forward` 返回 `Future` ，当 `Stream` 处理完成后转换为 `Sink`，且 `Sink` 关闭和刷新后，该 `Future` 完成。\n\n现在，无论我们的消息长度是多少，我们都能正确的在收到的消息尾部添加一个爱心表情：\n\n```console\n$ just telnet\n> this is a really really really long message kinda\nthis is a really really really long message kinda ❤️\n```\n\n## 05\\) 服务器增加`/help`和`/quit`命令\n\n`Telnet` 退出比较烦人。通常使用的技巧如 `esc`, `^C`, 和 `^D` 都不起作用。我们必须按下 `^]` 进入命令模式，然后输入 `quit` 回车才能退出。🤦\n\n我们可以通过自定义命令实现服务器更用户友好，从 `/help` 和 `/quit`命令开始。 `/help` 将打印服务器支持的命令列表及说明，`/quit` 将导致服务器关闭本连接（从而使得telnet退出）。\n\n这些命令使用方法是在客户端连接之后立即发送给客户端，以便用户知道。下面是所有代码：\n\n```rust\nuse futures::{SinkExt, StreamExt};\nuse tokio::net::TcpListener;\nuse tokio_util::codec::{FramedRead, FramedWrite, LinesCodec};\n\nconst HELP_MSG: &str = include_str!(\"help.txt\");\n\n#[tokio::main]\nasync fn main() -> anyhow::Result<()> {\n    let server = TcpListener::bind(\"127.0.0.1:42069\").await?;\n    loop {\n        let (mut tcp, _) = server.accept().await?;\n        let (reader, writer) = tcp.split();\n        let mut stream = FramedRead::new(reader, LinesCodec::new());\n        let mut sink = FramedWrite::new(writer, LinesCodec::new());\n        // send list of server commands to\n        // the user as soon as they connect\n        sink.send(HELP_MSG).await?;\n        while let Some(Ok(mut msg)) = stream.next().await {\n            // handle new /help command\n            if msg.starts_with(\"/help\") {\n                sink.send(HELP_MSG).await?;\n            // handle new /quit command\n            } else if msg.starts_with(\"/quit\") {\n                break;\n            // handle regular message\n            } else {\n                msg.push_str(\" ❤️\");\n                sink.send(msg).await?;\n            }\n        }\n    }\n}\n```\n\n让我们来试试看：\n\n```console\n$ just telnet\nServer commands\n  /help - prints this message\n  /quit - quits server\n> /help # new command\nServer commands\n  /help - prints this message\n  /quit - quits server\n> woohoo it works\nwoohoo it works ❤️\n> /quit # new command\nConnection closed by foreign host.\n```\n\n## 06\\) 并发处理多个连接\n\n现在我们服务器最大的问题是一次只能处理一个连接！如果我们在两个不同的终端运行 `just telnet` ，可以看到服务器只会响应第一个连接的请求，直到第一个连接退出才会响应第二个连接。尽管我们已经使用了大量的异步API，但是目前实现和同步单线程没有区别。让我们来改变一下：\n\n```rust\nuse futures::{SinkExt, StreamExt};\nuse tokio::net::{TcpListener, TcpStream};\nuse tokio_util::codec::{FramedRead, FramedWrite, LinesCodec};\n\nconst HELP_MSG: &str = include_str!(\"help.txt\");\n\n#[tokio::main]\nasync fn main() -> anyhow::Result<()> {\n    let server = TcpListener::bind(\"127.0.0.1:42069\").await?;\n    loop {\n        let (tcp, _) = server.accept().await?;\n        // spawn a separate task for\n        // to handle every connection\n        tokio::spawn(handle_user(tcp));\n    }\n}\n\nasync fn handle_user(mut tcp: TcpStream) -> anyhow::Result<()> {\n    let (reader, writer) = tcp.split();\n    let mut stream = FramedRead::new(reader, LinesCodec::new());\n    let mut sink = FramedWrite::new(writer, LinesCodec::new());\n    sink.send(HELP_MSG).await?;\n    while let Some(Ok(mut msg)) = stream.next().await {\n        if msg.starts_with(\"/help\") {\n            sink.send(HELP_MSG).await?;\n        } else if msg.starts_with(\"/quit\") {\n            break;\n        } else {\n            msg.push_str(\" ❤️\");\n            sink.send(msg).await?;\n        }\n    }\n    Ok(())\n}\n```\n\n`tokio::spawn` 接受一个 `Future` 并生成一个异步任务来执行。执行是立即开始，我们不需要像在`Future`那样在返回的join句柄使用 `await` 调用。一个任务和一个线程一样，区别是线程是由操作系统管理，而任务是由 `tokio` 管理。你可能已经通过其它的名词知道这个概念： 轻量级线程、绿色线程、用户空间线程。\n\n## 07\\) 让用户聊天\n\n现在正式开始，我们升级回显服务器为聊天服务器，让独立的并发连接相互通信。\n\n> [!NOTE]\n> 代码开始变得冗长且复杂，下面所有代码将重点突出关键修改，但是你仍可以在 [这个仓库](https://github.com/pretzelhammer/chat-server) 的 [examples目录](https://github.com/pretzelhammer/chat-server/tree/main/examples) 找到所有代码。通过运行 `just diff {number} {number}` 来查看两个示例之间的差异。例如，运行`just diff 06 07` 查看这个示例和上一个示例之间的差异。\n\n```rust\n// ...\nasync fn main() -> anyhow::Result<()> {\n    // ...\n    // create broadcast channel\n    let (tx, _) = broadcast::channel::<String>(32);\n    // ...\n    // clone it for every connected client\n    tokio::spawn(handle_user(tcp, tx.clone()));\n}\n\nasync fn handle_user(\n    mut tcp: TcpStream,\n    tx: Sender<String>\n) -> anyhow::Result<()> {\n    // ...\n    // get a receiver from the sender\n    let mut rx = tx.subscribe();\n    // ...\n    while let Some(Ok(mut user_msg)) = stream.next().await {\n        // ...\n        // send all messages to the channel\n        tx.send(user_msg)?;\n        // ...\n        // receive all of our and others'\n        // messages from the channel\n        let peer_msg = rx.recv().await?;\n        sink.send(peer_msg).await?;\n    }\n    // ...\n}\n```\n\n我们在不同客户端之间使用广播通道进行通信。在创建通道后，我们得到一个发送者 `Sender` 和一个接收者 `Receiver` ，我们可以调用任意次数的 `clone` 来克隆它并将其发送给不同线程。每一个通过`Sender` 发送和 `Receiver` 接收的值的类型都需要实现 `Clone` 特性。\n\n在此之前，我们从客户端的流获取消息并立即写到客户端接收端。现在，当我们从客户端的流获取消息后，我们通过广播通道将其传递，然后再通过广播通道取回并发送给客户端接收端。每一个客户端都会从共享通道中收到它自己的以及其它的客户端发送的消息。\n\n让我们通过同时连接两个客户端来尝试我们的新代码：\n\n```console\n$ just telnet # concurrent client 1\n> 1: hello # msg 1\n1: hello ❤️\n> 1: anybody there? # msg 2\n1: anybody there? ❤️\n\n$ just telnet # concurrent client 2\n> 2: hey there # msg 3\n1: hello ❤️\n> 2: how are you # msg 4\n1: anybody there? ❤️\n> 2: i am right here # msg 5\n2: hey there ❤️\n> 2: wtf # msg 6\n2: how are you ❤️\n```\n\n每一个客户端都可以看到彼此发送的消息，但是由于某些原因，目前看起来好像有点延迟和错乱，应该是某个地方不对。\n\n代码中的bug如下：\n\n```rust\n// the client must first send a message\nwhile let Some(Ok(mut user_msg)) = stream.next().await {\n    // in order to receive a message\n    let peer_msg = rx.recv().await?;\n    // and these two things always alternate\n}\n```\n\n为了接收对端消息，我们必须首先发送一个消息。如果我们是一个潜水者呢？又或者对方更健谈呢？另一方面，如果我们更健谈，那么我们主要看到自己的回显消息，几乎看不到对方发送的消息。\n\n为了解决这个问题，我们需要能够同时 `await` 两个 `Future` 。在这种情况下，一个是从 `stream.next()` 用于获取客户端的发送的消息, 另外一个从 `rx.recv()` 用于通道发来的消息。\n\n## 08\\) 让用户真正的聊天\n\n`tokio::select!` 让我们同时探询多个 `Future` ：\n\n```rust\nasync fn handle_user(\n    mut tcp: TcpStream,\n    tx: Sender<String>\n) -> anyhow::Result<()> {\n    // ...\n    loop {\n        tokio::select! {\n            user_msg = stream.next() => {\n                // ...\n            },\n            peer_msg = rx.recv() => {\n                // ...\n            },\n        }\n    }\n    // ...\n}\n```\n\n我们执行先完成的分支，其它将被抛弃。\n\n现在，如果我们尝试我们服务器：\n\n```console\n$ just telnet # concurrent client 1\n> 1: hello # msg 1\n1: hello ❤️\n> 1: anybody there? # msg 2\n1: anybody there? ❤️\n2: i am right here ❤️\n2: how are you ❤️\n> 1: i am doing great # msg 5\n\n$ just telnet # concurrent client 2\n1: hello ❤️\n1: anybody there? ❤️\n> 2: i am right here # msg 3\n2: i am right here ❤️\n> 2: how are you? # msg 4\n2: how are you ❤️\n1: i am doing great ❤️\n```\n\n可以工作！先别庆祝，我们需要考虑安全取消。如之前所述，Rust的 `Future` 是惰性的，它只有在 `poll` 的时候才会执行。`poll` 和 `await` 有点不同。`await` 一个 `Future` 意味着要 `poll` 直至完成，而 `poll` 一个 `Future` 意味着它取得一些进展，但不一定是完成。\n\n译注：`poll` 取得一些进展是指状态机发生变化即 `Pending` 状态，而状态机完成是指 `Ready` 状态。\n\n一方面，这个功能很棒，因为我们开始 `poll` 一个 `Future` 随后可以决定不再需要等待其最终结果，我们可以停止`poll`从而不会浪费CPU做无效的工作。另一方面，这个功能在某些场景下会有危险，比如我们在一个 `Future` 正在执行重要操作的中途取消它，这时候如果执行没有完成,会造成数据的丢失；或者让数据处于损坏状态。\n\n让我们看一个取消`Future`的例子。取消并不是一个显式的操作，它只是意味着我们开始轮询一个`Future`，但是在完成之前就停止了轮询。\n\n```rust\nuse tokio::time::sleep;\nuse std::time::Duration;\n\nasync fn count_to(num: u8) {\n    for i in 1..=num {\n        sleep(Duration::from_millis(100)).await;\n        println!(\"{i}\");\n    }\n}\n\n#[tokio::main]\nasync fn main() {\n    println!(\"start counting\");\n    // the select! macro polls each\n    // future until one of them completes,\n    // and then we execute the match arm\n    // of the completed future and drop\n    // all of the other futures\n    tokio::select! {\n        _ = count_to(3) => {\n            println!(\"counted to 3\");\n        },\n        _ = count_to(10) => {\n            println!(\"counted to 10\");\n        },\n    };\n    println!(\"stop counting\");\n    // this sleep is here to demonstrate\n    // that the count_to(10) doesn't make\n    // any progress after we stop polling\n    // it, even if we go to sleep and do\n    // nothing else for a while\n    sleep(Duration::from_millis(1000)).await;\n}\n```\n\n上述程序输出结果：\n\n```\nstart counting\n1\n1\n2\n2\n3\n3\ncounted to 3\nstop counting\n```\n\n上述我们取消了 `count_to(10)` 的`Future`. 在这个简单示例中，如果我们不关心计数是否完成那么这个`Future`取消就是安全的，如果完成计数对应用程序至关重要，那么取消操作就是有问题的。为了保证`Future`完成，我们在`tokio::select!`之后使用`await`：\n\n```rust\n// ...\nasync fn main() {\n    println!(\"start counting\");\n    let count_to_10 = count_to(10);\n    tokio::select! {\n        _ = count_to(3) => {\n            println!(\"counted to 3\");\n        },\n        _ = count_to_10 => { // ❌\n            println!(\"counted to 10\");\n        },\n    };\n    println!(\"stop counting\");\n    println!(\"jk, keep counting\");\n    count_to_10.await; // ❌\n    println!(\"finished counting to 10\");\n}\n```\n\nThrows:\n\n```\nerror[E0382]: use of moved value: count_to_10\n```\n\n糟糕，我们犯了书中最常见的错误，试图使用已经移动的值，改成可变引用：\n\n```rust\n// ...\nasync fn main() {\n    println!(\"start counting\");\n    let count_to_10 = count_to(10);\n    tokio::select! {\n        _ = count_to(3) => {\n            println!(\"counted to 3\");\n        },\n        _ = &mut count_to_10 => { // ❌\n            println!(\"counted to 10\");\n        },\n    };\n    println!(\"stop counting\");\n    println!(\"jk, keep counting\");\n    count_to_10.await;\n    println!(\"counted to 10\");\n}\n```\n\n现在抛出如下异常:\n\n```\nerror[E0277]: {async fn body@src/main.rs:23:28: 28:2}\n              cannot be unpinned\n   -> src/main.rs:34:5\n   |\n23 |   async fn count_to(num: u8) {\n   |   ----------------- within this impl futures::Future<Output = ()>\n...\n34 | /     tokio::select! {\n35 | |         _ = count_to(3) => {\n36 | |             println!(\"counted to 3\");\n37 | |         },\n...  \n41 | |     };\n   | |     ^\n   | |     |\n   | |_____within impl futures::Future<Output = ()>,\n   |       the trait Unpin is not implemented for\n   |       {async fn body@src/main.rs:23:28: 28:2},\n   |       which is required by &mut impl\n   |       futures::Future<Output = ()>: futures::Future\n   |       required by a bound introduced by this call\n   |\n   = note: consider using the pin! macro\n           consider using Box::pin if you need to access\n           the pinned value outside of the current scope\n```\n\n我们需要固定`Future`，按编译器建议进行修改：\n\n```rust\n#[tokio::main]\nasync fn main() {\n    println!(\"start counting\");\n    let count_to_10 = count_to(10);\n    tokio::pin!(count_to_10); // ✔️\n    tokio::select! {\n        _ = count_to(3) => {\n            println!(\"counted to 3\");\n        },\n        _ = &mut count_to_10 => {\n            println!(\"counted to 10\");\n        },\n    };\n    println!(\"stop counting\");\n    println!(\"jk, keep counting\");\n    count_to_10.await;\n    println!(\"finished counting to 10\");\n}\n```\n\n编译后运行输出：\n\n```\nstart counting\n1\n1\n2\n2\n3\n3\ncounted to 3\nstop counting\njk, keep counting\n4\n5\n6\n7\n8\n9\n10\nfinished counting to 10\n```\n\n在Rust中，`pin` 就是将其内存位置固定。一旦它被固定就不能移动，`Future` 在 `poll` 前需要固定的原因是其底层可能包含自引用指针，一旦 `Future` 移动，这些指针将会失效。\n\n如果最后一部分你暂时不理解也没关系，我也不是完全理解。不用担心，当这类问题出现时，我们可以遵从一个通用算法来解决：\n\n**1\\)** 如果我们写的泛型代码使用 `Future` 或产生 `Future` ，我们可以在trait的边界上增加 `+ Unpin` ，如下面的例子不会被编译：\n\n```rust\nuse futures::{Stream, StreamExt};\n\nasync fn iterate<T>(\n    mut items: impl Stream<Item = T>\n) {\n    while let Some(item) = items.next().await { // ❌\n        todo!()\n    }\n}\n```\n\n抛出异常：\n\n```\nerror[E0277]: impl Stream<Item = T> cannot be unpinned\n```\n\n但是我们将`Unpin`添加到函数签名中，它就可以正常工作了：\n\n```rust\nasync fn iterate<T>(\n    mut items: impl Stream<Item = T> + Unpin // ✔️\n) {\n    while let Some(item) = items.next().await {\n        todo!()\n    }\n}\n```\n\n**2\\)** 然而，假设在代码的其他地方导致的编译错误，是因为我们传递给这个函数的stream不是 `Unpin` 。我们可以从函数签名中删除 `Unpin` ，并在函数内使用 `pin!` 宏固定stream:\n\n```rust\nasync fn iterate<T>(\n    mut items: impl Stream<Item = T>\n) {\n    tokio::pin!(items); // ✔️\n    while let Some(item) = items.next().await {\n        todo!()\n    }\n}\n```\n\n将它固定到栈上，这样他就不会从当前作用域逃离。\n\n**3\\)** 如果笃定对象需要逃离当前作用域，可以使用 `Box::pin` 将其固定在堆上：\n\n```rust\nasync fn iterate<T>(\n    mut items: impl Stream<Item = T>\n) {\n    let mut items = Box::pin(items); // ✔️\n    while let Some(item) = items.next().await {\n        todo!()\n    }\n}\n```\n\n**4\\)** 或者可以让调用者指定：\n\n```rust\nasync fn iterate<T, S: Stream<Item = T> + ?Sized>(\n    mut items: Pin<&mut S>\n) {\n    while let Some(item) = items.next().await {\n        todo!()\n    }\n}\n```\n\n然而，在这种情况下，调用者也是我们，所以方案2和3没什么用。\n\n> [!IMPORTANT]\n> 总结：当我们将 `Future` 传递给可能无法 `poll` 完成的时候，需要留意哪些是可以安全取消，哪些是不能安全取消，比如 `tokio::select!` 。 如果你正在编写一个 `poll Future` 的Rust库， 你需要在文档中说明 `Future` 是否可以安全取消。如果你正在使用这样的库，你需要仔细阅读文档。\n\n## 09\\) 为用户分配名称\n\n在当前聊天服务器迭代版本中，很难区分谁说了什么。我们准备将每一个连接地址放到对应消息的前面以区分，就像下面这样：\n\n```console\n$ just telnet\n> hello\n127.0.0.1:51270: hello\n```\n\n然而这样看起来比较丑陋和乏味。我们使用随机的形容词加上一个动物作为名称，在客户端加入时分配给它：\n\n```rust\npub static ADJECTIVES: [&str; 628] = [\n    \"Mushy\",\n    \"Starry\",\n    \"Peaceful\",\n    \"Phony\",\n    \"Amazing\",\n    \"Queasy\",\n    // ...\n];\n\npub static ANIMALS: [&str; 243] = [\n    \"Owl\",\n    \"Mantis\",\n    \"Gopher\",\n    \"Robin\",\n    \"Vulture\",\n    \"Prawn\",\n    // ...\n];\n\npub fn random_name() -> String {\n    let adjective = fastrand::choice(ADJECTIVES).unwrap();\n    let animal = fastrand::choice(ANIMALS).unwrap();\n    format!(\"{adjective}{animal}\")\n}\n```\n\n以下是一些由此产生的名字样本：\n\n```\nHushedLlama\nDimpledDinosaur\nUrbanMongoose\nYawningMinotaur\nRomanticRhino\nDapperPeacock\nPlasticCentaur\nBubblyChicken\nAnxiousGriffin\nSpicyAlpaca\nMindlessOctopus\nWealthyPelican\nCruelCapybara\nRegalFrog\nPinkPoodle\nQuirkyGazelle\nPoshGopher\nCarelessBobcat\nSomberWeasel\nZenMammoth\nDazzlingSquid\n```\n\n为了保持`main`文件简洁，我们将这个功能放到`lib`文件中并导入：\n\n```rust\nuse chat_server::random_name;\n\n// ...\n\nasync fn handle_user(\n    mut tcp: TcpStream,\n    tx: Sender<String>\n) -> anyhow::Result<()> {\n    // ...\n    // generate random name\n    let name = random_name();\n    // ...\n    // tell user their name\n    sink.send(format!(\"You are {name}\")).await?;\n    // ...\n    user_msg = stream.next() => {\n        // ...\n        // prepend user's name to their messages\n        tx.send(format!(\"{name}: {user_msg}\"))?;\n    },\n    // ...\n}\n```\n\n再试一次:\n\n```console\n$ just chat\nYou are MeatyPuma\n> hello\nMeatyPuma: hello\nPeacefulGibbon: howdy\n```\n\n非常好。\n\n> [!NOTE]\n> 我从使用 `just telnet` 切换到 `just chat` ，这是因为我厌倦了使用 `telnet` ，构建了一个更好用的客户端，即 `just chat` 。\n\n## 10\\) 使用`/name`命令编辑自己的名字\n\n我们希望名字在服务器是唯一的。通过使用 `HashSet<String>` 维护名称。由于我们还想让用户通过 `/name` 修改他们自己的名字，所以我们需要跨线程共享使用这个名称集合。\n\n> [!TIP]\n> 要实现跨线程共享可变数据，我们可以用 `Arc<Mutex<T>>` 来包装，如果你之前用过 `Rc<RefCell<T>>`，这个其实就等同是一个线程安全的 `Rc<RefCell<T>>` 。\n\n让我们用一个新类型把 `Arc<Mutex<HashSet<T>>>` 包装一下以更易读：\n\n```rust\n// ...\n\n#[derive(Clone)]\nstruct Names(Arc<Mutex<HashSet<String>>>);\n\nimpl Names {\n    fn new() -> Self {\n        Self(Arc::new(Mutex::new(HashSet::new())))\n    }\n    // returns true if name was inserted,\n    // i.e. the name is unique\n    fn insert(&self, name: String) -> bool {\n        self.0.lock().unwrap().insert(name)\n    }\n    // returns unique name\n    fn get_unique(&self) -> String {\n        let mut name = random_name();\n        let mut guard = self.0.lock().unwrap();\n        while !guard.insert(name.clone()) {\n            name = random_name();\n        }\n        name\n    }\n}\n\n#[tokio::main]\nasync fn main() -> anyhow::Result<()> {\n    // ...\n    let names = Names::new();\n    // ...\n    tokio::spawn(handle_user(tcp, tx.clone(), names.clone()));\n}\n\nasync fn handle_user(\n    mut tcp: TcpStream,\n    tx: Sender<String>,\n    names: Names,\n) -> anyhow::Result<()> {\n    // ...\n    // get a unique name for new user\n    let mut name = names.get_unique();\n    // ...\n    // tell them their name\n    sink.send(format!(\"You are {name}\")).await?;\n    // ...\n    user_msg = stream.next() => {\n        // ...\n        // handle new /name command\n        if user_msg.starts_with(\"/name\") {\n            let new_name = user_msg\n                .split_ascii_whitespace()\n                .nth(1)\n                .unwrap()\n                .to_owned();\n            // check if name is unique\n            let changed_name = names.insert(new_name.clone());\n            if changed_name {\n                // notify everyone that user\n                // changed their name\n                tx.send(format!(\"{name} is now {new_name}\"))?;\n                name = new_name;\n            } else {\n                // tell user that name is\n                // already taken\n                sink.send(\n                    format!(\"{new_name} is already taken\")\n                ).await?;\n            }\n        }\n        // ...\n    },\n    // ...\n}\n```\n\n让我们测试一下：\n\n```console\n$ just chat\nServer commands\n  /help - prints this message\n  /name {name} - change name\n  /quit - quits server\nYou are FancyYak\n> hello\nFancyYak: hello\n> /name pretzelhammer # new command\nFancyYak is now pretzelhammer\n> 🦀🦀🦀\npretzelhammer: 🦀🦀🦀\n```\n\n> [!CAUTION]\n> Rust承诺编译安全的程序是没有内存漏洞的，但它没有承诺不会有死锁。当我们在程序中添加锁时，需要小心避免创建死锁场景。\n\n这里有一些避免死锁的建议：\n\n**1\\)** 不要在 `await` 点持有锁\n\n `await` 点是指异步函数中调用 `await` 的地方。当调用 `await` 时，程序将控制权还给 `tokio` 调度器。如果你的 `Future` 持有锁意味着任何其它执行的 `Future` 无法获取该锁，这种情况下将会导致其在等待时永远阻塞，从而导致持有锁的 `Future` 没有机会执行，这就是死锁。\n\n有点抽象，我们来看一个具体的例子。假设我们有一个单线程的 `tokio` 运行时，有三个 `Future`准备被轮询：\n\n```\nTokio scheduler, future queue:\n+---------+---------+---------+\n|  fut A  |  fut B  |  fut C  |\n+---------+---------+---------+\n```\n\n由于这是一个单线程运行时，一次只能执行一个 `Future` 。`tokio` 轮询第一个`Future`: `future A`，它运行的代码看起来像这样：\n\n```rust\nasync do_stuff<T: Debug>(mutex: Mutex<T>) {\n    // acquires lock\n    let guard = mutex.lock().unwrap();\n    // hits await point, i.e. yields to scheduler\n    other_async_fn().await?;\n    // releases lock\n    dbg!(guard);\n}\n```\n\n当它到达 `await` 点时，`Future` 返回到队列的末尾：\n\n```\nTokio scheduler, future queue:\n+---------+---------+---------+\n|  fut B  |  fut C  |  fut A* |\n+---------+---------+---------+\n* holding lock\n```\n\n这时候 `tokio` 尝试轮询下一个 `Future` : `future B`，其通过相同的代码路径运行，试图获取 `future A` 当前持有的同一个互斥锁！这将导致它永久阻塞！ `future B` 在 `future A` 释放锁之前无法继续执行，但是 `future A` 在 `future B` 返回调度器之前无法执行，所以死锁产生了。\n\n_但是如果我们使用异步互斥锁而不是同步互斥锁呢？_\n\n技巧1适用于同步互斥锁，如 `std::sync::Mutex` ，但不适用于异步互斥锁，如 `tokio::sync::Mutex` 。对于设计用于异步上下文中的互斥锁，我们可以在 `await` 点上持有锁，只是它们会变慢。 `tokio` 文档说明如下：\n\n> 与一般的观点相反，在异步代码中使用标准库中的普通锁是可行且更可取的方式。\n>\n> 与阻塞互斥锁相比，异步互斥锁提供了在 `await` 点上保持锁定的能力。这使得异步互斥锁比阻塞互斥锁开销更大，因此在可以使用阻塞互斥锁的情况下，应该优先使用它。异步互斥锁的主要用于是提供对IO资源的共享可变访问，如数据库连接。如果互斥锁对应的值是数据，那么使用标准库中的阻塞互斥锁通常更合适的。\n\n一般来说，如果我们的代码结构不需要在 `await` 点上持有锁，那么最好使用同步互斥锁，如果必须在 `await` 点上持有锁，则切换使用异步互斥锁。\n\n**2\\)** 不要重复多次获取同一个锁\n\n简单例子：\n\n```rust\nfn main() {\n   let mut mutex = Mutex::new(5);\n   // acquire lock\n   let g = mutex.lock().unwrap();\n   // try to acquire lock again\n   mutex.lock().unwrap(); // deadlocks\n}\n```\n\n虽然上述例子的代码错误非常明显，但是在真实代码<sup>TM</sup>中发生时，定位和调试都非常难。\n\n_\"如果使用读写锁，因为其支持为多个并发线程提供多个读锁，是不是就不用担心这个问题?\"_\n\n出人意料的是这个问题同样存在，即使在同一个线程中两次获取读锁也会产生死锁。借用标准库的 `RwLock` 文档的图表说明如下：\n\n```\n// Thread 1             |  // Thread 2\nlet _rg = lock.read();  |\n                        |  // will block\n                        |  let _wg = lock.write();\n// may deadlock         |\nlet _rg = lock.read();  |\n```\n\n引用 `parking_lot` 模块中 `RwLock` 文档如下 :\n\n> 为避免读写锁的饥饿，该锁使用公平锁策略，当写锁在等待获取锁时，即使锁还在未锁状态，如果读锁尝试获取锁的话也将阻塞，因此，试图在单线程中递归获取读锁可能会导致死锁。\n\n我想我们必须非常小心 🤷\n\n**3\\)** 在任何地方都要以相同的顺序获取锁\n\n如果我们执行某个操作时要安全获取多个锁，那么我们要以相同的顺序获取这些锁，否则死锁很容易发生，就像下面这样：\n\n```\n// Thread 1         |  // Thread 2\nlet _a = a.lock();  |  let _b = b.lock();\n// ...              |  // ...\nlet _b = b.lock();  |  let _a = a.lock();\n```\n\n_头都大了！肯定有一种更简单或更好的方法来处理锁的事情吧？_\n\n**4\\)** 使用无锁数据结构\n\n因为无锁数据结构不会死锁，所以可以忽略提示1-3。但是，无锁数据结构通常比大多数基于锁的数据结构执行更慢。\n\n**5\\)** 全部使用 `channel`\n\n因为通道不会引起死锁，使用该方案可以让您忽略提示1-3。我对使用通道与使用锁相比是否会降低或提高并发程序的性能的问题没法提供足够的信息。瞎猜一下，就像大多数计算机科学问题的答案一样，那就是**具体问题具体分析**。\n\n这种方法也常称之为 `actor模式` ，如果你在 `cargo` 上搜索 `actor` ，你会发现很多该模型框架，这些框架可以让更你容易编写 `actor模式` 程序。\n\n不管怎么说，这不是一个一蹴而就的事情。还是回到我们的聊天服务器。\n\n## 11\\) 在客户端断开连接时释放用户名\n\n我们的程序有一个bug，就是当用户断开连接时，名称不会从集合中删除，因此在获取名称之后，在重新启动服务器之前，它永远不会被再次使用。不幸的是，在解决这个问题，我们必须先解决一个棘手的问题。\n\n这个棘手的问题是用户可能由于错误而断开连接，我们使用 `?` 处理 `handle_user` 函数中的错误并将错误传播到 `main` 函数，但清理名称不应该是 `main` 的责任，这应该是 `handle_user` 中要处理细节。我们可以使用 `Result` 的模式匹配来替代 `?` 处理，但这会导致代码冗长且丑陋。如果我们想要应付一堆重复、丑陋、冗长代码，应该怎么做呢？答案是使用宏。\n\n快速回顾一下，请记住 `Rust` 中的所有块都是表达式，我们可以用一个值 `break` 代码块。示例如下：\n\n```rust\nfn main() {\n    // breaking from loop with value\n    let value = loop {\n        break \"value\";\n    };\n    assert_eq!(value, \"value\");\n\n    // to break from a non-loop block\n    // it needs to be labelled\n    let value = 'label: {\n        break 'label \"value\";\n    };\n    assert_eq!(value, \"value\");\n}\n```\n\n此外， `?` 操作不是魔法，可以通过宏来实现：\n\n```rust\nmacro_rules! question_mark {\n    ($result:expr) => {\n        match $result {\n            Ok(ok) => ok,\n            Err(err) => return Err(err.into()),\n        }\n    }\n}\n```\n\n这正是我们想要的，除了 `return` 应该要修改为 `break` ，因为我们想要在我们的函数中的处理错误，而不是将错误传播给调用者。我们实现一个新的宏 `b!` （是 `break` 的缩写）：\n\n```rust\nmacro_rules! b {\n    ($result:expr) => {\n        match $result {\n            Ok(ok) => ok,\n            Err(err) => break Err(err.into()),\n        }\n    }\n}\n```\n\n然后我们可以重构一个将错误传播给调用者的函数，像下面这样：\n\n```rust\nfn some_function() -> anyhow::Result<()> {\n    // initialize state here\n    loop {\n        fallible_statement_1?;\n        fallible_statement_2?;\n        // etc\n    }\n    // clean up state here, but\n    // this may never be reached\n    // because the ? returns from\n    // the function instead of\n    // breaking from the loop\n    Ok(())\n}\n```\n\n转换成捕获并处理自己的错误的函数：\n\n```rust\nfn some_function() {\n    // initialize state here\n    let result = loop {\n        b!(fallible_statement_1);\n        b!(fallible_statement_2);\n        // etc\n    };\n    // clean up state here, always reached\n    if let Err(err) = result {\n        // handle errors if necessary\n    }\n    // nothing to return anymore since\n    // we take care of everything within\n    // the function :)\n}\n```\n\n有了所有的上下文，这是更新后的代码（译注：即所有 `?` 调用的地方改用 `b!` 包裹）：\n\n```rust\n// ...\n\nasync fn handle_user(\n    mut tcp: TcpStream,\n    tx: Sender<String>,\n    names: Names,\n) -> anyhow::Result<()> {\n    // ...\n    // we now catch errors here\n    let result: anyhow::Result<()> = loop {\n        // all fallible statements\n        // from before are now wrapped\n        // with our b!() macro\n    };\n    // the line below is always reached\n    // and the user's name is always freed,\n    // regardless if they quit normally or\n    // abruptly disconnected due to an error\n    names.remove(&name);\n    // return result to caller if they want\n    // to do anything extra\n    result\n}\n```\n\n现在，当用户因任何原因断开连接时，我们总可以收回他们的名字。\n\n## 12\\) 增加`main`聊天室\n\n现在所有的用户都在同一个聊天室里，无法选择聊天室。将谈话保持在一个主题很难的，如果有多个侧谈同时发生，讨论就很难继续进行。所以应该在服务器中增加创建和加入不同聊天室的功能。第一步，重构当前的代码，将所有加入服务器的人添加到一个默认聊天室，称为 `main` 。更新后的代码：\n\n```rust\n// ...\n\nstruct Room {\n    tx: Sender<String>,\n}\n\nimpl Room {\n    fn new() -> Self {\n        let (tx, _) = broadcast::channel(32);\n        Self {\n            tx,\n        }\n    }\n}\n\nconst MAIN: &str = \"main\";\n\n#[derive(Clone)]\nstruct Rooms(Arc<RwLock<HashMap<String, Room>>>);\n\nimpl Rooms {\n    fn new() -> Self {\n        Self(Arc::new(RwLock::new(HashMap::new())))\n    }\n    fn join(&self, room_name: &str) -> Sender<String> {\n        // get read access\n        let read_guard = self.0.read().unwrap();\n        // check if room already exists\n        if let Some(room) = read_guard.get(room_name) {\n            return room.tx.clone();\n        }\n        // must drop read before acquiring write\n        drop(read_guard);\n        // create room if it doesn't yet exist\n        // get write access\n        let mut write_guard = self.0.write().unwrap();\n        let room = write_guard\n            .entry(room_name.to_owned())\n            .or_insert(Room::new());\n        room.tx.clone()\n    }\n}\n\n#[tokio::main]\nasync fn main() -> anyhow::Result<()> {\n    // ...\n    let rooms = Rooms::new();\n    // ...\n    tokio::spawn(handle_user(tcp, names.clone(), rooms.clone()));\n}\n\nasync fn handle_user(\n    mut tcp: TcpStream,\n    names: Names,\n    rooms: Rooms,\n) -> anyhow::Result<()> {\n    // ...\n    // when user connects to server\n    // automatically put them in\n    // the main room\n    let room_name = MAIN.to_owned();\n    let room_tx = rooms.join(&room_name);\n    let mut room_rx = room_tx.subscribe();\n    // notify everyone in room that\n    // a new user has joined\n    let _ = room_tx.send(format!(\"{name} joined {room_name}\"));\n    // ...\n    tokio::select! {\n        user_msg = stream.next() => {\n            // ...\n            // send messages to the room\n            // we're currently in\n            b!(room_tx.send(format!(\"{name}: {user_msg}\")));\n        },\n        // receive messages from the\n        // room we're currently in\n        peer_msg = room_rx.recv() => {\n            // ...\n        },\n    }\n    // ...\n    // notify everyone in room that\n    // we have left\n    let _ = room_tx.send(format!(\"{name} left {room_name}\"));\n    // ...\n}\n```\n\n`Room` 是对 `broadcast::Sender<String>` 的包装，`Rooms` 是 `Arc<RwLock<HashMap<String, Room>>>` 的包装，因为我们需要维护房间名到广播 `channel` 的映射，并且能在多个线程中共享和修改这个映射。\n\n我们还添加了用户加入和离开一个聊天室的通知。来一起看看是什么样的：\n\n```console\n$ just chat\nYou are AwesomeVulture\nAwesomeVulture joined main\nJealousHornet joined main\nJealousHornet: we are at the main room!\n> can we create other rooms?\nAwesomeVulture: can we create other rooms?\nJealousHornet: not yet, back to work we go\nJealousHornet left main\n```\n\n## 13\\) 使用`/join`加入或创建聊天室\n\n因为我们之前实现了类似的方法，增加一个 `join` 方法非常容易：\n\n```rust\n// ...\nasync fn handle_user(\n    mut tcp: TcpStream,\n    names: Names,\n    rooms: Rooms,\n) -> anyhow::Result<()> {\n    // ...\n    // automatically join main room\n    // on connect, as before\n    let mut room_name = MAIN.to_owned();\n    let mut room_tx = rooms.join(&room_name);\n    let mut room_rx = room_tx.subscribe();\n    // ...\n    if user_msg.starts_with(\"/join\") {\n        let new_room = user_msg\n            .split_ascii_whitespace()\n            .nth(1)\n            .unwrap()\n            .to_owned();\n        // check if user is already in the room\n        // they're trying to join\n        if new_room == room_name {\n            b!(sink.send(format!(\"You are in {room_name}\")).await);\n            continue;\n        }\n        // notify current room that we've left\n        b!(room_tx.send(format!(\"{name} left {room_name}\")));\n        // join new room, this creates\n        // the room if it doesn't\n        // already exist\n        room_tx = rooms.join(&new_room);\n        room_rx = room_tx.subscribe();\n        room_name = new_room;\n        // notify new room that we have joined\n        b!(room_tx.send(format!(\"{name} joined {room_name}\")));\n    }\n    // ...\n    // notify our current room that we've left\n    // on disconnect, as before\n    let _ = room_tx.send(format!(\"{name} left {room_name}\"));\n    // ...\n}\n```\n\n现在我们可以开始举办披萨派对了：\n\n```console\n$ just chat\nServer commands\n  /help - prints this message\n  /name {name} - change name\n  /join {room} - joins room\n  /quit - quits server\nYou are ElasticBonobo\nElasticBonobo joined main\nBlondCyclops joined main\n> /join pizza # new command\nElasticBonobo joined pizza\nBlondCyclops joined pizza\n> let's have a pizza party\nElasticBonobo: let's have a pizza party\nBlondCyclops: 🍕🥳\n```\n\n## 14\\) 使用`/rooms`列出所有聊天室\n\n现在，服务器上的披萨派对还不太容易被发现。如果用户进入 `main` 聊天室，他们就无法知道服务器上的其他用户都在  `pizza` 聊天室。让我们增加一个 `/rooms` 命令，列出服务器上的所有聊天室：\n\n```rust\n// ...\n\n#[derive(Clone)]\nstruct Rooms(Arc<RwLock<HashMap<String, Room>>>);\n\nimpl Rooms {\n    fn list(&self) -> Vec<(String, usize)> {\n        // iterate over rooms map\n        let mut list: Vec<_> = self\n            .0\n            .read()\n            .unwrap()\n            .iter()\n            // receiver_count tells us\n            // the # of users in the room\n            .map(|(name, room)| (\n                name.to_owned(),\n                room.tx.receiver_count(),\n            ))\n            .collect();\n        list.sort_by(|a, b| {\n            use std::cmp::Ordering::*;\n            // sort rooms by # of users first\n            match b.1.cmp(&a.1) {\n                // and by alphabetical order second\n                Equal => a.0.cmp(&b.0),\n                ordering => ordering,\n            }\n        });\n        list\n    }\n}\n\n// ...\n\nasync fn handle_user(\n    mut tcp: TcpStream,\n    names: Names,\n    rooms: Rooms,\n) -> anyhow::Result<()> {\n    // ...\n    // handle new /rooms command\n    if user_msg.starts_with(\"/rooms\") {\n        let rooms_list = rooms.list();\n        let rooms_list = rooms_list\n            .into_iter()\n            .map(|(name, count)| format!(\"{name} ({count})\"))\n            .collect::<Vec<_>>()\n            .join(\", \");\n        b!(sink.send(format!(\"Rooms - {rooms_list}\")).await);\n    }\n    // ...\n}\n```\n\n现在每个人都被邀请参加我们的披萨派对：\n\n```console\n$ just chat\nServer commands\n  /help - prints this message\n  /name {name} - change name\n  /rooms - list rooms\n  /join {room} - joins room\n  /quit - quits server\nYou are SilentYeti\nSilentYeti joined main\n> /rooms # new command\nRooms - pizza (2), main (1)\n> /join pizza\nSilentYeti joined pizza\n> can i be part of this pizza party? 🥺\nSilentYeti: can i be part of this pizza party? 🥺\nBulkyApe: of course ❤️\nAmazingDragon: 🔥🔥🔥\n```\n\n## 15\\) 删除空聊天室\n\n我们的程序有一个bug，就是聊天室一旦被创建后永远不会被删除，即使它里面没人。程序运行一段时间后，服务器聊天室列表将是这样的：\n\n```console\n> /rooms\nRooms - a (0), bunch (0), of (0), abandoned (0), rooms (0)\n```\n\n让我们来修复它：\n\n```rust\n// ...\n\n#[derive(Clone)]\nstruct Rooms(Arc<RwLock<HashMap<String, Room>>>);\n\nimpl Rooms {\n    // ...\n    fn leave(&self, room_name: &str) {\n        let read_guard = self.0.read().unwrap();\n        let mut delete_room = false;\n        if let Some(room) = read_guard.get(room_name) {\n            // if the receiver count is 1 then\n            // we're the last person in the room\n            // and can remove it\n            delete_room = room.tx.receiver_count() <= 1;\n        }\n        drop(read_guard);\n        if delete_room {\n            let mut write_guard = self.0.write().unwrap();\n            write_guard.remove(room_name);\n        }\n    }\n    fn change(\n        &self,\n        prev_room: &str,\n        next_room: &str\n    ) -> Sender<String> {\n        self.leave(prev_room);\n        self.join(next_room)\n    }\n    // ...\n}\n\nasync fn handle_user(\n    mut tcp: TcpStream,\n    names: Names,\n    rooms: Rooms,\n) -> anyhow::Result<()> {\n    // ...\n    if user_msg.starts_with(\"/join\") {\n        // ...\n        // now correctly deletes the room\n        // we're leaving if it becomes empty\n        room_tx = rooms.change(&room_name, &new_room);\n        // ...\n    }\n    // ...\n    // when we disconnect we also\n    // need to leave and delete the\n    // room if it's empty\n    rooms.leave(&room_name);\n    // ...\n}\n```\n\n## 16\\) 使用`/users`命令列出当前聊天室的用户\n\n聊天室的用户是不可发现的。增加一个  `/users` 命令用于列出当前聊天室中的所有用户。要实现这个功能，我们需要在 `Room` 结构体添加一个  `HashSet<String>` 保存用户名，并更新 `Rooms` 的相应方法，在用户加入，更改或离开聊天室时增加用户名的相关处理：\n\n```rust\n// ...\n\nstruct Room {\n    // ...\n    // keep track of the names\n    // of the users in the room\n    users: HashSet<String>,\n}\n\nimpl Room {\n    fn new() -> Self {\n        // ...\n        let users = HashSet::new();\n        Self {\n            // ...\n            users,\n        }\n    }\n}\n\n#[derive(Clone)]\nstruct Rooms(Arc<RwLock<HashMap<String, Room>>>);\n\nimpl Rooms {\n    // ...\n    fn join(&self, room_name: &str, user_name: &str) -> Sender<String> {\n        // ...\n        room.users.insert(user_name.to_owned());\n        // ...\n    }\n    fn leave(&self, room_name: &str, user_name: &str) {\n        // ...\n        room.users.remove(user_name);\n        // ...\n    }\n    // update user's name in room if they\n    // changed it using the /name command\n    fn change_name(\n        &self,\n        room_name: &str,\n        prev_name: &str,\n        new_name: &str\n    ) {\n        let mut write_guard = self.0.write().unwrap();\n        if let Some(room) = write_guard.get_mut(room_name) {\n            room.users.remove(prev_name);\n            room.users.insert(new_name.to_owned());\n        }\n    }\n    // returns list of users' names in the room\n    fn list_users(&self, room_name: &str) -> Option<Vec<String>> {\n        self\n            .0\n            .read()\n            .unwrap()\n            .get(room_name)\n            .map(|room| {\n                // get users in room\n                let mut users = room\n                    .users\n                    .iter()\n                    .cloned()\n                    .collect::<Vec<_>>();\n                // alphabetically sort\n                // users by names\n                users.sort();\n                users\n            })\n    }\n}\n\n// ...\n\nasync fn handle_user(\n    mut tcp: TcpStream,\n    names: Names,\n    rooms: Rooms,\n) -> anyhow::Result<()> {\n    // ...\n    // send our name when joining a room\n    room_tx = rooms.join(&room_name, &name);\n    // ...\n    if user_msg.starts_with(\"/name\") {\n        // ...\n        if changed_name {\n            // let room know we changed our name\n            rooms.change_name(&room_name, &name, &new_name);\n            // ...\n        }\n        // ...\n    } else if user_msg.starts_with(\"/join\") {\n        // ...\n        // send our name when changing rooms\n        room_tx = rooms.change(&room_name, &new_room, &name);\n        // ...\n    // handle new /users command\n    } else if user_msg.starts_with(\"/users\") {\n        let users_list = rooms\n            .list_users(&room_name)\n            .unwrap()\n            .join(\", \");\n        b!(sink.send(format!(\"Users - {users_list}\")).await);\n    }\n    // ...\n    rooms.leave(&room_name, &name);\n    // ...\n}\n```\n\n现在我们可以在聊天室里找到我们的朋友：\n\n```console\n$ just chat\nServer commands\n  /help - prints this message\n  /name {name} - change name\n  /rooms - list rooms\n  /join {room} - joins room\n  /users - lists users in current room\n  /quit - quits server\nYou are StarryDolphin\nStarryDolphin joined main\n> /users # new command\nUsers - ColorfulSheep, PaleHedgehog, StarryDolphin\n> hey colorful sheep! 👋\nStarryDolphin: hey colorful sheep! 👋\nColorfulSheep: good to see you again starry dolphin! 🙌\n```\n\n## 17\\) 性能优化\n\n我们将把性能优化分为三类：减少堆内存分配、减少锁竞争以及为运行性能提供的编译优化。\n\n还有其它类别，但我认为这些与我们的当前项目最相关。\n\n### 减少堆内存分配\n\n最快的代码是永远不会运行的代码。如果我们不需要在堆上分配内存，那么我们就不需要调用分配器。\n\n#### `String` -> `CompactString`\n\n程序中有大量的短字符串。在服务器上拥有数千个用户和数百个聊天室，并且用户名和聊天室名大多数都少于24个字符。我们可以将它们存储为 `CompactString` 而不是 `String` 。因为 `String` 是存储在堆上，而 `CompactString` 会将短于24字节长度的字符串存储在栈上，只有字符串长度大于24字节时才存储在堆上。如果我们强制用户名和聊天室名的最大长度为24个`ASCII`字符，那么就能保证永远不会为它们执行任何堆内存分配。\n\n#### `Sender<String>` -> `Sender<Arc<str>>`\n\n你应该还记得，当我们`send` 数据到广播通道时，每一个 `recv` 都会克隆这个数据。也就是说，当一个用户发送一个五段长的 `String` 消息到1000人的聊天室中，我们就要克隆这个消息1000次，也也意味着1000次的堆内存分配。我们知道消息一旦发送就是不可变的，所以没有必要发送 `String` ，可以使用 `Arc<str>` 替代，因为克隆`Arc<str>` 只是增加原子计数所以代价很低。\n\n#### 其它的小优化\n\n在梳理代码后，我们发现一些地方我们不小心分配了不必要的 `Vec` 和 `String` ，主要是 `/rooms` 和 `/users` 命令，当它们在产生响应时只分配一个 `String` 。\n\n### 减少锁竞争\n\n高锁竞争将增加线程等待锁释放的时间，减少锁竞争可以减少线程等待时间提高系统吞吐量。\n\n#### `Mutex<HashSet<String>>` -> `DashSet<CompactString>`\n\n当前程序将名字保存在 `Mutex<HashSet<String>>` 中，这是一个全局锁。与其给整个集合加一把锁，为什么不给集合中的每一个数据都分配一把锁？ `DashSet` 没那么极端，它在内部将数据分成多个分区，每一个分区一把锁。如下 `ASCII` 图表帮助理解：\n\n```\n+-------------------------------+\n| Mutex                         |\n| +---------------------------+ |\n| | HashSet                   | |\n| | +-----+-----+-----+-----+ | |\n| | | key | key | key | key | | |\n| | +-----+-----+-----+-----+ | |\n| +---------------------------+ |\n+-------------------------------+\n\n+-----------------------------------+\n| DashSet                           |\n| +---------------+---------------+ |\n| | RwLock        | RwLock        | |\n| | +-----+-----+ | +-----+-----+ | |\n| | | key | key | | | key | key | | |\n| | +-----+-----+ | +-----+-----+ | |\n| +-------------------+-----------+ |\n+-----------------------------------+\n```\n\n在保护相同数据情况下，使用更多的锁意味着线程之间的锁竞争更少。\n\n#### `RwLock<HashMap<String, Room>>` -> `DashMap<CompactString, Room>`\n\n将聊天室数据保存 `RwLock<HashMap<String, Room>>` 中，和上述同样的原因，使用 `DashMap` 可以减少锁竞争。\n\n#### 更好的随机名字生成\n\n我们的随机名称生成器存在一个严重问题。这是一个[生日问题](https://en.wikipedia.org/wiki/Birthday_problem)，只是换了一个名称。即使我们有600个独特的形容词和250个独特的动物，可以使用它们生成150k个独特的名称，我们期望前1k个生成的名称中发生碰撞的概率应该非常低，对吧？不幸的是，在生成460个名称后，发生碰撞的概率就已经超过50%，而在生成1000个名称后，发生碰撞的概率已经超过96%。更多的碰撞意味着随着服务器活跃用户数量的增加，线程将花费更多的时间来为每个加入服务器的用户寻找唯一的名称。\n\n我重构了名称生成器生成，以伪随机方式迭代所有可能的名称组合，因此生成的名称看起来仍是随机的，但现在可以保证对于600个唯一的形容词和250个唯一的动物，我们会连续生成150k个唯一的名称，而不会发生任何碰撞。\n\n#### 系统默认内存分配器 -> `jemalloc`\n\n`jemalloc` 在多线程程序运行更快，因为它使用每线程的内存区，从而减少了内存分配的争用。听起来不错，所以我们把内存分配器改成 `jemalloc` 吧。\n\n译注：实际使用的是 `tikv-jemallocator` ，使用可以[参考这个](https://crates.io/crates/tikv-jemallocator)。\n\n### 为运行性能提供的编译优化\n\n默认的 `cargo build` 命令被配置为快速编译运行缓慢的程序。相反，我们希望编译慢但是运行快速的程序。为此，我们需要在 `Cargo.toml` 文件中添加以下内容：\n\n```toml\n[profile.release]\ncodegen-units = 1\nlto = \"fat\"\n```\n\n译注：`lto`（链接时优化）是一种整体程序优化技术， `fat` 形式会最大化性能提升并减小二进制文件大小，但会增加构建时间\n\n然后使用如下标志执行 `build` 命令：\n\n```console\n$ RUSTFLAGS=\"-C target-cpu=native\" cargo build --release\n```\n\n无论如何，这一部分内容很多。你可以在[这里](https://github.com/pretzelhammer/chat-server/blob/main/examples/server-17.rs)查看完整的源代码，并且你可以通过运行 `just diff 16 17` 来查看未优化版本和优化版本之间的差异。\n\n## 18\\) 收尾工作\n\n到目前为止，我们忽略了日志记录、命令行参数解析和错误处理，因为它们很无聊，大多数人不喜欢阅读它们。让我们快速浏览一下。\n\n下面是我们如何设置 `tracing` 来记录 `stdout`:\n\n```rust\nuse std::io;\nuse tracing_subscriber::{fmt, EnvFilter, layer::SubscriberExt};\n\nfn setup_logging() {\n    let subscriber = tracing_subscriber::registry()\n        .with(EnvFilter::from_default_env())\n        .with(fmt::Layer::new()\n            .without_time()\n            .compact()\n            .with_ansi(true)\n            .with_writer(io::stdout)\n        );\n    tracing::subscriber::set_global_default(subscriber)\n            .expect(\"Unable to set a global subscriber\");\n}\n```\n\n在主函数开始地方执行 `setup_logging` ，然后我们就可以调用 `tracing` 库中的 `trace!`、`debug!` 、 `info!`、 `warn!` 和 `error!` 宏，它们的功能类似 `println!` 。我们还可以通过 `RUST_LOG` 环境变量来自定义日志级别。\n\n现在我们的服务器总是运行在 `127.0.0.1` 的 `42069` 端口。我们需要让服务器管理员在不重新编译代码的情况下自定义，我们可以命令行参数来接受这些配置，使用 `clap` 模块解析：\n\n```rust\nuse std::net::{IpAddr, SocketAddr, Ipv4Addr};\nuse clap::Parser;\n\nconst DEFAULT_IP: IpAddr = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1));\nconst DEFAULT_PORT: u16 = 42069;\n\n#[derive(Parser)]\n#[command(long_about = None)]\nstruct Cli {\n    #[arg(short, long, default_value_t = DEFAULT_IP)]\n    ip: IpAddr,\n\n    #[arg(short, long, default_value_t = DEFAULT_PORT)]\n    port: u16,\n}\n\nfn parse_socket_addr() -> SocketAddr {\n    let cli = Cli::parse();\n    SocketAddr::new(cli.ip, cli.port)\n}\n```\n\n对于错误处理，我们忽略了一堆琐碎的事情，因为没有一样特别值得写的。\n\n你可以在[这里](https://github.com/pretzelhammer/chat-server/blob/main/examples/server-18.rs)查看所有日志记录和错误处理的完整代码。你可以运行 `just diff 17 18` 查看与前面版本的代码差异。\n\n## 结论\n\n我们学到了很多！服务器的最终完整代码在[这里](https://github.com/pretzelhammer/chat-server/blob/main/src/bin/chat-server.rs)。你可以使用 `just server` 运行它。要开始聊天，请运行 `just chat` 。如果觉得孤独，请运行 `just bots` 。\n\n## 讨论\n\n在 [Github](https://github.com/pretzelhammer/rust-blog/discussions/75) 上讨论这篇文章。\n\n## 进一步阅读\n\n- [Rust 中常见的有关生命周期的误解](./common-rust-lifetime-misconceptions.md)\n- [Rust 标准库特性指南](./tour-of-rusts-standard-library-traits.md)\n- [Sizedness in Rust](../../sizedness-in-rust.md)\n- [RESTful API in Sync & Async Rust](../../restful-api-in-sync-and-async-rust.md)\n- [2020 年的 Rust 学习指南](./learning-rust-in-2020.md)\n- [Learn Assembly with Entirely Too Many Brainfuck Compilers](../../too-many-brainfuck-compilers.md)\n"
  },
  {
    "path": "posts/translations/zh-hans/common-rust-lifetime-misconceptions.md",
    "content": "# Rust 中常见的有关生命周期的误解\n\n_2020 年 5 月 19 日 · 预计阅读 30 分钟 · #rust · #生命周期_\n\n译者：[SHJ](https://github.com/Foreverhighness)\n\n**目录**\n- [引言](#引言)\n- [误解](#误解)\n    - [1) `T` 只包含所有权类型](#1-t-只包含所有权类型)\n    - [2) 如果 `T: 'static` 那么 `T` 直到程序结束为止都一定是有效的](#2-如果-t-static-那么-t-直到程序结束为止都一定是有效的)\n    - [3) `&'a T` 和 `T: 'a` 是一回事](#3-a-t-和-t-a-是一回事)\n    - [4) 我的代码里不含泛型也不含生命周期注解](#4-我的代码里不含泛型也不含生命周期注解)\n    - [5) 如果编译通过了，那么我标注的生命周期就是正确的](#5-如果编译通过了那么我标注的生命周期就是正确的)\n    - [6) 已装箱的 trait 对象不含生命周期注解](#6-已装箱的-trait-对象不含生命周期注解)\n    - [7) 编译报错的信息会告诉我怎样修复我的程序](#7-编译报错的信息会告诉我怎样修复我的程序)\n    - [8) 生命周期可以在运行时动态变长或变短](#8-生命周期可以在运行时动态变长或变短)\n    - [9) 将独占引用降级为共享引用是 safe 的](#9-将独占引用降级为共享引用是-safe-的)\n    - [10) 对闭包的生命周期省略规则和函数一样](#10-对闭包的生命周期省略规则和函数一样)\n    - [11) `'static` 引用总能被强制转换为 `'a` 引用](#11-static-引用总能被强制转换为-a-引用)\n- [总结](#总结)\n- [讨论](#讨论)\n- [拓展阅读](#拓展阅读)\n- [译者注](#译者注)\n\n\n\n## 引言\n\n我曾经也抱有上述的这些误解，并且现在仍有许多初学者深陷其中。本文中我使用的术语可能并不那么官方，因此下面列出了一个表格，记录我使用的短语及其想表达的含义。\n\n| 短语 | 意义 |\n|-|-|\n| `T` | 1) 所有可能类型的集合 _或_<br>2) 上述集合中的某一个具体类型 |\n| 所有权类型 | 某些非引用类型，其自身拥有所有权 例如 `i32`, `String`, `Vec` 等等 |\n| 1) 借用类型 _或_<br>2) 引用类型 | 引用类型，不考虑可变性 例如 `&i32`, `&mut i32` 等等 |\n| 1) 可变引用 _或_<br>2) 独占引用 | 独占可变引用, 即 `&mut T` |\n| 1) 不可变引用 _或_<br>2) 共享引用 | 可共享不可变引用, 即 `&T` |\n\n\n\n## 误解\n\n简单来讲，一个变量的生命周期是指一段时期，在这段时期内，该变量所指向的内存地址中的数据是有效的，这段时期是由编译器静态分析得出的，有效性由编译器保证。接下来我将探讨这些常见误解的细节。\n\n\n\n### 1) `T` 只包含所有权类型\n\n这更像是对泛型的误解而非对生命周期的误解，但在 Rust 中，泛型与生命周期的关系是如此紧密，以至于不可能只讨论其中一个而忽视另外一个。\n\n当我刚开始学习 Rust 时，我知道 `i32`, `&i32`, 和 `&mut i32` 是不同的类型，同时我也知泛型 `T` 表示所有可能类型的集合。然而，尽管能分别理解这两个概念，但我却没能将二者结合起来。在当时我这位 Rust 初学者的眼里，泛型是这样运作的：\n\n| | | | |\n|-|-|-|-|\n| **类型** | `T` | `&T` | `&mut T` |\n| **例子** | `i32` | `&i32` | `&mut i32` |\n\n其中 `T` 包全体所有权类型；`&T` 包括全体不可变引用；`&mut T` 包括全体可变引用；`T`, `&T`, 和 `&mut T` 是不相交的有限集。简洁明了，符合直觉，却完全错误。事实上泛型是这样运作的：\n\n| | | | |\n|-|-|-|-|\n| **类型** | `T` | `&T` | `&mut T` |\n| **例子** | `i32`, `&i32`, `&mut i32`, `&&i32`, `&mut &mut i32`, ... | `&i32`, `&&i32`, `&&mut i32`, ... | `&mut i32`, `&mut &mut i32`, `&mut &i32`, ... |\n\n`T`, `&T`, 和 `&mut T` 都是无限集，因为你可以借用一个类型无限次。`T` 是 `&T` 和 `&mut T` 的超集。`&T` 和 `&mut T` 是不相交的集合. 下面有一些例子来验证这些概念：\n\n```rust\ntrait Trait {}\n\nimpl<T> Trait for T {}\n\nimpl<T> Trait for &T {} // 编译错误\n\nimpl<T> Trait for &mut T {} // 编译错误\n```\n\n上述代码不能编译通过：\n\n```rust\nerror[E0119]: conflicting implementations of trait `Trait` for type `&_`:\n --> src/lib.rs:5:1\n  |\n3 | impl<T> Trait for T {}\n  | ------------------- first implementation here\n4 |\n5 | impl<T> Trait for &T {}\n  | ^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_`\n\nerror[E0119]: conflicting implementations of trait `Trait` for type `&mut _`:\n --> src/lib.rs:7:1\n  |\n3 | impl<T> Trait for T {}\n  | ------------------- first implementation here\n...\n7 | impl<T> Trait for &mut T {}\n  | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&mut _`\n```\n\n编译器不允许我们为 `&T` 和 `&mut T` 实现 `Trait`，因为这与我们为 `T` 实现的 `Trait` 发生了冲突，而 `T` 已经包括了 `&T` 和 `&mut T`. 因为 `&T` 和 `&mut T` 是不相交的，所以下面的代码可以通过编译：\n\n```rust\ntrait Trait {}\n\nimpl<T> Trait for &T {} // 编译通过\n\nimpl<T> Trait for &mut T {} // 编译通过\n```\n\n**关键点回顾**\n- `T` 是 `&T` 和 `&mut T` 的超集\n- `&T` 和 `&mut T` 是不相交的集合\n\n\n### 2) 如果 `T: 'static` 那么 `T` 直到程序结束为止都一定是有效的\n\n**错误的推论**\n- `T: 'static` 应该视为 _“`T` 有着 `'static`生命周期”_\n- `&'static T` 和 `T: 'static` 是一回事\n- 若 `T: 'static` 则 `T` 一定是不可变的\n- 若 `T: 'static` 则 `T` 只能在编译期创建\n\n让大多数 Rust 初学者第一次接触 `'static` 生命周期注解的代码示例大概是这样的：\n\n```rust\nfn main() {\n    let str_literal: &'static str = \"字符串字面量\";\n}\n```\n\n他们被告知说 `\"字符串字面量\"` 是被硬编码到编译出来的二进制文件当中去的，并在运行时被加载到只读内存中，所以它不可变且在程序的整个运行期间都有效，这也使其生命周期为 `'static`. 在了解到 Rust 使用 `static` 来定义静态变量这一语法后，这一观点还会被进一步加强。\n\n```rust\nstatic BYTES: [u8; 3] = [1, 2, 3];\nstatic mut MUT_BYTES: [u8; 3] = [1, 2, 3];\n\nfn main() {\n   MUT_BYTES[0] = 99; // 编译错误，修改静态变量是 unsafe 的\n\n    unsafe {\n        MUT_BYTES[0] = 99;\n        assert_eq!(99, MUT_BYTES[0]);\n    }\n}\n```\n\n关于静态变量\n- 它们只能在编译期创建\n- 它们应当是不可变的，修改静态变量是 unsafe 的\n- 它们在整个程序运行期间有效\n\n静态变量的默认生命周期很有可能是 `'static` , 对吧？所以可以合理推测 `'static` 生命周期也要遵循同样的规则，对吧？\n\n确实，但 _持有_ `'static` 生命周期注解的类型和一个满足 `'static` _约束_ 的类型是不一样的。后者可以于运行时被动态分配，能被安全自由地修改，也可以被 drop, 还能存活任意的时长。\n\n区分 `&'static T` 和 `T: 'static` 是非常重要的一点。\n\n`&'static T` 是一个指向 `T` 的不可变引用，其中 `T` 可以被安全地无期限地持有，甚至可以直到程序结束。这只有在 `T` 自身不可变且保证 _在引用创建后_ 不会被 move 时才有可能。`T` 并不需要在编译时创建。 我们可以以内存泄漏为代价，在运行时动态创建随机数据，并返回其 `'static` 引用，比如：\n\n```rust\nuse rand;\n\n// 在运行时生成随机 &'static str\nfn rand_str_generator() -> &'static str {\n    let rand_string = rand::random::<u64>().to_string();\n    Box::leak(rand_string.into_boxed_str())\n}\n```\n\n`T: 'static` 是指 `T` 可以被安全地无期限地持有，甚至可以直到程序结束。 `T: 'static` 在包括了全部 `&'static T` 的同时，还包括了全部所有权类型， 比如 `String`, `Vec` 等等。 数据的所有者保证，只要自身还持有数据的所有权，数据就不会失效，因此所有者能够安全地无期限地持有其数据，甚至可以直到程序结束。`T: 'static` 应当视为 _“`T` 满足 `'static` 生命周期约束”_ 而非 _“`T` 有着 `'static` 生命周期”_。 一个程序可以帮助阐述这些概念：\n\n```rust\nuse rand;\n\nfn drop_static<T: 'static>(t: T) {\n    std::mem::drop(t);\n}\n\nfn main() {\n    let mut strings: Vec<String> = Vec::new();\n    for _ in 0..10 {\n        if rand::random() {\n            // 所有字符串都是随机生成的\n            // 并且在运行时动态分配\n            let string = rand::random::<u64>().to_string();\n            strings.push(string);\n        }\n    }\n\n    // 这些字符串是所有权类型，所以他们满足 'static 生命周期约束\n    for mut string in strings {\n        // 这些字符串是可变的\n        string.push_str(\"a mutation\");\n        // 这些字符串都可以被 drop\n        drop_static(string); // 编译通过\n    }\n\n    // 这些字符串在程序结束之前就已经全部失效了\n    println!(\"i am the end of the program\");\n}\n```\n\n**关键点回顾**\n- `T: 'static` 应当视为 _“`T` 满足 `'static` 生命周期约束”_\n- 若 `T: 'static` 则 `T` 可以是一个有 `'static` 生命周期的引用类型 _或_ 是一个所有权类型\n- 因为 `T: 'static` 包括了所有权类型，所以 `T`\n  - 可以在运行时动态分配\n  - 不需要在整个程序运行期间都有效\n  - 可以安全，自由地修改\n  - 可以在运行时被动态的 drop\n  - 可以有不同长度的生命周期\n\n\n\n### 3) `&'a T` 和 `T: 'a` 是一回事\n\n这个误解是前一个误解的泛化版本。\n\n`&'a T` 要求并隐含了 `T: 'a` ，因为如果 `T` 本身不能在 `'a` 范围内保证有效，那么其引用也不能在 `'a` 范围内保证有效。例如，Rust 编译器不会运行构造一个 `&'static Ref<'a, T>`，因为如果 `Ref` 只在 `'a` 范围内有效，我们就不能给它 `'static` 生命周期。\n\n`T: 'a` 包括了全体 `&'a T`，但反之不成立。\n\n```rust\n// 只接受带有 'a 生命周期注解的引用类型\nfn t_ref<'a, T: 'a>(t: &'a T) {}\n\n// 接受满足 'a 生命周期约束的任何类型\nfn t_bound<'a, T: 'a>(t: T) {}\n\n// 内部含有引用的所有权类型\nstruct Ref<'a, T: 'a>(&'a T);\n\nfn main() {\n    let string = String::from(\"string\");\n\n    t_bound(&string); // 编译通过\n    t_bound(Ref(&string)); // 编译通过\n    t_bound(&Ref(&string)); // 编译通过\n\n    t_ref(&string); // 编译通过\n    t_ref(Ref(&string)); // 编译失败，期望得到引用，实际得到 struct\n    t_ref(&Ref(&string)); // 编译通过\n\n    // 满足 'static 约束的字符串变量可以转换为 'a 约束\n    t_bound(string); // 编译通过\n}\n```\n\n**关键点回顾**\n- `T: 'a` 比 `&'a T` 更泛化，更灵活\n- `T: 'a` 接受所有权类型，内部含有引用的所有权类型，和引用\n- `&'a T` 只接受引用\n- 若 `T: 'static` 则 `T: 'a` 因为对于所有 `'a` 都有 `'static` >= `'a`\n\n\n\n### 4) 我的代码里不含泛型也不含生命周期注解\n\n**错误的推论**\n- 避免使用泛型和生命周期注解是可能的\n\n这个让人爽到的误解之所以能存在，要得益于 Rust 的生命周期省略规则，这个规则能允许你在函数定义以及 `impl` 块中省略掉显式的生命周期注解，而由借用检查器来根据以下规则对生命周期进行隐式推导。\n- 第一条规则是每一个是引用的参数都有它自己的生命周期参数\n- 第二条规则是如果只有一个输入生命周期参数，那么它被赋予所有输出生命周期参数\n- 第三条规则是如果是有多个输入生命周期参数的方法，而其中一个参数是 `&self` 或 `&mut self`, 那么所有输出生命周期参数被赋予 `self` 的生命周期。\n- 其他情况下，生命周期必须有明确的注解\n\n这里有不少值得讲的东西，让我们来看一些例子：\n\n```rust\n// 展开前\nfn print(s: &str);\n\n// 展开后\nfn print<'a>(s: &'a str);\n\n// 展开前\nfn trim(s: &str) -> &str;\n\n// 展开后\nfn trim<'a>(s: &'a str) -> &'a str;\n\n// 非法，没有输入，不能确定返回值的生命周期\nfn get_str() -> &str;\n\n// 显式标注的方案\nfn get_str<'a>() -> &'a str; // 泛型版本\nfn get_str() -> &'static str; // 'static 版本\n\n// 非法，多个输入，不能确定返回值的生命周期\nfn overlap(s: &str, t: &str) -> &str;\n\n// 显式标注（但仍有部分标注被省略）的方案\nfn overlap<'a>(s: &'a str, t: &str) -> &'a str; // 返回值的生命周期不长于 s\nfn overlap<'a>(s: &str, t: &'a str) -> &'a str; // 返回值的生命周期不长于 t\nfn overlap<'a>(s: &'a str, t: &'a str) -> &'a str; // 返回值的生命周期不长于 s 且不长于 t\nfn overlap(s: &str, t: &str) -> &'static str; // 返回值的生命周期可以长于 s 或者 t\nfn overlap<'a>(s: &str, t: &str) -> &'a str; // 返回值的生命周期与输入无关\n\n// 展开后\nfn overlap<'a, 'b>(s: &'a str, t: &'b str) -> &'a str;\nfn overlap<'a, 'b>(s: &'a str, t: &'b str) -> &'b str;\nfn overlap<'a>(s: &'a str, t: &'a str) -> &'a str;\nfn overlap<'a, 'b>(s: &'a str, t: &'b str) -> &'static str;\nfn overlap<'a, 'b, 'c>(s: &'a str, t: &'b str) -> &'c str;\n\n// 展开前\nfn compare(&self, s: &str) -> &str;\n\n// 展开后\nfn compare<'a, 'b>(&'a self, &'b str) -> &'a str;\n```\n\n如果你写过\n- 结构体方法\n- 接收参数中有引用的函数\n- 返回值是引用的函数\n- 泛型函数\n- trait object(后面将讨论)\n- 闭包（后面将讨论）\n\n那么对于上面这些，你的代码中都有被省略的泛型生命周期注解。\n\n**关键点回顾**\n- 几乎所有的 Rust 代码都是泛型代码，并且到处都带有被省略掉的泛型生命周期注解\n\n\n\n### 5) 如果编译通过了，那么我标注的生命周期就是正确的\n\n**错误的推论**\n- Rust 对函数的生命周期省略规则总是对的\n- Rust 的借用检查器总是正确的，无论是技巧上还是语义上\n- Rust 比我更懂我程序的语义\n\n让一个 Rust 程序通过编译但语义上不正确是有可能的。来看看这个例子：\n\n```rust\nstruct ByteIter<'a> {\n    remainder: &'a [u8]\n}\n\nimpl<'a> ByteIter<'a> {\n    fn next(&mut self) -> Option<&u8> {\n        if self.remainder.is_empty() {\n            None\n        } else {\n            let byte = &self.remainder[0];\n            self.remainder = &self.remainder[1..];\n            Some(byte)\n        }\n    }\n}\n\nfn main() {\n    let mut bytes = ByteIter { remainder: b\"1\" };\n    assert_eq!(Some(&b'1'), bytes.next());\n    assert_eq!(None, bytes.next());\n}\n```\n\n`ByteIter` 是一个 byte 切片上的迭代器，简洁起见，我这里省略了 Iterator trait 的具体实现。这看起来没什么问题，但如果我们想同时检查多个 byte 呢？\n\n```rust\nfn main() {\n    let mut bytes = ByteIter { remainder: b\"1123\" };\n    let byte_1 = bytes.next();\n    let byte_2 = bytes.next();\n    if byte_1 == byte_2 {\n        // 一些代码\n    }\n}\n```\n\n编译错误：\n\n```rust\nerror[E0499]: cannot borrow `bytes` as mutable more than once at a time\n  --> src/main.rs:20:18\n   |\n19 |     let byte_1 = bytes.next();\n   |                  ----- first mutable borrow occurs here\n20 |     let byte_2 = bytes.next();\n   |                  ^^^^^ second mutable borrow occurs here\n21 |     if byte_1 == byte_2 {\n   |        ------ first borrow later used here\n```\n\n如果你说可以通过逐 byte 拷贝来避免编译错误，那么确实。当迭代一个 byte 数组上时，我们的确可以通过拷贝每个 byte 来达成目的。但是如果我想要将  `ByteIter` 改写成一个泛型的切片迭代器，使得我们能够对任意 `&'a [T]` 进行迭代，而此时如果有一个 `T`，其 copy 和 clone 的代价十分昂贵，那么我们该怎么避免这种昂贵的操作呢？哦，我想我们不能，毕竟代码都通过编译了，那么生命周期注解肯定也是对的，对吧？\n\n错，事实上现有的生命周期就是 bug 的源头！这个错误的生命周期被省略掉了以至于难以被发现。现在让我们展开这些被省略掉的生命周期来暴露出这个问题。\n\n```rust\nstruct ByteIter<'a> {\n    remainder: &'a [u8]\n}\n\nimpl<'a> ByteIter<'a> {\n    fn next<'b>(&'b mut self) -> Option<&'b u8> {\n        if self.remainder.is_empty() {\n            None\n        } else {\n            let byte = &self.remainder[0];\n            self.remainder = &self.remainder[1..];\n            Some(byte)\n        }\n    }\n}\n```\n\n感觉好像没啥用，我还是搞不清楚问题出在哪。这里有个 Rust 专家才知道的小技巧：给你的生命周期注解起一个更有含义的名字，让我们试一下：\n\n```rust\nstruct ByteIter<'remainder> {\n    remainder: &'remainder [u8]\n}\n\nimpl<'remainder> ByteIter<'remainder> {\n    fn next<'mut_self>(&'mut_self mut self) -> Option<&'mut_self u8> {\n        if self.remainder.is_empty() {\n            None\n        } else {\n            let byte = &self.remainder[0];\n            self.remainder = &self.remainder[1..];\n            Some(byte)\n        }\n    }\n}\n```\n\n每个返回的 byte 都被标注为 `'mut_self`, 但是显然这些 byte 都源于 `'remainder`! 让我们来修复一下这段代码。\n\n```rust\nstruct ByteIter<'remainder> {\n    remainder: &'remainder [u8]\n}\n\nimpl<'remainder> ByteIter<'remainder> {\n    fn next(&mut self) -> Option<&'remainder u8> {\n        if self.remainder.is_empty() {\n            None\n        } else {\n            let byte = &self.remainder[0];\n            self.remainder = &self.remainder[1..];\n            Some(byte)\n        }\n    }\n}\n\nfn main() {\n    let mut bytes = ByteIter { remainder: b\"1123\" };\n    let byte_1 = bytes.next();\n    let byte_2 = bytes.next();\n    std::mem::drop(bytes); // 我们现在甚至可以把这个迭代器给 drop 掉！\n    if byte_1 == byte_2 { // 编译通过\n        // 一些代码\n    }\n}\n```\n\n现在我们再回过头来看看我们上一版的实现，就能看出它是错的了，那么为什么 Rust 会编译通过呢？答案很简单：因为这是内存安全的。\n\nRust 借用检查器对生命周期注解的要求只到能静态验证程序的内存安全为止。即便生命周期注解有语义上的错误，Rust 也能让程序编译通过，哪怕这样做为程序带来不必要的限制。\n\n这儿有一个和之前相反的例子：在这个例子中，Rust 生命周期省略规则标注的生命周期是语义正确的，但是我们却在无意间使用了不必要的显式注解，导致写出了一个限制极其严格的方法。\n\n```rust\n#[derive(Debug)]\nstruct NumRef<'a>(&'a i32);\n\nimpl<'a> NumRef<'a> {\n    // 我定义的泛型结构体以 'a 为参数，这意味着我也需要给方法的参数\n    // 标注为 'a 生命周期，对吗？（答案：错）\n    fn some_method(&'a mut self) {}\n}\n\nfn main() {\n    let mut num_ref = NumRef(&5);\n    num_ref.some_method(); // 可变借用 num_ref 直至其生命周期结束\n    num_ref.some_method(); // 编译错误\n    println!(\"{:?}\", num_ref); // 同样编译错误\n}\n```\n\n如果我们有一个带 `'a` 泛型参数的结构体，我们几乎不可能去写一个带 `&'a mut self` 参数的方法。因为这相当于告诉 Rust “这个方法将独占借用该对象，直到对象生命周期结束”。实际上，这意味着 Rust 的借用检查器只会允许在该对象上调用至多一次 `some_method`, 此后该对象将一直被独占借用并会因此变得不再可用。这种用例极其罕见，但是因为这种代码能够通过编译，所以那些对生命周期还感到困惑的初学者们很容易写出这种 bug. 修复这种 bug 的方式是去除掉不必要的显式生命周期注解，让 Rust 生命周期省略规则来处理它：\n\n```rust\n#[derive(Debug)]\nstruct NumRef<'a>(&'a i32);\n\nimpl<'a> NumRef<'a> {\n    // 不再给 mut self 添加 'a 注解\n    fn some_method(&mut self) {}\n\n    // 上一行去掉语法糖后：\n    fn some_method_desugared<'b>(&'b mut self){}\n}\n\nfn main() {\n    let mut num_ref = NumRef(&5);\n    num_ref.some_method();\n    num_ref.some_method(); // 编译通过\n    println!(\"{:?}\", num_ref); // 编译通过\n}\n```\n\n**关键点回顾**\n- Rust 对函数的生命周期省略规则并不保证在任何情况下都正确\n- 在程序的语义方面，Rust 并不比你懂\n- 可以试试给你的生命周期注解起一个有意义的名字\n- 试着记住你在哪里添加了显式生命周期注解，以及为什么要加\n\n\n\n### 6) 已装箱的 trait 对象不含生命周期注解\n\n之前我们讨论了 Rust _对函数_ 的生命周期省略规则。Rust 对 trait 对象也存在生命周期省略规则，它们是：\n- 如果 trait 对象被用作泛型类型的一个类型参数，那么 trait 对象的生命周期约束会依据该类型参数的定义进行推导\n    - 若该类型参数有唯一的生命周期约束，则将这个约束赋给 trait 对象\n    - 若该类型参数不止一个生命周期约束，则 trait 对象的生命周期约束需要显式标注\n- 如果上面不成立，也就是说该类型参数没有生命周期约束，那么\n    - 若 trait 定义时有且仅有一个生命周期约束，则将这个约束赋给 trait 对象\n    - 若 trait 定义时生命周期约束中存在一个 `'static`, 则将 `'static` 赋给 trait 对象\n    - 若 trait 定义时没有生命周期约束，则当 trait 对象是表达式的一部分时，生命周期从表达式中推导而出，否则赋予 `'static``\n\n以上这些听起来特别复杂，但是可以简单地总结为一句话“一个 trait 对象的生命周期约束从上下文推导而出。”看下面这些例子后，我们会看到生命周期约束的推导其实很符合直觉，因此我们没必要去记忆上面的规则：\n\n```rust\nuse std::cell::Ref;\n\ntrait Trait {}\n\n// 展开前\ntype T1 = Box<dyn Trait>;\n// 展开后，Box<T> 没有对 T 的生命周期约束，所以推导为 'static\ntype T2 = Box<dyn Trait + 'static>;\n\n// 展开前\nimpl dyn Trait {}\n// 展开后\nimpl dyn Trait + 'static {}\n\n// 展开前\ntype T3<'a> = &'a dyn Trait;\n// 展开后，&'a T 要求 T: 'a, 所以推导为 'a\ntype T4<'a> = &'a (dyn Trait + 'a);\n\n// 展开前\ntype T5<'a> = Ref<'a, dyn Trait>;\n// 展开后，Ref<'a, T> 要求 T: 'a, 所以推导为 'a\ntype T6<'a> = Ref<'a, dyn Trait + 'a>;\n\ntrait GenericTrait<'a>: 'a {}\n\n// 展开前\ntype T7<'a> = Box<dyn GenericTrait<'a>>;\n// 展开后\ntype T8<'a> = Box<dyn GenericTrait<'a> + 'a>;\n\n// 展开前\nimpl<'a> dyn GenericTrait<'a> {}\n// 展开后\nimpl<'a> dyn GenericTrait<'a> + 'a {}\n```\n\n一个实现了 trait 的具体类型可以被引用，因此它们也会有生命周期约束，同样其对应的 trait 对象也有生命周期约束。你也可以直接对引用实现 trait, 引用显然是有生命周期约束的：\n\n```rust\ntrait Trait {}\n\nstruct Struct {}\nstruct Ref<'a, T>(&'a T);\n\nimpl Trait for Struct {}\nimpl Trait for &Struct {} // 直接为引用类型实现 Trait\nimpl<'a, T> Trait for Ref<'a, T> {} // 为包含引用的类型实现 Trait\n```\n\n总之，这个知识点值得反复理解，新手在重构一个使用 trait 对象的函数到一个泛型的函数或者反过来时，常常会因为这个知识点而感到困惑。来看看这个示例程序：\n\n```rust\nuse std::fmt::Display;\n\nfn dynamic_thread_print(t: Box<dyn Display + Send>) {\n    std::thread::spawn(move || {\n        println!(\"{}\", t);\n    }).join();\n}\n\nfn static_thread_print<T: Display + Send>(t: T) {\n    std::thread::spawn(move || {\n        println!(\"{}\", t);\n    }).join();\n}\n```\n\n这里编译器报错：\n\n```rust\nerror[E0310]: the parameter type `T` may not live long enough\n  --> src/lib.rs:10:5\n   |\n9  | fn static_thread_print<T: Display + Send>(t: T) {\n   |                        -- help: consider adding an explicit lifetime bound...: `T: 'static +`\n10 |     std::thread::spawn(move || {\n   |     ^^^^^^^^^^^^^^^^^^\n   |\nnote: ...so that the type `[closure@src/lib.rs:10:24: 12:6 t:T]` will meet its required lifetime bounds\n  --> src/lib.rs:10:5\n   |\n10 |     std::thread::spawn(move || {\n   |     ^^^^^^^^^^^^^^^^^^\n```\n\n很好，编译器告诉了我们怎样修复这个问题，让我们修复一下。\n\n```rust\nuse std::fmt::Display;\n\nfn dynamic_thread_print(t: Box<dyn Display + Send>) {\n    std::thread::spawn(move || {\n        println!(\"{}\", t);\n    }).join();\n}\n\nfn static_thread_print<T: Display + Send + 'static>(t: T) {\n    std::thread::spawn(move || {\n        println!(\"{}\", t);\n    }).join();\n}\n```\n\n现在它编译通过了，但是这两个函数对比起来看起来挺奇怪的，为什么第二个函数要求 `T` 满足 `'static` 约束而第一个函数不用呢？这是个刁钻的问题。事实上，通过生命周期省略规则，Rust 自动在第一个函数里推导并添加了一个 `'static` 约束，所以其实两个函数都含有 `'static` 约束。Rust 编译器实际看到的是这个样子的：\n\n```rust\nuse std::fmt::Display;\n\nfn dynamic_thread_print(t: Box<dyn Display + Send + 'static>) {\n    std::thread::spawn(move || {\n        println!(\"{}\", t);\n    }).join();\n}\n\nfn static_thread_print<T: Display + Send + 'static>(t: T) {\n    std::thread::spawn(move || {\n        println!(\"{}\", t);\n    }).join();\n}\n```\n\n关键点回顾\n- 所有 trait 对象都含有自动推导的生命周期\n\n\n\n### 7) 编译器的报错信息会告诉我怎样修复我的程序\n\n**错误的推论**\n- Rust 对 trait 对象的生命周期省略规则总是正确的\n- Rust 比我更懂我程序的语义\n\n这个误解是前两个误解的结合，来看一个例子：\n\n```rust\nuse std::fmt::Display;\n\nfn box_displayable<T: Display>(t: T) -> Box<dyn Display> {\n    Box::new(t)\n}\n```\n\n报错如下：\n\n```rust\nerror[E0310]: the parameter type `T` may not live long enough\n --> src/lib.rs:4:5\n  |\n3 | fn box_displayable<T: Display>(t: T) -> Box<dyn Display> {\n  |                    -- help: consider adding an explicit lifetime bound...: `T: 'static +`\n4 |     Box::new(t)\n  |     ^^^^^^^^^^^\n  |\nnote: ...so that the type `T` will meet its required lifetime bounds\n --> src/lib.rs:4:5\n  |\n4 |     Box::new(t)\n  |     ^^^^^^^^^^^\n```\n\n好，让我们按照编译器的提示进行修复。这里我们先忽略一个事实：返回值中装箱的 trait 对象有一个自动推导的 `'static` 约束，而编译器是基于这个没有显式说明的事实给出的修复建议。\n\n```rust\nuse std::fmt::Display;\n\nfn box_displayable<T: Display + 'static>(t: T) -> Box<dyn Display> {\n    Box::new(t)\n}\n```\n\n现在可以编译通过了，但这真的是我们想要的吗？可能是，也可能不是，编译器并没有提到其他修复方案，但下面这个也是一个合适的修复方案。\n\n```rust\nuse std::fmt::Display;\n\nfn box_displayable<'a, T: Display + 'a>(t: T) -> Box<dyn Display + 'a> {\n    Box::new(t)\n}\n```\n\n这个函数所能接受的实际参数比前一个函数多了不少！这个函数是不是更好？确实，但不一定必要，这取决于我们对程序的要求与约束。上面这个例子有点抽象，所以让我们看一个更简单明了的例子：\n\n```rust\nfn return_first(a: &str, b: &str) -> &str {\n    a\n}\n```\n\n报错：\n\n```rust\nerror[E0106]: missing lifetime specifier\n --> src/lib.rs:1:38\n  |\n1 | fn return_first(a: &str, b: &str) -> &str {\n  |                    ----     ----     ^ expected named lifetime parameter\n  |\n  = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `a` or `b`\nhelp: consider introducing a named lifetime parameter\n  |\n1 | fn return_first<'a>(a: &'a str, b: &'a str) -> &'a str {\n  |                ^^^^    ^^^^^^^     ^^^^^^^     ^^^\n```\n\n这个错误信息推荐我们给所有输入输出都标注上同样的生命周期注解。如果我们这么做了，那么程序将通过编译，但是这样写出的函数过度限制了返回类型。我们真正想要的是这个：\n\n```rust\nfn return_first<'a>(a: &'a str, b: &str) -> &'a str {\n    a\n}\n```\n\n**关键点回顾**\n- Rust 对 trait 对象的生命周期省略规则并不保证在任何情况下都正确\n- 在程序的语义方面，Rust 并不比你懂\n- Rust 编译错误的提示信息所提出的修复方案并不一定能满足你对程序的需求\n\n\n\n### 8) 生命周期可以在运行时动态变长或变短\n\n**错误的推论**\n- 容器类可以在运行时交换其内部的引用，从而改变自身的生命周期\n- Rust 借用检查器能进行高级的控制流分析\n\n这个编译不通过：\n\n```rust\nstruct Has<'lifetime> {\n    lifetime: &'lifetime str,\n}\n\nfn main() {\n    let long = String::from(\"long\");\n    let mut has = Has { lifetime: &long };\n    assert_eq!(has.lifetime, \"long\");\n\n    {\n        let short = String::from(\"short\");\n        // “转换到” 短的生命周期\n        has.lifetime = &short;\n        assert_eq!(has.lifetime, \"short\");\n\n        // “转换回” 长的生命周期（实际是并不是）\n        has.lifetime = &long;\n        assert_eq!(has.lifetime, \"long\");\n        // `short` 变量在这里 drop\n    }\n\n    // 编译失败， `short` 在 drop 后仍旧处于 “借用” 状态\n    assert_eq!(has.lifetime, \"long\");\n}\n```\n\n报错：\n\n```rust\nerror[E0597]: `short` does not live long enough\n  --> src/main.rs:11:24\n   |\n11 |         has.lifetime = &short;\n   |                        ^^^^^^ borrowed value does not live long enough\n...\n15 |     }\n   |     - `short` dropped here while still borrowed\n16 |     assert_eq!(has.lifetime, \"long\");\n   |     --------------------------------- borrow later used here\n```\n\n下面这个还是报错，报错信息也和上面一样：\n\n```rust\nstruct Has<'lifetime> {\n    lifetime: &'lifetime str,\n}\n\nfn main() {\n    let long = String::from(\"long\");\n    let mut has = Has { lifetime: &long };\n    assert_eq!(has.lifetime, \"long\");\n\n    // 这个代码块逻辑上永远不会被执行\n    if false {\n        let short = String::from(\"short\");\n        // “转换到” 短的生命周期\n        has.lifetime = &short;\n        assert_eq!(has.lifetime, \"short\");\n\n        // “转换回” 长的生命周期（实际是并不是）\n        has.lifetime = &long;\n        assert_eq!(has.lifetime, \"long\");\n        // `short` 变量在这里 drop\n    }\n\n    // 还是编译失败， `short` 在 drop 后仍旧处于 “借用” 状态\n    assert_eq!(has.lifetime, \"long\");\n}\n```\n\n生命周期必须在编译时被静态确定，而且 Rust 借用检查器只会做基本的控制流分析，所以它假设每个 `if-else` 块和 `match` 块的每个分支都能被执行，然后选出一个最短的生命周期赋给块中的变量。一旦一个变量被一个生命周期约束了，那么它将 _永远_ 被这个生命周期所约束。一个变量的生命周期只能缩短，而且所有的缩短时机都在编译时确定。\n\n**关键点回顾**\n- 生命周期在编译时被静态确定\n- 生命周期在运行时不能被改变\n- Rust 借用检查器假设所有代码路径都能被执行，所以总是选择尽可能短的生命周期赋给变量\n\n\n\n### 9) 将独占引用降级为共享引用是 safe 的\n\n**错误的推论**\n- 通过重借用引用内部的数据，能抹掉其原有的生命周期，然后赋一个新的上去\n\n你可以将一个独占引用作为参数传给一个接收共享引用的函数，因为 Rust 将隐式地重借用独占引用内部的数据，生成一个共享引用：\n\n```rust\nfn takes_shared_ref(n: &i32) {}\n\nfn main() {\n    let mut a = 10;\n    takes_shared_ref(&mut a); // 编译通过\n    takes_shared_ref(&*(&mut a)); // 上面那行去掉语法糖\n}\n```\n\n这在直觉上是合理的，因为将一个独占引用转换为共享引用显然是无害的，对吗？令人讶异的是，这并不对，下面的这段程序不能通过编译：\n\n```rust\nfn main() {\n    let mut a = 10;\n    let b: &i32 = &*(&mut a); // 重借用为不可变引用\n    let c: &i32 = &a;\n    dbg!(b, c); // 编译失败\n}\n```\n\n报错如下：\n\n```rust\nerror[E0502]: cannot borrow `a` as immutable because it is also borrowed as mutable\n --> src/main.rs:4:19\n  |\n3 |     let b: &i32 = &*(&mut a);\n  |                     -------- mutable borrow occurs here\n4 |     let c: &i32 = &a;\n  |                   ^^ immutable borrow occurs here\n5 |     dbg!(b, c);\n  |          - mutable borrow later used here\n```\n\n代码里确实有一个独占引用，但是它立即重借用变成了一个共享引用，然后自身就被 drop 掉了。但是为什么 Rust 好像把这个重借用出来的共享引用看作是有一个独占的生命周期呢？上面这个例子中，允许独占引用直接降级为共享引用是没有问题的，但是这个允许确实会导致潜在的内存安全问题。\n\n```rust\nuse std::sync::Mutex;\n\nstruct Struct {\n    mutex: Mutex<String>\n}\n\nimpl Struct {\n    // 将 self 的独占引用降级为 str 的共享引用\n    fn get_string(&mut self) -> &str {\n        self.mutex.get_mut().unwrap()\n    }\n    fn mutate_string(&self) {\n        // 如果 Rust 允许独占引用降级为共享引用，那么下面这一行代码执行后，\n        // 所有通过 get_string 方法返回的 &str 都将变为非法引用\n        *self.mutex.lock().unwrap() = \"surprise!\".to_owned();\n    }\n}\n\nfn main() {\n    let mut s = Struct {\n        mutex: Mutex::new(\"string\".to_owned())\n    };\n    let str_ref = s.get_string(); // 独占引用降级为共享引用\n    s.mutate_string(); // str_ref 失效，变成非法引用，现在是一个悬垂指针\n    dbg!(str_ref); // 当然，实际上会编译错误\n}\n```\n\n这里的关键点在于，你在重借用一个独占引用为共享引用时，就已经落入了一个陷阱：为了保证重借用得到的共享引用在其生命周期内有效，被重借用的独占引用也必须保证在这段时期有效，这延长了独占引用的生命周期！哪怕独占引用自身已经被 drop 掉了，但独占引用的生命周期却一直延续到共享引用的生命周期结束。\n\n使用重借用得到的共享引用是很难受的，因为它明明是一个共享引用但是却不能和其他共享引用共存。重借用得到的共享引用有着独占引用和共享引用的缺点，却没有二者的优点。我认为重借用一个独占引用为共享引用的行为应当被视为 Rust 的一种反模式。知道这种反模式是很重要的，当你看到这样的代码时，你就能轻易地发现错误了：\n\n```rust\n// 将独占引用降级为共享引用\nfn some_function<T>(some_arg: &mut T) -> &T;\n\nstruct Struct;\n\nimpl Struct {\n    // 将独占的 self 引用降级为共享的 self 引用\n    fn some_method(&mut self) -> &self;\n\n    // 将独占的 self 引用降级为共享的 T 引用\n    fn other_method(&mut self) -> &T;\n}\n```\n\n尽管你可以在函数和方法的声明里避免重借用，但是由于 Rust 会自动做隐式重借用，所以很容易无意识地遇到这种情况。\n\n```rust\nuse std::collections::HashMap;\n\ntype PlayerID = i32;\n\n#[derive(Debug, Default)]\nstruct Player {\n    score: i32,\n}\n\nfn start_game(player_a: PlayerID, player_b: PlayerID, server: &mut HashMap<PlayerID, Player>) {\n    // 从 server 中得到 player, 如果不存在就创建一个默认的 player 并得到这个新创建的。\n    let player_a: &Player = server.entry(player_a).or_default();\n    let player_b: &Player = server.entry(player_b).or_default();\n\n    // 对得到的 player 做一些操作\n    dbg!(player_a, player_b); // 编译错误\n}\n```\n\n上面这段代码会编译失败。这里 `or_default()` 会返回一个 `&mut Player`，但是由于我们添加了一个显式的类型标注，它会被隐式重借用成 `&Player`。而为了达成我们真正的目的，我们不得不这样做：\n\n```rust\nuse std::collections::HashMap;\n\ntype PlayerID = i32;\n\n#[derive(Debug, Default)]\nstruct Player {\n    score: i32,\n}\n\nfn start_game(player_a: PlayerID, player_b: PlayerID, server: &mut HashMap<PlayerID, Player>) {\n    // 因为编译器不允许这两个返回值共存，所有这里直接丢弃这两个 &mut Player\n    server.entry(player_a).or_default();\n    server.entry(player_b).or_default();\n\n    // 再次获取 player, 这次我们直接拿到共享引用，避免隐式的重借用\n    let player_a = server.get(&player_a);\n    let player_b = server.get(&player_b);\n\n    // 对得到的 player 做一些操作\n    dbg!(player_a, player_b); // 现在能编译通过了\n}\n```\n\n难用，而且很蠢，但这是我们为了内存安全这一信条所做出的牺牲。\n\n**关键点回顾**\n- 尽量避免重借用一个独占引用为共享引用，不然你会遇到很多麻烦\n- 重借用一个独占引用并不会结束其生命周期，哪怕它自身已经被 drop 掉了\n\n\n\n### 10) 对闭包的生命周期省略规则和函数一样\n\n这更像是 Rust 的陷阱而非误解\n\n尽管闭包可以被当作是一个函数，但是并不遵循和函数同样的生命周期省略规则。\n\n```rust\nfn function(x: &i32) -> &i32 {\n    x\n}\n\nfn main() {\n    let closure = |x: &i32| x;\n}\n```\n\n报错：\n\n```rust\nerror: lifetime may not live long enough\n --> src/main.rs:6:29\n  |\n6 |     let closure = |x: &i32| x;\n  |                       -   - ^ returning this value requires that `'1` must outlive `'2`\n  |                       |   |\n  |                       |   return type of closure is &'2 i32\n  |                       let's call the lifetime of this reference `'1`\n```\n\n去掉语法糖后，我们得到的是：\n\n```rust\n// 输入的生命周期应用到了输出上\nfn function<'a>(x: &'a i32) -> &'a i32 {\n    x\n}\n\nfn main() {\n    // 输入和输出有它们自己各自的生命周期\n    let closure = for<'a, 'b> |x: &'a i32| -> &'b i32 { x };\n    // 注意：上一行并不是合法的语句，但是我们需要它来描述我们目的\n}\n```\n\n出现这种差异并没有什么好处。只是在闭包最初的实现中，使用的类型推断语义与函数不同，而现在将二者做一个统一将是一个 breaking change, 因此现在已经没法改了。那么我们怎么显式地标注一个闭包的类型呢？我们有以下几种方案：\n\n```rust\nfn main() {\n    // 转换成 trait 对象，但这样是不定长的，所以会编译错误\n    let identity: dyn Fn(&i32) -> &i32 = |x: &i32| x;\n\n    // 可以分配到堆上作为替代方案，但是在这里堆分配感觉有点蠢\n    let identity: Box<dyn Fn(&i32) -> &i32> = Box::new(|x: &i32| x);\n\n    // 可以不用堆分配而直接创建一个 'static 引用\n    let identity: &dyn Fn(&i32) -> &i32 = &|x: &i32| x;\n\n    // 上一行去掉语法糖 :)\n    let identity: &'static (dyn for<'a> Fn(&'a i32) -> &'a i32 + 'static) = &|x: &i32| -> &i32 { x };\n\n    // 这看起来很完美，但可惜不符合语法\n    let identity: impl Fn(&i32) -> &i32 = |x: &i32| x;\n\n    // 这个也行，但也不符合语法\n    let identity = for<'a> |x: &'a i32| -> &'a i32 { x };\n\n    // 但是 \"impl trait\" 可以作为函数的返回值类型\n    fn return_identity() -> impl Fn(&i32) -> &i32 {\n        |x| x\n    }\n    let identity = return_identity();\n\n    // 上一个解决方案的泛化版本\n    fn annotate<T, F>(f: F) -> F where F: Fn(&T) -> &T {\n        f\n    }\n    let identity = annotate(|x: &i32| x);\n}\n```\n\n我想你应该注意到了，在上面的例子中，如果对闭包应用 trait 约束，闭包会和函数遵循同样的生命周期省略规则。\n\n这里没有什么现实的教训或见解，只是说明一下闭包是这样的。\n\n**关键点回顾**\n- 每个语言都有其陷阱 🤷\n\n\n### 11) `'static` 引用总能被强制转换为 `'a` 引用\n\n我之前有过这样的代码：\n\n```rust\nfn get_str<'a>() -> &'a str; // 泛型版本\nfn get_str() -> &'static str; // 'static 版本\n```\n\n一些读者联系我，问这两者之间是否有实际的差异。我一开始并不确定，但一番研究过后遗憾地发现，是的，这二者确实有差异。\n\n通常在使用值时，我们能用 `'static` 引用直接代替一个 `'a` 引用，因为 Rust 会自动把 `'static` 引用强制转换为 `'a` 引用。直觉上这很合理，因为在一个对生命周期要求比较短的地方用一个生命周期比较长的引用绝不会导致任何内存安全问题。下面的这段代码通过编译，和预期一致：\n\n```rust\nuse rand;\n\nfn generic_str_fn<'a>() -> &'a str {\n    \"str\"\n}\n\nfn static_str_fn() -> &'static str {\n    \"str\"\n}\n\nfn a_or_b<T>(a: T, b: T) -> T {\n    if rand::random() {\n        a\n    } else {\n        b\n    }\n}\n\nfn main() {\n    let some_string = \"string\".to_owned();\n    let some_str = &some_string[..];\n    let str_ref = a_or_b(some_str, generic_str_fn()); // 编译通过\n    let str_ref = a_or_b(some_str, static_str_fn()); // 编译通过\n}\n```\n\n然而当引用作为函数类型签名的一部分时，强制类型转换并不生效。所以下面这段代码不能通过编译：\n\n```rust\nuse rand;\n\nfn generic_str_fn<'a>() -> &'a str {\n    \"str\"\n}\n\nfn static_str_fn() -> &'static str {\n    \"str\"\n}\n\nfn a_or_b_fn<T, F>(a: T, b_fn: F) -> T\n    where F: Fn() -> T\n{\n    if rand::random() {\n        a\n    } else {\n        b_fn()\n    }\n}\n\nfn main() {\n    let some_string = \"string\".to_owned();\n    let some_str = &some_string[..];\n    let str_ref = a_or_b_fn(some_str, generic_str_fn); // 编译通过\n    let str_ref = a_or_b_fn(some_str, static_str_fn); // 编译错误\n}\n```\n\n报错如下：\n\n```rust\nerror[E0597]: `some_string` does not live long enough\n  --> src/main.rs:23:21\n   |\n23 |     let some_str = &some_string[..];\n   |                     ^^^^^^^^^^^ borrowed value does not live long enough\n...\n25 |     let str_ref = a_or_b_fn(some_str, static_str_fn);\n   |                   ---------------------------------- argument requires that `some_string` is borrowed for `'static`\n26 | }\n   | - `some_string` dropped here while still borrowed\n```\n\n很难说这是不是 Rust 的一个陷阱，把 `for<T> Fn() -> &'static T` 强制转换成 `for<'a, T> Fn() -> &'a T` 并不是一个像把 `&'static str` 强制转换为 `&'a str` 这样简单直白的情况。前者是类型之间的转换，后者是值之间的转换。\n\n**关键点回顾**\n- `for <'a，T> fn（）->＆'a T` 签名的函数比 `for <T> fn（）->＆'static T` 签名的函数要更灵活，并且泛用于更多场景\n\n\n\n## 总结\n\n- `T` 是 `&T` 和 `&mut T` 的超集\n- `&T` 和 `&mut T` 是不相交的集合\n- `T: 'static` 应当视为 _“`T` 满足 `'static` 生命周期约束”_\n- 若 `T: 'static` 则 `T` 可以是一个有 `'static` 生命周期的引用类型 _或_ 是一个所有权类型\n- 因为 `T: 'static` 包括了所有权类型，所以 `T`\n    - 可以在运行时动态分配\n    - 不需要在整个程序运行期间都有效\n    - 可以安全，自由地修改\n    - 可以在运行时被动态的 drop\n    - 可以有不同长度的生命周期\n- `T: 'a` 比 `&'a T` 更泛化，更灵活\n- `T: 'a` 接受所有权类型，内部含有引用的所有权类型，和引用\n- `&'a T` 只接受引用\n- 若 `T: 'static` 则 `T: 'a` 因为对于所有 `'a` 都有 `'static` >= `'a`\n- 几乎所有的 Rust 代码都是泛型代码，并且到处都带有被省略掉的泛型生命周期注解e\n- Rust 生命周期省略规则并不保证在任何情况下都正确\n- 在程序的语义方面，Rust 并不比你懂\n- 可以试试给你的生命周期注解起一个有意义的名字\n- 试着记住你在哪里添加了显式生命周期注解，以及为什么要\n- 所有 trait 对象都含有自动推导的生命周期\n- Rust 编译错误的提示信息所提出的修复方案并不一定能满足你对程序的需求\n- 生命周期在编译时被静态确定\n- 生命周期在运行时不能被改变\n- Rust 借用检查器假设所有代码路径都能被执行，所以总是选择尽可能短的生命周期赋给变量\n- 尽量避免重借用一个独占引用为共享引用，不然你会遇到很多麻烦\n- 重借用一个独占引用并不会结束其生命周期，哪怕它自身已经被 drop 掉了\n- 每个语言都有其陷阱 🤷\n- `for <'a，T> fn（）->＆'a T` 签名的函数比 `for <T> fn（）->＆'static T` 签名的函数要更灵活，并且泛用于更多场\n\n\n\n## 讨论\n\n可以在这些地方进行讨论\n- [learnrust subreddit](https://www.reddit.com/r/learnrust/comments/gmrcrq/common_rust_lifetime_misconceptions/)\n- [official Rust users forum](https://users.rust-lang.org/t/blog-post-common-rust-lifetime-misconceptions/42950)\n- [Twitter](https://twitter.com/pretzelhammer/status/1263505856903163910)\n- [rust subreddit](https://www.reddit.com/r/rust/comments/golrsx/common_rust_lifetime_misconceptions/)\n- [Hackernews](https://news.ycombinator.com/item?id=23279731)\n- [Github](https://github.com/pretzelhammer/rust-blog/discussions)\n\n\n\n## 拓展阅读\n\n- [Sizedness in Rust](./sizedness-in-rust.md)\n- [2020 年的 Rust 学习指南](./learning-rust-in-2020.md)\n- [Learn Assembly with Entirely Too Many Brainfuck Compilers](./too-many-brainfuck-compilers.md)\n\n## 译者注\n\n本文参考了\n- [whfuyn 的译文](https://github.com/whfuyn/rust-blog/blob/master/posts/Rust生命周期的常见误解.md)\n- [Rust 语言术语中英文对照表](https://rustwiki.org/zh-CN/rust-wiki/translate/english-chinese-glossary-of-rust.html)\n- [The book 中文版](https://kaisery.github.io/trpl-zh-cn/)\n\n文中部分语句采用意译，部分单词不译。\n"
  },
  {
    "path": "posts/translations/zh-hans/learning-rust-in-2020.md",
    "content": "# 2020 年的 Rust 学习指南\n\n_2020年 5月 9日 · #rust · #programming · #exercises_\n\n**目录**\n- [前言](#前言)\n- [省流](#省流)\n- [Rust 练习平台比较](#rust-练习平台比较)\n    - [HackerRank](#hackerrank)\n    - [Project Euler](#project-euler)\n    - [LeetCode](#leetcode)\n    - [Codewars](#codewars)\n    - [Advent of Code](#advent-of-code)\n    - [Rustlings](#rustlings)\n    - [Exercism](#exercism)\n- [结论](#结论)\n- [讨论](#讨论)\n- [参阅](#参阅)\n\n\n\n## 前言\n\n我开始学习 Rust 时犯了一个错误：\n完全按照 [Rust 程序设计语言](https://rustwiki.org/zh-CN/book/) 的指导学习。\n虽然这本书确实不错，但是跟一个初学者讲“先啃下这本只有 20 章的小书”还是太劝退了，\n很多人因此刚入门就入土了。可没人跟 Javascript 或 Python 初学者说什么\n“先啃下这本只有 20 章的小书”。\nRust 确实很难入门，但是比起读20章的“小书”，大家更希望先试试。\n编程很有趣，但是读书很无聊，尤其是20章的“小书”。\n\n本文的前 10% 是一点建议，帮助你在 2020 年通过 *练习* 上手 Rust。\n读完之后你就可以退出了（下文会告诉你在哪里退出）。\n之后是关于各大 OJ 平台对 Rust 支持程度的意见和个人排名。\n\n\n\n## 省流\n\n如果你之前完全没了解过Rust，想要尽可能多学点，\n可以读 fasterthanlime 的[《A half-hour to learn Rust》](https://fasterthanli.me/blog/2020/a-half-hour-to-learn-rust/)，\n然后看看 [Rustlings](https://github.com/rust-lang/rustlings) 并完成练习。\n\n如果你刚开始学习，应该去看看 [Exercism.io 的 Rust 练习](https://exercism.io/tracks/rust)。\n如果遇到了困难，可以问问 Google 或者 StatckOverflow。\n建议花点儿时间简单看看 [Rust 标准库文档](https://doc.rust-lang.org/std),\n里面有很多简单的例子，帮助你更好地学习标准库。\n[《Rust by Example》](https://doc.rust-lang.org/rust-by-example/) \n也很好地阐述了 Rust 的语法和特性。\n如果想要深入理解 Rust 的某个概念，\n可以在[Rust 程序设计语言](https://rustwiki.org/zh-CN/book/)中检索相关章节。\nExercism.io 的好处是可以看到其他人的解法，并通过 Star 数找到优秀的题解加以学习，\n这个方法很好！\n\n现在，你已经初步进入了 Rust 抽象之塔的大门，并且可以自己继续前进。\n如果想尝试编写一些小程序，需要更多指导，建议完成 [Advent of Code 2018 Calendar](https://adventofcode.com/2018) \n推荐 2018 Calendar 的原因是完成之后可以参考 [BurntSushi 的 Advent of Code 2018 Calendar Rust 题解](https://github.com/BurntSushi/advent-of-code)。\n他的代码简洁干净，易于阅读。\n阅读优秀的 Rust 代码可以让你学到和自己写一遍不相上下的经验。\n\n可以退出了。\n\n（译注：中文学习者可以考虑 [Rust 圣经](https://course.rs/about-book.html) ）\n\n\n\n## Rust 练习平台比较\n\n_又名：对供 Rust 初学者练习编写简单代码的免费在线资源的比较_\n\n以下大部分平台都不是专门为 Rust 搭建的，但是仍然可以用于学习 Rust，\n且大部分平台明确地支持 Rust 并提供题目的 Rust 变体。\n\n以下平台从差到好排序。\n\n\n\n### [HackerRank](https://www.hackerrank.com)\n\n支持 Rust，但大部分题目不支持 Rust 题解。\n尝试提交题解，被当场拒绝：\n\n![建 议 改 为： FailRank](../../../assets/hackerrank-more-like-failrank.png)\n\n6。可以看到别人的，但是不能上传自己的。\nGoogle 了一圈，未能发现有用的信息，建议直接放弃。\n\n\n### [Project Euler](https://projecteuler.net/archives)\n\n当年我开始学习编程时（2012年），我经常听到“快速学编程，上Project Euler！”之类的话。\n当年确实没多少选择，但我认为 Projet Euler 更侧重于数学，而不是编程。\n不建议，除非数学很好。\n\n\n\n### [LeetCode](https://leetcode.com/problemset/all/)\n\nLeetCode 支持 Rust。\n在 LeetCode 上，每题有一个答案模板，包含一个待实现函数，\n需要实现所有函数，然后提交。\n更复杂的题目可能会包含一个 `struct` 和一个 `impl`，包含几个待实现方法。\n可惜，这些模板由机器生成，而不是人类。这导致这些模板良莠不齐，比如：\n\n| LeetCode 生成的 Rust | 一般的 Rust |\n|-|-|\n| 树相关问题用 `Option<Rc<RefCell<Node>>>` 表示边。 |  `Option<Box<Node>>` 更简单好用。 |\n| 借用可变性错误： `fn insert(&self, val: i32)` | 应用可变借用： `fn insert(&mut self, val: i32)` |\n| 总是使用有符号数，即使题目不关心负数。 `fn nth_fib(n: i32) -> i32` | 应用无符号数： `fn nth_fib(n: u32) -> u32` |\n| 总是吃掉参数的所有权： `fn sum(nums: Vec<i32>) -> i32` | 只需要借用就好： `fn sum(nums: &[i32]) -> i32` |\n| 忽略特殊情况：`nums` 为空时 `fn get_max(nums: Vec<i32>) -> i32` 的返回值未定义 | 应用 `Option` 包裹返回值： `fn get_max(nums: &[i32]) -> Option<i32>` |\n\nRust 特供槽点：\n- 禁止引入依赖，即使是像 Rust 这样标准库里连正则表达式都没有的语言；\n- 禁止向 `concurrency` 分区里的题提交题解。众所周知，安全高效的并发是 Rust 的一大亮点。\n- 很少有 Rust 题解。（因为过于小众？）\n\n统一槽点：\n- 有很多低质量题目。用户可以为题解点赞或点踩，但题目不会被删除。\n  有这么一道题，有 100 多个评价，八成都是踩，却像在数据库里长了根一样。\n- 题目难度不准。有三等：Easy（简单）、Medium（中等）和 Hard（困难），\n  但是很多 Easy 题 AC 率比 Hard 题还低。\n- 不是所有题都支持用所有语言提交，且无法通过支持的语言筛选题目。\n  比如，所有图论题都不支持 Rust。\n- 需要按月付费才能查看“premium”题，但是没有任何试用期，\n  所以没有办法提前判断是否有必要交钱。\n\n优点：\n- 可以查看 WA 测试点。\n- 所有 Rust 代码模板均符合 rustfmt 的要求。\n\n\n\n### [Codewars](https://www.codewars.com/join?language=rust)\n\nCodewars 这个名字容易让人误解。Codewars 上没有什么 war（*n.* 战争）。\n答案不会 TLE，也不会用时间或内存用量排名。人与人之间没有竞争——这并不是什么坏事。\n\nCodewars 支持 Rust。所有题目都提供一个答案模板，通常包含一个待实现函数。\n答案模板是人工编写的，但编写模板的人不一定熟悉 Rust，\n所以时不时会冒出一些没那么好的模板，例如：\n\n| Codewars 的部分 Rust 答案模板 | 一般的 Rust |\n|-|-|\n| 不遵守 rustfmt 要求： `fn makeUppercase(s:&str)->String` | 用 rustfmt 格式化：`fn make_uppercase(s: &str) -> String` |\n| 使用有符号数，即使题目不关心负数。 `fn nth_fib(n: i32) -> i32` | 应用无符号数： `fn nth_fib(n: u32) -> u32` |\n| 用 `-1` 表示未找到：`fn get_index(needle: i32, haystack: &[i32]) -> i32` | 应用 `Option::None`：`fn get_index(needle: i32, haystack: &[i32]) -> Option<usize>` |\n| 使用一般的引用：`fn do_stuff(s: &String, list: &Vec<i32>)` | 使用切片：`fn do_stuff(s: &str, list: &[i32])` |\n\n因为 Codewars 上编写模板的人水平良莠不齐，所以时不时会有以上问题，至少比 LeetCode 好多了（后者是“时不时没有问题”）。\n但是，写 Rust 的 Codewars 用户普遍经验不足，时不时会有质量较低的高赞题解，例如：\n\n| Codewars 上题目的高赞 Rust 题解 | 一般的 Rust |\n|-|-|\n| 在代码块最后使用 `return result;` | `return` 和分号可省略：`result` |\n| 通过删减空格使题解显得更加“简洁” | 遵守 rustfmt 规范 |\n| 无用内存分配：`str_slice.to_string().chars()` | 不分配：`str_slice.chars()` |\n| 迭代器上瘾 | 当迭代器太多时应该重构 |\n\n重复：只是“时不时”。有经验的 Rustacean 可以一眼看穿以上问题，但有很多 Rust 新手不能。\n\nRust 特供槽点：\n- 在 Codewars 上 Rust 还很小众，一共九千多题，只有三百多题有 Rust 版本 :(\n\n统一槽点：\n- 无法看到 WA 测试点。如果这个测试点刚好是一个边界情况，题目又没有讲清楚，就很烦人了。\n\n优点：\n- 可以使用以下第三方库解 Rust 题目：rand、chrono、regex、serde、itertools 和 lazy_static，使 Rust 的功能赶上其他语言。\n- 可以按语言筛选题目。\n- 答案通过时会自动发布为题解。可以查看他人的题解。可以按赞数排序题解，方便看简洁聪明（而且很多时候也很优雅）的题解。\n- 问题难度的设计十分优雅！与 LeetCode 不同，Codewars 用 8 kyu 到 1 kyu 从简单到困难排序。我完成了很多 8～4 kyu 的题，每一 kyu 的题都刚好比上一 kyu 难一点，符合我的预期。\n\n\n\n### [Advent of Code](https://adventofcode.com/)\n\nAdvent of Code 的题目语言无关。也许刚开始这像一个扣分项，\n但是和前面几个做一下对比，你就知道这多么先进了。\nAdvent of Code 的题目也得到了上面一些平台的收录，因为它们确实又有趣有优秀。\n\n槽点：\n- 不提供题解，想看得自己搜，搜了也不知道好不好。\n\n建议完成 2018 Calendar 然后把答案和 [BurntSushi 的](https://github.com/BurntSushi/advent-of-code)\n做对比。BurntSushi 的代码干净整洁，可读性强。\n如果想做 2019 Calendar，可以用 [bcmyers 的答案](https://github.com/bcmyers/aoc2019)\n做参考。\n推荐他的原因是他做了 [一系列关于这些题目解法的视频](https://www.youtube.com/playlist?list=PLQXBtq4j4Ozkx3r4eoMstdkkOG98qpBfg)，\n而且讲得很好。\n\n优点：\n- 高质量、有趣且精心策划的题目；\n- 语言无关，所以虽然不会有高质量代码，但至少不会冒出来不规范的代码。\n\n\n\n### [Rustlings](https://github.com/rust-lang/rustlings)\n\nRustlings 非常好。Rustling 上的所有题目都专门为 Rust 所编写。\n而且，它真的是奔着教会你优雅的代码去的！\n\n如果你是一个完全的 Rust 萌新，你肯定要做一做 [Rustlings](https://github.com/rust-lang/rustlings)\n上的练习。极力推荐 [fasterthanlime 的 《A half hour to learn Rust》](https://fasterthanli.me/blog/2020/a-half-hour-to-learn-rust)，\n可以帮你快速了解很多 Rust 的语法和概念。\n\n只有一个小缺陷：在“error-handling”和“conversions”几节难度忽然飙升，\n让很多人不知所措。希望大家都能挺过去。\n\n也有一个小建议（不是批评）：太短了。之所以不是批评，是因为 Rustlings 的目标就是\n快速帮人入门 Rust。但是它真的写得太好了，希望多来点儿。\n\n\n\n### [Exercism](https://exercism.io/tracks/rust)\n\nExercism 有一个 “Rust track”，就是一列题目，大致按难度排序。\nRust track 和其他 tracks 共享很多题目，但是所有题目均由专业人员译为 Rust 题目，\n不会出现像 LeetCode 和 Codewars 那样的问题。\n有十几道题需要实现标准库 trait，写几个宏，写点多线程并发，或者 `unsafe {}`。\n这些题目是这个 track 的亮点，希望多来点。\nExercism 仅次于 Rustlings。将它排在 Rustlings 后面的唯一原因是 Rustlings 一晚上就可以完成，\n但 Exercism 的 Rust track 需要至少一个月。\n\nRust 特供槽点：\n- 因为很多指导员不活跃，“指导模式”基本没用，不如用“练习模式”。\n- 大约有 92 道题，但其中有很多题并没有新东西，像在做无用功，不如删掉二十几题。\n\n优点：\n- 所有题目均有专业人士译为 Rust 题目。\n- 有专门讲 Rust 引入的新东西的题目。\n- 题目分级准确。\n- 可以随意引入第三方库。\n- 所有测试点均公开，可以知道错在哪了；\n- 可以浏览其他用户的题解，并按 star 数排序。\n\n\n\n## 结论\n\n同 [TL;DR](#tldr) :)\n\n\n\n## 讨论\n\n在以下区域讨论本文：\n- [learnrust subreddit](https://www.reddit.com/r/learnrust/comments/ggj8tf/learning_rust_in_2020/)\n- [official Rust users forum](https://users.rust-lang.org/t/blog-post-learning-rust-in-2020/42373)\n- [rust subreddit](https://www.reddit.com/r/rust/comments/gie64f/learning_rust_in_2020/)\n- [Hackernews](https://news.ycombinator.com/item?id=23160975)\n- [Github](https://github.com/pretzelhammer/rust-blog/discussions)\n\n\n## 参阅\n\n- [Rust 中常见的有关生命周期的误解](./common-rust-lifetime-misconceptions.md)\n- [Rust 标准库特性指南](./tour-of-rusts-standard-library-traits.md)\n- [Sizedness in Rust](./../../sizedness-in-rust.md)\n- [RESTful API in Sync & Async Rust](./restful-api-in-sync-and-async-rust.md)\n- [Learn Assembly with Entirely Too Many Brainfuck Compilers](./too-many-brainfuck-compilers.md)\n"
  },
  {
    "path": "posts/translations/zh-hans/learning-rust-in-2024.md",
    "content": "# 2024 年的 Rust 学习指南\n\n_2024 年 9 月 21 日 · #rust · #coding · #exercises_\n\n**目录**\n\n- [TL; DR](#tl-dr)\n- [0）参考资料](#0参考资料)\n- [1）阅读 《半小时学会 Rust》](#1阅读-半小时学会-rust)\n- [2）完成 rustlings](#2完成-rustlings)\n- [3）花 10 小时编写 Rust 代码](#3花-10-小时编写-rust-代码)\n  - [100 个练习学会 Rust](#100-个练习学会-rust)\n  - [Exercism 上的 Rust 课程](#exercism-上的-rust-课程)\n  - [Advent of Code](#advent-of-code)\n    - [设置](#设置)\n    - [2020 年](#2020-年)\n    - [2022 年](#2022-年)\n  - [教程](#教程)\n- [4）阅读 《常见的 Rust 生命周期误解》](#4阅读-常见的-rust-生命周期误解)\n- [5）再花 10 小时用 Rust 编程](#5再花-10-小时用-rust-编程)\n- [6）阅读 《导览 Rust 标准库特征》](#6阅读-导览-rust-标准库特征)\n- [接下来做什么？](#接下来做什么)\n- [荣誉提名](#荣誉提名)\n  - [Tour of Rust](#tour-of-rust)\n  - [Comprehensive Rust](#comprehensive-rust)\n  - [Rust 模块系统的清晰解释](#rust-模块系统的清晰解释)\n- [讨论](#讨论)\n- [进一步阅读](#进一步阅读)\n\n这是我的个人指南，教你如何尽快从对 Rust 一无所知到不错的水平。如果我是今天开始学 Rust，那我也会告诉自己这些东西。\n\n## TL; DR\n\n1. 阅读 [《半小时学会 Rust》](https://fasterthanli.me/articles/a-half-hour-to-learn-rust)（30 - 60 分钟）\n2. 完成 [rustlings](https://github.com/rust-lang/rustlings)（2 - 3 小时）\n3. 花 10 小时用 Rust 编程（8 - 12 小时）\n4. 阅读 [《常见的 Rust 生命周期误解》](./common-rust-lifetime-misconceptions.md)（30 - 60 分钟）\n5. 再花 10 小时用 Rust 编程（8 - 12 小时）\n6. 阅读 [《导览 Rust 标准库特征》](./tour-of-rusts-standard-library-traits.md)（2 - 4 小时）\n\n按这样的过程，经过短短的 19 到 30 小时，你将从 Rust 初学者变成 Rust 高级初学者 😎\n\n## 0）参考资料\n\n学习 Rust 时，建议在浏览器中打开 [Rust by Example](https://doc.rust-lang.org/rust-by-example/index.html) 和 [Rust 标准库文档](https://doc.rust-lang.org/std/)。如果你遇到问题，可以在这两个资源中搜索答案。它们的顶部都有搜索栏，方便你快速查找。\n\n其它不错的选择还有 StackOverflow 和 ChatGPT（或者其它你更喜欢的大型语言模型）。几乎每个 Rust 初学者的问题，都在 StackOverflow 上被提问过并得到回答。它们都可以通过 Google 搜索到。至于 ChatGPT，尽管有一半的时间可能给出错误答案，但至少能为你指明大致方向，让你知道下一步去哪里搜索答案。\n\n如果你尝试了以上所有方式，但仍无法解决问题，那可以去一些适合初学者的 Rust 在线社区：[r/rust](https://www.reddit.com/r/rust/) 子版块，[r/learnrust](https://www.reddit.com/r/learnrust/) 子版块，以及 [官方 Rust 用户论坛](https://users.rust-lang.org/)。\n\n另外，最好在浏览器标签页中打开 [Rust Playground](https://play.rust-lang.org/)。这是一个在线的 Rust 代码编辑器和编译器。它非常适合用来调试小的示例，以巩固你在阅读时学到的知识。\n\n## 1）阅读 [《半小时学会 Rust》](https://fasterthanli.me/articles/a-half-hour-to-learn-rust)\n\n相比其他资源，我更推荐 [《半小时学会 Rust》](https://fasterthanli.me/articles/a-half-hour-to-learn-rust)。它以一种非常系统和循循渐进的方法介绍 Rust 的语法和概念。它从最简单的例子开始，并在后续的例子中逐渐增加复杂性。这种安排非常符合逻辑，也易于理解。\n\n## 2）完成 [rustlings](https://github.com/rust-lang/rustlings)\n\n[Rustlings](https://github.com/rust-lang/rustlings) 是一组按序编排的 Rust 编程小练习。每个练习都是一段无法编译或未能通过单元测试的 Rust 代码。你的任务是修复这些代码，使其能够编译并通过单元测试。\n\n开始 rustlings 之前，你需要安装 Rust。我建议使用 [rustup](https://rustup.rs/) 来管理 Rust 的安装。一旦安装了 `rustup`，你只需要运行 `rustup update`，就能随时更新你机器上的 Rust。\n\n用 Rust 编程时，你可以使用任何你喜欢的代码编辑器。但我建议使用支持 [rust-analyzer](https://rust-analyzer.github.io/) 的编辑器。我使用 [VS Code](https://code.visualstudio.com/)，并安装了 [这个扩展](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer) 来启用 rust-analyzer。\n\n使用 rustlings 非常简单，可以用 `cargo` 来安装它。Cargo 是 Rust 的依赖管理器和构建工具，随 Rust 一起安装。如果你使用 `rustup` 安装 Rust，那么你也会同时会安装 Cargo。\n\n运行 `cargo install rustlings` 来安装 rustlings。默认情况下，rustlings 的二进制文件会被放在 `$HOME/.cargo/bin` 中。因此，如果这个路径不在你的 `$PATH` 变量中，那你应该添加进去，例如：\n\n```sh\nexport PATH=\"$HOME/.cargo/bin:$PATH\"\n```\n\n现在运行 `rustlings`，它将为你创建一个 `rustlings/` 目录，里面包含了所有的练习。在代码编辑器中打开该目录，然后在目录内运行命令 `rustlings`，并按照其指示操作，它会告诉你应该做哪个练习。完成当前的练习后，命令会告诉你接下来应该做哪个练习。重复这个过程，直到你全部完成。\n\n## 3）花 10 小时编写 Rust 代码\n\n你可以编写任何代码。但对于你的前 10 小时，我建议使用单线程同步的 Rust。这里面有足够新颖且具有挑战性的 Rust 概念\\*，足以让你至少忙上 10 小时。很多人甚至需要更长的时间才能完全理解。多线程异步 Rust 引入了更多复杂概念\\*\\*，在基础知识不牢固之前就开始学习，很容易让人感到不知所措。\n\n\\*：所有权（ownership）、借用（borrowing）、生命周期（lifetimes）、生命周期省略（lifetime elision）、可变与不可变引用（mutable vs immutable references）、固定大小（sizedness）、解引用强制转换（deref coercion）、特征（traits）、特征对象（trait objects）、泛型（generics）、常量泛型（const generics）、静态与动态分派（static vs dynamic dispatch）、错误处理（error handling）、迭代器（iterators）、模块（modules）、声明宏（declarative macros）、过程宏（procedural macros）...\n\n\\*\\*：futures、固定（pinning）、轮询（polling）、异步等待（awaiting）、send、sync、取消（cancellation）、流（streams）、sinks、锁（locks）、原子数（atomics）、通道（channels）、actors ...\n\n如果你不知道要写什么代码，那么我有一些建议。\n\n### [100 个练习学会 Rust](https://rust-exercises.com/100-exercises/)\n\n如果你喜欢 rustlings 的难度和节奏，那么你会喜欢《100 个练习学会 Rust》（100 Exercises To Learn Rust，100ELR）。尽管由不同的作者制作，但 100ELR 显然从 rustlings 获得了大量的灵感，更像是后者的延续，。\n\n开始 100 ELR，首先要克隆 [mainmatter/100-exercises-to-learn-rust](https://github.com/mainmatter/100-exercises-to-learn-rust) 仓库到你的机器上，接着使用 `cargo install --locked workshop-runner` 安装测试套件的运行程序，然后就能开始阅读 [配套书籍](https://rust-exercises.com/100-exercises/) 了。它有 100 章，每章结束时，都会告诉你在仓库中做哪个练习。完成一个练习后，在项目根目录运行 `wr` 来检查你的解答是否通过了单元测试，如果通过了，就继续下一章。重复这个过程，直到你完成所有练习。\n\n虽然 100 个章节听起来很多，但它们都很短，所以你会比想象中更快地完成它们。大多数人来说。完成整本书可能需要 15 到 25 小时。\n\n然而，如果你觉得 rustlings 太简单，并且想尝试更具挑战性的东西，那么你可能想要跳过 100ELR。\n\n### Exercism 上的 [Rust 课程](https://exercism.org/tracks/rust)\n\n除了 rustlings 和 100ELR 之外，Exercism 上的 [Rust 课程](https://exercism.org/tracks/rust) 是互联网上最好的 Rust 小练习。它的优秀在于，许多练习是由 Rustaceans（指 Rust 开发者，译者注）制作的，旨在教你 Rust 相较于其它编程语言的独特之处。有一个练习要求你编写一个声明式宏！甚至有一个练习要求你编写不安全的代码！\n\n为了开始该课程，你需要在 Exercism 上注册账户，并加入 Rust 课程（两者都是免费的）。然后，你可以用 Exercism 的在线代码编辑器完成练习，或者将练习下载到你的机器上，使用自己的代码编辑器完成它们，并通过 `exercism` cli 工具将解答提交到 Exercism 上。\n\n我建议使用 `exercism` cli 工具。它有很多优点。首先，你的代码编辑器有 rust-analyzer，而 Exercism 的在线代码编辑器没有。其次，你可以在编辑器中使用暗黑模式，但在 Exercism 上只有付费后才能使用（这是高级功能）。第三，你可以使用 git 跟踪你的解答。第四，在编写答案时，你可以选择运行哪些单元测试，而不是每次都运行完整的测试套件。[这里](https://exercism.org/docs/using/solving-exercises/working-locally) 是如何在本地机器上进行练习的官方说明。\n\nExercism 上的每个练习都有一个「学习模式」和「练习模式」。目前，由于 Exercism 团队正在重新设计，Rust 课程的「学习模式」已被禁用。但不管如何，我认为「练习模式」更好，因为它允许你按任意顺序进行练习。虽然现在没有选择，但如果将来 Rust 课程的「学习模式」和「练习模式」重新开放，我建议选择「练习模式」。\n\n虽然 Rust 课程上的练习是按序的，但这个顺序是任意的，是否遵循并不重要。除了 [Luhn](https://exercism.org/tracks/rust/exercises/luhn)，[Luhn From](https://exercism.org/tracks/rust/exercises/luhn-from)，和 [Luhn Trait](https://exercism.org/tracks/rust/exercises/luhn-trait) 以外，所有其他的练习都彼此无关，可以按任何顺序完成。\n\n完成练习后最好的地方，是去浏览和点赞其他人的解答。我建议完成练习后看看它们，尤其是那些点赞最多的解答，可以教你一些你没有发现的优雅和惯用的 Rust 写法。\n\n练习按难度分为：简单、中等和困难。目前 Rust 课程共有 99 个练习，我认为有 30 个非常好，其他的 59 个只是从其他课程中复制粘贴过来的普通练习。完成整个课程的人占比不到 0.1%。如果完成一半的人不到 1%，我也丝毫不会吃惊。我已经完成了所有练习。考虑到你可能不会完成所有练习，所以我将推荐我认为最好的那些。\n\n你应该从简单练习开始。难度方面，它们比你在 rustlings 或 100ELR 中的稍微更具挑战性。质量方面，它们都还不错。完成任何一个简单练习都不会超过 20 分钟。另外，如果完成简单练习不再让你感到有收获，那就转到中等练习。不要强迫自己完成所有的简单练习。\n\n就中等难度而言，以下是我个人认为的最好练习（排名不分先后）：\n\n- [PaaS I/O](https://exercism.org/tracks/rust/exercises/paasio)\n- [Simple Linked List](https://exercism.org/tracks/rust/exercises/simple-linked-list)\n- [Fizzy](https://exercism.org/tracks/rust/exercises/fizzy)\n- [Parallel Letter Frequency](https://exercism.org/tracks/rust/exercises/parallel-letter-frequency)\n- [Macros](https://exercism.org/tracks/rust/exercises/macros)\n- [Robot Name](https://exercism.org/tracks/rust/exercises/robot-name)\n- [Triangle](https://exercism.org/tracks/rust/exercises/triangle)\n- [Robot Simulator](https://exercism.org/tracks/rust/exercises/robot-simulator)\n- [Accumulate](https://exercism.org/tracks/rust/exercises/accumulate)\n- [Word Count](https://exercism.org/tracks/rust/exercises/word-count)\n- [Grep](https://exercism.org/tracks/rust/exercises/grep)\n- [Luhn](https://exercism.org/tracks/rust/exercises/luhn)\n- [Luhn From](https://exercism.org/tracks/rust/exercises/luhn-from)\n- [Luhn Trait](https://exercism.org/tracks/rust/exercises/luhn-trait)\n- [Clock](https://exercism.org/tracks/rust/exercises/clock)\n- [Space Age](https://exercism.org/tracks/rust/exercises/space-age)\n- [Sublist](https://exercism.org/tracks/rust/exercises/sublist)\n- [Binary Search](https://exercism.org/tracks/rust/exercises/binary-search)\n- [ETL](https://exercism.org/tracks/rust/exercises/etl)\n- [Grade School](https://exercism.org/tracks/rust/exercises/grade-school)\n- [Hamming](https://exercism.org/tracks/rust/exercises/hamming)\n- [Isogram](https://exercism.org/tracks/rust/exercises/isogram)\n- [Nucleotide Count](https://exercism.org/tracks/rust/exercises/nucleotide-count)\n\n根据你选择的练习，完成时间可能需要 10 到 45 分钟。\n\n当你准备好再次提高难度时，以下是我认为最好的困难练习（排名不分先后）：\n\n- [Xorcism](https://exercism.org/tracks/rust/exercises/xorcism)\n- [React](https://exercism.org/tracks/rust/exercises/react)\n- [Circular Buffer](https://exercism.org/tracks/rust/exercises/circular-buffer)\n- [Forth](https://exercism.org/tracks/rust/exercises/forth)\n- [Doubly Linked List](https://exercism.org/tracks/rust/exercises/doubly-linked-list)\n\n根据你选择的练习，完成时间可能需要 30 到 90 分钟。\n\n完成一系列简单练习，再加上我推荐的中等和困难练习，大概会花费约 20 小时。完成整个课程可能需要两倍的时间，约 40 小时。话虽如此，如果你觉得自己开始失去兴趣，就不要勉强自己完成整个课程。此时最好调整方向，尝试 Rust 的其它东西。学习过程中最重要的事，是保持乐趣。\n\n### [Advent of Code](https://adventofcode.com/)\n\n[Advent of Code](https://adventofcode.com/)（AoC）是一组编程谜题。自 2015 年起，每年从 12 月 1 日到 25 日，每天都会发布一个新的谜题，每个谜题有两个部分。每年的前 10-15 个谜题往往是简单或中等难度，最后 10-15 个谜题通常很难。谜题被设计成与语言无关，意味着你可以使用任何编程语言来解决。如果你的目标是学习 Rust，那么仅完成谜题并不会给你太多帮助。但如果完成一个谜题后，再看看一位经验丰富的 Rustacean 的解决方案，就可能会帮你学到 Rust 的很多知识。\n\n在这里，这位经验丰富的 Rustacean 就是 fasterthanlime。他不仅发布了 2020 年和 2022 年 AoC 谜题的解答，还写了一些面向初学者的博客文章，解释每个谜题的解决思路。如果你打算通过 AoC 学习 Rust，那么你应该从 2020 年的谜题开始，在完成每个谜题后，阅读 fasterthanlime 对应的博客文章。无论是哪一年，我都不建议做第 10 个之后的谜题，因为它们可能会变得极具挑战性，你会绞尽脑汁，花费大部分时间去想如何解决问题，而不是学习 Rust。\n\n#### 设置\n\n首先，在 [AoC](https://adventofcode.com/) 上创建账号。其次，由于 AoC 与语言无关，你必须设置你自己的 cargo 项目并搭建脚手架来解决这些谜题。这样做可能非常有教育意义，但也相当枯燥。我建议跳过这一步，使用这个 Github 模板：[fspoettel/advent-of-code-rust](https://github.com/fspoettel/advent-of-code-rust)：点击 `Use this template` -> `Create a new repository`，然后 `git clone` 克隆仓库到你的机器上。在 `.cargo/config.toml` 中将 `AOC_YEAR` 设置为 `2020`。\n\n你还可以安装 `aoc-cli` 工具，从你的 AoC 账户获取指令和输入到你的机器上。为此，要运行 `cargo install aoc-cli --version 0.12.0`，然后创建文件 `$HOME/.adventofcode.session`，并将你的 AoC 的 cookie 粘贴进去。获取 cookie，需要在 AoC 网站中，按 `F12` 打开浏览器开发者工具，然后在 `Application` 或 `Storage` 选项卡下找到 `Cookies`，复制 `session` cookie 的值。\n\n完成这些步骤后，你可以在项目目录中运行 `cargo download {day}`，生成脚手架并下载当天的谜题。一旦你认为已经完成，就可以运行 `cargo solve {day}`，通过 AoC 网站提交解答并进行验证。例如，对于第 1 天，命令将是 `cargo download 1` 和 `cargo solve 1`。\n\n#### 2020 年\n\n正如前面提到的，一定要在 `.cargo/config.toml` 中将 `AOC_YEAR` 设置为 `2020`。完成一个谜题后，去阅读 fasterthanlime 在他的博客上发布的解决方案。这是他前 10 个谜题解决方案的链接：\n\n1. [AoC 2020 Day 1](https://fasterthanli.me/series/advent-of-code-2020/part-1)\n2. [AoC 2020 Day 2](https://fasterthanli.me/series/advent-of-code-2020/part-2)\n3. [AoC 2020 Day 3](https://fasterthanli.me/series/advent-of-code-2020/part-3)\n4. [AoC 2020 Day 4](https://fasterthanli.me/series/advent-of-code-2020/part-4)\n5. [AoC 2020 Day 5](https://fasterthanli.me/series/advent-of-code-2020/part-5)\n6. [AoC 2020 Day 6](https://fasterthanli.me/series/advent-of-code-2020/part-6)\n7. [AoC 2020 Day 7](https://fasterthanli.me/series/advent-of-code-2020/part-7)\n8. [AoC 2020 Day 8](https://fasterthanli.me/series/advent-of-code-2020/part-8)\n9. [AoC 2020 Day 9](https://fasterthanli.me/series/advent-of-code-2020/part-9)\n10. [AoC 2020 Day 10](https://fasterthanli.me/series/advent-of-code-2020/part-10)\n\n#### 2022 年\n\n如果你已经完成了至少 10 个 2020 年的谜题，那么推荐接下来做 2022 年的谜题。再克隆一份 [fspoettel/advent-of-code-rust](https://github.com/fspoettel/advent-of-code-rust)，并在 `.cargo/config.toml` 中将 `AOC_YEAR` 设置为 `2022`。这是 fasterthanlime 对 2022 年谜题的解答的链接：\n\n1. [AoC 2022 Day 1](https://fasterthanli.me/series/advent-of-code-2022/part-1)\n2. [AoC 2022 Day 2](https://fasterthanli.me/series/advent-of-code-2022/part-2)\n3. [AoC 2022 Day 3](https://fasterthanli.me/series/advent-of-code-2022/part-3)\n4. [AoC 2022 Day 4](https://fasterthanli.me/series/advent-of-code-2022/part-4)\n5. [AoC 2022 Day 5](https://fasterthanli.me/series/advent-of-code-2022/part-5)\n6. [AoC 2022 Day 6](https://fasterthanli.me/series/advent-of-code-2022/part-6)\n7. [AoC 2022 Day 7](https://fasterthanli.me/series/advent-of-code-2022/part-7)\n8. [AoC 2022 Day 8](https://fasterthanli.me/series/advent-of-code-2022/part-8)\n9. [AoC 2022 Day 9](https://fasterthanli.me/series/advent-of-code-2022/part-9)\n10. [AoC 2022 Day 10](https://fasterthanli.me/series/advent-of-code-2022/part-10)\n\n### 教程\n\n大多数 Rust 教程的目标，是向你展示如何用 Rust 实现某个软件，而不一定是教你 Rust 语言本身。因此，许多教程作者都假设读者已经对这门语言有一定的了解，为了保持教程的重点和简洁，会省略许多针对初学者的解释。\n\n话虽如此，编写一个有一定难度的软件，比完成一堆小练习要更有趣和更有成就感。所以这种方法可能更适合保持你的学习动力，特别是当你在构建一个你真正感兴趣和兴奋的东西时。\n\n我希望在这里推荐一些教程。但是已经有太多教程，很难一一评估和按质量排名。不过，质量可能并不是那么重要，重要的是你在编写 Rust 代码并享受这个过程。所以，选择任何看起来有趣的教程并跟着学习，不要过分纠结细节。\n\n不过，我要特别提一下 [Codecrafters](https://codecrafters.io)。他们的教程质量非常高，而且所有教程都提供了 Rust 模板。在教程的每一步，他们都会给出指导和提示，告诉你如何实现程序的下一部分。你完成并提交代码后，它会运行一个测试套件，来检查是否所有内容都正确实现。\n\nCodecrafters 的最大缺点是费用，每月要 40 美元。他们偶尔会有促销活动，免费开放某个教程一个月。你在浏览他们网站时，可能会幸运地发现一个你感兴趣的教程是免费的。然而，这个定价表明，他们的目标是那些希望培训其工程师的软件公司，而不是个人工程师。如果你在这样的公司工作，可以查看你的公司是否为类似 Codecrafters 的课程提供培训津贴，这样你就可以用这些津贴来支付费用。\n\n## 4）阅读 [《常见的 Rust 生命周期误解》](./common-rust-lifetime-misconceptions.md)\n\n免责声明：这是我写的。\n\n阅读 [《常见的 Rust 生命周期误解》](./common-rust-lifetime-misconceptions.md) 将帮助你理解，为什么在过去的 10 个小时的 Rust 编程中，你一半的尝试都不起作用 🙂\n\n玩笑归玩笑，理解生命周期可能是许多初学者在学习 Rust 时遇到的最大绊脚石。这篇文章澄清了关于生命周期的最常见误解，它们常常引起人们的困惑和挫败感。\n\n我之所以建议在至少有 10 小时的 Rust 编码实践经验后再阅读它，是因为对纯粹的初学者来说，这篇文章可能包含了过多的技术细节，会让人感到不知所措，而不是提供帮助。\n\n## 5）再花 10 小时用 Rust 编程\n\n如果你仍然不知道要编写什么代码，我的建议保仍然是：[100 个练习学会 Rust](https://rust-exercises.com/100-exercises/)，Exercism 上的 [Rust 课程](https://exercism.org/tracks/rust)，[Advent of Code](https://adventofcode.com/)，或其它教程。\n\n现在你已经有了一些 Rust 经验。如果你喜欢冒险，可以尝试用 Rust 编写一些多线程异步代码。\n\n## 6）阅读 [《导览 Rust 标准库特征》](./tour-of-rusts-standard-library-traits.md)\n\n免责声明：这是我写的。\n\n特征（Trait）是 Rust 中编写多态代码的主要方式。它们无处不在，尤其是对来自标准库的特征来说。本文对最常见的标准库特征进行了导览，介绍了它们的方法、如何使用它们以及何时为你的自定义类型实现它们。这篇文章相当详尽，并分享了大量实用的技巧。尽管篇幅较长，但你不必读阅读全文就能从中受益，所以不要被它的长度吓到。\n\n## 接下来做什么？\n\n恭喜你！你做到了。你肯定已经掌握了足够的 Rust 知识，可以自行探索前进的道路。祝你好运并玩得开心。\n\n## 荣誉提名\n\n这些是我非常喜欢的其他的 Rust 初学者资源，但我不知道应该将它们放在本指南的何处。\n\n### [Tour of Rust](https://tourofrust.com/)\n\n这是一个非常好的资源。然而，它涉及很多其他资源已经覆盖的内容，所以为了保持指南的简洁性，我没有将其包括在内。\n\n### [Comprehensive Rust](https://google.github.io/comprehensive-rust/)\n\n这是 Google 的 Android 团队开发的 Rust 课程。它是一个幻灯片集合，本应由一位具有 Rust 经验的讲者来讲解，但书籍版本在每页底部有讲者注释，因此也可以作为独立资源来学习。\n\n这门课程非常简洁，节奏很快，同时还涵盖了其他初学者资源中通常忽略的 Rust 部分，例如 [裸机 Rust](https://google.github.io/comprehensive-rust/bare-metal.html) 和 [Rust 中的并发性](https://google.github.io/comprehensive-rust/concurrency/welcome.html)。然而，因为它更适合由讲者来呈现，所以不太适合放入面向自学者的指南中。\n\n### [Rust 模块系统的清晰解释](https://www.sheshbabu.com/posts/rust-module-system/)\n\n这是一篇很棒的文章。它可以放在该指南中的任何地方，所以我不确定将它放在哪里。理想情况下，学习者开始将 Rust 代码分散到多个文件时，应该阅读这篇文章。在每个人的 Rust 编码旅程中，这个时间点会有所不同。无论如何，当你到了那一步时，请阅读这篇文章。\n\n## 讨论\n\n在以下平台讨论本文：\n\n- [Github](https://github.com/pretzelhammer/rust-blog/discussions/84)\n\n## 进一步阅读\n\n- [常见的 Rust 生命周期误解](./common-rust-lifetime-misconceptions.md)\n- [Rust 标准库特性指南](./tour-of-rusts-standard-library-traits.md)\n- [并发编程初学者指南：使用 Tokio 编写多线程聊天服务器](./chat-server.md)\n- [Sizedness in Rust](../../sizedness-in-rust.md)\n- [RESTful API in Sync & Async Rust](../../restful-api-in-sync-and-async-rust.md)\n- [Learn Assembly with Entirely Too Many Brainfuck Compilers](../../too-many-brainfuck-compilers.md)\n"
  },
  {
    "path": "posts/translations/zh-hans/rust-in-non-rust-servers.md",
    "content": "# 在非 Rust 服务器中逐步引入 Rust 以提高性能\n\n_2024 年 10 月 22 日 · #rust · #wasm · #ffi · #performance_\n\n**目录**\n\n- [介绍](#介绍)\n- [策略](#策略)\n  - [第 0 层：不使用 Rust](#第-0-层不使用-Rust)\n  - [第 1 层：Rust CLI 工具](#第-1-层Rust-CLI-工具)\n  - [第 2 层：Rust Wasm 模块](#第-2-层Rust-Wasm-模块)\n    - [手动编写 Wasm 绑定](#手动编写-Wasm-绑定)\n  - [第 3 层：Rust 原生函数](#第-3-层Rust-原生函数)\n  - [第 4 层：Rust 重写](#第-4-层Rust-重写)\n- [总结](#总结)\n- [讨论](#讨论)\n- [延伸阅读](#延伸阅读)\n- [通知](#通知)\n\n## 介绍\n\n在本文中，我将讨论如何逐步将 Rust 引入到用其他语言（如 JavaScript、Python、Java、Go、PHP、Ruby 等）编写的服务器中。主要原因是，当你对服务器进行性能分析后，发现某个热点函数由于 CPU 瓶颈无法满足性能要求，而通常的优化手段（如函数记忆化或改进算法）在这种情况下不可行或无效时，你可能会考虑将该函数的实现替换为用更高效的 CPU 语言（如 Rust）编写的版本。如果你正面临这种情况，那么这篇文章非常适合你。\n\n这些策略按“层级”排序，其中“层级”指的是“Rust 采用的层级”。第一层是完全不使用 Rust，最后一层则是将整个服务器重写为 Rust。\n\n我们将在一个用 JS 编写的 Node.js 示例服务器上应用和基准测试这些策略。不过，这些策略可以推广到任何其他语言或运行时。\n\n> [!NOTE]\n> 本文中所有示例的完整源代码可以在 [此仓库](https://github.com/pretzelhammer/using-rust-in-non-rust-servers) 中找到。\n\n## 策略\n\n### 第 0 层：不使用 Rust\n\n假设我们有一个 Node.js 服务器，它有一个 HTTP 端点，该端点接收一个文本字符串作为查询参数，并返回一个 200px × 200px 的 PNG 图像，图像内容是该文本的二维码。\n\n以下是服务器代码：\n\n```js\nconst express = require(\"express\");\nconst generateQrCode = require(\"./generate-qr.js\");\n\nconst app = express();\napp.get(\"/qrcode\", async (req, res) => {\n  const { text } = req.query;\n\n  if (!text) {\n    return res.status(400).send('missing \"text\" query param');\n  }\n\n  if (text.length > 512) {\n    return res.status(400).send(\"text must be <= 512 bytes\");\n  }\n\n  try {\n    const qrCode = await generateQrCode(text);\n    res.setHeader(\"Content-Type\", \"image/png\");\n    res.send(qrCode);\n  } catch (err) {\n    res.status(500).send(\"failed generating QR code\");\n  }\n});\n\napp.listen(42069, \"127.0.0.1\");\n```\n\n以下是热点函数的代码：\n\n```js\nconst QRCode = require(\"qrcode\");\n\n/**\n * @param {string} text - 要编码的文本\n * @returns {Promise<Buffer>|Buffer} - 二维码\n */\nmodule.exports = function generateQrCode(text) {\n  return QRCode.toBuffer(text, {\n    type: \"png\",\n    errorCorrectionLevel: \"L\",\n    width: 200,\n    rendererOpts: {\n      // 这些选项在测试中提供了速度和压缩之间的最佳平衡\n      deflateLevel: 9, // 0 - 9\n      deflateStrategy: 3, // 1 - 4\n    },\n  });\n};\n```\n\n我们可以通过以下方式调用该端点：\n\n```\nhttp://localhost:42069/qrcode?text=https://www.reddit.com/r/rustjerk/top/?t=all\n```\n\n这将正确生成以下二维码 PNG：\n\n![QR code for rustjerk subreddit](../../../assets/rustjerk-subreddit-qr-code.png)\n\n现在，让我们在 30 秒内向该服务器发送数万个请求，看看它的表现如何：\n\n| 层级    | 吞吐量       | 平均延迟 | p99 延迟 | 平均响应大小 | 内存    |\n| ------- | ------------ | -------- | -------- | ------------ | ------- |\n| 第 0 层 | 1464 请求/秒 | 68 毫秒  | 96 毫秒  | 1506 字节    | 1353 MB |\n\n由于我还没有描述我的基准测试方法，这些结果本身是没有意义的，我们无法判断这是“好”还是“坏”的性能。这没关系，因为我们不关心具体的数字，我们将使用这些结果作为基线，与所有后续实现进行比较。每个服务器都在相同的环境中进行测试，因此相对比较是准确的。\n\n关于异常高的内存使用量，这是因为我在“集群模式”下运行 Node.js，该模式根据测试机器上的 12 个 CPU 核心生成了 12 个进程，每个进程都是一个独立的 Node.js 实例，这就是为什么即使我们有一个非常简单的服务器，它也会占用 1300+ MB 的内存。JS 是单线程的，所以如果我们希望 Node.js 服务器充分利用多核 CPU，就必须这样做。\n\n### 第 1 层：Rust CLI 工具\n\n对于此策略，我们将热点函数重写为 Rust，将其编译为独立的 CLI 工具，然后从主服务器调用它。\n\n首先，我们将函数重写为 Rust：\n\n```rust\n/** qr_lib/lib.rs **/\n\nuse qrcode::{QrCode, EcLevel};\nuse image::Luma;\nuse image::codecs::png::{CompressionType, FilterType, PngEncoder};\n\npub type StdErr = Box<dyn std::error::Error>;\n\npub fn generate_qr_code(text: &str) -> Result<Vec<u8>, StdErr> {\n    let qr = QrCode::with_error_correction_level(text, EcLevel::L)?;\n    let img_buf = qr.render::<Luma<u8>>()\n        .min_dimensions(200, 200)\n        .build();\n    let mut encoded_buf = Vec::with_capacity(512);\n    let encoder = PngEncoder::new_with_quality(\n        &mut encoded_buf,\n        // 这些选项在测试中提供了速度和压缩之间的最佳平衡\n        CompressionType::Default,\n        FilterType::NoFilter,\n    );\n    img_buf.write_with_encoder(encoder)?;\n    Ok(encoded_buf)\n}\n```\n\n然后我们将其制作成 CLI 工具：\n\n```rust\n/** qr_cli/main.rs **/\n\nuse std::{env, process};\nuse std::io::{self, BufWriter, Write};\nuse qr_lib::StdErr;\n\nfn main() -> Result<(), StdErr> {\n    let mut args = env::args();\n    if args.len() != 2 {\n        eprintln!(\"Usage: qr-cli <text>\");\n        process::exit(1);\n    }\n\n    let text = args.nth(1).unwrap();\n    let qr_png = qr_lib::generate_qr_code(&text)?;\n\n    let stdout = io::stdout();\n    let mut handle = BufWriter::new(stdout.lock());\n    handle.write_all(&qr_png)?;\n\n    Ok(())\n}\n```\n\n我们可以像这样使用这个 CLI：\n\n```bash\nqr-cli https://youtu.be/cE0wfjsybIQ?t=74 > crab-rave.png\n```\n\n这将正确生成以下二维码 PNG：\n\n![QR code for crab rave youtube video](../../../assets/crab-rave-qr-code.png)\n\n现在，我们更新主服务器中的热点函数以调用此 CLI：\n\n```js\nconst { spawn } = require(\"child_process\");\nconst path = require(\"path\");\nconst qrCliPath = path.resolve(__dirname, \"./qr-cli\");\n\n/**\n * @param {string} text - 要编码的文本\n * @returns {Promise<Buffer>} - 二维码\n */\nmodule.exports = function generateQrCode(text) {\n  return new Promise((resolve, reject) => {\n    const qrCli = spawn(qrCliPath, [text]);\n    const qrCodeData = [];\n    qrCli.stdout.on(\"data\", (data) => {\n      qrCodeData.push(data);\n    });\n    qrCli.stderr.on(\"data\", (data) => {\n      reject(new Error(`error generating qr code: ${data}`));\n    });\n    qrCli.on(\"error\", (err) => {\n      reject(new Error(`failed to start qr-cli ${err}`));\n    });\n    qrCli.on(\"close\", (code) => {\n      if (code === 0) {\n        resolve(Buffer.concat(qrCodeData));\n      } else {\n        reject(new Error(\"qr-cli exited unsuccessfully\"));\n      }\n    });\n  });\n};\n```\n\n现在让我们看看这个更改对性能的影响：\n\n绝对测量值\n\n| 层级    | 吞吐量          | 平均延迟   | p99 延迟   | 平均响应大小 | 内存       |\n| ------- | --------------- | ---------- | ---------- | ------------ | ---------- |\n| 第 0 层 | 1464 请求/秒    | 68 毫秒    | 96 毫秒    | 1506 字节    | 1353 MB    |\n| 第 1 层 | 2572 请求/秒 🥇 | 39 毫秒 🥇 | 78 毫秒 🥇 | 778 字节 🥇  | 1240 MB 🥇 |\n\n相对测量值\n\n| 层级    | 吞吐量   | 平均延迟 | p99 延迟 | 平均响应大小 | 内存     |\n| ------- | -------- | -------- | -------- | ------------ | -------- |\n| 第 0 层 | 1.00x    | 1.00x    | 1.00x    | 1.00x        | 1.00x    |\n| 第 1 层 | 1.76x 🥇 | 0.57x 🥇 | 0.82x 🥇 | 0.52x 🥇     | 0.92x 🥇 |\n\n哇，我没想到吞吐量会增加 76%！这是一个非常粗糙的策略，所以看到它如此有效真是有趣。平均响应大小也从 1506 字节减少到 778 字节，Rust 库中的压缩算法一定比 JS 库中的更好。我们每秒处理的请求数显著增加，返回的响应大小显著减小，所以我认为这是一个很好的结果。\n\n### 第 2 层：Rust Wasm 模块\n\n对于此策略，我们将 Rust 函数编译为 Wasm 模块，然后使用 Wasm 运行时从主服务器加载并运行它。以下是一些不同语言的 Wasm 运行时链接：\n\n| 语言       | Wasm 运行时                                              | GitHub 星数 |\n| ---------- | -------------------------------------------------------- | ----------- |\n| JavaScript | 内置                                                     | -           |\n| 多种语言   | [Wasmer](https://github.com/wasmerio/wasmer)             | 19.2K+      |\n| 多种语言   | [Wasmtime](https://github.com/bytecodealliance/wasmtime) | 15.7K+      |\n| 多种语言   | [WasmEdge](https://github.com/WasmEdge/WasmEdge)         | 8.7K+       |\n| 多种语言   | [wasm3](https://github.com/wasm3/wasm3)                  | 7.4k+       |\n| Go         | [Wazero](https://github.com/tetratelabs/wazero)          | 5.1k+       |\n| 多种语言   | [Extism](https://github.com/extism/extism)               | 4.6k+       |\n| Java       | [Chicory](https://github.com/dylibso/chicory)            | 560+        |\n\n由于我们正在集成到 Node.js 服务器中，让我们使用 `wasm-bindgen` 来生成 Rust Wasm 代码和 JS 代码之间交互的粘合代码。\n\n以下是更新后的 Rust 代码：\n\n```rust\n/** qr_wasm_bindgen/lib.rs **/\n\nuse wasm_bindgen::prelude::*;\n\n#[wasm_bindgen(js_name = generateQrCode)]\npub fn generate_qr_code(text: &str) -> Result<Vec<u8>, JsError> {\n    qr_lib::generate_qr_code(text)\n        .map_err(|e| JsError::new(&e.to_string()))\n}\n```\n\n使用 `wasm-pack` 编译该代码后，我们可以将构建的资产复制到 Node.js 服务器中，并在热点函数中使用它们，如下所示：\n\n```js\nconst wasm = require(\"./qr_wasm_bindgen.js\");\n\n/**\n * @param {string} text - 要编码的文本\n * @returns {Buffer} - 二维码\n */\nmodule.exports = function generateQrCode(text) {\n  return Buffer.from(wasm.generateQrCode(text));\n};\n```\n\n更新后的基准测试：\n\n绝对测量值\n\n| 层级    | 吞吐量          | 平均延迟   | p99 延迟   | 平均响应大小 | 内存       |\n| ------- | --------------- | ---------- | ---------- | ------------ | ---------- |\n| 第 0 层 | 1464 请求/秒    | 68 毫秒    | 96 毫秒    | 1506 字节    | 1353 MB    |\n| 第 1 层 | 2572 请求/秒    | 39 毫秒    | 78 毫秒    | 778 字节 🥇  | 1240 MB 🥇 |\n| 第 2 层 | 2978 请求/秒 🥇 | 34 毫秒 🥇 | 63 毫秒 🥇 | 778 字节 🥇  | 1286 MB    |\n\n相对测量值\n\n| 层级    | 吞吐量   | 平均延迟 | p99 延迟 | 平均响应大小 | 内存     |\n| ------- | -------- | -------- | -------- | ------------ | -------- |\n| 第 0 层 | 1.00x    | 1.00x    | 1.00x    | 1.00x        | 1.00x    |\n| 第 1 层 | 1.76x    | 0.57x    | 0.82x    | 0.52x 🥇     | 0.92x 🥇 |\n| 第 2 层 | 2.03x 🥇 | 0.50x 🥇 | 0.66x 🥇 | 0.52x 🥇     | 0.95x    |\n\n使用 Wasm 使我们的吞吐量比基线翻了一番！然而，与之前调用 CLI 工具的原始策略相比，性能提升比我预期的要小。\n\n总之，虽然 `wasm-bindgen` 是一个优秀的 JS 到 Rust Wasm 绑定生成器，但对于其他语言（如 Python、Java、Go、PHP、Ruby 等）没有等效的工具。我不想让这些人失望，所以我会解释如何手动编写绑定。免责声明：代码会变得很丑陋，所以除非你真的对底层实现感兴趣，否则你可以跳过下一节。\n\n#### 手动编写 Wasm 绑定\n\nWasm 的一个有趣之处在于它只支持四种数据类型：`i32`、`i64`、`f32` 和 `f64`。然而，对于我们的用例，我们需要将字符串从主机传递给 Wasm 函数，并且 Wasm 函数需要返回一个数组给主机。Wasm 没有字符串或数组。那么我们该如何解决这个问题呢？\n\n答案在于以下几点：\n\n- Wasm 模块的内存由 Wasm 实例和主机共享，两者都可以读取和修改它。\n- Wasm 模块最多只能请求 4GB 的内存，因此每个可能的内存地址都可以编码为 `i32`，因此该数据类型也用作内存地址指针。\n\n如果我们想将字符串从主机传递给 Wasm 函数，主机必须直接将字符串写入 Wasm 模块的内存，然后传递两个 `i32` 给 Wasm 函数：一个指向字符串的内存地址，另一个指定字符串的字节长度。\n\n如果我们想将数组从 Wasm 函数传递给主机，主机首先需要为 Wasm 函数提供一个 `i32`，指向数组应写入的内存地址，然后当 Wasm 函数完成时，它返回一个 `i32`，表示写入的字节数。\n\n然而，现在我们有一个新问题：当主机写入 Wasm 模块的内存时，如何确保它不会覆盖 Wasm 模块正在使用的内存？为了让主机能够安全地写入内存，它必须首先请求 Wasm 模块为其分配空间。\n\n好的，现在有了所有这些背景知识，我们终于可以看这段代码并真正理解它了：\n\n```rust\n/** qr_wasm/lib.rs **/\n\nuse std::{alloc::Layout, mem, slice, str};\n\n// 主机调用此函数以分配空间，以便安全地写入数据\n#[no_mangle]\npub unsafe extern \"C\" fn alloc(size: usize) -> *mut u8 {\n    let layout = Layout::from_size_align_unchecked(\n        size * mem::size_of::<u8>(),\n        mem::align_of::<usize>(),\n    );\n    std::alloc::alloc(layout)\n}\n\n// 在分配文本缓冲区和输出缓冲区后，主机调用此函数以生成二维码 PNG\n#[no_mangle]\npub unsafe extern \"C\" fn generateQrCode(\n    text_ptr: *const u8,\n    text_len: usize,\n    output_ptr: *mut u8,\n    output_len: usize,\n) -> usize {\n    // 从内存中读取文本，主机已将其写入\n    let text_slice = slice::from_raw_parts(text_ptr, text_len);\n    let text = str::from_utf8_unchecked(text_slice);\n\n    let qr_code = match qr_lib::generate_qr_code(text) {\n        Ok(png_data) => png_data,\n        // 错误：无法生成二维码\n        Err(_) => return 0,\n    };\n\n    if qr_code.len() > output_len {\n        // 错误：输出缓冲区太小\n        return 0;\n    }\n\n    // 将生成的二维码 PNG 写入输出缓冲区，主机将在函数返回后从中读取\n    let output_slice = slice::from_raw_parts_mut(output_ptr, qr_code.len());\n    output_slice.copy_from_slice(&qr_code);\n\n    // 返回写入的 PNG 数据长度\n    qr_code.len()\n}\n```\n\n编译此 Wasm 模块后，我们可以从 JS 中使用它，如下所示：\n\n```js\nconst path = require(\"path\");\nconst fs = require(\"fs\");\n\n// 获取 Wasm 文件\nconst qrWasmPath = path.resolve(__dirname, \"./qr_wasm.wasm\");\nconst qrWasmBinary = fs.readFileSync(qrWasmPath);\n\n// 实例化 Wasm 模块\nconst qrWasmModule = new WebAssembly.Module(qrWasmBinary);\nconst qrWasmInstance = new WebAssembly.Instance(qrWasmModule, {});\n\n// JS 字符串是 UTF16，但我们需要将其重新编码为 UTF8 再传递给 Wasm 模块\nconst textEncoder = new TextEncoder();\n\n// 告诉 Wasm 模块为我们分配两个缓冲区：\n// - 第一个缓冲区：输入缓冲区，我们将写入 UTF8 字符串，generateQrCode 函数将从中读取\n// - 第二个缓冲区：输出缓冲区，generateQrCode 函数将写入二维码 PNG 字节，我们将从中读取\nconst textMemLen = 1024;\nconst textMemOffset = qrWasmInstance.exports.alloc(textMemLen);\nconst outputMemLen = 4096;\nconst outputMemOffset = qrWasmInstance.exports.alloc(outputMemLen);\n\n/**\n * @param {string} text - 要编码的文本\n * @returns {Buffer} - 二维码\n */\nmodule.exports = function generateQrCode(text) {\n  // 将 UTF16 JS 字符串转换为 Uint8Array\n  let encodedText = textEncoder.encode(text);\n  let encodedTextLen = encodedText.length;\n\n  // 将字符串写入 Wasm 内存\n  qrWasmMemory = new Uint8Array(qrWasmInstance.exports.memory.buffer);\n  qrWasmMemory.set(encodedText, textMemOffset);\n\n  const wroteBytes = qrWasmInstance.exports.generateQrCode(\n    textMemOffset,\n    encodedTextLen,\n    outputMemOffset,\n    outputMemLen\n  );\n\n  if (wroteBytes === 0) {\n    throw new Error(\"failed to generate qr\");\n  }\n\n  // 从 Wasm 内存中读取二维码 PNG 字节并返回\n  return Buffer.from(\n    qrWasmInstance.exports.memory.buffer,\n    outputMemOffset,\n    wroteBytes\n  );\n};\n```\n\n这就是当我们使用像 `wasm-bindgen` 这样的库时，底层生成的代码。总之，我对其进行了基准测试，手写绑定的性能与生成的绑定在此情况下的性能几乎相同。\n\n所以，编写主机和 Wasm 模块之间的粘合代码显然不是一件有趣的事情。幸运的是，积极参与 Wasm 规范制定的人们已经意识到这一点，他们目前正在制定“组件模型 Component Model”提案，该提案将标准化一种称为 WIT（Wasm 接口类型, Wasm Interface Type）的 IDL（接口定义语言, Interface Definition Language），绑定生成器和 Wasm 运行时可以围绕它构建。\n\n目前，有一个名为 `wit-bindgen` 的 Rust 项目，它可以根据 WIT 文件为用 Rust 编写的 Wasm 模块生成粘合代码，但你需要一个单独的工具来生成主机粘合代码，比如 `jco`，它可以根据 Wasm 和 WIT 文件生成 JS 粘合代码。\n\n使用 `wit-bingen` + `jco` 将给你类似于使用 `wasm-bindgen` 的结果，但希望未来会有更多针对其他语言的 WIT 主机绑定生成器，这样 Python、Java、Go、PHP、Ruby 等程序员就能拥有像 `wasm-bindgen` 对 JS 程序员那样方便易用的解决方案。\n\n### 第 3 层：Rust 原生函数\n\n对于此策略，我们将用 Rust 编写函数，将其编译为原生代码，然后从主机运行时加载并执行它。以下是各种语言的 Rust 绑定生成器库表：\n\n| 语言       | Rust 绑定生成器                                           | GitHub 星数 |\n| ---------- | --------------------------------------------------------- | ----------- |\n| Python     | [pyo3](https://github.com/pyo3/pyo3)                      | 12.7k+      |\n| JavaScript | [napi-rs](https://github.com/napi-rs/napi-rs)             | 6.3k+       |\n| Erlang     | [rustler](https://github.com/rusterlium/rustler)          | 4.4k+       |\n| 多种语言   | [uniffi-rs](https://github.com/mozilla/uniffi-rs)         | 3k+         |\n| Java       | [jni-rs](https://github.com/jni-rs/jni-rs)                | 1.3k+       |\n| Ruby       | [rutie](https://github.com/danielpclark/rutie)            | 970+        |\n| PHP        | [ext-php-rs](https://github.com/davidcole1340/ext-php-rs) | 610+        |\n| 多种语言   | [diplomat](https://github.com/rust-diplomat/diplomat)     | 560+        |\n\n由于我们的示例服务器是用 JS 编写的，我们将使用 `napi-rs`。以下是 Rust 代码：\n\n```rust\nuse napi::bindgen_prelude::*;\nuse napi_derive::napi;\n\n#[napi]\npub fn generate_qr_code(text: String) -> Result<Vec<u8>, Status> {\n    qr_lib::generate_qr_code(&text)\n        .map_err(|e| Error::from_reason(e.to_string()))\n}\n```\n\n我喜欢它的简单性。在前一节中从头开始编写 Wasm 模块后，我对实现和维护绑定生成器库的人们有了新的欣赏和尊重。\n\n构建上述代码后，我们可以从 Node.js 中使用它，如下所示：\n\n```js\nconst native = require(\"./qr_napi.node\");\n\n/**\n * @param {string} text - 要编码的文本\n * @returns {Buffer} - 二维码\n */\nmodule.exports = function generateQrCode(text) {\n  return Buffer.from(native.generateQrCode(text));\n};\n```\n\n现在让我们看看这个家伙能否飞起来：\n\n绝对测量值\n\n| 层级    | 吞吐量          | 平均延迟   | p99 延迟   | 平均响应大小 | 内存       |\n| ------- | --------------- | ---------- | ---------- | ------------ | ---------- |\n| 第 0 层 | 1464 请求/秒    | 68 毫秒    | 96 毫秒    | 1506 字节    | 1353 MB    |\n| 第 1 层 | 2572 请求/秒    | 39 毫秒    | 78 毫秒    | 778 字节 🥇  | 1240 MB 🥇 |\n| 第 2 层 | 2978 请求/秒    | 34 毫秒    | 63 毫秒    | 778 字节 🥇  | 1286 MB    |\n| 第 3 层 | 5490 请求/秒 🥇 | 18 毫秒 🥇 | 37 毫秒 🥇 | 778 字节 🥇  | 1309 MB    |\n\n相对测量值\n\n| 层级    | 吞吐量   | 平均延迟 | p99 延迟 | 平均响应大小 | 内存     |\n| ------- | -------- | -------- | -------- | ------------ | -------- |\n| 第 0 层 | 1.00x    | 1.00x    | 1.00x    | 1.00x        | 1.00x    |\n| 第 1 层 | 1.76x    | 0.57x    | 0.82x    | 0.52x 🥇     | 0.92x 🥇 |\n| 第 2 层 | 2.03x    | 0.50x    | 0.66x    | 0.52x 🥇     | 0.95x    |\n| 第 3 层 | 3.75x 🥇 | 0.26x 🥇 | 0.39x 🥇 | 0.52x 🥇     | 0.97x    |\n\n事实证明，原生代码非常快！我们的吞吐量几乎比基线增加了四倍，比 Wasm 实现增加了一倍。\n\n### 第 4 层：Rust 重写\n\n在此策略中，我们将用 Rust 重写主机服务器。诚然，这对于大多数现实世界的情况来说是不切实际的，因为服务器代码库通常有 10 万行以上的代码。在这些情况下，我们可以只重写主机服务器的一部分。如今，大多数人在后端运行的所有内容都位于反向代理之后，因此部署一个新的 Rust 服务器并修改反向代理配置以将一些请求路由到 Rust 服务器并不会给许多人的后端设置带来太多额外的操作开销。\n\n所以，这是用 Rust 重写的服务器：\n\n```rust\n/** qr-server/main.rs **/\n\nuse std::process;\nuse axum::{\n    extract::Query,\n    http::{header, StatusCode},\n    response::{IntoResponse, Response},\n    routing::get,\n    Router,\n};\n\n#[derive(serde::Deserialize)]\nstruct TextParam {\n    text: String,\n}\n\n#[tokio::main]\nasync fn main() {\n    let app = Router::new().route(\"/qrcode\", get(handler));\n    let listener = tokio::net::TcpListener::bind(\"127.0.0.1:42069\")\n        .await\n        .unwrap();\n    println!(\n        \"server {} listening on {}\",\n        process::id(),\n        listener.local_addr().unwrap(),\n    );\n    axum::serve(listener, app).await.unwrap();\n}\n\nasync fn handler(\n    Query(param): Query<TextParam>\n) -> Result<Response, (StatusCode, &'static str)> {\n    if param.text.len() > 512 {\n        return Err((\n            StatusCode::BAD_REQUEST,\n            \"text must be <= 512 bytes\"\n        ));\n    }\n    match qr_lib::generate_qr_code(&param.text) {\n        Ok(bytes) => Ok((\n            [(header::CONTENT_TYPE, \"image/png\"),],\n            bytes,\n        ).into_response()),\n        Err(_) => Err((\n            StatusCode::INTERNAL_SERVER_ERROR,\n            \"failed to generate qr code\"\n        )),\n    }\n}\n```\n\n让我们看看它是否名副其实：\n\n绝对测量值\n\n| 层级    | 吞吐量          | 平均延迟   | p99 延迟   | 平均响应大小 | 内存     |\n| ------- | --------------- | ---------- | ---------- | ------------ | -------- |\n| 第 0 层 | 1464 请求/秒    | 68 毫秒    | 96 毫秒    | 1506 字节    | 1353 MB  |\n| 第 1 层 | 2572 请求/秒    | 39 毫秒    | 78 毫秒    | 778 字节 🥇  | 1240 MB  |\n| 第 2 层 | 2978 请求/秒    | 34 毫秒    | 63 毫秒    | 778 字节 🥇  | 1286 MB  |\n| 第 3 层 | 5490 请求/秒    | 18 毫秒    | 37 毫秒    | 778 字节 🥇  | 1309 MB  |\n| 第 4 层 | 7212 请求/秒 🥇 | 14 毫秒 🥇 | 27 毫秒 🥇 | 778 字节 🥇  | 13 MB 🥇 |\n\n相对测量值\n\n| 层级    | 吞吐量   | 平均延迟 | p99 延迟 | 平均响应大小 | 内存     |\n| ------- | -------- | -------- | -------- | ------------ | -------- |\n| 第 0 层 | 1.00x    | 1.00x    | 1.00x    | 1.00x        | 1.00x    |\n| 第 1 层 | 1.76x    | 0.57x    | 0.82x    | 0.52x 🥇     | 0.92x    |\n| 第 2 层 | 2.03x    | 0.50x    | 0.66x    | 0.52x 🥇     | 0.95x    |\n| 第 3 层 | 3.75x    | 0.26x    | 0.39x    | 0.52x 🥇     | 0.97x    |\n| 第 4 层 | 4.93x 🥇 | 0.21x 🥇 | 0.28x 🥇 | 0.52x 🥇     | 0.01x 🥇 |\n\n这不是打字错误。Rust 服务器在处理 7200+ 请求/秒时，真的只使用了 13 MB 的内存。我认为它确实名副其实！\n\n## 总结\n\n我认为所有这些策略都很好，但第 3 层脱颖而出，性价比最高。如果你可以使用现成的绑定生成器库，那么用 Rust 编写原生函数非常容易，并且它可以对性能产生深远的影响。\n\n第 3 层最困难的部分可能是如果你还不了解 Rust，那么学习 Rust 可能会有些困难，但如果你处于这种情况，你应该阅读 [2024 年学习 Rust](./learning-rust-in-2024.md)，它将帮助你弄清楚如何开始。\n\n## 讨论\n\n在以下平台讨论本文：\n\n- [Github](https://github.com/pretzelhammer/rust-blog/discussions/87)\n- [official Rust users forum](https://users.rust-lang.org/t/using-rust-in-non-rust-servers-to-improve-performance/120121)\n- [rust subreddit](https://www.reddit.com/r/rust/comments/1gabrdh/using_rust_in_nonrust_servers_to_improve/)\n- [Hackernews](https://news.ycombinator.com/item?id=41941451)\n\n## 延伸阅读\n\n- [Common Rust Lifetime Misconceptions](./common-rust-lifetime-misconceptions.md)\n- [Tour of Rust's Standard Library Traits](./tour-of-rusts-standard-library-traits.md)\n- [Beginner's Guide to Concurrent Programming: Coding a Multithreaded Chat Server using Tokio](./chat-server.md)\n- [Learning Rust in 2024](./learning-rust-in-2024.md)\n- [Sizedness in Rust](./sizedness-in-rust.md)\n- [RESTful API in Sync & Async Rust](./restful-api-in-sync-and-async-rust.md)\n- [Learn Assembly with Entirely Too Many Brainfuck Compilers](./too-many-brainfuck-compilers.md)\n\n## 通知\n\n通过以下方式在新博客文章发布时获得通知：\n\n- 订阅此仓库的 [releases RSS feed](https://github.com/pretzelhammer/rust-blog/releases.atom) 或\n- 关注此仓库的 releases (点击 `Watch` → 点击 `Custom` → 选择 `Releases` → 点击 `Apply`)\n"
  },
  {
    "path": "posts/translations/zh-hans/sizedness-in-rust.md",
    "content": "# Rust中的Sizedness\n\n_22 July 2020 · #rust · #sizedness_\n\n**目录**\n\n- [介绍](#介绍)\n- [Sizedness(大小确定性)](#sizedness大小确定性)\n- [`Sized` Trait](#sized-trait)\n- [泛型中的`Sized`](#泛型中的sized)\n- [不定大小类型(Unsized Types)](#不定大小类型unsized-types)\n  - [Slices(切片)](#slices切片)\n  - [Trait Objects(特性对象)](#trait-objects特性对象)\n  - [trait object的限制](#trait-object的限制)\n    - [不能将不定大小类型强转为trait object](#不能将不定大小类型强转为trait-object)\n    - [不能创建多特性对象](#不能创建多特性对象)\n  - [用户定义的不定大小类型](#用户定义的不定大小类型)\n- [0大小类型](#0大小类型)\n  - [单元类型](#单元类型)\n  - [用户定义的单元大小结构](#用户定义的单元大小结构)\n  - [不可能类型（Never Type）](#不可能类型never-type)\n  - [用户定义的伪不可能类型](#用户定义的伪不可能类型)\n  - [PhantomData(伪数据)](#phantomdata伪数据)\n- [总结](#总结)\n- [讨论](#讨论)\n- [进一步阅读](#进一步阅读)\n- [通知](#通知)\n\n## 介绍\n\n大小确定性(Sizedness)在Rust的众多重要概念中是相对不引人注目的一个。它以隐晦的方式与众多其它语言特性互相作用，并且往往只以错误提示的形式让我们了解到它的存在，这个错误我们Rustacean大概常遇到，就是\"_x doesn't have size known at compile time_\"(_x没有确定的编译时大小_)。本文将介绍与Sizeness相关的各种语言特性，包括: 确定大小类型(sized types)，不定大小类型(unsized types)，以及0大小类型(zero-sized types)，我们将探讨它们的使用场景，应用，痛点，以及在必要的时候如何绕过Sizeness带来的困扰。\n\n名词解释:\n\n| 名词 | 解释 |\n|-|-|\n| sizedness(大小确定性) | 表明特定类型有或没有确定的大小 |\n| sized type(确定大小类型) | 编译时有确定大小的类型 |\n| 1) unsized type(不定大小类型) _或_<br>2) DST | 动态大小类型，也就是说，该类型的大小不能在编译时确定 |\n| ?sized type(未知大小类型) | 可能是sized type，也可能是unsized type |\n| unsized coercion(不定大小强转) | 将一个确定大小类型强转为一个不定大小类型 |\n| ZST | zero-sized type(0大小类型)，即，该类型的大小为0字节 |\n| width(宽度) | 一个度量单位，用于描述指针宽度 |\n| 1) 瘦指针 _或_<br>2) 单width指针 | 大小为 _1 width_ 的指针 |\n| 1) 胖指针 _or_<br>2) 双width指针 | 大小为 _2 widths_ 的指针|\n| 1) 指针 _or_<br>2) 引用 | 指针，其具体 _width_ 会在相应的上下文中说明 |\n| slice(切片) | 指向某个数组动态大小视图的双width指针 |\n| (译者补充: trait object(特性对象)) | 实现某个trait的对象([dyn SomeTrait](https://github.com/mercury-2025/rust-blog/blob/master/posts/tour-of-rusts-standard-library-traits.md#trait-objects)) |\n\n\n## Sizedness(大小确定性)\n\n在Rust中，所谓的Sizedness是指一个类型的具体大小是否可以在编译时确定。确定类型大小之所以重要，是因为这样一来，才有可能为类型的实例在栈上分配相应的空间。确定大小类型(Sized types)可以使用传值或传引用的方式到处传递。同样的，如果一个类型的大小不能在编译时确定，我们就称它为不定大小类型(unsized type)或者DST，又或者叫它动态大小类型。因为不定大小类型不能放到栈上，所以它们只能以引用的形式传递。 下面是一部分 _确定大小类型_ 和 _不定大小类型_ 的例子：\n\n```rust\nuse std::mem::size_of;\n\nfn main() {\n    // 原始类型\n    assert_eq!(4, size_of::<i32>());\n    assert_eq!(8, size_of::<f64>());\n\n    // 元组\n    assert_eq!(8, size_of::<(i32，i32)>());\n\n    // 数组\n    assert_eq!(0, size_of::<[i32; 0]>());\n    assert_eq!(12, size_of::<[i32; 3]>());\n\n    struct Point {\n        x: i32,\n        y: i32,\n    }\n\n    // 结构体\n    assert_eq!(8, size_of::<Point>());\n\n    // 枚举\n    assert_eq!(8, size_of::<Option<i32>>());\n\n    // 取指针宽度:\n    // 在32位目标上为4字节，或者\n    // 在64位目标上为8字节\n    const WIDTH: usize = size_of::<&()>();\n\n    // 指向确定大小类型的指针，其width为1\n    assert_eq!(WIDTH, size_of::<&i32>());\n    assert_eq!(WIDTH, size_of::<&mut i32>());\n    assert_eq!(WIDTH, size_of::<Box<i32>>());\n    assert_eq!(WIDTH, size_of::<fn(i32) -> i32>());\n\n    const DOUBLE_WIDTH: usize = 2 * WIDTH;\n\n    // 不定大小结构体\n    struct Unsized {\n        unsized_field: [i32],\n    }\n\n    // 指向不定大小类型的指针，其width为2\n    assert_eq!(DOUBLE_WIDTH, size_of::<&str>()); // 切片\n    assert_eq!(DOUBLE_WIDTH, size_of::<&[i32]>()); // 切片\n    assert_eq!(DOUBLE_WIDTH, size_of::<&dyn ToString>()); // trait object\n    assert_eq!(DOUBLE_WIDTH, size_of::<Box<dyn ToString>>()); // trait object\n    assert_eq!(DOUBLE_WIDTH, size_of::<&Unsized>()); // 用户定义的不定大小类型\n\n    // 不定大小类型\n    size_of::<str>(); // 编译报错\n    size_of::<[i32]>(); // 编译报错\n    size_of::<dyn ToString>(); // 编译报错\n    size_of::<Unsized>(); // 编译报错\n}\n```\n\n我们怎么知道某个类型是否为 _确定大小类型_ 呢? 很简单: 所有原始类型和指针都有确定的大小，同时所有的结构、元组、枚举和数组，它们或者直接由原始类型和指针构成，或者由它们嵌套得到，所以，只要把这些组成元素的大小加起来，那也能确定地计算出它们的大小（当然计算过程要考虑padding和对齐）。同样道理，我们也可以知道一个类型为 _不定大小类型_：切片可以有任意数量的成员，所以在运行时可能会有任意的大小，而trait object可能是任意实现了该特性的结构/枚举，因此其运行时大小也不确定。\n\n**要点**\n- 指向数组动态视图的指针在Rust中被称为slice(切片)，例如`&str`是 _\"string slice\"_，而`&[i32]`是 _\"i32 slice\"_\n- 切片为双width，原因在于其存储了一个指向数组的指针，同时还要保存数组中元素的数量\n- trait object为双width，原因在于其存储了指向原数据的指针，以及一个指向虚表的指针\n- 不定大小结构的指针为双width，原因在于其存储了指向原数据的指针，同时也保存了该结构的大小\n- 不定大小结构只能有一个不定大小的字段，并且该字段必须是该结构的最后一个字段\n  \n\n来看下面这个带注释的例子，该例子比较切片和数组，通过这个例子我们可以看到，为什么不定大小结构的指针为双width:\n\n```rust\nuse std::mem::size_of;\n\nconst WIDTH: usize = size_of::<&()>();\nconst DOUBLE_WIDTH: usize = 2 * WIDTH;\n\nfn main() {\n    // 长度保存在类型中\n    // [i32; 3] 是3个i32的数组\n    let nums: &[i32; 3] = &[1, 2, 3];\n\n    // 单width指针\n    assert_eq!(WIDTH, size_of::<&[i32; 3]>());\n\n    let mut sum = 0;\n\n    // 可以安全地迭代nums\n    // Rust知道它有3个元素\n    for num in nums {\n        sum += num;\n    }\n\n    assert_eq!(6, sum);\n\n    // 将[i32; 3]不定大小强转(unsized coercion)为切片[i32]\n    // 数据长度现在保存在指针内\n    let nums: &[i32] = &[1, 2, 3];\n\n    // 指针为双width，因为需要还要保存数据长度\n    assert_eq!(DOUBLE_WIDTH, size_of::<&[i32]>());\n\n    let mut sum = 0;\n\n    // 也可以安全地迭代nums\n    // 因为Rust知道它有3个元素(译者注: 通过指针中的第二个width保存)\n    for num in nums {\n        sum += num;\n    }\n\n    assert_eq!(6, sum);\n}\n```\n\n下面是另一个例子，该例子比较结构与trait objects:\n\n```rust\nuse std::mem::size_of;\n\nconst WIDTH: usize = size_of::<&()>();\nconst DOUBLE_WIDTH: usize = 2 * WIDTH;\n\ntrait Trait {\n    fn print(&self);\n}\n\nstruct Struct;\nstruct Struct2;\n\nimpl Trait for Struct {\n    fn print(&self) {\n        println!(\"struct\");\n    }\n}\n\nimpl Trait for Struct2 {\n    fn print(&self) {\n        println!(\"struct2\");\n    }\n}\n\nfn print_struct(s: &Struct) {\n    // 永远打印出\"struct\"\n    // 这个信息在编译时已知\n    s.print();\n    // 单width pointer\n    assert_eq!(WIDTH, size_of::<&Struct>());\n}\n\nfn print_struct2(s2: &Struct2) {\n    // 永远打印出\"struct2\"\n    // 这个信息在编译时已知\n    s2.print();\n    // 单width pointer\n    assert_eq!(WIDTH, size_of::<&Struct2>());\n}\n\nfn print_trait(t: &dyn Trait) {\n    // 会打印出\"struct\"还是\"struct2\"?\n    // 这点在编译时不能确定\n    t.print();\n    // Rust必须在运行时检查指针内容\n    // 以确定是使用Struct的\n    // 还是Struct2的\"print\"实现\n    // 所以这里pointer必须为双width(译者注: 第二个width用于保存虚表)\n    assert_eq!(DOUBLE_WIDTH, size_of::<&dyn Trait>());\n}\n\nfn main() {\n    // 指向数据的单width指针\n    let s = &Struct; \n    print_struct(s); // 打印出\"struct\"\n    \n    // 指向数据的单width指针\n    let s2 = &Struct2;\n    print_struct2(s2); // 打印出\"struct2\"\n    \n    // 将Struct强转为不定长度的dyn Trait\n    // 需要双width指针，以便同时指向数据和Struct的vtable\n    let t: &dyn Trait = &Struct;\n    print_trait(t); // 会打印出\"struct\"\n    \n    // 将Struct2强转为不定长度的dyn Trait\n    // 需要双width指针，以便同时指向数据和Struct2的vtable\n    let t: &dyn Trait = &Struct2;\n    print_trait(t); // 会打印出\"struct2\"\n}\n```\n\n**要点**\n- 只有确定大小类型才能放在栈上，也只有它们才能在程序中按值传递\n- 不定大小类型不能放在栈上，只能按引用传递\n- 指向不定大小类型数据的指针是双width的，因为除了指向数据本身之外，还需要有额外的记录以追踪数据的长度或者结构的虚表\n\n\n## `Sized` Trait\n\nRust中的`Sized`是auto trait(自动特性)，同时也是marker trait(标记特性)。\n\n所谓的auto trait是指在满足一定条件的情况下，该特性会自动实现，而无需手动impl。而marker trait是指那些用于标记类型具备特定属性的特性。marker trait不需要有方法/关联函数/关联常量/关联类型之类的特性item。所有的auto traits都是marker traits，但不是所有的marker traits都是auto traits。之所以auto traits必须是marker traits，是因为只有这样，编译器才能为它们提供默认的实现，否则，如果特性有任何item，那编译器就无法知道怎么自动实现它们了。\n\n对于特定类型来说，如果其所有成员都是`Sized`，那该类型也自动为`Sized`。这里的'成员'具体含义取决于该type的类别，比如：结构的成员字段，枚举的变量，数组的元素，元组的成员，等等。如果一个类型为`Sized`，那就意味着其大小在编译时是确定的。\n\n还有一些其它的auto marker traits，比如`Send` 和 `Sync`。如果一个类型(的实例)可以安全地在线程间转移的话，则该类型为`Send`的，同样，如果一个类型可以安全地在多个线程间共享引用，则该类型为`Sync`的。如果一个类型的所有成员都是`Send` && `Sync`，则该型自身也为`Send` && `Sync`。对于特性`Sized`，有一点特殊的是，开发者不能自行改变或取消(opt-out)掉该特性，这和其它auto marker trait不同。\n\n```rust\n#![feature(negative_impls)]\n\n// 该类型为Sized，Send，Sync\nstruct Struct;\n\n// 取消(opt-out) Send特性\nimpl !Send for Struct {} // ✅\n\n// 取消(opt-out) Sync特性\nimpl !Sync for Struct {} // ✅\n\n// 不能取消(opt-out) Sized特性\nimpl !Sized for Struct {} // ❌\n```\n\n关于不能取消`Sized`这一点，也容易理解。因为可能有时我们不想某个类型在线程间传递，或者在不同线程中共享该类型，但很难想像在哪个场景下，我们会需要编译器\"忘记\"某个类型的确定大小性质，并把它当成不定大小类型来使用，这样做不会带来任何好处，只会使这个类型变得更难使用。\n\n另外，如果非要严格地说的话，其实`Sized`不算auto trait，它没使用`auto`关键字，只不过编译器对它作了特殊处理，使得其表现上与其它auto traits一样，总之，在开发中把它当成auto trait没有任何问题。\n\n**要点**\n- `Sized`是auto marker trait —— 自动标记特性\n\n\n## 泛型中的`Sized`\n\n初看起来不明显，但实际上每次我们写泛型代码时，每个泛型参数都默认自动绑定了`Sized`特性(译者注: 除非我们手动指定了`?Sized`):\n\n```rust\n// 对于这个泛型函数...\nfn func<T>(t: T) {}\n\n// 它被展开后是这样的...\nfn func<T: Sized>(t: T) {}\n\n// 对于上面这个自动绑定的Sized，我们可以显式指定?Sized来取消掉它\nfn func<T: ?Sized>(t: T) {} // ❌\n\n// 一旦像上面这样做了，则上面的代码就编不过了，因为它可能没有确定的大小(译者注: 而不定大小类型不能以传值方式使用)\n// 所以我们必须把它放到某个指针后面去，比如:\nfn func<T: ?Sized>(t: &T) {} // ✅\nfn func<T: ?Sized>(t: Box<T>) {} // ✅\n```\n\n**要点**\n- `?Sized` 可以念成 _\"可选 sized\"_ 或者 _\"可能 sized\"_，把它加到到类型的限定中去后，表示这个类型可能是'确定大小类型'，也可能是'不定大小型'\n- `?Sized` 通常也被称为 _\"解除bound\"_ 或者 _\"宽松bound\"_，因为它放宽了原有限制，而不是在为原类型添加更多的限制\n- `?Sized` 是Rust中唯一的 _\"解除bound\"_\n\n所以，上面说的这些有什么用呢？嗯，实际上只要我们写泛型类型，并且通过指针来使用这个类型，那基本上都会需要取消掉这个默认的`Sized`绑定，这样我们的函数才能更自由地接受各种参数类型，而如果我们不这样做，那最后，我们大概率会遇到麻烦，并被编译器的错误提示弄糊涂。\n\n来看看我在Rust中写的第一个泛型函数。我在`dbg!`宏正式进入Rust前就开始学习Rust了，所以那时打印调试值的唯一办法是`println!(\"{:?}\"，some_value);`，因为到处写这段代码有点麻烦，所以我决定写一个下面这样的`debug`辅助函数:\n\n```rust\nuse std::fmt::Debug;\n\nfn debug<T: Debug>(t: T) { // T: Debug + Sized\n    println!(\"{:?}\", t);\n}\n\nfn main() {\n    debug(\"my str\"); // T = &str, &str: Debug + Sized ✅\n}\n```\n\n目前为止一切都很完美，但这个函数会拿走传入参数的所有权，这点有些烦人，所以我修改了下，将函数签名改为使用引用:\n\n```rust\nuse std::fmt::Debug;\n\nfn dbg<T: Debug>(t: &T) { // T: Debug + Sized\n    println!(\"{:?}\", t);\n}\n\nfn main() {\n    dbg(\"my str\"); // &T = &str, T = str, str: Debug + !Sized ❌\n}\n```\n\n但是这段代码编不过:\n\n```none\nerror[E0277]: the size for values of type `str` cannot be known at compilation time\n --> src/main.rs:8:9\n  |\n3 | fn dbg<T: Debug>(t: &T) {\n  |        - required by this bound in `dbg`\n...\n8 |     dbg(\"my str\");\n  |         ^^^^^^^^ doesn't have a size known at compile-time\n  |\n  = help: the trait `std::marker::Sized` is not implemented for `str`\n  = note: to learn more，visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>\nhelp: consider relaxing the implicit `Sized` restriction\n  |\n3 | fn dbg<T: Debug + ?Sized>(t: &T) {\n  |   \n```\n\n第一次遇到这个错时，我真的被搞懵了。我只是给参数加了个比之前更严格的限制，过去能编通的代码，现在竟然编不过了？到底发生了什么？\n\n其实在上面代码的注释里，我已经作了一定解释了，本质原因在于：Rust在编译时将`T`替换为具体类型时作了模式匹配。通过下面这个表格可能看得更清楚些：\n\n| 类型 | `T` | `&T` |\n|------------|---|----|\n| `&str` | `T` = `&str` | `T` = `str` |\n\n| 类型 | `Sized`（是否确定大小） |\n|-|-|\n| `str` | ❌ |\n| `&str` | ✅ |\n| `&&str` | ✅ |\n\n所以，在把参数改成引用后，我需要同时加上`?Sized`(译者注:放宽对T的限制)，这样下面这段代码就可以正常工作了:\n\n```rust\nuse std::fmt::Debug;\n\nfn debug<T: Debug + ?Sized>(t: &T) { // T: Debug + ?Sized\n    println!(\"{:?}\"，t);\n}\n\nfn main() {\n    debug(\"my str\"); // &T = &str，T = str，str: Debug + !Sized ✅\n}\n```\n\n**要点**\n- 所有的泛型类型都有一个默认的`Sized`绑定\n- 如果我们的泛型函数有指针形式的参数`T`，比如`&T`，`Box<T>`，`Rc<T>`， 等等，那我们几乎总是要通过`T: ?Sized`来取消默认的`Sized`\n\n\n## 不定大小类型(Unsized Types)\n\n\n\n### Slices(切片)\n\n最常见的切片是字符串切片 `&str` 和数组切片 `&[T]`。切片有一个优点：很多其它类型可以强转为切片，利用这一点，以及Rust的自动类型强转，我们可以构造更加灵活的API。\n\n类型强转可以在好些个不同的场景下发生，最常见的是在函数传参以及方法调用。这里，我们感兴趣的是deref（解引用）强转和不定大小强转（unsized coercions）。解引用强转是指`T`通过deref操作强转为`U`，也就是`T: Deref<Target = U>`，比如`String.deref() -> str`。 而不定大小强转则是指将`T`强转为`U`，这里的`T`是一个确定大小类型，而`U`为不定大小类型，也就是`T: Unsize<U>`，比如`[i32; 3] -> [i32]`。\n\n```rust\ntrait Trait {\n    fn method(&self) {}\n}\n\nimpl Trait for str {\n    // 现在能够调用下面这些类型的\"method\"\n    // 1) str\n    // 2) String (因为String实现了Deref<Target = str>)\n}\nimpl<T> Trait for [T] {\n    // 现在能够调用下面这些类型的\"method\"\n    // 1) 任意 &[T]\n    // 2) 任意 U where U: Deref<Target = [T]>，比如Vec<T>\n    // 3) [T; N]，因为[T; N]: Unsize<[T]>\n}\n\nfn str_fun(s: &str) {}\nfn slice_fun<T>(s: &[T]) {}\n\nfn main() {\n    let str_slice: &str = \"str slice\";\n    let string: String = \"string\".to_owned();\n\n    // 函数参数\n    str_fun(str_slice);\n    str_fun(&string); // 解引用强转\n\n    // 方法调用\n    str_slice.method();\n    string.method(); // 解引用强转\n\n    let slice: &[i32] = &[1];\n    let three_array: [i32; 3] = [1, 2, 3];\n    let five_array: [i32; 5] = [1, 2, 3, 4, 5];\n    let vec: Vec<i32> = vec![1];\n\n    // 函数参数\n    slice_fun(slice);\n    slice_fun(&vec); // 解引用强转\n    slice_fun(&three_array); // 不定大小强转\n    slice_fun(&five_array); // 不定大小强转\n\n    // 方法调用\n    slice.method();\n    vec.method(); // 解引用强转\n    three_array.method(); // 不定大小强转\n    five_array.method(); // 不定大小强转\n}\n```\n\n**关键点**\n- 利用切片和Rust的自动类型强转，我们可以写出更灵活的API\n\n\n\n### Trait Objects(特性对象)\n\n特性默认是`?Sized`的。下面这段代码：\n\n```rust\ntrait Trait: ?Sized {}\n```\n\n编译时会报错：\n\n```none\nerror: `?Trait` is not permitted in supertraits\n --> src/main.rs:1:14\n  |\n1 | trait Trait: ?Sized {}\n  |              ^^^^^^\n  |\n  = note: traits are `?Sized` by default\n```\n\n后面我们会讨论为什么traits默认是`?Sized`的，现在，我们先问下自己：trait为`?Sized`究竟是什么意思？我们把上面的代码展开来看：\n\n```rust\ntrait Trait where Self: ?Sized {}\n```\n\n好的，所以默认的trait是指允许self为确定大小类型或者不定大小类型。而我们现在已经知道，不可以使用传值的方式传递不定大小类型，所以这个默认trait在效果上限制了我们可以在trait中定义的方法。具体说就是，我们不能写接受或返回传值形式的`self`。但是，奇怪的是，下面这个代码是可以通过编译的：\n\n```rust\ntrait Trait {\n    fn method(self); // ✅\n}\n```\n\n不过，一旦我们真正开始实现这一方法，或者为这个方法提供默认实现，或者为不定大小类型实现这个trait的话，我们就会得到编译错误:\n\n```rust\ntrait Trait {\n    fn method(self) {} // ❌\n}\n\nimpl Trait for str {\n    fn method(self) {} // ❌\n}\n```\n\n错误类似这样:\n\n```none\nerror[E0277]: the size for values of type `Self` cannot be known at compilation time\n --> src/lib.rs:2:15\n  |\n2 |     fn method(self) {}\n  |               ^^^^ doesn't have a size known at compile-time\n  |\n  = help: the trait `std::marker::Sized` is not implemented for `Self`\n  = note: to learn more，visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>\n  = note: all local variables must have a statically known size\n  = help: unsized locals are gated as an unstable feature\nhelp: consider further restricting `Self`\n  |\n2 |     fn method(self) where Self: std::marker::Sized {}\n  |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nerror[E0277]: the size for values of type `str` cannot be known at compilation time\n --> src/lib.rs:6:15\n  |\n6 |     fn method(self) {}\n  |               ^^^^ doesn't have a size known at compile-time\n  |\n  = help: the trait `std::marker::Sized` is not implemented for `str`\n  = note: to learn more，visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>\n  = note: all local variables must have a statically known size\n  = help: unsized locals are gated as an unstable feature\n```\n\n如果我们可以确保只以传值的方式使用`self`，那可以通过给这个trait显式绑定`Sized`来解决上面的编译错误：\n\n```rust\ntrait Trait: Sized {\n    fn method(self) {} // ✅\n}\n\nimpl Trait for str { // ❌\n    fn method(self) {}\n}\n```\n\n上面代码中，为str实现Trait时的编译报错为:\n\n```none\nerror[E0277]: the size for values of type `str` cannot be known at compilation time\n --> src/lib.rs:7:6\n  |\n1 | trait Trait: Sized {\n  |              ----- required by this bound in `Trait`\n...\n7 | impl Trait for str {\n  |      ^^^^^ doesn't have a size known at compile-time\n  |\n  = help: the trait `std::marker::Sized` is not implemented for `str`\n  = note: to learn more，visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>\n```\n\n这是符合预期的，因为，既然我们为这个trait指定了`Sized`绑定，那自然就不能为不定大小的类型(比如`str`)实现该trait。另一方面，如果确实要为`str`实现该trait，那我们可以使用另一种方式，也就是保持trait的`?Sized`绑定，同时改用引用方式来传递`self`:\n\n```rust\ntrait Trait {\n    fn method(&self) {} // ✅\n}\n\nimpl Trait for str {\n    fn method(&self) {} // ✅\n}\n```\n\n通过标记特性的方法而不是标记整个特性为`?Sized`或`Sized`，我们可以获得更细的控制粒度，比如：\n\n```rust\ntrait Trait {\n    fn method(self) where Self: Sized {}\n}\n\nimpl Trait for str {} // ✅!?\n\nfn main() {\n    \"str\".method(); // ❌\n}\n```\n\n有些让人吃惊的是，上面`impl Trait for str {}`一行可以通过编译，但最终，Rust会在我们试图在不定大小类型上调用`method`时捕捉到这一错误，所以一切都还好。虽然有一点奇怪，但它的确为我们提供了一些自由度：我们的trait可以有一些方法被绑定到`Sized`，同时我们还可以为不定大小类型实现该trait，只要我们永远不调用这些(译者注：绑定到`Sized`的)方法就不会有问题:\n\n```rust\ntrait Trait {\n    fn method(self) where Self: Sized {}\n    fn method2(&self) {}\n}\n\nimpl Trait for str {} // ✅\n\nfn main() {\n    // 我们永远不调用method，所以也就不会有报错\n    \"str\".method2(); // ✅\n}\n```\n\n现在回到前面提出的那个问题，为什么trait默认是`?Sized`（未知大小类型）? 答案在于trait objects。Trait objects是不定大小的，因为任意大小的类型都可以实现同一个trait，所以只有当`Trait: ?Sized`时，我们才有可能为`dyn Trait`实现`Trait`。看看实际代码的情况：\n\n```rust\ntrait Trait: ?Sized {}\n\n// 上面这一行对下面的`impl`是必须的\n\nimpl Trait for dyn Trait {\n    // compiler magic here\n}\n\n// 因为`dyn Trait`是不定大小的\n\n// 这样，我们在程序里才可以使用`dyn Trait`\n\nfn function(t: &dyn Trait) {} // ✅\n```\n\n如果我们编译上面这段代码，会得到如下编译错误:\n\n```none\nerror[E0371]: the object type `(dyn Trait + 'static)` automatically implements the trait `Trait`\n --> src/lib.rs:5:1\n  |\n5 | impl Trait for dyn Trait {\n  | ^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Trait + 'static)` automatically implements trait `Trait`\n```\n\n这是编译器在告诉我们，它已经自动地为`dyn Trait`实现了`Trait`，所以我们不需要再手动显式这样做。再一次地，因为`dyn Trait`是不定大小的，所以编译器只能提供针对`Trait: ?Sized`的实现。反之，如果我们给`Trait`绑定`Sized`，那么`Trait`就会成为 _\"object unsafe\"_， 这是一个专有名词，它意味着我们不能将实现该trait的类型强转为`dyn Trait`的trait object。所以，下面的这段代码是编不过的：\n\n```rust\ntrait Trait: Sized {}\n\nfn function(t: &dyn Trait) {} // ❌\n```\n\n抛出的错误如下:\n\n```none\nerror[E0038]: the trait `Trait` cannot be made into an object\n --> src/lib.rs:3:18\n  |\n1 | trait Trait: Sized {}\n  |       -----  ----- ...because it requires `Self: Sized`\n  |       |\n  |       this trait cannot be made into an object...\n2 | \n3 | fn function(t: &dyn Trait) {}\n  |                ^^^^^^^^^^ the trait `Trait` cannot be made into an object\n```\n\n我们来写一个带`Sized`绑定方法的`?Sized`特性，然后试下看能否将其强转为trait object:\n\n```rust\ntrait Trait {\n    fn method(self) where Self: Sized {}\n    fn method2(&self) {}\n}\n\nfn function(arg: &dyn Trait) { // ✅\n    arg.method(); // ❌\n    arg.method2(); // ✅\n}\n```\n\n就像我们前面已经看到的那样，不调用这个`Sized`方法那一切都没有问题，反之则会报错。\n\n**要点**\n- 所有特性默认都是`?Sized`的\n- `Trait: ?Sized`对于为`dyn Trait`实现`Trait`很关键\n- 我们可以在方法粒度上指定`Self: Sized`\n- `Sized`绑定的特性不能转成trait object\n\n\n### trait object的限制\n\n特性对象安全使得我们可以使用dyn Trait，不过，仍然有一些边缘的用例，限制了什么类型可以强转为trait object以及哪些特性可以用trait object来表示。\n\n\n#### 不能将不定大小类型强转为trait object\n\n```rust\nfn generic<T: ToString>(t: T) {}\nfn trait_object(t: &dyn ToString) {}\n\nfn main() {\n    generic(String::from(\"String\")); // ✅\n    generic(\"str\"); // ✅\n    trait_object(&String::from(\"String\")); // ✅ - 不定大小强转\n    trait_object(\"str\"); // ❌ - 不能作不定大小强转\n}\n```\n\n上面这段代码抛出的错误如下:\n\n```none\nerror[E0277]: the size for values of type `str` cannot be known at compilation time\n --> src/main.rs:8:18\n  |\n8 |     trait_object(\"str\");\n  |                  ^^^^^ doesn't have a size known at compile-time\n  |\n  = help: the trait `std::marker::Sized` is not implemented for `str`\n  = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>\n  = note: required for the cast to the object type `dyn std::string::ToString`\n```\n\n之所以可以将`String`强转为`&dyn ToString`，是因为`String`的确实现了`ToString`特性，并且，我们可以将一个确定大小类型(`String`)转为一个不定大小类型(`dyn ToString`)，Rust中支持这种强转，前文提到过，这种强转叫做不定大小强转。另一方面，`str`也实现了`ToString`特性，如果要将`str`转为`dyn ToString`，那也需要执行一次不定大小强转(译者注:因为dyn ToString是不定大小的)，但是这里的问题在于：`str`已经是不定大小的了，我们怎么样才能将一个不定大小的类型转为另一个不定大小类型呢？(译者注：答案是不支持，接下来是原因解释)\n\n前文提到过，`&str`指针是双width的，它存储了指向数据的指针以及数据的长度。`&dyn ToString`指针也是双width的，保存了指向数据的指针以及指向虚表的指针。因此如果要将`&str`强转为`&dyn toString`，那就需要一个3倍width的指针，以同时保存指向数据的指针、数据长度以及指向虚表的指针。Rust不支持3倍width的指针，这就是我们不能将一个不定长度类型强转为trait object的原因。\n\n将上面两段话总结成表格的话，就是下面这样:\n\n| 类型 | 指向数据的指针 | 数据长度 | 指向虚表的指针 | 总Width |\n|-|-|-|-|-|\n| `&String` | ✅ | ❌ | ❌ | 1 ✅ |\n| `&str` | ✅ | ✅ | ❌ | 2 ✅ |\n| `&String as &dyn ToString` | ✅ | ❌ | ✅ | 2 ✅ |\n| `&str as &dyn ToString` | ✅ | ✅ | ✅ | 3 ❌ |\n\n\n\n#### 不能创建多特性对象\n\n```rust\ntrait Trait {}\ntrait Trait2 {}\n\nfn function(t: &(dyn Trait + Trait2)) {}\n```\n\n上面代码编译报错如下：\n\n```none\nerror[E0225]: only auto traits can be used as additional traits in a trait object\n --> src/lib.rs:4:30\n  |\n4 | fn function(t: &(dyn Trait + Trait2)) {}\n  |                      -----   ^^^^^^\n  |                      |       |\n  |                      |       additional non-auto trait\n  |                      |       trait alias used in trait object type (additional use)\n  |                      first non-auto trait\n  |                      trait alias used in trait object type (first use)\n```\n\n让我们回想下：trait object的指针是双width的，它保存了一个指向数据的指针和一个指向虚表的指针，但上面的代码有两个trait，所以这里就有两个虚表，也就是说`&(dyn Trait + Trait2)`得是3倍width才行。（译者补充: 但我们经常在代码里看到`dyn Object + Send + Sync`这类写法是怎么回事？）自动特性之所以可以相加，是因为像`Sync`和`Send`这种自动特性它们没有方法，因此也就没有虚表，所以它们没有这个限制。\n\n绕过这一限制的方法是，通过将不同trait组合成另一个trait来把虚表组合到一起：\n\n```rust\ntrait Trait {\n    fn method(&self) {}\n}\n\ntrait Trait2 {\n    fn method2(&self) {}\n}\n\ntrait Trait3: Trait + Trait2 {}\n\n// 为任何同时实现了Trait和Trait2的类型自动实现Trait3(译者注: 参见[Generic Blanket Impls](https://github.com/mercury-2025/rust-blog/blob/master/posts/tour-of-rusts-standard-library-traits.md#generic-blanket-impls))\nimpl<T: Trait + Trait2> Trait3 for T {}\n\n// 将`dyn Trait + Trait2`改为`dyn Trait3` \nfn function(t: &dyn Trait3) {\n    t.method(); // ✅\n    t.method2(); // ✅\n}\n```\n\n这种方法的缺点在于，Rust不支持到supertrait的向上强转。也就是我们不能将`dyn Trait3`用于需要`dyn Trait`或`dyn Trait2`的地方。下面这样的代码编不过：\n\n```rust\ntrait Trait {\n    fn method(&self) {}\n}\n\ntrait Trait2 {\n    fn method2(&self) {}\n}\n\ntrait Trait3: Trait + Trait2 {}\n\nimpl<T: Trait + Trait2> Trait3 for T {}\n\nstruct Struct;\nimpl Trait for Struct {}\nimpl Trait2 for Struct {}\n\nfn takes_trait(t: &dyn Trait) {}\nfn takes_trait2(t: &dyn Trait2) {}\n\nfn main() {\n    let t: &dyn Trait3 = &Struct;\n    takes_trait(t); // ❌\n    takes_trait2(t); // ❌\n}\n```\n\n上面代码编译报错如下：\n\n```none\nerror[E0308]: mismatched types\n  --> src/main.rs:22:17\n   |\n22 |     takes_trait(t);\n   |                 ^ expected trait `Trait`, found trait `Trait3`\n   |\n   = note: expected reference `&dyn Trait`\n              found reference `&dyn Trait3`\n\nerror[E0308]: mismatched types\n  --> src/main.rs:23:18\n   |\n23 |     takes_trait2(t);\n   |                  ^ expected trait `Trait2`, found trait `Trait3`\n   |\n   = note: expected reference `&dyn Trait2`\n              found reference `&dyn Trait3`\n```\n\n报错原因在于，`dyn Trait3`是与`dyn Trait`/`dyn Trait2`完全不同的另一类型，因为他们有不同的虚表结构，虽然实际上`dyn Trait3`确实有`dyn Trait`和`dyn Trait2`的所有方法。要解决此问题，可以使用显式强转:\n\n```rust\ntrait Trait {}\ntrait Trait2 {}\n\ntrait Trait3: Trait + Trait2 {\n    fn as_trait(&self) -> &dyn Trait;\n    fn as_trait2(&self) -> &dyn Trait2;\n}\n\nimpl<T: Trait + Trait2> Trait3 for T {\n    fn as_trait(&self) -> &dyn Trait {\n        self\n    }\n    fn as_trait2(&self) -> &dyn Trait2 {\n        self\n    }\n}\n\nstruct Struct;\nimpl Trait for Struct {}\nimpl Trait2 for Struct {}\n\nfn takes_trait(t: &dyn Trait) {}\nfn takes_trait2(t: &dyn Trait2) {}\n\nfn main() {\n    let t: &dyn Trait3 = &Struct;\n    takes_trait(t.as_trait()); // ✅\n    takes_trait2(t.as_trait2()); // ✅\n}\n```\n\n这种方式简单而直观，看起来Rust编译器似乎应该帮我们自动化地做掉这个事情。Rust已经在deref或不定大小强转等情形下帮我们做过这类自动转换了，所以在这里为什么它就不能帮我们把这个向上强转也自动做掉呢? 这是一个很好的问题，答案你应该也很熟悉了: Rust核心团队正在做其它一些更高优先级以及影响更大的事情，很说得过去。\n\n**要点**\n- Rust不支持超过2倍宽度的指针，所以：\n    - 我们不能将不定大小类型转为trait objects\n    - 我们不能同时trait object定多个trait，但是我们可以通过将多个trait组合为单个trait来应对这一限制\n\n\n### 用户定义的不定大小类型\n\n```rust\nstruct Unsized {\n    unsized_field: [i32],\n}\n```\n\n我们可以通过为结构增加一个不定大小字段来定义一个不定大小结构。不定大小结构只能有一个不定大小字段，并且该字段只能是结构的最后一个字段。因为只有这样，编译器才能在编译期确定地知道结构中每个字段的起始偏移，这一点对于有效和快速的字段存取来说至关重要。并且，由于双width指针最多只能描述单个不定大小字段，所以我们不能有更多的不定大小字段，因为它们将会需要更大的width以存储这些信息。\n\n那么，我们怎么才能初始化这样一个自定义的不定大小结构呢? 与我们构造系统原生不定大小类型时的做法一样: 先构造一个确定大小类型的版本，然后将其强转为不定大小的版本。但是，上面的`Unsized`类型就是不定大小类型啊，它的确定大小类型版本又是什么，我们又怎么能构造一个这样的确定大小版本`Unsized`呢? 唯一办法是：使用一个泛型参数来定义我们的不定大小字段成员，这样这个成员既可以是确定大小类型，也可以是不定大小类型:\n\n```rust\nstruct MaybeSized<T: ?Sized> {\n    maybe_sized: T,\n}\n\nfn main() {\n    // 将MaybeSized<[i32; 3]>不定大小强转为MaybeSized<[i32]>\n    let ms: &MaybeSized<[i32]> = &MaybeSized { maybe_sized: [1, 2, 3] };\n}\n```\n\n好了，那这种东西具体有什么用处呢? 答案是，我们想不到有什么特别有说服力的场景需要它，用户定义的不定大小类型目前仅仅是个半成品，它们的限制超过了它们的收益。大家知道有这么回事就可以了。\n\n**有趣的是:** `std::ffi::OsStr` 和 `std::path::Path`是标准库中的两个不定大小结构，你可能已经用过它们了，但没有意识到它们是不定大小的!\n\n**要点**\n- 用户自定义的不定大小类型目前还是半成品，它们的限制超出了它们的收益\n\n\n## 0大小类型\n\nZST听起来有点怪，但他们实际上无处不在。\n\n\n\n### 单元类型\n\n最常见的ZST是单元类型: `()`。所有空的代码块`{}`都返回`()`，如果代码块非空，但最后一个表达式以分号`;`结尾，则它也返回`()`。比如：\n\n```rust\nfn main() {\n    let a: () = {};\n    let b: i32 = {\n        5\n    };\n    let c: () = {\n        5;\n    };\n}\n```\n\n所有没有显式返回值的函数默认也返回`()`。比如：\n\n```rust\n// 展开前\nfn function() {}\n\n// 展开后\nfn function() -> () {}\n```\n\n由于`()`是0大小的，所以不同的`()`是相等的，这一点导致了部分相当简单的`Default`，`PartialEq`，以及 `Ord` 实现:\n\n```rust\nuse std::cmp::Ordering;\n\nimpl Default for () {\n    fn default() {}\n}\n\nimpl PartialEq for () {\n    fn eq(&self, _other: &()) -> bool {\n        true\n    }\n    fn ne(&self, _other: &()) -> bool {\n        false\n    }\n}\n\nimpl Ord for () {\n    fn cmp(&self, _other: &()) -> Ordering {\n        Ordering::Equal\n    }\n}\n```\n\n编译器知道`()`是0大小的，所以会优化掉与`()`实例相关的交互。比如，一个`Vec<()>`永远不会执行堆上的分配，在这个`Vec`中pushing和popping`()`只是增减它的`len`字段：\n\n```rust\nfn main() {\n    // '存储'无穷多个()只需要0预留容量\n    let mut vec: Vec<()> = Vec::with_capacity(0);\n    // 因为这里不涉及任何堆分配或者vec的容量改变\n    vec.push(()); // len++\n    vec.push(()); // len++\n    vec.push(()); // len++\n    vec.pop(); // len--\n    assert_eq!(2, vec.len());\n}\n```\n\n上面这个例子没有什么实际用处，还有没有更实际有用的场景可以利用上面这一点的？回答是yes，我们可以通过 `HashMap<Key, Value>` 来得到高效的 `HashSet<Key>` 实现， 方法是将`Value`设为`()`，实际上这正是Rust标准库的做法：\n\n```rust\n// std::collections::HashSet\npub struct HashSet<T> {\n    map: HashMap<T, ()>,\n}\n```\n\n**要点**\n- 特定ZST类型的所有实例都彼此相等\n- Rust编译器会优化掉与ZST相关的交互\n\n\n### 用户定义的单元大小结构\n\n单元大小结构是不含任何成员字段的结构，也就是:\n\n```rust\nstruct Struct;\n```\n\n单元大小结构比`()`更好的地方在于:\n- 可以在其上实现我们需要的任何特性，Rust的特性隔离原则上阻止了我们为`()`实现trait的可能，因为`()`定义在标准库而不是我们的代码里\n- 我们可以给单元大小结构赋一个在程序上下文中看起来更有意义的名字\n- 与所有其它结构一样，单元大小结构默认是non-Copy的，这一点在我们程序的上下文中有可能会很重要\n\n\n### 不可能类型（Never Type）\n\n第二个常见的ZST是不可能类型: `!`。它之所以叫不可能类型，是因为它表示不可能计算为任何值的操作结果。\n\n`!`不同于`()`的一些有趣特性:\n- `!` 可以强转成任意其它类型(译者注: 编译器语法解析时)\n- 我们无法在代码中创建`!`类型的实例\n\n上述第一个属性很有用，有了这一属性，我们才可以使用下面这样的宏：\n\n```rust\n// 对于快速写原型很有用\nfn example<T>(t: &[T]) -> Vec<T> {\n    unimplemented!() // ! 强转为 Vec<T>\n}\n\nfn example2() -> i32 {\n    // 我们知道parse操作永远不会失败\n    match \"123\".parse::<i32>() {\n        Ok(num) => num,\n        Err(_) => unreachable!(), // ! 强转为 i32\n    }\n}\n\nfn example3(some_condition: bool) -> &'static str {\n    if !some_condition {\n        panic!() // ! 强转为 &str\n    } else {\n        \"str\"\n    }\n}\n```\n\n`break`，`continue`，和 `return` 表达式类型也是 `!`:\n\n```rust\nfn example() -> i32 {\n    // 在这里x可被设置为任何类型\n    // 因为在这里代码块永远不会有返回值(译者注: 代码块中的return是example返回，而不是将return的值赋给x)\n    let x: String = {\n        return 123 // ! 强转为 String\n    };\n}\n\nfn example2(nums: &[i32]) -> Vec<i32> {\n    let mut filtered = Vec::new();\n    for num in nums {\n        filtered.push(\n            if *num < 0 {\n                break // ! 强转为 i32\n            } else if *num % 2 == 0 {\n                *num\n            } else {\n                continue // ! 强转为 i32\n            }\n        );\n    }\n    filtered\n}\n```\n\n上面所说的第二个有趣特性，使得我们可以在类型这一层上标记代码中的不可能的情形。我们通过下面的函数签名例子来解释这具体是什么意思：\n\n```rust\nfn function() -> Result<Success, Error>;\n```\n\n我们知道，如果函数成功返回，则`Result`会包含类型`Success`的某个实例，如果函数失败，则`Result`会包含类型`Error`的某个实例。现在看下面这个函数签名：\n\n```rust\nfn function() -> Result<Success, !>;\n```\n\n同样的，如果函数成功返回，则`Result`会包含类型`Success`的某个实例，如果函数失败，嗯...， 但是等一下，它永远不能失败，因为根据上述第二个特性，我们不可能构造一个`!`的实例。所以，通过上面这个函数签名，我们知道这个函数永远不会失败。那下面这个函数呢：\n\n```rust\nfn function() -> Result<!, Error>;\n```\n\n反过来也一样: 既然不可能构造成功时的返回值，我们可以确定只要返回，则这个函数肯定失败了。\n\n前一种形式的实际应用可以在`String`的`FromStr`实现中看到，因为将`&str`转为`String`不可能失败：\n\n```rust\n#![feature(never_type)]\n\nuse std::str::FromStr;\n\nimpl FromStr for String {\n    type Err = !;\n    fn from_str(s: &str) -> Result<String, Self::Err> {\n        Ok(String::from(s))\n    }\n}\n```\n\n第二种形式的实际应用可以是一个执行无限循环永不结束的函数，比如一个处理客户端请求的server，除非遇到错误，否则这个函数永不返回：\n\n```rust\n#![feature(never_type)]\n\nfn run_server() -> Result<!, ConnectionError> {\n    loop {\n        let (request, response) = get_request()?;\n        let result = request.process();\n        response.send(result);\n    }\n}\n```\n\n上面代码中的特性标记(feature flag)是必须的，因为不可能类型本身只存在和工作于Rust内部，在用户代码中使用仍然还只是实验性的。\n\n**要点**\n- `!`可以转成任何其它类型(译者注：语法上)\n- `!`类型不可以创建任何实例这一特性，使得我们可以在类型层次上声明特定的不可能状态\n\n\n\n### 用户定义的伪不可能类型\n\n虽然我们不能定义一个可以转成任何其它类型的自定义类型，但我们可以定义一个不能创建任何实际实例的类型，比如一个不包含任何成员的`enum`：\n\n```rust\nenum Void {}\n```\n\n通过这种自定义类型，我们可以免去上面所说的特性标记(译者注： `#![feature(never_type)]`):\n\n```rust\nenum Void {}\n\n// example 1\nimpl FromStr for String {\n    type Err = Void;\n    fn from_str(s: &str) -> Result<String, Self::Err> {\n        Ok(String::from(s))\n    }\n}\n\n// example 2\nfn run_server() -> Result<Void, ConnectionError> {\n    loop {\n        let (request, response) = get_request()?;\n        let result = request.process();\n        response.send(result);\n    }\n}\n```\n\n这也是Rust标准库中使用的方法，在`String`的`FromStr`实现中，`Err`类型为`std::convert::Infallible`，它长这样：\n\n```rust\npub enum Infallible {}\n```\n\n\n\n### PhantomData(伪数据)\n\n第3种常见ZST大概是`PhantomData`。`PhantomData`是一个0大小标记结构，它可以用于标记所在的结构具有特定的属性。它有点像自动标记trait，比如`Sized`，`Send`，以及`Sync`，但使用方式上有一点区别。完整的`PhantomData`解释以及它的各种应用超出了本文的范围，所以我们只简单看一个例子。前文提到过这样一段代码：\n\n```rust\n#![feature(negative_impls)]\n\n// 该结构为Send+Sync\nstruct Struct;\n\n// 取消Send特性\nimpl !Send for Struct {}\n\n// 取消Sync特性\nimpl !Sync for Struct {}\n```\n\n在上面代码中，我们得使用feature flag。那能不能只使用稳定Rust达到同样目的呢? 我们已经知道，当一个结构的所有成员都是`Send`/`Sync`时，该结构自动为`Send`/`Sync`，所以如果我们给`Struct`加一个`!Send`/`!Sync`成员，比如`Rc<()>`的话，那也可以达到取消自动特性的目的：\n\n```rust\nuse std::rc::Rc;\n\n// 该结构非Send或Sync\nstruct Struct {\n    // 每个实例多了8字节\n    _not_send_or_sync: Rc<()>,\n}\n```\n\n但这种方式不够理想，因为它增加了`Struct`具体实例的大小，每次我们构造`Struct`时，都得凭空多造一个`Rc<()>`。不过，由于`PhantomData`为ZST，它可以在这里帮助我们解决此问题:\n\n```rust\nuse std::rc::Rc;\nuse std::marker::PhantomData;\n\ntype NotSendOrSyncPhantom = PhantomData<Rc<()>>;\n\n// 该结构非Send或Sync\nstruct Struct {\n    // 不会增加实例的大小\n    _not_send_or_sync: NotSendOrSyncPhantom,\n}\n```\n\n**要点**\n- `PhantomData`是0大小标记结构，它可以用于标记其所在结构的某些特定属性\n\n\n\n## 总结\n\n- 只有确定大小类型可以放在栈上，也就是说，只有它们可以通过值的方式传递\n- 不定大小类型不能放在栈上，且只能以引用方式传递\n- 指向不定大小类型的指针是双width的，因为除了指向数据的指针之外，它们还需要额外的比特来记录数据的大小 _或者_ 指向虚表的指针\n- `Sized` 是一个\"自动的\"特性标记\n- 所有泛型参数默认自动绑定`Sized`\n- 如果我们有一个泛型函数，它的参数为某种指向`T`的指针，比如：`&T`，`Box<T>`，`Rc<T>`，等等，那么我们基本上都要取消默认的`Sized`绑定：`T: ?Sized`\n- 利用切片和Rust的自动类型转换，我们可以写出更灵活的API\n- 所有trait默认都是`?Sized`的\n- `Trait: ?Sized`对于`impl Trait for dyn Trait`是必须的\n- 我们可以在单方法的粒度上指定`Self: Sized`\n- 绑定`Sized`的特性不能用作trait object\n- Rust不支持大于2widths的指针，所以: \n    - 我们不能将不定大小类型强转为trait object\n    - 我们不能定义多特性trait object，但可以通过组合多个特性至单个特性来绕过这一点\n- 用户定义的不定大小类型目前是半成品，它们的限制大于它们可能有的任何好处\n- 一个ZST的所有实例都彼此相等\n- Rust编译器会优化掉与ZST的交互\n- `!`可以转成任何其它类型(译者注: 语法上)\n- 不可能构造`!`的实例，我们可以利用这一点在类型层次上声明不可能情形\n- `PhantomData`是0大小标记结构，它可以用于\"标记\"所在的结构有特定的属性\n\n\n\n## 讨论\n\n可以到下列地点讨论本文\n- [official Rust users forum](https://users.rust-lang.org/t/blog-post-sizedness-in-rust/46293?u=pretzelhammer)\n- [learnrust subreddit](https://www.reddit.com/r/learnrust/comments/hx2jd0/sizedness_in_rust/)\n- [rust subreddit](https://www.reddit.com/r/rust/comments/hxips7/sizedness_in_rust/)\n- [Github](https://github.com/pretzelhammer/rust-blog/discussions)\n\n\n## 进一步阅读\n\n- [Common Rust Lifetime Misconceptions](./common-rust-lifetime-misconceptions.md)\n- [Tour of Rust's Standard Library Traits](./tour-of-rusts-standard-library-traits.md)\n- [Beginner's Guide to Concurrent Programming: Coding a Multithreaded Chat Server using Tokio](./chat-server.md)\n- [Learning Rust in 2024](./learning-rust-in-2024.md)\n- [Using Rust in Non-Rust Servers to Improve Performance](./rust-in-non-rust-servers.md)\n- [RESTful API in Sync & Async Rust](./restful-api-in-sync-and-async-rust.md)\n- [Learn Assembly with Entirely Too Many Brainfuck Compilers](./too-many-brainfuck-compilers.md)\n\n\n## 通知\n\n在新blog发布时得到通知\n- 订阅本仓库 [releases RSS feed](https://github.com/pretzelhammer/rust-blog/releases.atom) or\n- 监控本仓库的发布 (click `Watch` → click `Custom` → select `Releases` → click `Apply`)\n"
  },
  {
    "path": "posts/translations/zh-hans/tour-of-rusts-standard-library-traits.md",
    "content": "# Rust 标准库特性指南\n\n_2021年 3月 31日 · #rust · #traits_\n\n**目录**\n\n- [引入 Intro](#引入-intro)\n- [特性的基础知识 Trait Basics](#特性的基础知识-trait-basics)\n    - [特性的记号 Trait Items](#特性的记号-trait-items)\n        - [Self](#self)\n        - [函数 Functions](#函数-functions)\n        - [方法 Methods](#方法-methods)\n        - [关联类型 Associated Types](#关联类型-associated-types)\n        - [泛型参数 Generic Parameters](#泛型参数-generic-parameters)\n        - [泛型类型与关联类型 Generic Types vs Associated Types](#泛型类型与关联类型-generic-types-vs-associated-types)\n    - [作用域 Scope](#作用域-scope)\n    - [衍生宏 Derive Macros](#衍生宏-derive-macros)\n    - [默认实现 Default Impls](#默认实现-default-impls)\n    - [一揽子泛型实现 Generic Blanket Impls](#一揽子泛型实现-generic-blanket-impls)\n    - [子特性与超特性 Subtraits & Supertraits](#子特性与超特性-subtraits--supertraits)\n    - [特性对象 Trait Objects](#特性对象-trait-objects)\n    - [仅用于标记的特性 Marker Traits](#仅用于标记的特性-marker-traits)\n    - [可自动实现的特性 Auto Traits](#可自动实现的特性-auto-traits)\n    - [不安全的特性 Unsafe Traits](#不安全的特性-unsafe-traits)\n- [可自动实现的特性 Auto Traits](#可自动实现的特性-auto-traits-1)\n    - [Send & Sync](#send--sync)\n    - [Sized](#sized)\n- [常用特性 General Traits](#常用特性-general-traits)\n    - [Default](#default)\n    - [Clone](#clone)\n    - [Copy](#copy)\n    - [Any](#any)\n- [文本格式化特性 Formatting Traits](#文本格式化特性-formatting-traits)\n    - [Display & ToString](#display--tostring)\n    - [Debug](#debug)\n- [算符重载特性 Operator Traits](#算符重载特性-operator-traits)\n    - [比较特性 Comparison Traits](#比较特性-comparison-traits)\n        - [PartialEq & Eq](#partialeq--eq)\n        - [Hash](#hash)\n        - [PartialOrd & Ord](#partialord--ord)\n    - [算术特性 Arithmetic Traits](#算术特性-arithmetic-traits)\n        - [Add & AddAssign](#add--addassign)\n    - [闭包特性 Closure Traits](#闭包特性-closure-traits)\n        - [FnOnce, FnMut, & Fn](#fnonce-fnmut--fn)\n    - [其它特性 Other Traits](#其它特性-other-traits)\n        - [Deref & DerefMut](#deref--derefmut)\n        - [Index & IndexMut](#index--indexmut)\n        - [Drop](#drop)\n- [转换特性 Conversion Traits](#转换特性-conversion-traits)\n    - [From & Into](#from--into)\n- [错误处理 Error Handling](#错误处理-error-handling)\n    - [Error](#error)\n- [转换特性深入 Conversion Traits Continued](#转换特性深入-conversion-traits-continued)\n    - [TryFrom & TryInto](#tryfrom--tryinto)\n    - [FromStr](#fromstr)\n    - [AsRef & AsMut](#asref--asmut)\n    - [Borrow & BorrowMut](#borrow--borrowmut)\n    - [ToOwned](#toowned)\n- [迭代特性 Iteration Traits](#迭代特性-iteration-traits)\n    - [Iterator](#iterator)\n    - [IntoIterator](#intoiterator)\n    - [FromIterator](#fromiterator)\n- [输入输出特性 I/O Traits](#输入输出特性-io-traits)\n    - [Read & Write](#read--write)\n- [结语 Conclusion](#结语-conclusion)\n- [讨论 Discuss](#讨论-discuss)\n- [更多资料 Further Reading](#更多资料-further-reading)\n- [翻译 Translation](#翻译-translation)\n\n\n\n## 引入 Intro\n\n> Have you ever wondered what's the difference between:\n> - `Deref<Target = T>`, `AsRef<T>`, and `Borrow<T>`?\n> - `Clone`, `Copy`, and `ToOwned`?\n> - `From<T>` and `Into<T>`?\n> - `TryFrom<&str>` and `FromStr`?\n> - `FnOnce`, `FnMut`, `Fn`, and `fn`?\n>\n\n你是否曾对以下特性的区别感到困惑：\n- `Deref<Target = T>` ， `AsRef<T>` 和 `Borrow<T>`？\n- `Clone` ， `Copy` 和 `ToOwned`？\n- `From<T>` 和 `Into<T>`？\n- `TryFrom<&str>` 和 `FromStr`？\n- `FnOnce` ， `FnMut` ， `Fn` 和 `fn`？\n\n> Or ever asked yourself the questions:\n> - _\"When do I use associated types vs generic types in my trait?\"_\n> - _\"What are generic blanket impls?\"_\n> - _\"How do subtraits and supertraits work?\"_\n> - _\"Why does this trait not have any methods?\"_\n>\n\n或者有这样的疑问：\n\n- _“我应该在特性中使用关联类型还是泛型类型？”_\n- _\"什么是一揽子泛型实现？\"_\n- _\"子特性与超特性是如何工作的？\"_\n- _\"为什么某个特性没有实现任何方法？\"_\n\n> Well then this is the article for you! It answers all of the above questions and much much more. Together we'll do a quick flyby tour of all of the most popular and commonly used traits from the Rust standard library!\n>\n\n本文正是为你解答以上困惑而撰写！而且本文绝不仅仅只回答了以上问题。下面，我们将一起对 Rust 标准库中所有最流行、最常用的特性做一个走马观花般的概览！\n\n> You can read this article in order section by section or jump around to whichever traits interest you the most because each trait section begins with a list of links to **Prerequisite** sections that you should read to have adequate context to understand the current section's explanations.\n>\n\n你可以按顺序阅读本文，也可以直接跳读至你最感兴趣的特性。每节都会提供**预备知识**列表，它会帮助你获得相应的背景知识，不必担心跳读带来的理解困难。\n\n\n\n## 特性的基础知识 Trait Basics\n\n> We'll cover just enough of the basics so that the rest of the article can be streamlined without having to repeat the same explanations of the same concepts over and over as they reappear in different traits.\n>\n\n本章覆盖了特性的基础知识，相应内容在以后的章节中不再赘述。\n\n\n\n### 特性的记号 Trait Items\n\n> Trait items are any items that are part of a trait declaration.\n\n特性的记号指的是，在特性的声明中可使用的记号。\n\n\n\n#### Self\n\n> `Self` always refers to the implementing type.\n\n`Self` 永远引用正被实现的类型。\n\n\n\n```rust\ntrait Trait {\n    // always returns i32\n    // 总是返回 i32\n    fn returns_num() -> i32;\n\n    // returns implementing type\n    // 总是返回正被实现的类型\n    fn returns_self() -> Self;\n}\n\nstruct SomeType;\nstruct OtherType;\n\nimpl Trait for SomeType {\n    fn returns_num() -> i32 {\n        5\n    }\n\n    // Self == SomeType\n    fn returns_self() -> Self {\n        SomeType\n    }\n}\n\nimpl Trait for OtherType {\n    fn returns_num() -> i32 {\n        6\n    }\n\n    // Self == OtherType\n    fn returns_self() -> Self {\n        OtherType\n    }\n}\n```\n\n\n\n#### 函数 Functions\n\n> A trait function is any function whose first parameter does not use the `self` keyword.\n\n特性的函数指的是，任何不以 `self` 关键字作为首参数的函数。\n\n```rust\ntrait Default {\n    // function\n    // 函数\n    fn default() -> Self;\n}\n```\n\n> Trait functions can be called namespaced by the trait or implementing type:\n\n特性的函数同时声明在特性本身以及具体实现类型的命名空间中。\n\n```rust\nfn main() {\n    let zero: i32 = Default::default();\n    let zero = i32::default();\n}\n```\n\n\n\n#### 方法 Methods\n\n> A trait method is any function whose first parameter uses the `self` keyword and is of type `Self`, `&Self`, `&mut Self`. The former types can also be wrapped with a `Box`, `Rc`, `Arc`, or `Pin`.\n\n特性的方法指的是，任何以 `self` 关键字作为首参数的函数，其类型是 `Self` ， `&Self` 或 `&mut Self`。前者的类型也可以包裹在 `Box` ， `Rc` ， `Arc` 或 `Pin` 中。\n\n```rust\ntrait Trait {\n    // methods\n    // 方法\n    fn takes_self(self);\n    fn takes_immut_self(&self);\n    fn takes_mut_self(&mut self);\n\n    // above methods desugared\n    // 以上代码等价于\n    fn takes_self(self: Self);\n    fn takes_immut_self(self: &Self);\n    fn takes_mut_self(self: &mut Self);\n}\n\n// example from standard library\n// 来自于标准库的示例\ntrait ToString {\n    fn to_string(&self) -> String;\n}\n```\n\n> Methods can be called using the dot operator on the implementing type:\n\n可以使用点算符在具体实现类型上调用方法：\n\n```rust\nfn main() {\n    let five = 5.to_string();\n}\n```\n\n> However, similarly to functions, they can also be called namespaced by the trait or implementing type:\n\n并且，与函数相似地，方法也声明在特性本身以及具体实现类型的命名空间中。\n\n```rust\nfn main() {\n    let five = ToString::to_string(&5);\n    let five = i32::to_string(&5);\n}\n```\n\n\n\n#### 关联类型 Associated Types\n\n> A trait can have associated types. This is useful when we need to use some type other than `Self` within function signatures but would still like the type to be chosen by the implementer rather than being hardcoded in the trait declaration:\n\n特性内部可以声明关联类型。当我们希望在特性函数的签名中使用某种 `Self` 以外的类型，又不希望硬编码这种类型，而是希望后来的实现该特性的程序员来选择该类型具体是什么的时候，关联类型会很有用。\n\n```rust\ntrait Trait {\n    type AssociatedType;\n    fn func(arg: Self::AssociatedType);\n}\n\nstruct SomeType;\nstruct OtherType;\n\n// any type implementing Trait can\n// choose the type of AssociatedType\n// 我们可以在实现 Trait 特性的时候\n// 再决定 AssociatedType 的具体类型\n// 而不必是在声明 Trait 特性的时候\n\nimpl Trait for SomeType {\n    type AssociatedType = i8; // chooses i8\n    fn func(arg: Self::AssociatedType) {}\n}\n\nimpl Trait for OtherType {\n    type AssociatedType = u8; // chooses u8\n    fn func(arg: Self::AssociatedType) {}\n}\n\nfn main() {\n    SomeType::func(-1_i8); // can only call func with i8 on SomeType\n    OtherType::func(1_u8); // can only call func with u8 on OtherType\n                           // 同一特性实现在不同类型上时，可以具有不同的函数签名\n}\n```\n\n\n\n#### 泛型参数 Generic Parameters\n\n> _\"Generic parameters\"_ broadly refers to generic type parameters, generic lifetime parameters, and generic const parameters. Since all of those are a mouthful to say people commonly abbreviate them to _\"generic types\"_, _\"lifetimes\"_, and _\"generic consts\"_. Since generic consts are not used in any of the standard library traits we'll be covering they're outside the scope of this article.\n>\n\n“泛型参数” 是泛型类型参数、泛型寿命参数以及泛型常量参数的统称。由于这些术语过于佶屈聱牙，我们通常将他们缩略为“泛型类型”，“泛型寿命”和“泛型常量”。鉴于标准库中的特性无一采用泛型常量，本文也略过不讲。\n\n> We can generalize a trait declaration using parameters:\n\n我们可以使用以下参数来声明特性：\n\n```rust\n// trait declaration generalized with lifetime & type parameters\n// 使用泛型寿命与泛型类型声明特性\ntrait Trait<'a, T> {\n    // signature uses generic type\n    // 在签名中使用泛型类型\n    fn func1(arg: T);\n    \n    // signature uses lifetime\n    // 在签名中使用泛型寿命\n    fn func2(arg: &'a i32);\n    \n    // signature uses generic type & lifetime\n    // 在签名中同时使用泛型类型与泛型寿命\n    fn func3(arg: &'a T);\n}\n\nstruct SomeType;\n\nimpl<'a> Trait<'a, i8> for SomeType {\n    fn func1(arg: i8) {}\n    fn func2(arg: &'a i32) {}\n    fn func3(arg: &'a i8) {}\n}\n\nimpl<'b> Trait<'b, u8> for SomeType {\n    fn func1(arg: u8) {}\n    fn func2(arg: &'b i32) {}\n    fn func3(arg: &'b u8) {}\n}\n```\n\n> It's possible to provide default values for generic types. The most commonly used default value is `Self` but any type works:\n\n可以为泛型类型指定默认值，最常用的默认值是 `Self` ，此外任何其它类型都是可以的。\n\n```rust\n// make T = Self by default\n// T 的默认值是 Self\ntrait Trait<T = Self> {\n    fn func(t: T) {}\n}\n\n// any type can be used as the default\n// 任何其它类型都可用作默认值\ntrait Trait2<T = i32> {\n    fn func2(t: T) {}\n}\n\nstruct SomeType;\n\n// omitting the generic type will\n// cause the impl to use the default\n// value, which is Self here\n// 省略泛型类型时， impl 块使用默认值，在这里是 Self\nimpl Trait for SomeType {\n    fn func(t: SomeType) {}\n}\n\n// default value here is i32\n// 这里的默认值是 i32\nimpl Trait2 for SomeType {\n    fn func2(t: i32) {}\n}\n\n// the default is overridable as we'd expect\n// 默认值可以被重写，正如我们希望的那样\nimpl Trait<String> for SomeType {\n    fn func(t: String) {}\n}\n\n// overridable here too\n// 这里也可以重写\nimpl Trait2<String> for SomeType {\n    fn func2(t: String) {}\n}\n```\n\n> Aside from parameterizing the trait it's also possible to parameterize individual functions and methods:\n\n不仅可以为特性提供泛型，也可以独立地为函数或方法提供泛型。\n\n```rust\ntrait Trait {\n    fn func<'a, T>(t: &'a T);\n}\n```\n\n\n\n#### 泛型类型与关联类型 Generic Types vs Associated Types\n\n> Both generic types and associated types defer the decision to the implementer on which concrete types should be used in the trait's functions and methods, so this section seeks to explain when to use one over the other.\n\n通过使用泛型类型与关联类型，我们都可以将具体类型的选择问题抛给后来实现该特性的程序员来决定，这一节将解释我们如何在相似的两者之间做出选择。\n\n> The general rule-of-thumb is:\n> - Use associated types when there should only be a single impl of the trait per type.\n> - Use generic types when there can be many possible impls of the trait per type.\n>\n\n按照惯常的经验：\n- 对于某一特性，每个类型仅应当有单一实现时，使用关联类型。\n- 对于某一特性，每个类型可以有多个实现时，使用泛型类型。\n\n> Let's say we want to define a trait called `Add` which allows us to add values together. Here's an initial design and impl that only uses associated types:\n\n例如，我们声明一个 `Add` 特性，它允许将各值加总在一起。这是仅使用关联类型的初始设计：\n\n```rust\ntrait Add {\n    type Rhs;\n    type Output;\n    fn add(self, rhs: Self::Rhs) -> Self::Output;\n}\n\nstruct Point {\n    x: i32,\n    y: i32,\n}\n\nimpl Add for Point {\n    type Rhs = Point;\n    type Output = Point;\n    fn add(self, rhs: Point) -> Point {\n        Point {\n            x: self.x + rhs.x,\n            y: self.y + rhs.y,\n        }\n    }\n}\n\nfn main() {\n    let p1 = Point { x: 1, y: 1 };\n    let p2 = Point { x: 2, y: 2 };\n    let p3 = p1.add(p2);\n    assert_eq!(p3.x, 3);\n    assert_eq!(p3.y, 3);\n}\n```\n\n> Let's say we wanted to add the ability to add `i32`s to `Point`s where the `i32` would be added to both the `x` and `y` members:\n\n例如，我们希望程序允许将 i32 类型的值与 Point 类型的值相加，其规则是该 i32 类型的值分别加到成员 `x` 与成员 `y` 。\n\n```rust\ntrait Add {\n    type Rhs;\n    type Output;\n    fn add(self, rhs: Self::Rhs) -> Self::Output;\n}\n\nstruct Point {\n    x: i32,\n    y: i32,\n}\n\nimpl Add for Point {\n    type Rhs = Point;\n    type Output = Point;\n    fn add(self, rhs: Point) -> Point {\n        Point {\n            x: self.x + rhs.x,\n            y: self.y + rhs.y,\n        }\n    }\n}\n\nimpl Add for Point { // ❌\n    type Rhs = i32;\n    type Output = Point;\n    fn add(self, rhs: i32) -> Point {\n        Point {\n            x: self.x + rhs,\n            y: self.y + rhs,\n        }\n    }\n}\n\nfn main() {\n    let p1 = Point { x: 1, y: 1 };\n    let p2 = Point { x: 2, y: 2 };\n    let p3 = p1.add(p2);\n    assert_eq!(p3.x, 3);\n    assert_eq!(p3.y, 3);\n    \n    let p1 = Point { x: 1, y: 1 };\n    let int2 = 2;\n    let p3 = p1.add(int2); // ❌\n    assert_eq!(p3.x, 3);\n    assert_eq!(p3.y, 3);\n}\n```\n\n> Throws:\n\n编译出错：\n\n```none\nerror[E0119]: conflicting implementations of trait `Add` for type `Point`:\n  --> src/main.rs:23:1\n   |\n12 | impl Add for Point {\n   | ------------------ first implementation here\n...\n23 | impl Add for Point {\n   | ^^^^^^^^^^^^^^^^^^ conflicting implementation for `Point`\n```\n\n> Since the `Add` trait is not parameterized by any generic types we can only impl it once per type, which means we can only pick the types for both `Rhs` and `Output` once! To allow adding both `Points`s and `i32`s to `Point` we have to refactor `Rhs` from an associated type to a generic type, which would allow us to impl the trait multiple times for `Point` with different type arguments for `Rhs`:\n\n由于 `Add` 特性未提供泛型类型，因而每个类型只能具有该特性的单一实现，这即是说一旦我们指定了 `Rhs` 和 `Output` 的类型后就不可再更改了！为了 Point 类型的值能同时接受 i32 类型和 Point 类型的值作为被加数，我们应当重构之以将 `Rhs` 从关联类型改为泛型类型，这将允许我们为 `Rhs` 指定不同的类型并为同一类型多次实现某一特性。\n\n```rust\ntrait Add<Rhs> {\n    type Output;\n    fn add(self, rhs: Rhs) -> Self::Output;\n}\n\nstruct Point {\n    x: i32,\n    y: i32,\n}\n\nimpl Add<Point> for Point {\n    type Output = Self;\n    fn add(self, rhs: Point) -> Self::Output {\n        Point {\n            x: self.x + rhs.x,\n            y: self.y + rhs.y,\n        }\n    }\n}\n\nimpl Add<i32> for Point { // ✅\n    type Output = Self;\n    fn add(self, rhs: i32) -> Self::Output {\n        Point {\n            x: self.x + rhs,\n            y: self.y + rhs,\n        }\n    }\n}\n\nfn main() {\n    let p1 = Point { x: 1, y: 1 };\n    let p2 = Point { x: 2, y: 2 };\n    let p3 = p1.add(p2);\n    assert_eq!(p3.x, 3);\n    assert_eq!(p3.y, 3);\n    \n    let p1 = Point { x: 1, y: 1 };\n    let int2 = 2;\n    let p3 = p1.add(int2); // ✅\n    assert_eq!(p3.x, 3);\n    assert_eq!(p3.y, 3);\n}\n```\n\n> Let's say we add a new type called `Line` which contains two `Point`s, and now there are contexts within our program where adding two `Point`s should produce a `Line` instead of a `Point`. This is not possible given the current design of the `Add` trait where `Output` is an associated type but we can satisfy these new requirements by refactoring `Output` from an associated type into a generic type:\n\n例如，我们现在声明一个包含两个 `Point` 类型的新类型 `Line` ，要求当两个 `Point` 类型相加时返回 `Line` 而不是 `Point` 。在当前 `Add` 特性的设计中 `Output` 是关联类型，不能满足这一要求，重构之以将关联类型改为泛型类型：\n\n```rust\ntrait Add<Rhs, Output> {\n    fn add(self, rhs: Rhs) -> Output;\n}\n\nstruct Point {\n    x: i32,\n    y: i32,\n}\n\nimpl Add<Point, Point> for Point {\n    fn add(self, rhs: Point) -> Point {\n        Point {\n            x: self.x + rhs.x,\n            y: self.y + rhs.y,\n        }\n    }\n}\n\nimpl Add<i32, Point> for Point {\n    fn add(self, rhs: i32) -> Point {\n        Point {\n            x: self.x + rhs,\n            y: self.y + rhs,\n        }\n    }\n}\n\nstruct Line {\n    start: Point,\n    end: Point,\n}\n\nimpl Add<Point, Line> for Point { // ✅\n    fn add(self, rhs: Point) -> Line {\n        Line {\n            start: self,\n            end: rhs,\n        }\n    }\n}\n\nfn main() {\n    let p1 = Point { x: 1, y: 1 };\n    let p2 = Point { x: 2, y: 2 };\n    let p3: Point = p1.add(p2);\n    assert!(p3.x == 3 && p3.y == 3);\n\n    let p1 = Point { x: 1, y: 1 };\n    let int2 = 2;\n    let p3 = p1.add(int2);\n    assert!(p3.x == 3 && p3.y == 3);\n\n    let p1 = Point { x: 1, y: 1 };\n    let p2 = Point { x: 2, y: 2 };\n    let l: Line = p1.add(p2); // ✅\n    assert!(l.start.x == 1 && l.start.y == 1 && l.end.x == 2 && l.end.y == 2)\n}\n```\n\n> So which `Add` trait above is the best? It really depends on the requirements of your program! They're all good in the right situations.\n\n所以说，哪一种 `Add` 特性最好？答案是具体问题具体分析！不管白猫黑猫，会捉老鼠就是好猫。\n\n\n\n### 作用域 Scope\n\n> Trait items cannot be used unless the trait is in scope. Most Rustaceans learn this the hard way the first time they try to write a program that does anything with I/O because the `Read` and `Write` traits are not in the standard library prelude:\n\n特性仅当被引入当前作用域时才可以使用。绝大多数的初学者要在编写 I/O 程序时经历一番痛苦挣扎后，才能领悟到这一点，原因是 `Read` 和 `Write` 两个特性并未包含在标准库的 prelude 模块中。\n\n```rust\nuse std::fs::File;\nuse std::io;\n\nfn main() -> Result<(), io::Error> {\n    let mut file = File::open(\"Cargo.toml\")?;\n    let mut buffer = String::new();\n    file.read_to_string(&mut buffer)?; // ❌ read_to_string not found in File\n                                       // ❌ 当前文件中找不到 read_to_string\n    Ok(())\n}\n```\n\n> `read_to_string(buf: &mut String)` is declared by the `std::io::Read` trait and implemented by the `std::fs::File` struct but in order to call it `std::io::Read` must be in scope:\n\n`read_to_string(buf: &mut String)` 声明于 `std::io::Read` 特性，并实现于 `std::fs::File` 类型，若要调用该函数还须得 `std::io::Read` 特性处于当前作用域中：\n\n```rust\nuse std::fs::File;\nuse std::io;\nuse std::io::Read; // ✅\n\nfn main() -> Result<(), io::Error> {\n    let mut file = File::open(\"Cargo.toml\")?;\n    let mut buffer = String::new();\n    file.read_to_string(&mut buffer)?; // ✅\n    Ok(())\n}\n```\n\n> The standard library prelude is a module in the standard library, i.e. `std::prelude::v1`, that gets auto imported at the top of every other module, i.e. `use std::prelude::v1::*`. Thus the following traits are always in scope and we never have to explicitly import them ourselves because they're part of the prelude:\n\n诸如 `std::prelude::v1` ，prelude 是标准库的一类模块，其特点是该模块命名空间下的成员将被自动导入到任何其它模块的顶部，其作用等效于 `use std::prelude::v1::*` 。因此，以下 prelude 模块中的特性无需我们显式导入，它们永远存在于当前作用域：\n\n- [AsMut](#asref--asmut)\n- [AsRef](#asref--asmut)\n- [Clone](#clone)\n- [Copy](#copy)\n- [Default](#default)\n- [Drop](#drop)\n- [Eq](#partialeq--eq)\n- [Fn](#fnonce-fnmut--fn)\n- [FnMut](#fnonce-fnmut--fn)\n- [FnOnce](#fnonce-fnmut--fn)\n- [From](#from--into)\n- [Into](#from--into)\n- [ToOwned](#toowned)\n- [IntoIterator](#intoiterator)\n- [Iterator](#iterator)\n- [PartialEq](#partialeq--eq)\n- [PartialOrd](#partialord--ord)\n- [Send](#send--sync)\n- [Sized](#sized)\n- [Sync](#send--sync)\n- [ToString](#display--tostring)\n- [Ord](#partialord--ord)\n\n\n\n### 衍生宏 Derive Macros\n\n> The standard library exports a handful of derive macros which we can use to quickly and conveniently impl a trait on a type if all of its members also impl the trait. The derive macros are named after the traits they impl:\n\n标准库导出了一系列实用的衍生宏，我们可以利用它们方便快捷地为特定类型实现某种特性，前提是该类型的成员亦实现了相应的特性。衍生宏与它们各自所实现的特性同名：\n\n- [Clone](#clone)\n- [Copy](#copy)\n- [Debug](#debug)\n- [Default](#default)\n- [Eq](#partialeq--eq)\n- [Hash](#hash)\n- [Ord](#partialord--ord)\n- [PartialEq](#partialeq--eq)\n- [PartialOrd](#partialord--ord)\n\n> Example usage:\n>\n\n用例：\n\n```rust\n// macro derives Copy & Clone impl for SomeType\n// 利用宏的方式为特定类型衍生出 Copy 与 Clone 特性的具体实现\n#[derive(Copy, Clone)]\nstruct SomeType;\n```\n\n> Note: derive macros are just procedural macros and can do anything, there's no hard rule that they must impl a trait or that they can only work if all the members of the type impl a trait, these are just the conventions followed by the derive macros in the standard library.\n>\n\n注意：衍生宏仅是一种机械的过程，宏展开之后发生的事情并无一定之规。并没有绝对的规定要求衍生宏展开之后必须要为类型实现某种特性，又或者它们必须要求该类型的所有成员都必须实现某种特性才能为当前类型实现该特性，这仅仅是在标准库衍生宏的编纂过程中逐渐约定俗成的规则。\n\n\n\n### 默认实现 Default Impls\n\n> Traits can provide default impls for their functions and methods.\n\n特性可为函数与方法提供默认的实现。\n\n```rust\ntrait Trait {\n    fn method(&self) {\n        println!(\"default impl\");\n    }\n}\n\nstruct SomeType;\nstruct OtherType;\n\n// use default impl for Trait::method\n// 省略时使用默认实现\nimpl Trait for SomeType {}\n\nimpl Trait for OtherType {\n    // use our own impl for Trait::method\n    // 重写时覆盖默认实现\n    fn method(&self) {\n        println!(\"OtherType impl\");\n    }\n}\n\nfn main() {\n    SomeType.method(); // prints \"default impl\"\n    OtherType.method(); // prints \"OtherType impl\"\n}\n```\n\n> This is especially handy if some of the trait methods can be implemented solely using other trait methods.\n\n这对于实现特性中某些仅依赖于其它方法的方法来说极其方便。\n\n```rust\ntrait Greet {\n    fn greet(&self, name: &str) -> String;\n    fn greet_loudly(&self, name: &str) -> String {\n        self.greet(name) + \"!\"\n    }\n}\n\nstruct Hello;\nstruct Hola;\n\nimpl Greet for Hello {\n    fn greet(&self, name: &str) -> String {\n        format!(\"Hello {}\", name)\n    }\n    // use default impl for greet_loudly\n    // 省略时使用 greet_loudly 的默认实现\n}\n\nimpl Greet for Hola {\n    fn greet(&self, name: &str) -> String {\n        format!(\"Hola {}\", name)\n    }\n    // override default impl\n    // 重写时覆盖 greet_loudly 的默认实现\n    fn greet_loudly(&self, name: &str) -> String {\n        let mut greeting = self.greet(name);\n        greeting.insert_str(0, \"¡\");\n        greeting + \"!\"\n    }\n}\n\nfn main() {\n    println!(\"{}\", Hello.greet(\"John\")); // prints \"Hello John\"\n    println!(\"{}\", Hello.greet_loudly(\"John\")); // prints \"Hello John!\"\n    println!(\"{}\", Hola.greet(\"John\")); // prints \"Hola John\"\n    println!(\"{}\", Hola.greet_loudly(\"John\")); // prints \"¡Hola John!\"\n}\n```\n\n> Many traits in the standard library provide default impls for many of their methods.\n\n标准库中的许多特性都为它们的方法提供默认实现。\n\n\n\n### 一揽子泛型实现 Generic Blanket Impls\n\n> A generic blanket impl is an impl on a generic type instead of a concrete type. To explain why and how we'd use one let's start by writing an `is_even` method for number types:\n\n一揽子泛型实现是对泛型类型的实现，与之对应的是对特定类型的实现。我们将以 is_even 方法为例说明如何对数字类型实现一揽子泛型实现。\n\n```rust\ntrait Even {\n    fn is_even(self) -> bool;\n}\n\nimpl Even for i8 {\n    fn is_even(self) -> bool {\n        self % 2_i8 == 0_i8\n    }\n}\n\nimpl Even for u8 {\n    fn is_even(self) -> bool {\n        self % 2_u8 == 0_u8\n    }\n}\n\nimpl Even for i16 {\n    fn is_even(self) -> bool {\n        self % 2_i16 == 0_i16\n    }\n}\n\n// etc\n\n#[test] // ✅\nfn test_is_even() {\n    assert!(2_i8.is_even());\n    assert!(4_u8.is_even());\n    assert!(6_i16.is_even());\n    // etc\n}\n```\n\n> Obviously, this is very verbose. Also, all of our impls are almost identical. Furthermore, in the unlikely but still possible event that Rust decides to add more number types in the future we have to remember to come back to this code and update it with the new number types. We can solve all these problems using a generic blanket impl:\n\n显而易见地，我们重复实现了近乎相同的逻辑，这非常的繁琐。进一步来讲，如果 Rust 在将来决定增加更多的数字类型（小概率事件并非绝不可能），那么我们将不得不重新回到这里对新增的数字类型编写代码。一揽子泛型实现恰可以解决这些问题：\n\n```rust\nuse std::fmt::Debug;\nuse std::convert::TryInto;\nuse std::ops::Rem;\n\ntrait Even {\n    fn is_even(self) -> bool;\n}\n\n// generic blanket impl\n// 一揽子泛型实现\nimpl<T> Even for T\nwhere\n    T: Rem<Output = T> + PartialEq<T> + Sized,\n    u8: TryInto<T>,\n    <u8 as TryInto<T>>::Error: Debug,\n{\n    fn is_even(self) -> bool {\n        // these unwraps will never panic\n        // 以下 unwrap 永远不会 panic\n        self % 2.try_into().unwrap() == 0.try_into().unwrap()\n    }\n}\n\n#[test] // ✅\nfn test_is_even() {\n    assert!(2_i8.is_even());\n    assert!(4_u8.is_even());\n    assert!(6_i16.is_even());\n    // etc\n}\n```\n\n> Unlike default impls, which provide _an_ impl, generic blanket impls provide _the_ impl, so they are not overridable.\n\n默认实现可以重写，而一揽子泛型实现不可重写。\n\n```rust\nuse std::fmt::Debug;\nuse std::convert::TryInto;\nuse std::ops::Rem;\n\ntrait Even {\n    fn is_even(self) -> bool;\n}\n\nimpl<T> Even for T\nwhere\n    T: Rem<Output = T> + PartialEq<T> + Sized,\n    u8: TryInto<T>,\n    <u8 as TryInto<T>>::Error: Debug,\n{\n    fn is_even(self) -> bool {\n        self % 2.try_into().unwrap() == 0.try_into().unwrap()\n    }\n}\n\nimpl Even for u8 { // ❌\n    fn is_even(self) -> bool {\n        self % 2_u8 == 0_u8\n    }\n}\n```\n\n> Throws:\n\n编译出错：\n\n```none\nerror[E0119]: conflicting implementations of trait `Even` for type `u8`:\n  --> src/lib.rs:22:1\n   |\n10 | / impl<T> Even for T\n11 | | where\n12 | |     T: Rem<Output = T> + PartialEq<T> + Sized,\n13 | |     u8: TryInto<T>,\n...  |\n19 | |     }\n20 | | }\n   | |_- first implementation here\n21 | \n22 |   impl Even for u8 {\n   |   ^^^^^^^^^^^^^^^^ conflicting implementation for `u8`\n```\n\n> These impls overlap, hence they conflict, hence Rust rejects the code to ensure trait coherence. Trait coherence is the property that there exists at most one impl of a trait for any given type. The rules Rust uses to enforce trait coherence, the implications of those rules, and workarounds for the implications are outside the scope of this article.\n\n重叠的实现产生了冲突，于是 Rust 拒绝了该代码以确保特性一致性。特性一致性指的是，对任意给定类型，仅能对某一特性具有单一实现。Rust 强制实现特性一致性，而这一规则的潜在影响与变通方法超出了本文的讨论范围。\n\n\n\n### 子特性与超特性 Subtraits & Supertraits\n\n> The \"sub\" in \"subtrait\" refers to subset and the \"super\" in \"supertrait\" refers to superset. If we have this trait declaration:\n\n子特性的“子”即为子集，超特性的“超”即为超集。若有下列特性声明：\n\n```rust\ntrait Subtrait: Supertrait {}\n```\n\n> All of the types which impl `Subtrait` are a subset of all the types which impl `Supertrait`, or to put it in opposite but equivalent terms: all the types which impl `Supertrait` are a superset of all the types which impl `Subtrait`.\n\n所有实现了子特性的类型都是实现了超特性的类型的子集，也可以说，所有实现了超特性的类型都是实现了子特性的类型的超集。\n\n> Also, the above is just syntax sugar for:\n\n以上代码等价于：\n\n```rust\ntrait Subtrait where Self: Supertrait {}\n```\n\n> It's a subtle yet important distinction to understand that the bound is on `Self`, i.e. the type impling `Subtrait`, and not on `Subtrait` itself. The latter would not make any sense, since trait bounds can only be applied to concrete types which can impl traits. Traits cannot impl other traits:\n\n这是一种易于忽略但又至关重要的区别 —— 约束是 `Self` 的约束，而不是 `Subtrait` 的约束。后者没有任何意义，因为特性约束只能应用于具体类型。不能用一种特性去实现其它特性：\n\n```rust\ntrait Supertrait {\n    fn method(&self) {\n        println!(\"in supertrait\");\n    }\n}\n\ntrait Subtrait: Supertrait {\n    // this looks like it might impl or\n    // override Supertrait::method but it\n    // does not\n    // 这可能会令你产生超特性的方法被覆盖的错觉（实际不会）\n    fn method(&self) {\n        println!(\"in subtrait\")\n    }\n}\n\n\nstruct SomeType;\n\n// adds Supertrait::method to SomeType\nimpl Supertrait for SomeType {}\n\n// adds Subtrait::method to SomeType\nimpl Subtrait for SomeType {}\n\n// both methods exist on SomeType simultaneously\n// neither overriding or shadowing the other\n// 两个同名方法同时存在于同一类型时，既不重写也不影射\n\nfn main() {\n    SomeType.method(); // ❌ ambiguous method call\n                       // ❌ 不允许语义模糊的函数调用\n    // must disambiguate using fully-qualified syntax\n    // 必须使用完全限定的记号来明确你要使用的函数\n    <SomeType as Supertrait>::method(&st); // ✅ prints \"in supertrait\"\n    <SomeType as Subtrait>::method(&st); // ✅ prints \"in subtrait\"\n}\n```\n\n> Furthermore, there are no rules for how a type must impl both a subtrait and a supertrait. It can use the methods from either in the impl of the other.\n\n此外，对于特定类型如何同时实现子特性与超特性并没有规定。子、超特性之间的方法也可以相互调用。\n\n```rust\ntrait Supertrait {\n    fn super_method(&mut self);\n}\n\ntrait Subtrait: Supertrait {\n    fn sub_method(&mut self);\n}\n\nstruct CallSuperFromSub;\n\nimpl Supertrait for CallSuperFromSub {\n    fn super_method(&mut self) {\n        println!(\"in super\");\n    }\n}\n\nimpl Subtrait for CallSuperFromSub {\n    fn sub_method(&mut self) {\n        println!(\"in sub\");\n        self.super_method();\n    }\n}\n\nstruct CallSubFromSuper;\n\nimpl Supertrait for CallSubFromSuper {\n    fn super_method(&mut self) {\n        println!(\"in super\");\n        self.sub_method();\n    }\n}\n\nimpl Subtrait for CallSubFromSuper {\n    fn sub_method(&mut self) {\n        println!(\"in sub\");\n    }\n}\n\nstruct CallEachOther(bool);\n\nimpl Supertrait for CallEachOther {\n    fn super_method(&mut self) {\n        println!(\"in super\");\n        if self.0 {\n            self.0 = false;\n            self.sub_method();\n        }\n    }\n}\n\nimpl Subtrait for CallEachOther {\n    fn sub_method(&mut self) {\n        println!(\"in sub\");\n        if self.0 {\n            self.0 = false;\n            self.super_method();\n        }\n    }\n}\n\nfn main() {\n    CallSuperFromSub.super_method(); // prints \"in super\"\n    CallSuperFromSub.sub_method(); // prints \"in sub\", \"in super\"\n    \n    CallSubFromSuper.super_method(); // prints \"in super\", \"in sub\"\n    CallSubFromSuper.sub_method(); // prints \"in sub\"\n    \n    CallEachOther(true).super_method(); // prints \"in super\", \"in sub\"\n    CallEachOther(true).sub_method(); // prints \"in sub\", \"in super\"\n}\n```\n\n> Hopefully the examples above show that the relationship between subtraits and supertraits can be complex. Before introducing a mental model that neatly encapsulates all of that complexity let's quickly review and establish the mental model we use for understanding trait bounds on generic types:\n\n通过以上示例，希望读者能够领会到，子特性与超特性之间的关系并未被一刀切的限制住。接下来我们将学习一种将所有这些复杂性巧妙地封装在一起的心智模型，在这之前我们先来回顾一下我们用来理解泛型类型与特性约束的关系的心智模型。\n\n```rust\nfn function<T: Clone>(t: T) {\n    // impl\n}\n```\n\n> Without knowing anything about the impl of this function we could reasonably guess that `t.clone()` gets called at some point because when a generic type is bounded by a trait that strongly implies it has a dependency on the trait. The mental model for understanding the relationship between generic types and their trait bounds is a simple and intuitive one: generic types _depend on_ their trait bounds.\n\n即便我们不知道这个函数的具体实现，我们仍旧可以有理有据地猜测 `t.clone()` 将在函数的某处被调用，因为当泛型类型被特性所约束的时候，会给人一种它依赖于该特性的强烈暗示。这就是一种理解泛型类型与特性约束的关系的心智模型，它简单且可凭直觉 —— 泛型类型依赖于它们的特性约束。\n\n> Now let's look the trait declaration for `Copy`:\n\n现在，让我们看看 `Copy` 特性的声明：\n\n```rust\ntrait Copy: Clone {}\n```\n\n> The syntax above looks very similar to the syntax for applying a trait bound on a generic type and yet `Copy` doesn't depend on `Clone` at all. The mental model we developed earlier doesn't help us here. In my opinion, the most simple and elegant mental model for understanding the relationship between subtraits and supertraits is: subtraits _refine_ their supertraits.\n\n以上的记号和之前我们为泛型添加特性约束的记号非常相似，但是 `Copy` 却完全不依赖 `Clone` 。早前建立的心智模型现在不适用了。在我看来，理解子特性与超特性的关系的最简单和最优雅的心智模型莫过于 —— 子特性 *改良* 了超特性。\n\n> \"Refinement\" is intentionally kept somewhat vague because it can mean different things in different contexts:\n> - a subtrait might make its supertrait's methods' impls more specialized, faster, use less memory, e.g. `Copy: Clone`\n> - a subtrait might make additional guarantees about the supertrait's methods' impls, e.g. `Eq: PartialEq`, `Ord: PartialOrd`, `ExactSizeIterator: Iterator`\n> - a subtrait might make the supertrait's methods more flexible or easier to call, e.g. `FnMut: FnOnce`, `Fn: FnMut`\n> - a subtrait might extend a supertrait and add new methods, e.g. `DoubleEndedIterator: Iterator`, `ExactSizeIterator: Iterator`\n>\n\n“改良”一词故意地预留了一些模糊的空间，它的具体含义在不同的上下文中有所不同：\n\n- 子特性可能比超特性的方法更加特异化、运行更快或使用更少内存等等，例如 `Copy: Clone` \n- 子特性可能比超特性的方法具有额外的功能，例如 `Eq: PartialEq` ， `Ord: PartialOrd` 和 `ExactSizeIterator: Iterator` \n- 子特性可能比超特性的方法更灵活和更易于调用，例如 `FnMut: FnOnce` 和 `Fn: FnMut`\n- 子特性可能扩展了超特性并添加了新的方法，例如 `DoubleEndedIterator: Iterator` 和 `ExactSizeIterator: Iterator` \n\n### 特性对象 Trait Objects\n\n> Generics give us compile-time polymorphism where trait objects give us run-time polymorphism. We can use trait objects to allow functions to dynamically return different types at run-time:\n\n如果说泛型给了我们编译时的多态性，那么特性对象就给了我们运行时的多态性。通过特性对象，我们可以允许函数在运行时动态地返回不同的类型。\n\n```rust\nfn example(condition: bool, vec: Vec<i32>) -> Box<dyn Iterator<Item = i32>> {\n    let iter = vec.into_iter();\n    if condition {\n        // Has type:\n        // Box<Map<IntoIter<i32>, Fn(i32) -> i32>>\n        // But is cast to:\n        // Box<dyn Iterator<Item = i32>>\n        Box::new(iter.map(|n| n * 2))\n    } else {\n        // Has type:\n        // Box<Filter<IntoIter<i32>, Fn(&i32) -> bool>>\n        // But is cast to:\n        // Box<dyn Iterator<Item = i32>>\n        Box::new(iter.filter(|&n| n >= 2))\n    }\n}\n        // 以上代码中，两种不同的指针类型转换成相同的指针类型\n```\n\n> Trait objects also allow us to store heterogeneous types in collections:\n\n特性对象也允许我们在集合中存储不同类型的值：\n\n```rust\nuse std::f64::consts::PI;\n\nstruct Circle {\n    radius: f64,\n}\n\nstruct Square {\n    side: f64\n}\n\ntrait Shape {\n    fn area(&self) -> f64;\n}\n\nimpl Shape for Circle {\n    fn area(&self) -> f64 {\n        PI * self.radius * self.radius\n    }\n}\n\nimpl Shape for Square {\n    fn area(&self) -> f64 {\n        self.side * self.side\n    }\n}\n\nfn get_total_area(shapes: Vec<Box<dyn Shape>>) -> f64 {\n    shapes.into_iter().map(|s| s.area()).sum()\n}\n\nfn example() {\n    let shapes: Vec<Box<dyn Shape>> = vec![\n        Box::new(Circle { radius: 1.0 }), // Box<Circle> cast to Box<dyn Shape>\n        Box::new(Square { side: 1.0 }), // Box<Square> cast to Box<dyn Shape>\n    ];\n    assert_eq!(PI + 1.0, get_total_area(shapes)); // ✅\n}\n```\n\n> Trait objects are unsized so they must always be behind a pointer. We can tell the difference between a concrete type and a trait object at the type level based on the presence of the `dyn` keyword within the type:\n\n特性对象的结构体大小是未知的，所以必须要通过指针来引用它们。具体类型与特性对象在字面上的区别在于，特性对象必须要用 `dyn` 关键字来修饰前缀，了解了这一点我们可以轻松辨别二者。\n\n```rust\nstruct Struct;\ntrait Trait {}\n\n// regular struct\n// 这是一般的结构\n&Struct\nBox<Struct>\nRc<Struct>\nArc<Struct>\n\n// trait objects\n// 这是特性对象\n&dyn Trait\nBox<dyn Trait>\nRc<dyn Trait>\nArc<dyn Trait>\n```\n\n> Not all traits can be converted into trait objects. A trait is object-safe if it meets these requirements:\n> - trait doesn't require `Self: Sized`\n> - all of the trait's methods are object-safe\n>\n\n并非全部的特性都可以转换为特性对象，一个 “对象安全” 的特性必须满足：\n\n- 该特性不要求 `Self: Sized`\n- 该特性的所有方法都是 “对象安全” 的\n\n> A trait method is object-safe if it meets these requirements:\n>\n> - method requires `Self: Sized` or\n> - method only uses a `Self` type in receiver position\n>\n\n一个特性的方法若要是 “对象安全” 的，必须满足：\n\n- 该方法要求 `Self: Sized` \n- 该方法仅在接收参数中使用 `Self` 类型\n\nUnderstanding why the requirements are what they are is not relevant to the rest of this article, but if you're still curious it's covered in [Sizedness in Rust](../../sizedness-in-rust.md).\n\n关于具有这些限制条件的原因超出了本文的讨论范围且与下文无关，如果你对此深感兴趣不妨阅读 [Sizedness in Rust](../../sizedness-in-rust.md) 以了解详情。\n\n\n\n### 仅用于标记的特性 Marker Traits\n\n> Marker traits are traits that have no trait items. Their job is to \"mark\" the implementing type as having some property which is otherwise not possible to represent using the type system.\n\n仅用于标记的特性，即是某种声明体为空的特性。它们存在的意义在于 “标记” 所实现的类型，且该类型具有某种类型系统所无法表达的属性。\n\n```rust\n// Impling PartialEq for a type promises\n// that equality for the type has these properties:\n// - symmetry: a == b implies b == a, and\n// - transitivity: a == b && b == c implies a == c\n// But DOES NOT promise this property:\n// - reflexivity: a == a\n// 为特定类型实现 PartialEq 特性确保了该类型的相等算符具有以下性质：\n// - 对称性： 若有 a == b ， 则必有 b == a\n// - 传递性： 若有 a == b 和 b == c ， 则必有 a == c\n// 但是不能确保具有以下性质：\n// - 自反性： a == a\ntrait PartialEq {\n    fn eq(&self, other: &Self) -> bool;\n}\n\n// Eq has no trait items! The eq method is already\n// declared by PartialEq, but \"impling\" Eq\n// for a type promises this additional equality property:\n// - reflexivity: a == a\n// Eq 特性的声明体是空的！ 而 eq 方法已经被 PartialEq 所声明，\n// 但是对特定类型“实现” Eq 特性确保了额外的相等性质：\n// - 自反性： a == a\ntrait Eq: PartialEq {}\n\n// f64 impls PartialEq but not Eq because NaN != NaN\n// i32 impls PartialEq & Eq because there's no NaNs :)\n// f64 实现了 PartialEq 特性但是没有实现 Eq 特性，因为 NaN != NaN\n// i32 同时实现了 PartialEq 特性与 Eq 特性，因为没有 NaN 来捣乱 :)\n```\n\n\n\n### 可自动实现的特性 Auto Traits\n\n> Auto traits are traits that get automatically implemented for a type if all of its members also impl the trait. What \"members\" means depends on the type, for example: fields of a struct, variants of an enum, elements of an array, items of a tuple, and so on.\n\n可自动实现的特性指的是，存在这样一种特性，若给定类型的成员都实现了该特性，那么该类型就隐式地自动实现该特性。这里所说的 “成员” 依据上下文而具有不同的含义，包括而又不限于结构体的字段、枚举的变量、数组的元素和元组的内容等等。\n\n> All auto traits are marker traits but not all marker traits are auto traits. Auto traits must be marker traits so the compiler can provide an automatic default impl for them, which would not be possible if they had any trait items.\n\n所有可自动实现的特性都是仅用于标记的特性，反之则不是。正是由于可自动实现的特性必须是仅用于标记的特性，所以编译器才能够自动为其提供一个默认实现，反之编译器就无能为力了。\n\n> Examples of auto traits:\n\n可自动实现的特性的示例：\n\n```rust\n// implemented for types which are safe to send between threads\n// 实现 Send 特性的类型可以安全地往返于多个线程\nunsafe auto trait Send {}\n\n// implemented for types whose references are safe to send between threads\n// 实现 Sync 特性的类型，其引用可以安全地往返于多个线程\nunsafe auto trait Sync {}\n```\n\n\n\n### 不安全的特性 Unsafe Traits\n\n> Traits can be marked unsafe to indicate that impling the trait might require unsafe code. Both `Send` and `Sync` are marked `unsafe` because if they aren't automatically implemented for a type that means it must contains some non-`Send` or non-`Sync` member and we have to take extra care as the implementers to make sure there are no data races if we want to manually mark the type as `Send` and `Sync`.\n\n以 `unsafe` 修饰前缀的特性，意味着该特性的实现可能需要不安全的代码。`Send` 特性与 `Sync` 特性以 `unsafe` 修饰前缀意味着，如果特定类型没有自动实现该特性，那么说明该类型的成员并非都实现了该特性，这提示着我们手动实现该特性一定要谨慎小心，以确保没有发生数据竞争。\n\n```rust\n// SomeType is not Send or Sync\n// SomeType 没有实现 Send 和 Sync\nstruct SomeType {\n    not_send_or_sync: *const (),\n}\n\n// but if we're confident that our impl doesn't have any data\n// races we can explicitly mark it as Send and Sync using unsafe\n// 倘若我们得以社会主义伟大成就的庇佑自信地写出没有数据竞争的代码\n// 可以使用 unsafe 来修饰前缀，以显式地实现 Send 特性与 Sync 特性\nunsafe impl Send for SomeType {}\nunsafe impl Sync for SomeType {}\n```\n\n\n\n## 可自动实现的特性 Auto Traits\n\n\n\n### Send & Sync\n\n预备知识\n- [Marker Traits](#marker-traits)\n- [Auto Traits](#auto-traits)\n- [Unsafe Traits](#unsafe-traits)\n\n```rust\nunsafe auto trait Send {}\nunsafe auto trait Sync {}\n```\n\n> If a type is `Send` that means it's safe to send between threads. If a type is `Sync` that means it's safe to share references of it between threads. In more precise terms some type `T` is `Sync` if and only if `&T` is `Send`.\n\n实现 `Send` 特性的类型可以安全地往返于多线程。实现 `sync` 特性的类型，其引用可以安全地往返于多线程。用更加准确的术语来讲，当且仅当 `&T` 实现 `Send` 特性时，`T` 才能实现 `Sync` 特性。\n\n> Almost all types are `Send` and `Sync`. The only notable `Send` exception is `Rc` and the only notable `Sync` exceptions are `Rc`, `Cell`, `RefCell`. If we need a `Send` version of `Rc` we can use `Arc`. If we need a `Sync` version of `Cell` or `RefCell` we can `Mutex` or `RwLock`. Although if we're using the `Mutex` or `RwLock` to just wrap a primitive type it's often better to use the atomic primitive types provided by the standard library such as `AtomicBool`, `AtomicI32`, `AtomicUsize`, and so on.\n\n几乎所有类型都实现了 `Send` 特性和 `Sync` 特性。对于 `Send` 唯一需要注意的例外是 `Rc` ，对于 `Sync` 唯三需要注意的例外是 `Rc`，`Cell` 和 `RefCell` 。如果我们需要 `Send` 版的 `Rc` ，可以使用 `Arc` 。如果我们需要 `Sync` 版的 `Cell` 或 `RefCell` ，可以使用 `Mutex` 或 `RwLock` 。尽管我们可以使用 `Mutex` 或 `RwLock` 来包裹住原语类型，但通常使用标准库提供的原子原语类型会更好，诸如 `AtomicBool` ，`AtomicI32` 和 `AtomicUsize` 等等。\n\n> That almost all types are `Sync` might be a surprise to some people, but yup, it's true even for types without any internal synchronization. This is possible thanks to Rust's strict borrowing rules.\n\n多亏了 Rust 严格的借用规则，几乎所有的类型都是 `Sync` 的。这对于一些人来讲可能会很惊讶，但事实胜于雄辩，甚至对于那些没有内部同步机制的类型来说也是如此。\n\n> We can pass many immutable references to the same data to many threads and we're guaranteed there are no data races because as long as any immutable references exist Rust statically guarantees the underlying data cannot be mutated:\n\n对于同一数据，我们可以放心地将该数据的多个不可变引用传递给多个线程，因为只要当前存在一个该数据的不可变引用，那么 Rust 就会静态地确保该数据不会被改变：\n\n```rust\nuse crossbeam::thread;\n\nfn main() {\n    let mut greeting = String::from(\"Hello\");\n    let greeting_ref = &greeting;\n    \n    thread::scope(|scoped_thread| {\n        // spawn 3 threads\n        // 产生三个线程\n        for n in 1..=3 {\n            // greeting_ref copied into every thread\n            // greeting_ref 被拷贝到每个线程\n            scoped_thread.spawn(move |_| {\n                println!(\"{} {}\", greeting_ref, n); // prints \"Hello {n}\"\n            });\n        }\n        \n        // line below could cause UB or data races but compiler rejects it\n        // 下面这行代码可能导致数据竞争，于是编译器拒绝了它\n        greeting += \" world\"; \n        // ❌ cannot mutate greeting while immutable refs exist\n        // ❌ 当不可变引用存在时，不可以修改引用的数据\n    });\n    \n    // can mutate greeting after every thread has joined\n    // 当所有的线程结束之后，可以修改数据\n    greeting += \" world\"; // ✅\n    println!(\"{}\", greeting); // prints \"Hello world\"\n}\n```\n\n> Likewise we can pass a single mutable reference to some data to a single thread and we're guaranteed there will be no data races because Rust statically guarantees aliased mutable references cannot exist and the underlying data cannot be mutated through anything other than the single existing mutable reference:\n\n同样地，我们可以将某个数据的单个可变引用传递给单个线程，在此过程中不必担心出现数据竞争，因为 Rust 静态地确保了不存在其它可变引用。以下数据即仅可通过已经存在的单个可变引用而改变：\n\n```rust\nuse crossbeam::thread;\n\nfn main() {\n    let mut greeting = String::from(\"Hello\");\n    let greeting_ref = &mut greeting;\n    \n    thread::scope(|scoped_thread| {\n        // greeting_ref moved into thread\n        // greeting_ref 移动到当前线程\n        scoped_thread.spawn(move |_| {\n            *greeting_ref += \" world\";\n            println!(\"{}\", greeting_ref); // prints \"Hello world\"\n        });\n        \n        // line below could cause UB or data races but compiler rejects it\n        // 下面这行代码可能导致数据竞争，于是编译器拒绝了它\n        greeting += \"!!!\"; \n        // ❌ cannot mutate greeting while mutable refs exist\n        // ❌ 可变引用存在时不可改变数据\n    });\n    \n    // can mutate greeting after the thread has joined\n    // 当所有的线程结束之后，可以修改数据\n    greeting += \"!!!\"; // ✅\n    println!(\"{}\", greeting); // prints \"Hello world!!!\"\n}\n```\n\n> This is why most types are `Sync` without requiring any explicit synchronization. In the event we need to simultaneously mutate some data `T` across multiple threads the compiler won't let us until we wrap the data in a `Arc<Mutex<T>>` or `Arc<RwLock<T>>` so the compiler enforces that explicit synchronization is used when it's needed.\n>\n\n这就是为什么绝大多数的类型都是 Sync 的而不需要实现任何显式的同步机制。对于数据 T ，如果我们试图从多个线程同时修改的话，编译器会对我们作出警告，除非我们将数据包裹在 `Arc<Mutex<T>>` 或 `Arc<RwLock<T>>` 中。所以说，当我们真的需要显式的同步机制时，编译器会强制要求我们这样做的。\n\n\n\n### Sized\n\n预备知识\n- [Marker Traits](#marker-traits)\n- [Auto Traits](#auto-traits)\n\n> If a type is `Sized` that means its size in bytes is known at compile-time and it's possible to put instances of the type on the stack.\n\n如果一个类型实现了 `Sized` ，那么说明该类型具体大小的字节数在编译时可以确定，并且也就说明该类型的实例可以存放在栈上。\n\n> Sizedness of types and its implications is a subtle yet huge topic that affects a lot of different aspects of the language. It's so important that I wrote an entire article on it called [Sizedness in Rust](../../sizedness-in-rust.md) which I highly recommend reading for anyone who would like to understand sizedness in-depth. I'll summarize a few key things which are relevant to this article.\n\n类型的大小以及其所带来的潜在影响，是一个易于忽略但是又十分宏大的话题，它深刻地影响着本门语言的诸多方面。鉴于它的重要性，我已经写了一整篇文章（[Sizedness in Rust](../../sizedness-in-rust.md)）来具体阐述其内容，我高度推荐对于希望深入 sizedness 的人阅读此篇文章。下面是此篇文章的要点：\n\n> 1. All generic types get an implicit `Sized` bound.\n\n1. 所有的泛型类型都具有隐式的 `Sized` 约束。\n\n```rust\nfn func<T>(t: &T) {}\n\n// example above desugared\n// 以上代码等价于\nfn func<T: Sized>(t: &T) {}\n```\n\n> 2. Since there's an implicit `Sized` bound on all generic types, if we want to opt-out of this implicit bound we need to use the special _\"relaxed bound\"_ syntax `?Sized` which currently only exists for the `Sized` trait:\n\n2. 由于所有的泛型类型都具有隐式的 `Sized` 约束，如果我们希望摆脱这样的隐式约束，那么我们需要使用特殊的 *“宽松约束”* 记号 `?Sized` ，目前这样的记号仅适用于 `Sized` 特性：\n\n```rust\n// now T can be unsized\n// 现在 T 的大小可以是未知的\nfn func<T: ?Sized>(t: &T) {}\n```\n\n> 3. There's an implicit `?Sized` bound on all traits.\n\n3. 所有的特性都具有隐式的 `?Sized` 约束。\n\n```rust\ntrait Trait {}\n\n// example above desugared\n// 以上代码等价于\ntrait Trait: ?Sized {}\n```\n\n> This is so that trait objects can impl the trait. Again, all of the nitty gritty details are in [Sizedness in Rust](../../sizedness-in-rust.md).\n\n这就是为什么特性对象可以实现具体特性。再次，向您推荐关于一切真相的[Sizedness in Rust](../../sizedness-in-rust.md)。\n\n\n\n## 常用特性 General traits\n\n\n\n### Default\n\n预备知识\n- [Self](#self)\n- [Functions](#functions)\n- [Derive Macros](#derive-macros)\n\n```rust\ntrait Default {\n    fn default() -> Self;\n}\n```\n\n> It's possible to construct default values of `Default` types.\n\n为特定类型实现 `Default` 特性时，即为该类型赋予了可选的默认值。\n\n```rust\nstruct Color {\n    r: u8,\n    g: u8,\n    b: u8,\n}\n\nimpl Default for Color {\n    // default color is black\n    // 默认颜色是黑色\n    fn default() -> Self {\n        Color {\n            r: 0,\n            g: 0,\n            b: 0,\n        }\n    }\n}\n```\n\n> This is useful for quick prototyping but also in any instance where we just need an instance of a type and aren't picky about what it is:\n\n这不仅利于快速原型设计，另外，在有时我们仅仅只是需要该类型的一个值，却完全不在意该值是什么的时候，这也非常方便。\n\n```rust\nfn main() {\n    // just give me some color!\n    let color = Color::default();\n}\n```\n\n> This is also an option we may want to explicitly expose to the users of our functions:\n\n如此，我们可以明确地向该函数的用户传达出该函数某个参数的可选择性：\n\n```rust\nstruct Canvas;\nenum Shape {\n    Circle,\n    Rectangle,\n}\n\nimpl Canvas {\n    // let user optionally pass a color\n    // 用户可选地传入一个 color\n    fn paint(&mut self, shape: Shape, color: Option<Color>) {\n        // if no color is passed use the default color\n        // 若用户没有传入 color ，即使用默认的 color\n        let color = color.unwrap_or_default();\n        // etc\n    }\n}\n```\n\n> `Default` is also useful in generic contexts where we need to construct generic types:\n\n在泛型编程的语境中，`Default` 特性也可显其威力。\n\n```rust\nfn guarantee_length<T: Default>(mut vec: Vec<T>, min_len: usize) -> Vec<T> {\n    for _ in 0..min_len.saturating_sub(vec.len()) {\n        vec.push(T::default());\n    }\n    vec\n}\n```\n\n> Another way we can take advantage of `Default` types is for partial initialization of structs using Rust's struct update syntax. We may have a `new` constructor for `Color` which takes every member as an argument:\n\n另外，我们在使用 update 记号构造结构体时也可享受到 `Default` 特性带来的便利。我们以 `Color` 结构的 `new` 构造器函数为例，它接受该结构的全部成员作为参数：\n\n```rust\nimpl Color {\n    fn new(r: u8, g: u8, b: u8) -> Self {\n        Color {\n            r,\n            g,\n            b,\n        }\n    }\n}\n```\n\n> However we can also have convenience constructors that only accept a particular struct member each and fall back to the default values for the other struct members:\n\n考虑以下更加便捷的构造器函数 —— 它仅接受该结构的部分成员作为参数，其它未指定的成员则回落到默认值：\n\n```rust\nimpl Color {\n    fn red(r: u8) -> Self {\n        Color {\n            r,\n            ..Color::default()\n        }\n    }\n    fn green(g: u8) -> Self {\n        Color {\n            g,\n            ..Color::default()\n        }\n    }\n    fn blue(b: u8) -> Self {\n        Color {\n            b,\n            ..Color::default()\n        }\n    }\n}\n```\n\n> There's also a `Default` derive macro for so we can write `Color` like this:\n\n`Default` 特性也可以用衍生宏的方式来实现：\n\n```rust\n// default color is still black\n// because u8::default() == 0\n// 默认颜色仍旧是黑色\n// 因为 u8::default() == 0\n#[derive(Default)]\nstruct Color {\n    r: u8,\n    g: u8,\n    b: u8\n}\n```\n\n\n\n### Clone\n\n预备知识\n- [Self](#self)\n- [Methods](#methods)\n- [Default Impls](#default-impls)\n- [Derive Macros](#derive-macros)\n\n```rust\ntrait Clone {\n    fn clone(&self) -> Self;\n\n    // provided default impls\n    // 提供默认实现\n    fn clone_from(&mut self, source: &Self);\n}\n```\n\n> We can convert immutable references of `Clone` types into owned values, i.e. `&T` -> `T`. `Clone` makes no promises about the efficiency of this conversion so it can be slow and expensive. To quickly impl `Clone` on a type we can use the derive macro:\n\n对于实现了 `Clone` 特性的类型，我们可以将一个不可变的引用转换为自有的类型，比如 `&T` -> `T` 。`Clone` 特性对于这种转换的效率不做出保证，所以这样的转换速度可能很慢，代价可能很昂贵。\n\n```rust\n#[derive(Clone)]\nstruct SomeType {\n    cloneable_member1: CloneableType1,\n    cloneable_member2: CloneableType2,\n    // etc\n}\n\n// macro generates impl below\n// 宏展开后为\nimpl Clone for SomeType {\n    fn clone(&self) -> Self {\n        SomeType {\n            cloneable_member1: self.cloneable_member1.clone(),\n            cloneable_member2: self.cloneable_member2.clone(),\n            // etc\n        }\n    }\n}\n```\n\n> `Clone` can also be useful in constructing instances of a type within a generic context. Here's an example from the previous section except using `Clone` instead of `Default`:\n\n`Clone` 特性也有利于在泛型编程的语境中构造类型。请看下例：\n\n```rust\nfn guarantee_length<T: Clone>(mut vec: Vec<T>, min_len: usize, fill_with: &T) -> Vec<T> {\n    for _ in 0..min_len.saturating_sub(vec.len()) {\n        vec.push(fill_with.clone());\n    }\n    vec\n}\n```\n\n> People also commonly use cloning as an escape hatch to avoid dealing with the borrow checker. Managing structs with references can be challenging, but we can turn the references into owned values by cloning them.\n\n克隆确是一个可以逃避借用检查器的好方法。倘若我们编写的代码无法通过借用检查，那么不妨通过克隆将这些引用转换为自有类型。\n\n```rust\n// oof, we gotta worry about lifetimes 😟\n// 糟糕！我们真的有自信处理好 lifetime 吗？ 😟\nstruct SomeStruct<'a> {\n    data: &'a Vec<u8>,\n}\n\n// now we're on easy street 😎\n// 好耶！人生苦短，我用 Clone ! 😎\nstruct SomeStruct {\n    data: Vec<u8>,\n}\n```\n\n> If we're working on a program where performance is not the utmost concern then we don't need to sweat cloning data. Rust is a low-level language that exposes a lot of low-level details so it's easy to get caught up in premature optimizations instead of actually solving the problem at hand. For many programs the best order of priorities is usually to build for correctness first, elegance second, and performance third, and only focus on performance after the program has been profiled and the performance bottlenecks have been identified. This is good general advice to follow, and if it doesn't apply to your particular program then you would know.\n\n如果性能因素微不足道，我们不必羞于使用克隆。Rust 是一门底层语言，人们可以自由地控制程序行为的方方面面，这就很容易令人陷入盲目追求优化的陷阱，而不是专注于着手解决问题。对此我给出的建议是：正确第一，优雅第二，性能第三。只有程序初具雏形后，性能瓶颈的问题才可能凸显，这时我们再解决性能问题也不迟。与其说这是一条编程建议，更不如说这是一条人生建议，万事万物大抵如此，如果你现在不信，总有一天你会的。\n\n\n\n### Copy\n\n预备知识\n- [Marker Traits](#marker-traits)\n- [Subtraits & Supertraits](#subtraits--supertraits)\n- [Derive Macros](#derive-macros)\n\n```rust\ntrait Copy: Clone {}\n```\n\n> We copy `Copy` types, e.g. `T` -> `T`. `Copy` promises the copy operation will be a simple bitwise copy so it will be very fast and efficient. We cannot impl `Copy` ourselves, only the compiler can provide an impl, but we can tell it to do so by using the `Copy` derive macro, together with the `Clone` derive macro since `Copy` is a subtrait of `Clone`:\n\n对于实现了 `Copy` 特性的类型，我们可以拷贝它，即 `T` -> `T` 。`Copy` 特性确保了拷贝操作是按位的拷贝，所以它更快更高效。`Copy` 特性不可手动实现，必须由编译器提供其实现。注意：当使用衍生宏为类型实现 `Copy` 特性时，必须同时使用 `Clone` 衍生宏，因为 `Copy` 是 `Clone` 的子特性：\n\n```rust\n#[derive(Copy, Clone)]\nstruct SomeType;\n```\n\n> `Copy` refines `Clone`. A clone may be slow and expensive but a copy is guaranteed to be fast and cheap, so a copy is just a fast clone. If a type impls `Copy` that makes the `Clone` impl trivial:\n\n`Copy` 改良了 `Clone` 。克隆操作可能速度缓慢且代价昂贵，但是拷贝操作一定是高效低耗的，可以说拷贝就是一种物美价廉的克隆。`Copy` 特性的实现会令 `Clone` 特性的实现变得微不足道：\n\n```rust\n// this is what the derive macro generates\n// 衍生宏展开如下\nimpl<T: Copy> Clone for T {\n    // the clone method becomes just a copy\n    // 克隆实际上变成了一种拷贝\n    fn clone(&self) -> Self {\n        *self\n    }\n}\n```\n\n> Impling `Copy` for a type changes its behavior when it gets moved. By default all types have _move semantics_ but once a type impls `Copy` it gets _copy semantics_. To explain the difference between the two let's examine these simple scenarios:\n\n实现了 `Copy` 特性的类型，其在移动时的行为会发生变化。默认情况下，所有的类型都具有 _移动语义_ ，但是一旦该类型实现了 `Copy` 特性，则会变为 _拷贝语义_。 请考虑下例中语义的不同：\n\n```rust\n// a \"move\", src: !Copy\n// 移动语义，src 没有实现 Copy 特性\nlet dest = src; \n\n// a \"copy\", src: Copy\n// 拷贝语义，src 实现 Copy 特性\nlet dest = src;\n```\n> In both cases, `dest = src` performs a simple bitwise copy of `src`'s contents and moves the result into `dest`, the only difference is that in the case of _\"a move\"_ the borrow checker invalidates the `src` variable and makes sure it's not used anywhere else later and in the case of _\"a copy\"_ `src` remains valid and usable.\n\n事实上，这两种语义背后执行的操作是完全相同的，都是将 `src` 按位复制到 `dest` 。其不同在于，在移动语义下，借用检查器从此吊销了 `src` 的可用性，而在拷贝语义下，`src` 保持可用。\n\n> In a nutshell: Copies _are_ moves. Moves _are_ copies. The only difference is how they're treated by the borrow checker.\n\n言而总之，拷贝就是移动，移动就是拷贝。它们在底层毫无二致，仅仅是借用检查器对待它们的方式不同。\n\n> For a more concrete example of a move, imagine `src` was a `Vec<i32>` and its contents looked something like this:\n\n对于移动行为来讲更具体的例子 —— 你可以将 `src` 想象为一个 `Vec<i32>`，它的结构体大致如下：\n\n```rust\n{ data: *mut [i32], length: usize, capacity: usize }\n```\n\n> When we write `dest = src` we end up with:\n\n执行 `desc = src` 的结果如下：\n\n```rust\nsrc = { data: *mut [i32], length: usize, capacity: usize }\ndest = { data: *mut [i32], length: usize, capacity: usize }\n```\n\n> At this point both `src` and `dest` have aliased mutable references to the same data, which is a big no-no, so the borrow checker invalidates the `src` variable so it can't be used again without throwing a compile error.\n\n此时 `src` 和 `dest` 就都是同一数据的可变引用了，这可就糟tm的大糕了，所以借用检查器就吊销了 `src` 的可用性，一旦再次使用 `src` 就会引发编译错误。\n\n> For a more concrete example of a copy, imagine `src` was an `Option<i32>` and its contents looked something like this:\n\n对于拷贝行为来讲更具体的例子 —— 你可以将 `src` 想象为一个 `Option<i32>` ，它的结构体大致如下：\n\n```rust\n{ is_valid: bool, data: i32 }\n```\n\n> Now when we write `dest = src` we end up with:\n\n执行 `desc = src` 的结果如下：\n\n```rust\nsrc = { is_valid: bool, data: i32 }\ndest = { is_valid: bool, data: i32 }\n```\n\n> These are both usable simultaneously! Hence `Option<i32>` is `Copy`.\n\n此时两者同时可用！因为 `Option<i32>` 实现了 `Copy` 。\n\n> Although `Copy` could be an auto trait the Rust language designers decided it's simpler and safer for types to explicitly opt into copy semantics rather than silently inheriting copy semantics whenever the type is eligible, as the latter can cause surprising confusing behavior which often leads to bugs.\n\n或许你已经注意到，令 `Copy` 特性成为可自动实现的特性在理论上是可行的。但是 Rust 语言的设计者认为，比之于在恰当时隐式地继承拷贝语义，显示地声明为拷贝语义更加的简单和安全。前者可能会导致 Rust 语言产生十分反人类的行为，也更容易出现 bug 。\n\n\n\n### Any\n\n预备知识\n- [Self](#self)\n- [Generic Blanket Impls](#generic-blanket-impls)\n- [Subtraits & Supertraits](#subtraits--supertraits)\n- [Trait Objects](#trait-objects)\n\n```rust\ntrait Any: 'static {\n    fn type_id(&self) -> TypeId;\n}\n```\n\n> Rust's style of polymorphism is parametric, but if we're looking to use a more ad-hoc style of polymorphism similar to dynamically-typed languages then we can emulate that using the `Any` trait. We don't have to manually impl this trait for our types because that's already covered by this generic blanket impl:\n\nRust 的多态性风格本身是参数化的，但如果我们希望临时使用一种更贴近于动态语言的多态性风格，可以借用 `Any` 特性来模拟。我们不需要手动实现 `Any` 特性，因为该特性通常由一揽子泛型实现所实现。\n\n```rust\nimpl<T: 'static + ?Sized> Any for T {\n    fn type_id(&self) -> TypeId {\n        TypeId::of::<T>()\n    }\n}\n```\n\n> The way we get a `T` out of a `dyn Any` is by using the `downcast_ref::<T>()` and `downcast_mut::<T>()` methods:\n\n对于 `dyn Any` 的特性对象，我们可以使用 `downcast_ref::<T>()` 或 `downcast_mut::<T>()` 来尝试解析出 `T` 。\n\n```rust\nuse std::any::Any;\n\n#[derive(Default)]\nstruct Point {\n    x: i32,\n    y: i32,\n}\n\nimpl Point {\n    fn inc(&mut self) {\n        self.x += 1;\n        self.y += 1;\n    }\n}\n\nfn map_any(mut any: Box<dyn Any>) -> Box<dyn Any> {\n    if let Some(num) = any.downcast_mut::<i32>() {\n        *num += 1;\n    } else if let Some(string) = any.downcast_mut::<String>() {\n        *string += \"!\";\n    } else if let Some(point) = any.downcast_mut::<Point>() {\n        point.inc();\n    }\n    any\n}\n\nfn main() {\n    let mut vec: Vec<Box<dyn Any>> = vec![\n        Box::new(0),\n        Box::new(String::from(\"a\")),\n        Box::new(Point::default()),\n    ];\n    // vec = [0, \"a\", Point { x: 0, y: 0 }]\n    vec = vec.into_iter().map(map_any).collect();\n    // vec = [1, \"a!\", Point { x: 1, y: 1 }]\n}\n```\n\n> This trait rarely _needs_ to be used because on top of parametric polymorphism being superior to ad-hoc polymorphism in most scenarios the latter can also be emulated using enums which are more type-safe and require less indirection. For example, we could have written the above example like this:\n\n这个特性鲜少被使用，因为参数化的多态性时常要优于这样变通使用的多态性，且后者也可以使用更加类型安全和更加直接的枚举来模拟。如下例：\n\n```rust\n#[derive(Default)]\nstruct Point {\n    x: i32,\n    y: i32,\n}\n\nimpl Point {\n    fn inc(&mut self) {\n        self.x += 1;\n        self.y += 1;\n    }\n}\n\nenum Stuff {\n    Integer(i32),\n    String(String),\n    Point(Point),\n}\n\nfn map_stuff(mut stuff: Stuff) -> Stuff {\n    match &mut stuff {\n        Stuff::Integer(num) => *num += 1,\n        Stuff::String(string) => *string += \"!\",\n        Stuff::Point(point) => point.inc(),\n    }\n    stuff\n}\n\nfn main() {\n    let mut vec = vec![\n        Stuff::Integer(0),\n        Stuff::String(String::from(\"a\")),\n        Stuff::Point(Point::default()),\n    ];\n    // vec = [0, \"a\", Point { x: 0, y: 0 }]\n    vec = vec.into_iter().map(map_stuff).collect();\n    // vec = [1, \"a!\", Point { x: 1, y: 1 }]\n}\n```\n\n> Despite `Any` rarely being _needed_ it can still be convenient to use sometimes, as we'll later see in the **Error Handling** section.\n\n尽管 `Any` 特性鲜少是必须要被使用的，但有时它又是一种非常便捷的用法，我们将在 **错误处理** 一章中领会这一点。\n\n\n\n## 文本格式化特性 Formatting Traits\n\n> We can serialize types into strings using the formatting macros in `std::fmt`, the most well-known of the bunch being `println!`. We can pass formatting parameters to the `{}` placeholders used within format `str`s which are then used to select which trait impl to use to serialize the placeholder's argument.\n\n我们可以使用 `std::fmt` 中提供的文本格式化宏来序列化结构体，例如我们最熟悉的 `println!` 。我们可以将文本格式化的参数传入 `{}` 占位符，以选择具体用哪个特性来序列化该结构。\n\n| 特性 | 占位符 | 描述 |\n|-------|-------------|-------------|\n| `Display` | `{}` | 常规序列化 |\n| `Debug` | `{:?}` | 调试序列化 |\n| `Octal` | `{:o}` | 八进制序列化 |\n| `LowerHex` | `{:x}` | 小写十六进制序列化 |\n| `UpperHex` | `{:X}` | 大写十六进制序列化 |\n| `Pointer` | `{:p}` | 内存地址 |\n| `Binary` | `{:b}` | 二进制序列化 |\n| `LowerExp` | `{:e}` | 小写指数序列化 |\n| `UpperExp` | `{:E}` | 大写十六进制序列化 |\n\n\n\n### Display & ToString\n\n预备知识\n- [Self](#self)\n- [Methods](#methods)\n- [Generic Blanket Impls](#generic-blanket-impls)\n\n```rust\ntrait Display {\n    fn fmt(&self, f: &mut Formatter<'_>) -> Result;\n}\n```\n\n> `Display` types can be serialized into `String`s which are friendly to the end users of the program. Example impl for `Point`:\n\n实现 `Display` 特性的类型可以被序列化为 `String` 。这对于程序的用户来说非常的友好。例如：\n\n```rust\nuse std::fmt;\n\n#[derive(Default)]\nstruct Point {\n    x: i32,\n    y: i32,\n}\n\nimpl fmt::Display for Point {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        write!(f, \"({}, {})\", self.x, self.y)\n    }\n}\n\nfn main() {\n    println!(\"origin: {}\", Point::default());\n    // prints \"origin: (0, 0)\"\n\n    // get Point's Display representation as a String\n    // Point 表达为可显示的 String\n    let stringified_point = format!(\"{}\", Point::default());\n    assert_eq!(\"(0, 0)\", stringified_point); // ✅\n}\n```\n\n> Aside from using the `format!` macro to get a type's display representation as a `String` we can use the `ToString` trait:\n\n除了使用 `format!` 宏来序列化结构体，我们也可以使用 `ToString` 特性：\n\n```rust\ntrait ToString {\n    fn to_string(&self) -> String;\n}\n```\n\n> There's no need for us to impl this ourselves. In fact we can't, because of this generic blanket impl that automatically impls `ToString` for any type which impls `Display`:\n\n我们不需要自己手动实现，事实上，我们也不能，因为对于实现了 `Display` 的类型来说，`ToString` 是由一揽子泛型实现所自动实现的。\n\n```rust\nimpl<T: Display + ?Sized> ToString for T;\n```\n\n> Using `ToString` with `Point`:\n\n对 `Point` 使用 `ToString` 特性：\n\n```rust\n#[test] // ✅\nfn display_point() {\n    let origin = Point::default();\n    assert_eq!(format!(\"{}\", origin), \"(0, 0)\");\n}\n\n#[test] // ✅\nfn point_to_string() {\n    let origin = Point::default();\n    assert_eq!(origin.to_string(), \"(0, 0)\");\n}\n\n#[test] // ✅\nfn display_equals_to_string() {\n    let origin = Point::default();\n    assert_eq!(format!(\"{}\", origin), origin.to_string());\n}\n```\n\n\n\n### Debug\n\n预备知识\n- [Self](#self)\n- [Methods](#methods)\n- [Derive Macros](#derive-macros)\n- [Display & ToString](#display--tostring)\n\n```rust\ntrait Debug {\n    fn fmt(&self, f: &mut Formatter<'_>) -> Result;\n}\n```\n\n> `Debug` has an identical signature to `Display`. The only difference is that the `Debug` impl is called when we use the `{:?}` formatting specifier. `Debug` can be derived:\n\n`Debug` 与 `Display` 具有相同的签名。唯一的区别在于我们使用 `{:?}` 文本格式化指令来调用 `Debug` 特性。 `Debug` 特性可以使用如下方法衍生：\n\n```rust\nuse std::fmt;\n\n#[derive(Debug)]\nstruct Point {\n    x: i32,\n    y: i32,\n}\n\n// derive macro generates impl below\n// 衍生宏展开如下\nimpl fmt::Debug for Point {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.debug_struct(\"Point\")\n            .field(\"x\", &self.x)\n            .field(\"y\", &self.y)\n            .finish()\n    }\n}\n```\n\n> Impling `Debug` for a type also allows it to be used within the `dbg!` macro which is superior to `println!` for quick and dirty print logging. Some of its advantages:\n> 1. `dbg!` prints to stderr instead of stdout so the debug logs are easy to separate from the actual stdout output of our program.\n> 2. `dbg!` prints the expression passed to it as well as the value the expression evaluated to.\n> 3. `dbg!` takes ownership of its arguments and returns them so you can use it within expressions:\n\n为特定类型实现 `Debug` 特性的同时，这也使得我们可以使用 `dbg!` 宏来快速地调试程序，这种方式要优于 `println!` 。其优点在于：\n1. `dbg!` 输出到标准错误流而不是标准输出流，所以我们能够很容易地将调试信息提取出来。\n2. `dbg!` 同时输出值和值的求值表达式。\n3. `dbg!` 接管参数的属权，但不会吞掉参数，而是再抛出来，所以可以将它用在表达式中：\n\n```rust\nfn some_condition() -> bool {\n    true\n}\n\n// no logging\n// 没有日志\nfn example() {\n    if some_condition() {\n        // some code\n    }\n}\n\n// println! logging\n// 使用 println! 打印日志\nfn example_println() {\n    // 🤦\n    let result = some_condition();\n    println!(\"{}\", result); // just prints \"true\"\n                            // 仅仅打印 \"true\"\n    if result {\n        // some code\n    }\n}\n\n// dbg! logging\n// 使用 dbg! 打印日志\nfn example_dbg() {\n    // 😍\n    if dbg!(some_condition()) { // prints \"[src/main.rs:22] some_condition() = true\"\n                                // 太棒了！打印出丰富的调试信息\n        // some code\n    }\n}\n```\n\n> The only downside is that `dbg!` isn't automatically stripped in release builds so we have to manually remove it from our code if we don't want to ship it in the final executable.\n\n`dbg!` 宏唯一的缺点是，它不能在构建最终发布的二进制文件时自动删除，我们不得不手动删除相关代码。\n\n\n\n## 算符重载特性 Operator Traits\n\n> All operators in Rust are associated with traits. If we'd like to impl operators for our types we have to impl the associated traits.\n\n在 Rust 中，所有的算符都与相应的特性相关联。为特定类型实现相应特性，即为该类型实现了相应算符。\n\n| 特性 | 类别 | 算符 | 描述 |\n|----------|----------|-------------|-------------|\n| `Eq`, `PartialEq` | 比较 | `==` | 相等 |\n| `Ord`, `PartialOrd` | 比较 | `<`, `>`, `<=`, `>=` | 比较 |\n| `Add` | 算数 | `+` | 加 |\n| `AddAssign` | 算数 | `+=` | 加等于 |\n| `BitAnd` | 算数 | `&` | 按位与 |\n| `BitAndAssign` | 算数 | `&=` | 按位与等于 |\n| `BitXor` | 算数 | `^` | 按位异或 |\n| `BitXorAssign` | 算数 | `^=` | 按位异或等于 |\n| `Div` | 算数 | `/` | 除 |\n| `DivAssign` | 算数 | `/=` | 除等于 |\n| `Mul` | 算数 | `*` | 乘 |\n| `MulAssign` | 算数 | `*=` | 乘等于 |\n| `Neg` | 算数 | `-` | 一元负 |\n| `Not` | 算数 | `!` | 一元逻辑非 |\n| `Rem` | 算数 | `%` | 求余 |\n| `RemAssign` | 算数 | `%=` | 求余等于 |\n| `Shl` | 算数 | `<<` | 左移 |\n| `ShlAssign` | 算数 | `<<=` | 左移等于 |\n| `Shr` | 算数 | `>>` | 右移 |\n| `ShrAssign` | 算数 | `>>=` | 右移等于 |\n| `Sub` | 算数 | `-` | 减 |\n| `SubAssign` | 算数 | `-=` | 减等于 |\n| `Fn` | 闭包 | `(...args)` | 不可变闭包调用 |\n| `FnMut` | 闭包 | `(...args)` | 可变闭包调用 |\n| `FnOnce` | 闭包 | `(...args)` | 一次性闭包调用 |\n| `Deref` | 其它 | `*` | 不可变解引用 |\n| `DerefMut` | 其它 | `*` | 可变解引用 |\n| `Drop` | 其它 | - | 类型析构 |\n| `Index` | 其它 | `[]` | 不可变索引 |\n| `IndexMut` | 其它 | `[]` | 可变索引 |\n| `RangeBounds` | 其它 | `..` | 范围迭代 |\n\n\n\n### 比较特性 Comparison Traits\n\n| 特性 | 类别 | 算符 | 描述 |\n|----------|----------|-------------|-------------|\n| `Eq`, `PartialEq` | 比较 | `==` | 相等 |\n| `Ord`, `PartialOrd` | 比较 | `<`, `>`, `<=`, `>=` | 比较 |\n\n\n#### PartialEq & Eq\n\n预备知识\n- [Self](#self)\n- [Methods](#methods)\n- [Generic Parameters](#generic-parameters)\n- [Default Impls](#default-impls)\n- [Generic Blanket Impls](#generic-blanket-impls)\n- [Marker Traits](#marker-traits)\n- [Subtraits & Supertraits](#subtraits--supertraits)\n- [Sized](#sized)\n\n```rust\ntrait PartialEq<Rhs = Self> \nwhere\n    Rhs: ?Sized, \n{\n    fn eq(&self, other: &Rhs) -> bool;\n\n    // provided default impls\n    // 提供默认实现\n    fn ne(&self, other: &Rhs) -> bool;\n}\n```\n\n> `PartialEq<Rhs>` types can be checked for equality to `Rhs` types using the `==` operator.\n\n实现了 `PartialEq<Rhs>` 特性的类型可以使用 `==` 算符来检查与 `Rhs` 的相等性。\n\n> All `PartialEq<Rhs>` impls must ensure that equality is symmetric and transitive. That means > for all `a`, `b`, and `c`:\n> - `a == b` implies `b == a` (symmetry)\n> - `a == b && b == c` implies `a == c` (transitivity) \n\n对 `PartialEq<Rhs>` 的实现须确保实现对称性与传递性。这意味着对于任意 `a` ， `b` 和 `c` 有：\n- 若 `a == b` 则 `b == a` （对称性）\n- 若 `a == b && b == c` 则 `a == c` （传递性）\n\n> By default `Rhs = Self` because we almost always want to compare instances of a type to each other, and not to instances of different types. This also automatically guarantees our impl is symmetric and transitive.\n>\n\n默认情况下 `Rhs = Self` 是因为我们几乎总是在相同类型之间进行比较。这也自动地确保了我们的实现是对称的、可传递的。\n\n```rust\nstruct Point {\n    x: i32,\n    y: i32\n}\n\n// Rhs == Self == Point\nimpl PartialEq for Point {\n    // impl automatically symmetric & transitive\n    // 该实现自动确保了对称性于传递性\n    fn eq(&self, other: &Point) -> bool {\n        self.x == other.x && self.y == other.y\n    }\n}\n```\n\n> If all the members of a type impl `PartialEq` then it can be derived:\n\n如果特定类型的成员都实现了 `PartialEq` 特性，那么该类型也可衍生该特性：\n\n```rust\n#[derive(PartialEq)]\nstruct Point {\n    x: i32,\n    y: i32\n}\n\n#[derive(PartialEq)]\nenum Suit {\n    Spade,\n    Heart,\n    Club,\n    Diamond,\n}\n```\n\n> Once we impl `PartialEq` for our type we also get equality comparisons between references of our type for free thanks to these generic blanket impls:\n\n多亏了一揽子泛型实现，一旦我们为特定类型实现了 `PartialEq` 特性，那么直接使用该类型的引用互相比较也是可以的：\n\n```rust\n// this impl only gives us: Point == Point\n// 该衍生宏本身只允许我们在结构体之间进行比较\n#[derive(PartialEq)]\nstruct Point {\n    x: i32,\n    y: i32\n}\n\n// all of the generic blanket impls below\n// are provided by the standard library\n// 以下的一揽子泛型实现由标准库提供\n\n// this impl gives us: &Point == &Point\n// 这个一揽子泛型实现允许我们通过不可变引用之间进行比较\nimpl<A, B> PartialEq<&'_ B> for &'_ A\nwhere A: PartialEq<B> + ?Sized, B: ?Sized;\n\n// this impl gives us: &mut Point == &Point\n// 这个一揽子泛型实现允许我们通过可变引用与不可变引用进行比较\nimpl<A, B> PartialEq<&'_ B> for &'_ mut A\nwhere A: PartialEq<B> + ?Sized, B: ?Sized;\n\n// this impl gives us: &Point == &mut Point\n// 这个一揽子泛型实现允许我们通过不可变引用与可变引用进行比较\nimpl<A, B> PartialEq<&'_ mut B> for &'_ A\nwhere A: PartialEq<B> + ?Sized, B: ?Sized;\n\n// this impl gives us: &mut Point == &mut Point\n// 这个一揽子泛型实现允许我们通过可变引用之间进行比较\nimpl<A, B> PartialEq<&'_ mut B> for &'_ mut A\nwhere A: PartialEq<B> + ?Sized, B: ?Sized;\n```\n\n> Since this trait is generic we can define equality between different types. The standard library leverages this to allow checking equality between the many string-like types such as `String`, `&str`, `PathBuf`, `&Path`, `OsString`, `&OsStr`, and so on.\n\n由于该特性提供泛型，我们可以定义不同类型之间的可相等性。标准库正是利用这一点提供了不同类型字符串之间的比较功能，例如`String`， `&str`， `PathBuf`，`&Path`，`OsString` 和 `&OsStr`等等。\n\n> Generally, we should only impl equality between different types _if they contain the same kind of data_ and the only difference between the types is how they represent the data or how they allow interacting with the data.\n\n通常来说我们仅会实现相同类型之间的可相等性，除非两种类型虽然包含同一类数据，但又有表达形式或交互形式的差异，这时我们才会考虑实现不同类型之间的可相等性。\n\n> Here's a cute but bad example of how someone might be tempted to impl `PartialEq` to check equality between different types that don't meet the above criteria:\n\n以下是一个有趣但糟糕的例子，它尝试为不同类型实现 `PartialEq` 但又违背了上述要求：\n\n```rust\n#[derive(PartialEq)]\nenum Suit {\n    Spade,\n    Club,\n    Heart,\n    Diamond,\n}\n\n#[derive(PartialEq)]\nenum Rank {\n    Ace,\n    Two,\n    Three,\n    Four,\n    Five,\n    Six,\n    Seven,\n    Eight,\n    Nine,\n    Ten,\n    Jack,\n    Queen,\n    King,\n}\n\n#[derive(PartialEq)]\nstruct Card {\n    suit: Suit,\n    rank: Rank,\n}\n\n// check equality of Card's suit\n// 检查花色的相等性\nimpl PartialEq<Suit> for Card {\n    fn eq(&self, other: &Suit) -> bool {\n        self.suit == *other\n    }\n}\n\n// check equality of Card's rank\n// 检查牌序的相等性\nimpl PartialEq<Rank> for Card {\n    fn eq(&self, other: &Rank) -> bool {\n        self.rank == *other\n    }\n}\n\nfn main() {\n    let AceOfSpades = Card {\n        suit: Suit::Spade,\n        rank: Rank::Ace,\n    };\n    assert!(AceOfSpades == Suit::Spade); // ✅\n    assert!(AceOfSpades == Rank::Ace); // ✅\n}\n```\n\n> It works and kinda makes sense. A card which is an Ace of Spades is both an Ace and a Spade, and if we're writing a library to handle playing cards it's reasonable that we'd want to make it easy and convenient to individually check the suit and rank of a card. However, something's missing: symmetry! We can `Card == Suit` and `Card == Rank` but we cannot `Suit == Card` or `Rank == Card` so let's fix that:\n\n上述代码有效且其逻辑有几分道理，黑桃 A 既是黑桃也是 A 。但如果我们真的去写一个处理扑克牌的库的话，最简单也最方便的方法莫过于独立地检查牌面的花色和牌序。而且，上述代码并不满足对称性！我们可以使用 `Card == Suit` 和 `Card == Rank` ，但却不能使用 `Suit == Card` 和 `Rank == Card`， 让我们来修复这一点：\n\n```rust\n// check equality of Card's suit\n// 检查花色的相等性\nimpl PartialEq<Suit> for Card {\n    fn eq(&self, other: &Suit) -> bool {\n        self.suit == *other\n    }\n}\n\n// added for symmetry\n// 增加对称性\nimpl PartialEq<Card> for Suit {\n    fn eq(&self, other: &Card) -> bool {\n        *self == other.suit\n    }\n}\n\n// check equality of Card's rank\n// 检查牌序的相等性\nimpl PartialEq<Rank> for Card {\n    fn eq(&self, other: &Rank) -> bool {\n        self.rank == *other\n    }\n}\n\n// added for symmetry\n// 增加对称性\nimpl PartialEq<Card> for Rank {\n    fn eq(&self, other: &Card) -> bool {\n        *self == other.rank\n    }\n}\n```\n\n> We have symmetry! Great. Adding symmetry just broke transitivity! Oops. This is now possible:\n\n我们实现了对称性！棒！但是实现对称性却破坏了传递性！糟tm大糕！考虑以下代码：\n\n```rust\nfn main() {\n    // Ace of Spades\n    // ♠A\n    let a = Card {\n        suit: Suit::Spade,\n        rank: Rank::Ace,\n    };\n    let b = Suit::Spade;\n    // King of Spades\n    // ♠K\n    let c = Card {\n        suit: Suit::Spade,\n        rank: Rank::King,\n    };\n    assert!(a == b && b == c); // ✅\n    assert!(a == c); // ❌\n}\n```\n\n> A good example of impling `PartialEq` to check equality between different types would be a program that works with distances and uses different types to represent different units of measurement.\n\n关于对不同类型实现 `PartialEq` 特性的绝佳示例如下，本程序的功能在于处理空间上的距离，它使用不同的类型以表示不同的测量单位：\n\n```rust\n#[derive(PartialEq)]\nstruct Foot(u32);\n\n#[derive(PartialEq)]\nstruct Yard(u32);\n\n#[derive(PartialEq)]\nstruct Mile(u32);\n\nimpl PartialEq<Mile> for Foot {\n    fn eq(&self, other: &Mile) -> bool {\n        self.0 == other.0 * 5280\n    }\n}\n\nimpl PartialEq<Foot> for Mile {\n    fn eq(&self, other: &Foot) -> bool {\n        self.0 * 5280 == other.0\n    }    \n}\n\nimpl PartialEq<Mile> for Yard {\n    fn eq(&self, other: &Mile) -> bool {\n        self.0 == other.0 * 1760\n    }\n}\n\nimpl PartialEq<Yard> for Mile {\n    fn eq(&self, other: &Yard) -> bool {\n        self.0 * 1760 == other.0\n    }    \n}\n\nimpl PartialEq<Foot> for Yard {\n    fn eq(&self, other: &Foot) -> bool {\n        self.0 * 3 == other.0\n    }\n}\n\nimpl PartialEq<Yard> for Foot {\n    fn eq(&self, other: &Yard) -> bool {\n        self.0 == other.0 * 3\n    }\n}\n\nfn main() {\n    let a = Foot(5280);\n    let b = Yard(1760);\n    let c = Mile(1);\n    \n    // symmetry\n    // 对称性\n    assert!(a == b && b == a); // ✅\n    assert!(b == c && c == b); // ✅\n    assert!(a == c && c == a); // ✅\n\n    // transitivity\n    // 传递性\n    assert!(a == b && b == c && a == c); // ✅\n    assert!(c == b && b == a && c == a); // ✅\n}\n```\n\n> `Eq` is a marker trait and a subtrait of `PartialEq<Self>`.\n\n`Eq` 是仅用于标记的特性，也是 `PartialEq<Self>` 的子特性。\n\n```rust\ntrait Eq: PartialEq<Self> {}\n```\n\n> If we impl `Eq` for a type, on top of the symmetry & transitivity properties required by `PartialEq`, we're also guaranteeing reflexivity, i.e. `a == a` for all `a`. In this sense `Eq` refines `PartialEq` because it represents a stricter version of equality. If all members of a type impl `Eq` then the `Eq` impl can be derived for the type.\n\n鉴于 `PartialEq` 特性提供的对称性与传递性，一旦我们实现 `Eq` 特性，我们也就确保了该类型具有自反性，即对任意 `a` 有 `a == a` 。可以说， `Eq` 改良了 `PartialEq` ，因为它实现了一个比后者更加严格的可相等性。如果一个类型的全部成员都实现了 `Eq` 特性，那么该类型本身也可以衍生出该特性。\n\n> Floats are `PartialEq` but not `Eq` because `NaN != NaN`. Almost all other `PartialEq` types are trivially `Eq`, unless of course if they contain floats.\n\n所有的浮点类型都实现了 `PartialEq` 但是没有实现 `Eq` ，因为 `NaN != NaN` 。几乎所有其它实现 `PartialEq` 的类型也都自然地实现了 `Eq` ，除非它们包含了浮点数。\n\n> Once a type impls `PartialEq` and `Debug` we can use it in the `assert_eq!` macro. We can also compare collections of `PartialEq` types.\n\n对于实现了 `PartialEq` 和 `Debug` 的类型，我们也可以将它用于 `assert_eq!`  宏。并且，我们可以对实现 `PartialEq` 特性的类型组成的集合进行比较。\n\n```rust\n#[derive(PartialEq, Debug)]\nstruct Point {\n    x: i32,\n    y: i32,\n}\n\nfn example_assert(p1: Point, p2: Point) {\n    assert_eq!(p1, p2);\n}\n\nfn example_compare_collections<T: PartialEq>(vec1: Vec<T>, vec2: Vec<T>) {\n    // if T: PartialEq this now works!\n    if vec1 == vec2 {\n        // some code\n    } else {\n        // other code\n    }\n}\n```\n\n\n\n#### Hash\n\n预备知识\n- [Self](#self)\n- [Methods](#methods)\n- [Generic Parameters](#generic-parameters)\n- [Default Impls](#default-impls)\n- [Derive Macros](#derive-macros)\n- [PartialEq & Eq](#partialeq--eq)\n\n```rust\ntrait Hash {\n    fn hash<H: Hasher>(&self, state: &mut H);\n\n    // provided default impls\n    // 提供默认实现\n    fn hash_slice<H: Hasher>(data: &[Self], state: &mut H);\n}\n```\n\n> This trait is not associated with any operator, but the best time to talk about it is right after `PartialEq` & `Eq` so here it is. `Hash` types can be hashed using a `Hasher`.\n\n本特性并未关联到任何算符，之所以在这里提及，是因为它与 `PartialEq` 与 `Eq` 密切的关系。实现 `Hash` 特性的类型可以通过 `Hasher` 作哈希运算。\n\n```rust\nuse std::hash::Hasher;\nuse std::hash::Hash;\n\nstruct Point {\n    x: i32,\n    y: i32,\n}\n\nimpl Hash for Point {\n    fn hash<H: Hasher>(&self, hasher: &mut H) {\n        hasher.write_i32(self.x);\n        hasher.write_i32(self.y);\n    }\n}\n```\n\n> There's a derive macro which generates the same impl as above:\n\n以下衍生宏展开与以上代码中相同的实现：\n\n```rust\n#[derive(Hash)]\nstruct Point {\n    x: i32,\n    y: i32,\n}\n```\n\n> If a type impls both `Hash` and `Eq` those impls must agree with each other such that for all `a` and `b` if `a == b` then `a.hash() == b.hash()`. So we should always use the derive macro to impl both or manually impl both, but not mix the two, otherwise we risk breaking the above invariant.\n\n如果一个类型同时实现了 `Hash` 和 `Eq` ，那么二者必须要实现步调一致，即对任意 `a` 与 `b` ， 若有 `a == b` ， 则必有 `a.hash() == b.hash()` 。所以，对于同时实现二者，要么都用衍生宏，要么都手动实现，不要一个用衍生宏，而另一个手动实现，否则我们将冒着步调不一致的极大风险。\n\n> The main benefit of impling `Eq` and `Hash` for a type is that it allows us to store that type as keys in `HashMap`s and `HashSet`s.\n\n实现`Eq` 和 `Hash` 特性的主要好处在于，这允许我们将该类型作为一个键存储于 `HashMap` 和 `HashSet` 中。\n\n```rust\nuse std::collections::HashSet;\n\n// now our type can be stored\n// in HashSets and HashMaps!\n// 现在我们的类型可以存储于 HashSet 和 HashMap 中了！\n#[derive(PartialEq, Eq, Hash)]\nstruct Point {\n    x: i32,\n    y: i32,\n}\n\nfn example_hashset() {\n    let mut points = HashSet::new();\n    points.insert(Point { x: 0, y: 0 }); // ✅\n}\n```\n\n\n\n#### PartialOrd & Ord\n\n预备知识\n- [Self](#self)\n- [Methods](#methods)\n- [Generic Parameters](#generic-parameters)\n- [Default Impls](#default-impls)\n- [Subtraits & Supertraits](#subtraits--supertraits)\n- [Derive Macros](#derive-macros)\n- [Sized](#sized)\n- [PartialEq & Eq](#partialeq--eq)\n\n```rust\nenum Ordering {\n    Less,\n    Equal,\n    Greater,\n}\n\ntrait PartialOrd<Rhs = Self>: PartialEq<Rhs> \nwhere\n    Rhs: ?Sized, \n{\n    fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;\n\n    // provided default impls\n    // 提供默认实现\n    fn lt(&self, other: &Rhs) -> bool;\n    fn le(&self, other: &Rhs) -> bool;\n    fn gt(&self, other: &Rhs) -> bool;\n    fn ge(&self, other: &Rhs) -> bool;\n}\n```\n\n> `PartialOrd<Rhs>` types can be compared to `Rhs` types using the `<`, `<=`, `>`, and `>=` operators.\n\n实现 `PartialOrd<Rhs>` 的类型可以和 `Rhs` 的类型之间使用 `<`，`<=`，`>`，和 `>=` 算符。\n\n> All `PartialOrd` impls must ensure that comparisons are asymmetric and transitive. That means for all `a`, `b`, and `c`:\n> - `a < b` implies `!(a > b)` (asymmetry)\n> - `a < b && b < c` implies `a < c` (transitivity)\n>\n\n实现 `PartialOrd` 时须确保比较的非对称性和传递性。这意味着对任意 `a`，`b`，`c`有：\n\n- 若 `a < b` 则 `!(a > b)` （非对称性）\n- 若 `a < b && b < c` 则 `a < c` （传递性）\n\n> `PartialOrd` is a subtrait of `PartialEq` and their impls must always agree with each other.\n\n`PartialOrd` 是 `PartialEq` 的子特性，二者必须要实现步调一致。\n\n```rust\nfn must_always_agree<T: PartialOrd + PartialEq>(t1: T, t2: T) {\n    assert_eq!(t1.partial_cmp(&t2) == Some(Ordering::Equal), t1 == t2);\n}\n```\n\n> `PartialOrd` refines `PartialEq` in the sense that when comparing `PartialEq` types we can check if they are equal or not equal, but when comparing `PartialOrd` types we can check if they are equal or not equal, and if they are not equal we can check if they are unequal because the first item is less than or greater than the second item.\n\n`PartialOrd` 改良了 `PartialEq` ，后者仅能比较是否相等，而前者除了能比较是否相等，还能比较孰大孰小。\n\n> By default `Rhs = Self` because we almost always want to compare instances of a type to each other, and not to instances of different types. This also automatically guarantees our impl is symmetric and transitive.\n\n默认情况下 `Rhs = Self` ，因为我们几乎总是在相同类型的实例之间相比较，而不是不同类型之间。这一点自动保证了我们的实现的对称性和传递性。\n\n```rust\nuse std::cmp::Ordering;\n\n#[derive(PartialEq, PartialOrd)]\nstruct Point {\n    x: i32,\n    y: i32\n}\n\n// Rhs == Self == Point\nimpl PartialOrd for Point {\n    // impl automatically symmetric & transitive\n    // 该实现自动确保了对称性与传递性\n    fn partial_cmp(&self, other: &Point) -> Option<Ordering> {\n        Some(match self.x.cmp(&other.x) {\n            Ordering::Equal => self.y.cmp(&other.y),\n            ordering => ordering,\n        })\n    }\n}\n```\n\n> If all the members of a type impl `PartialOrd` then it can be derived:\n\n如果特定类型的全部成员都实现了 `PartialOrd` 特性，那么该类型也可以衍生出该特性：\n\n```rust\n#[derive(PartialEq, PartialOrd)]\nstruct Point {\n    x: i32,\n    y: i32,\n}\n\n#[derive(PartialEq, PartialOrd)]\nenum Stoplight {\n    Red,\n    Yellow,\n    Green,\n}\n```\n\n> The `PartialOrd` derive macro orders types based on the lexicographical order of their members:\n\n`PartialOrd` 衍生宏依据 **类型成员的定义顺序** 对类型进行排序：\n\n```rust\n// generates PartialOrd impl which orders\n// Points based on x member first and\n// y member second because that's the order\n// they appear in the source code\n// 宏展开的 PartialOrd 实现排序时\n// 首先考虑 x 再考虑 y\n// 因为这是它们在源代码中出现的顺序\n#[derive(PartialOrd, PartialEq)]\nstruct Point {\n    x: i32,\n    y: i32,\n}\n\n// generates DIFFERENT PartialOrd impl\n// which orders Points based on y member\n// first and x member second\n// 这里宏展开的 PartialOrd 实现排序时\n// 首先考虑 y 再考虑 x\n#[derive(PartialOrd, PartialEq)]\nstruct Point {\n    y: i32,\n    x: i32,\n}\n```\n\n> `Ord` is a subtrait of `Eq` and `PartialOrd<Self>`:\n\n`Ord` 是 `Eq` 和 `PartialOrd<Self>` 的子特性：\n\n```rust\ntrait Ord: Eq + PartialOrd<Self> {\n    fn cmp(&self, other: &Self) -> Ordering;\n\n    // provided default impls\n    // 提供默认实现\n    fn max(self, other: Self) -> Self;\n    fn min(self, other: Self) -> Self;\n    fn clamp(self, min: Self, max: Self) -> Self;\n}\n```\n\n> If we impl `Ord` for a type, on top of the asymmetry & transitivity properties required by `PartialOrd`, we're also guaranteeing that the asymmetry is total, i.e. exactly one of `a < b`, `a == b` or `a > b` is true for any given `a` and `b`. In this sense `Ord` refines `Eq` and `PartialOrd` because it represents a stricter version of comparisons. If a type impls `Ord` we can use that impl to trivially impl `PartialOrd`, `PartialEq`, and `Eq`:\n\n鉴于 `PartialOrd` 提供的非对称性和传递性，对特定类型实现 `Ord` 特性的同时也就保证了其非对称性，即对于任意 `a` 与 `b` 有 `a < b` ，`a == b` ，`a < b` 。可以说， `Ord` 改良了 `Eq` 和 `PartialOrd` ，因为它提供了一种更加严格的比较。如果一个类型实现了 `Ord` ，那么 `PartialOrd` ，`PartialEq` 和 `Eq` 的实现也就微不足道了。\n\n```rust\nuse std::cmp::Ordering;\n\n// of course we can use the derive macros here\n// 可以使用衍生宏\n#[derive(Ord, PartialOrd, Eq, PartialEq)]\nstruct Point {\n    x: i32,\n    y: i32,\n}\n\n// note: as with PartialOrd, the Ord derive macro\n// orders a type based on the lexicographical order\n// of its members\n// 注意：与 PatrialOrd 相同，Ord 衍生宏衍生宏依据\n// 类型的成员的定义顺序 对类型进行排序\n\n// but here's the impls if we wrote them out by hand\n// 以下是我们手动的实现\nimpl Ord for Point {\n    fn cmp(&self, other: &Self) -> Ordering {\n        match self.x.cmp(&other.x) {\n            Ordering::Equal => self.y.cmp(&other.y),\n            ordering => ordering,\n        }\n    }\n}\nimpl PartialOrd for Point {\n    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {\n        Some(self.cmp(other))\n    }\n}\nimpl PartialEq for Point {\n    fn eq(&self, other: &Self) -> bool {\n        self.cmp(other) == Ordering::Equal\n    }\n}\nimpl Eq for Point {}\n```\n\n> Floats impl `PartialOrd` but not `Ord` because both `NaN < 0 == false` and `NaN >= 0 == false` are simultaneously true. Almost all other `PartialOrd` types are trivially `Ord`, unless of course if they contain floats.\n\n浮点数类型实现了 `PartialOrd` 但是没有实现 `Ord` ，因为 `NaN < 0 == false` 与 `NaN >= 0 == false` 同时为真。几乎所有其它实现 `PartialOrd` 的类型都实现了 `Ord` ，除非该类型包含浮点数。\n\n> Once a type impls `Ord` we can store it in `BTreeMap`s and `BTreeSet`s as well as easily sort it using the `sort()` method on slices and any types which deref to slices such as arrays, `Vec`s, and `VecDeque`s.\n\n对于实现了 `Ord` 特性的类型，我们可以将它存储于 `BTreeMap` 和 `BTreeSet` ，并且可以通过 `sort()` 方法对切片，或者任何可以自动解引用为切片的类型进行排序，例如 `Vec` 和 `VecDeque` 。\n\n```rust\nuse std::collections::BTreeSet;\n\n// now our type can be stored\n// in BTreeSets and BTreeMaps!\n// 现在我们的类型可以存储于 BTreeSet 和 BTreeMap 中了！\n#[derive(Ord, PartialOrd, PartialEq, Eq)]\nstruct Point {\n    x: i32,\n    y: i32,\n}\n\nfn example_btreeset() {\n    let mut points = BTreeSet::new();\n    points.insert(Point { x: 0, y: 0 }); // ✅\n}\n\n// we can also .sort() Ord types in collections!\n// 对于实现了 Ord 特性的类型，我们可以使用 .sort() 方法来对集合进行排序！\nfn example_sort<T: Ord>(mut sortable: Vec<T>) -> Vec<T> {\n    sortable.sort();\n    sortable\n}\n```\n\n\n\n### 算术特性 Arithmetic Traits\n\n| 特性           | 类别 | 算符  | 描述         |\n| -------------- | ---- | ----- | ------------ |\n| `Add`          | 算数 | `+`   | 加           |\n| `AddAssign`    | 算数 | `+=`  | 加等于       |\n| `BitAnd`       | 算数 | `&`   | 按位与       |\n| `BitAndAssign` | 算数 | `&=`  | 按位与等于   |\n| `BitXor`       | 算数 | `^`   | 按位异或     |\n| `BitXorAssign` | 算数 | `^=`  | 按位异或等于 |\n| `Div`          | 算数 | `/`   | 除           |\n| `DivAssign`    | 算数 | `/=`  | 除等于       |\n| `Mul`          | 算数 | `*`   | 乘           |\n| `MulAssign`    | 算数 | `*=`  | 乘等于       |\n| `Neg`          | 算数 | `-`   | 一元负       |\n| `Not`          | 算数 | `!`   | 一元逻辑非   |\n| `Rem`          | 算数 | `%`   | 求余         |\n| `RemAssign`    | 算数 | `%=`  | 求余等于     |\n| `Shl`          | 算数 | `<<`  | 左移         |\n| `ShlAssign`    | 算数 | `<<=` | 左移等于     |\n| `Shr`          | 算数 | `>>`  | 右移         |\n| `ShrAssign`    | 算数 | `>>=` | 右移等于     |\n| `Sub`          | 算数 | `-`   | 减           |\n| `SubAssign`    | 算数 | `-=`  | 减等于       |\n\n> Going over all of these would be very redundant. Most of these only apply to number types anyway. We'll only go over `Add` and `AddAssign` since the `+` operator is commonly overloaded to do other stuff like adding items to collections or concatenating things together, that way we cover the most interesting ground and don't repeat ourselves.\n>\n\n详解以上所有算术特性未免显得多余，且其大多仅用于操作数字类型。本文仅就最常见被重载的 `Add` 和 `AddAssign` 特性，亦即 `+` 和 `+=` 算符，进行说明，其重载广泛用于为集合增加内容或对不同事物的连接。这样，我们多侧重于最有趣的地方，而不是无趣枯燥地重复。\n\n\n#### Add & AddAssign\n\n预备知识\n- [Self](#self)\n- [Methods](#methods)\n- [Associated Types](#associated-types)\n- [Generic Parameters](#generic-parameters)\n- [Generic Types vs Associated Types](#generic-types-vs-associated-types)\n- [Derive Macros](#derive-macros)\n\n```rust\ntrait Add<Rhs = Self> {\n    type Output;\n    fn add(self, rhs: Rhs) -> Self::Output;\n}\n```\n\n> `Add<Rhs, Output = T>` types can be added to `Rhs` types and will produce `T` as output.\n\n实现 `Add<Rhs, Output = T>` 特性的类型，与 `Rhs` 类型相加得到 `T` 类型的值。\n\n> Example `Add<Point, Output = Point>` impl for `Point`:\n\n下例对 `Point` 类型实现了 `Add<Rhs, Output = T>` ：\n\n```rust\n#[derive(Clone, Copy)]\nstruct Point {\n    x: i32,\n    y: i32,\n}\n\nimpl Add for Point {\n    type Output = Point;\n    fn add(self, rhs: Point) -> Point {\n        Point {\n            x: self.x + rhs.x,\n            y: self.y + rhs.y,\n        }\n    }\n}\n\nfn main() {\n    let p1 = Point { x: 1, y: 2 };\n    let p2 = Point { x: 3, y: 4 };\n    let p3 = p1 + p2;\n    assert_eq!(p3.x, p1.x + p2.x); // ✅\n    assert_eq!(p3.y, p1.y + p2.y); // ✅\n}\n```\n\n> But what if we only had references to `Point`s? Can we still add them then? Let's try:\n\n如果我们对 `Point` 的引用进行如上操作还能将他们加在一起吗？我们试试：\n\n```rust\nfn main() {\n    let p1 = Point { x: 1, y: 2 };\n    let p2 = Point { x: 3, y: 4 };\n    let p3 = &p1 + &p2; // ❌\n}\n```\n\n> Unfortunately not. The compiler throws:\n\n遗憾的是，并不可以。编译器出错了：\n\n```none\nerror[E0369]: cannot add `&Point` to `&Point`\n  --> src/main.rs:50:25\n   |\n50 |     let p3: Point = &p1 + &p2;\n   |                     --- ^ --- &Point\n   |                     |\n   |                     &Point\n   |\n   = note: an implementation of `std::ops::Add` might be missing for `&Point`\n```\n\n> Within Rust's type system, for some type `T`, the types `T`, `&T`, and `&mut T` are all treated as unique distinct types which means we have to provide trait impls for each of them separately. Let's define an `Add` impl for `&Point`:\n>\n\n在 Rust 的类型系统中，对于特定类型 `T` 来讲，`T` ，`&T` ，`&mut T` 三者本身是具有不同类型的，这意味着我们需要对它们分别实现相应特性。下面我们对 `&Point` 实现 `Add` 特性：\n\n```rust\nimpl Add for &Point {\n    type Output = Point;\n    fn add(self, rhs: &Point) -> Point {\n        Point {\n            x: self.x + rhs.x,\n            y: self.y + rhs.y,\n        }\n    }\n}\n\nfn main() {\n    let p1 = Point { x: 1, y: 2 };\n    let p2 = Point { x: 3, y: 4 };\n    let p3 = &p1 + &p2; // ✅\n    assert_eq!(p3.x, p1.x + p2.x); // ✅\n    assert_eq!(p3.y, p1.y + p2.y); // ✅\n}\n```\n\n> However, something still doesn't feel quite right. We have two separate impls of `Add` for `Point` and `&Point` and they _happen_ to do the same thing currently but there's no guarantee that they will in the future! For example, let's say we decide that when we add two `Point`s together we want to create a `Line` containing those two `Point`s instead of creating a new `Point`, we'd update our `Add` impl like this:\n\n这是可行的，但是不觉得哪里怪怪的吗？我们对 `Point` 和 `&Point` 分别实现了 `Add` 特性，现在来看这两种实现能够保持步调一致，但是未来也能保证吗？例如，我们现在决定对两个 `Point` 相加要产生一个 `Line` 而不是 `Point` ，可以对 `Add` 特性的实现做出如下改动：\n\n```rust\nuse std::ops::Add;\n\n#[derive(Copy, Clone)]\nstruct Point {\n    x: i32,\n    y: i32,\n}\n\n#[derive(Copy, Clone)]\nstruct Line {\n    start: Point,\n    end: Point,\n}\n\n// we updated this impl\n// 我们更新了这个实现\nimpl Add for Point {\n    type Output = Line;\n    fn add(self, rhs: Point) -> Line {\n        Line {\n            start: self,\n            end: rhs,\n        }\n    }\n}\n\n// but forgot to update this impl, uh oh!\n// 但是忘记了更新这个实现，糟tm大糕！\nimpl Add for &Point {\n    type Output = Point;\n    fn add(self, rhs: &Point) -> Point {\n        Point {\n            x: self.x + rhs.x,\n            y: self.y + rhs.y,\n        }\n    }\n}\n\nfn main() {\n    let p1 = Point { x: 1, y: 2 };\n    let p2 = Point { x: 3, y: 4 };\n    let line: Line = p1 + p2; // ✅\n\n    let p1 = Point { x: 1, y: 2 };\n    let p2 = Point { x: 3, y: 4 };\n    let line: Line = &p1 + &p2; // ❌ expected Line, found Point\n                                // ❌ 期待得到 Line ，但是得到 Point\n}\n```\n\n> Our current impl of `Add` for `&Point` creates an unnecessary maintenance burden, we want the impl to match `Point`'s impl without having to manually update it every time we change `Point`'s impl. We'd like to keep our code as DRY (Don't Repeat Yourself) as possible. Luckily this is achievable:\n\n我们对 `&Point` 不可变引用类型的 `Add` 实现，给我们带来了不必要的维护困难。是否能够使得，当我们更改 `Point` 类型的实现时， `&Point` 类型的实现也能够自动发生匹配，而不需要我们手动维护呢？我们的愿望是尽可能写出 `DRY (Don't Repeat Yourself)` 的不重复的代码。幸运的是，我们可以如此实现这一点：\n\n```rust\n// updated, DRY impl\n// 使用一种更“干”的实现\nimpl Add for &Point {\n    type Output = <Point as Add>::Output;\n    fn add(self, rhs: &Point) -> Self::Output {\n        Point::add(*self, *rhs)\n    }\n}\n\nfn main() {\n    let p1 = Point { x: 1, y: 2 };\n    let p2 = Point { x: 3, y: 4 };\n    let line: Line = p1 + p2; // ✅\n\n    let p1 = Point { x: 1, y: 2 };\n    let p2 = Point { x: 3, y: 4 };\n    let line: Line = &p1 + &p2; // ✅\n}\n```\n\n> `AddAssign<Rhs>` types allow us to add + assign `Rhs` types to them. The trait declaration:\n\n实现 `AddAssign<Rhs>` 的类型，允许我们对 `Rhs` 的类型相加之并赋值到自身。该特性的声明为：\n\n```rust\ntrait AddAssign<Rhs = Self> {\n    fn add_assign(&mut self, rhs: Rhs);\n}\n```\n\n> Example impls for `Point` and `&Point`:\n\n对 `Point` 和 `&Point` 类型的实现示例：\n\n```rust\nuse std::ops::AddAssign;\n\n#[derive(Copy, Clone)]\nstruct Point {\n    x: i32,\n    y: i32\n}\n\nimpl AddAssign for Point {\n    fn add_assign(&mut self, rhs: Point) {\n        self.x += rhs.x;\n        self.y += rhs.y;\n    }\n}\n\nimpl AddAssign<&Point> for Point {\n    fn add_assign(&mut self, rhs: &Point) {\n        Point::add_assign(self, *rhs);\n    }\n}\n\nfn main() {\n    let mut p1 = Point { x: 1, y: 2 };\n    let p2 = Point { x: 3, y: 4 };\n    p1 += &p2;\n    p1 += p2;\n    assert!(p1.x == 7 && p1.y == 10);\n}\n```\n\n\n\n### 闭包特性 Closure Traits\n\n| 特性 | 类别 | 算符 | 描述 |\n|----------|----------|-------------|-------------|\n| `Fn` | 闭包 | `(...args)` | 不可变闭包调用 |\n| `FnMut` | 闭包 | `(...args)` | 可变闭包调用 |\n| `FnOnce` | 闭包 | `(...args)` | 一次性闭包调用 |\n\n\n\n#### FnOnce, FnMut, & Fn\n\n预备知识\n- [Self](#self)\n- [Methods](#methods)\n- [Associated Types](#associated-types)\n- [Generic Parameters](#generic-parameters)\n- [Generic Types vs Associated Types](#generic-types-vs-associated-types)\n- [Subtraits & Supertraits](#subtraits--supertraits)\n\n```rust\ntrait FnOnce<Args> {\n    type Output;\n    fn call_once(self, args: Args) -> Self::Output;\n}\n\ntrait FnMut<Args>: FnOnce<Args> {\n    fn call_mut(&mut self, args: Args) -> Self::Output;\n}\n\ntrait Fn<Args>: FnMut<Args> {\n    fn call(&self, args: Args) -> Self::Output;\n}\n```\n\n> Although these traits exist it's not possible to impl them for our own types in stable Rust. The only types we can create which impl these traits are closures. Depending on what the closure captures from its environment determines whether it impls `FnOnce`, `FnMut`, or `Fn`.\n\n事实上，在 stable Rust 中我们并不能对我们自己的类型实现上述特性，唯一的例外是闭包。对于闭包从环境中捕获的值的不同，该闭包会实现不同的特性：`FnOnce` ，`FnMut` ，`Fn` 。\n\n> An `FnOnce` closure can only be called once because it consumes some value as part of its execution:\n\n对于实现 `FnOnce` 的闭包，仅可调用一次，因为它消耗掉了其执行中必须的值：\n\n```rust\nfn main() {\n    let range = 0..10;\n    let get_range_count = || range.count();\n    assert_eq!(get_range_count(), 10); // ✅\n    get_range_count(); // ❌\n}\n```\n\n> The `.count()` method on iterators consumes the iterator so it can only be called once. Hence our closure can only be called once. Which is why when we try to call it a second time we get this error:\n\n迭代器上的 `.count()` 方法会消耗掉整个迭代器，所以该方法仅能调用一次。所以我们的闭包也就是能调用一次了，这就是为什么当第二次调用该闭包时会出错：\n\n```none\nerror[E0382]: use of moved value: `get_range_count`\n --> src/main.rs:5:5\n  |\n4 |     assert_eq!(get_range_count(), 10);\n  |                ----------------- `get_range_count` moved due to this call\n5 |     get_range_count();\n  |     ^^^^^^^^^^^^^^^ value used here after move\n  |\nnote: closure cannot be invoked more than once because it moves the variable `range` out of its environment\n --> src/main.rs:3:30\n  |\n3 |     let get_range_count = || range.count();\n  |                              ^^^^^\nnote: this value implements `FnOnce`, which causes it to be moved when called\n --> src/main.rs:4:16\n  |\n4 |     assert_eq!(get_range_count(), 10);\n  |                ^^^^^^^^^^^^^^^\n```\n\n> An `FnMut` closure can be called multiple times and can also mutate variables it has captured from its environment. We might say `FnMut` closures perform side-effects or are stateful. Here's an example of a closure that filters out all non-ascending values from an iterator by keeping track of the smallest value it has seen so far:\n\n对于实现 `FnMut` 特性的闭包，我们可以多次调用，且其可以改变其从环境捕获的值。我们可以说实现 `FnMut` 的闭包的执行具有副作用，或者说它是具有状态的。下例展示了一个闭包，它通过跟踪最小值，来找到一个迭代器中所有非升序的值：\n\n```rust\nfn main() {\n    let nums = vec![0, 4, 2, 8, 10, 7, 15, 18, 13];\n    let mut min = i32::MIN;\n    let ascending = nums.into_iter().filter(|&n| {\n        if n <= min {\n            false\n        } else {\n            min = n;\n            true\n        }\n    }).collect::<Vec<_>>();\n    assert_eq!(vec![0, 4, 8, 10, 15, 18], ascending); // ✅\n}\n```\n\n> `FnMut` refines `FnOnce` in the sense that `FnOnce` requires taking ownership of its arguments and can only be called once, but `FnMut` requires only taking mutable references and can be called multiple times. `FnMut` can be used anywhere `FnOnce` can be used.\n\n`FnMut` 改良了 `FnOnce` ，`FnOnce` 需要接管参数的属权因此只能调用一次，而 `FnMut` 只需要参数的可变引用即可并可调用多次。`FnMut` 可以在所有 `FnOnce` 可用的地方使用。\n\n> An `Fn` closure can be called multiple times and does not mutate any variables it has captured from its environment. We might say `Fn` closures have no side-effects or are stateless. Here's an example closure that filters out all values less than some stack variable it captures from its environment from an iterator:\n\n对于实现 `Fn ` 特性的闭包，我们可以调用多次，且其不改变任何从环境中捕获的变量。我们可以说实现 `Fn` 的闭包的执行不具有副作用，或者说它是不具有状态的。下例展示了一个闭包，它通过与栈上的值进行比较，过滤掉一个迭代器中所有比它小的值：\n\n```rust\nfn main() {\n    let nums = vec![0, 4, 2, 8, 10, 7, 15, 18, 13];\n    let min = 9;\n    let greater_than_9 = nums.into_iter().filter(|&n| n > min).collect::<Vec<_>>();\n    assert_eq!(vec![10, 15, 18, 13], greater_than_9); // ✅\n}\n```\n\n> `Fn` refines `FnMut` in the sense that `FnMut` requires mutable references and can be called multiple times, but `Fn` only requires immutable references and can be called multiple times. `Fn` can be used anywhere `FnMut` can be used, which includes anywhere `FnOnce` can be used.\n\n`Fn` 改良了 `FnMut` ，尽管它们都可以多次调用，但是 `FnMut` 需要参数的可变引用，而 `Fn` 仅需要参数的不可变引用。`Fn` 可以在所有 `FnMut` 和 `FnOnce` 可用的地方使用。\n\n> If a closure doesn't capture anything from its environment it's technically not a closure, but just an anonymously declared inline function, and can be casted to, used, and passed around as a regular function pointer, i.e. `fn`. Function pointers can be used anywhere `Fn` can be used, which includes anywhere `FnMut` and `FnOnce` can be used.\n\n如果一个闭包不从环境中捕获任何的值，那么从技术上讲它就不是闭包，而仅仅只是一个内联的匿名函数。并且它可以被转换为、用于或传递为一个常规函数指针，即 `fn`。函数指针可以用于任何 `Fn` ，`FnMut` ，`FnOnce` 可用的地方。\n\n```rust\nfn add_one(x: i32) -> i32 {\n    x + 1\n}\n\nfn main() {\n    let mut fn_ptr: fn(i32) -> i32 = add_one;\n    assert_eq!(fn_ptr(1), 2); // ✅\n    \n    // capture-less closure cast to fn pointer\n    // 不捕获环境的闭包可转换为普通函数指针\n    fn_ptr = |x| x + 1; // same as add_one\n    assert_eq!(fn_ptr(1), 2); // ✅\n}\n```\n\n> Example of passing a regular function pointer in place of a closure:\n\n以下示例中，将常规函数作为闭包而传入：\n\n```rust\nfn main() {\n    let nums = vec![-1, 1, -2, 2, -3, 3];\n    let absolutes: Vec<i32> = nums.into_iter().map(i32::abs).collect();\n    assert_eq!(vec![1, 1, 2, 2, 3, 3], absolutes); // ✅\n}\n```\n\n\n\n### 其它特性 Other Traits\n\n| 特性 | 类别 | 算符 | 描述 |\n|----------|----------|-------------|-------------|\n| `Deref` | 其它 | `*` | 不可变解引用 |\n| `DerefMut` | 其它 | `*` | 可变解引用 |\n| `Drop` | 其它 | - | 类型析构 |\n| `Index` | 其它 | `[]` | 不可变索引 |\n| `IndexMut` | 其它 | `[]` | 可变索引 |\n| `RangeBounds` | 其它 | `..` | 范围迭代 |\n\n\n\n#### Deref & DerefMut\n\n预备知识\n- [Self](#self)\n- [Methods](#methods)\n- [Associated Types](#associated-types)\n- [Subtraits & Supertraits](#subtraits--supertraits)\n- [Sized](#sized)\n\n```rust\ntrait Deref {\n    type Target: ?Sized;\n    fn deref(&self) -> &Self::Target;\n}\n\ntrait DerefMut: Deref {\n    fn deref_mut(&mut self) -> &mut Self::Target;\n}\n```\n\n> `Deref<Target = T>` types can dereferenced to `T` types using the dereference operator `*`. This has obvious use-cases for smart pointer types like `Box` and `Rc`. However, we rarely see the dereference operator explicitly used in Rust code, and that's because of a Rust feature called _deref coercion_.\n\n实现 `Deref<Target = T>` 的类型，可以通过 `*` 解引用算符，解引用到 `T` 类型。智能指针是该特性的著名实现者，例如 `Box` 和 `Rc` 。不过，我们很少在 Rust 编程中看到解引用算符，这是由于 Rust 的强制解引用的特性所导致的。\n\n> Rust automatically dereferences types when they're being passed as function arguments, returned from a function, or used as part of a method call. This is the reason why we can pass `&String` and `&Vec<T>` to functions expecting `&str` and `&[T]` because `String` impls `Deref<Target = str>` and `Vec<T>` impls `Deref<Target = [T]>`.\n\n当作为函数的参数、函数的返回值、方法的调用参数时，Rust 会自动地解引用。这就是为什么我们可以将 `&String` 或 `&Vec<T>` 类型的值作为参数传递给接受 `str` 或 `&[T]` 类型的参数的函数，因为 `String` 实现了 `Deref<Target = str>` ，`Vec<t>` 实现了 `Deref<Target = [T]>` 。\n\n> `Deref` and `DerefMut` should only be implemented for smart pointer types. The most common way people attempt to misuse and abuse these traits is to try to shoehorn some kind of OOP-style data inheritance into Rust. This does not work. Rust is not OOP. Let's examine a few different situations where, how, and why it does not work. Let's start with this example:\n\n`Deref` 和 `DerefMut` 仅应实现于智能指针类型。最常见的误用或滥用就是，人们经常希望强行把某种面向对象编程风格的数据继承塞到 Rust 编程中。这是不可能的，因为 Rust 不是面向对象的。让我们用一个例子来领会到底为什么这是不可以的：\n\n```rust\nuse std::ops::Deref;\n\nstruct Human {\n    health_points: u32,\n}\n\nenum Weapon {\n    Spear,\n    Axe,\n    Sword,\n}\n\n// a Soldier is just a Human with a Weapon\n// 士兵是手持武器的人类\nstruct Soldier {\n    human: Human,\n    weapon: Weapon,\n}\n\nimpl Deref for Soldier {\n    type Target = Human;\n    fn deref(&self) -> &Human {\n        &self.human\n    }\n}\n\nenum Mount {\n    Horse,\n    Donkey,\n    Cow,\n}\n\n// a Knight is just a Soldier with a Mount\n// 骑士是胯骑坐骑的士兵\nstruct Knight {\n    soldier: Soldier,\n    mount: Mount,\n}\n\nimpl Deref for Knight {\n    type Target = Soldier;\n    fn deref(&self) -> &Soldier {\n        &self.soldier\n    }\n}\n\nenum Spell {\n    MagicMissile,\n    FireBolt,\n    ThornWhip,\n}\n\n// a Mage is just a Human who can cast Spells\n// 法师是口诵咒语的人类\nstruct Mage {\n    human: Human,\n    spells: Vec<Spell>,\n}\n\nimpl Deref for Mage {\n    type Target = Human;\n    fn deref(&self) -> &Human {\n        &self.human\n    }\n}\n\nenum Staff {\n    Wooden,\n    Metallic,\n    Plastic,\n}\n\n// a Wizard is just a Mage with a Staff\n// 巫师是腰别法宝的法师\nstruct Wizard {\n    mage: Mage,\n    staff: Staff,\n}\n\nimpl Deref for Wizard {\n    type Target = Mage;\n    fn deref(&self) -> &Mage {\n        &self.mage\n    }\n}\n\nfn borrows_human(human: &Human) {}\nfn borrows_soldier(soldier: &Soldier) {}\nfn borrows_knight(knight: &Knight) {}\nfn borrows_mage(mage: &Mage) {}\nfn borrows_wizard(wizard: &Wizard) {}\n\nfn example(human: Human, soldier: Soldier, knight: Knight, mage: Mage, wizard: Wizard) {\n    // all types can be used as Humans\n    borrows_human(&human);\n    borrows_human(&soldier);\n    borrows_human(&knight);\n    borrows_human(&mage);\n    borrows_human(&wizard);\n    // Knights can be used as Soldiers\n    borrows_soldier(&soldier);\n    borrows_soldier(&knight);\n    // Wizards can be used as Mages\n    borrows_mage(&mage);\n    borrows_mage(&wizard);\n    // Knights & Wizards passed as themselves\n    borrows_knight(&knight);\n    borrows_wizard(&wizard);\n}\n```\n\n> So at first glance the above looks pretty good! However it quickly breaks down to scrutiny. First of all, deref coercion only works on references, so it doesn't work when we actually want to pass ownership:\n\n事实上，并不可以这么做。首先，强制解引用仅用于引用，所以我们不能移交属权：\n\n```rust\nfn takes_human(human: Human) {}\n\nfn example(human: Human, soldier: Soldier, knight: Knight, mage: Mage, wizard: Wizard) {\n    // all types CANNOT be used as Humans\n    takes_human(human);\n    takes_human(soldier); // ❌\n    takes_human(knight); // ❌\n    takes_human(mage); // ❌\n    takes_human(wizard); // ❌\n}\n```\n\n> Furthermore, deref coercion doesn't work in generic contexts. Let's say we impl some trait only on humans:\n\n其次，强制解引用不可用于泛型编程。例如某特性仅对人类实现：\n\n```rust\ntrait Rest {\n    fn rest(&self);\n}\n\nimpl Rest for Human {\n    fn rest(&self) {}\n}\n\nfn take_rest<T: Rest>(rester: &T) {\n    rester.rest()\n}\n\nfn example(human: Human, soldier: Soldier, knight: Knight, mage: Mage, wizard: Wizard) {\n    // all types CANNOT be used as Rest types, only Human\n    take_rest(&human);\n    take_rest(&soldier); // ❌\n    take_rest(&knight); // ❌\n    take_rest(&mage); // ❌\n    take_rest(&wizard); // ❌\n}\n```\n\n> Also, although deref coercion works in a lot of places it doesn't work everywhere. It doesn't work on operands, even though operators are just syntax sugar for method calls. Let's say, to be cute, we wanted `Mage`s to learn `Spell`s using the `+=` operator:\n\n强制解引用可以用于许多情况，但绝不是所有情况。例如对于算符的操作数而言就不行，即便算符仅是一种方法调用的语法糖。比如，我们希望使用 `+=` 算符来表达法师学习咒语。\n\n```rust\nimpl DerefMut for Wizard {\n    fn deref_mut(&mut self) -> &mut Mage {\n        &mut self.mage\n    }\n}\n\nimpl AddAssign<Spell> for Mage {\n    fn add_assign(&mut self, spell: Spell) {\n        self.spells.push(spell);\n    }\n}\n\nfn example(mut mage: Mage, mut wizard: Wizard, spell: Spell) {\n    mage += spell;\n    wizard += spell; // ❌ wizard not coerced to mage here\n                     // ❌ 在这里，巫师不能强制转换为法师\n    wizard.add_assign(spell); // oof, we have to call it like this 🤦\n                              // 所以，我们必须要这样做 🤦\n}\n```\n\n> In languages with OOP-style data inheritance the value of `self` within a method is always equal to the type which called the method but in the case of Rust the value of `self` is always equal to the type which implemented the method:\n\n在带有面向对象风格的数据继承的语言中，方法中的 `self` 值的类型总是等同于调用该方法的类型。但是在 Rust 语言中，`self` 值的类型总是等同于实现该方法时的类型。\n\n```rust\nstruct Human {\n    profession: &'static str,\n    health_points: u32,\n}\n\nimpl Human {\n    // self will always be a Human here, even if we call it on a Soldier\n    // 该方法中的 self 的类型永远是 Human ，即便我们在 Soldier 类型上调用\n    fn state_profession(&self) {\n        println!(\"I'm a {}!\", self.profession);\n    }\n}\n\nstruct Soldier {\n    profession: &'static str,\n    human: Human,\n    weapon: Weapon,\n}\n\nfn example(soldier: &Soldier) {\n    assert_eq!(\"servant\", soldier.human.profession);\n    assert_eq!(\"spearman\", soldier.profession);\n    soldier.human.state_profession(); // prints \"I'm a servant!\"\n    soldier.state_profession(); // still prints \"I'm a servant!\" 🤦\n}\n```\n\n> The above gotcha is especially damning when impling `Deref` or `DerefMut` on a newtype. Let's say we want to create a `SortedVec` type which is just a `Vec` but it's always in sorted order. Here's how we might do that:\n\n上述特性常令人感到困惑，特别是在对新类型实现 `Deref` 和 `DerefMut` 的时候。例如我们想要设计一个 `SortedVec` 类型，相比于 `Vec` 类型，它总是处于已排序的状态。我们可能会这样做：\n\n```rust\nstruct SortedVec<T: Ord>(Vec<T>);\n\nimpl<T: Ord> SortedVec<T> {\n    fn new(mut vec: Vec<T>) -> Self {\n        vec.sort();\n        SortedVec(vec)\n    }\n    fn push(&mut self, t: T) {\n        self.0.push(t);\n        self.0.sort();\n    }\n}\n```\n\n> Obviously we cannot impl `DerefMut<Target = Vec<T>>` here or anyone using `SortedVec` would be able to trivially break the sorted order. However, impling `Deref<Target = Vec<T>>` surely must be safe, right? Try to spot the bug in the program below:\n\n显然我们不能为其实现 `DerefMut<Target = Vec<T>>` ，因为这可能会破坏排序状态。实现 `Deref<Target = Vec<T>>` 必须要保证功能的正确性。尝试指出下列代码中的 bug ：\n\n```rust\nuse std::ops::Deref;\n\nstruct SortedVec<T: Ord>(Vec<T>);\n\nimpl<T: Ord> SortedVec<T> {\n    fn new(mut vec: Vec<T>) -> Self {\n        vec.sort();\n        SortedVec(vec)\n    }\n    fn push(&mut self, t: T) {\n        self.0.push(t);\n        self.0.sort();\n    }\n}\n\nimpl<T: Ord> Deref for SortedVec<T> {\n    type Target = Vec<T>;\n    fn deref(&self) -> &Vec<T> {\n        &self.0\n    }\n}\n\nfn main() {\n    let sorted = SortedVec::new(vec![2, 8, 6, 3]);\n    sorted.push(1);\n    let sortedClone = sorted.clone();\n    sortedClone.push(4);\n}\n```\n\n> We never implemented `Clone` for `SortedVec` so when we call the `.clone()` method the compiler is using deref coercion to resolve that method call on `Vec` and so it returns a `Vec` and not a `SortedVec`!\n\n鉴于我们从未对 `SortedVec` 实现 `Clone` 特性，所以当我们调用 `.clone()` 方法的时候，编译器会使用强制解引用将该方法调用解析为 `Vec` 的方法调用，所以该方法返回的是 `Vec` 而不是 `SortedVec` ！\n\n```rust\nfn main() {\n    let sorted: SortedVec<i32> = SortedVec::new(vec![2, 8, 6, 3]);\n    sorted.push(1); // still sorted\n\n    // calling clone on SortedVec actually returns a Vec 🤦\n    let sortedClone: Vec<i32> = sorted.clone();\n    sortedClone.push(4); // sortedClone no longer sorted 💀\n}\n```\n\n> Anyway, none of the above limitations, constraints, or gotchas are faults of Rust because Rust was never designed to be an OO language or to support any OOP patterns in the first place.\n\n切记，Rust 并非设计为面向对象的语言，也并不将面向对象编程的模式作为一等公民，所以以上的限制、约束和令人困惑的特性并不被认为是在语言中是错误的。\n\n> The main takeaway from this section is do not try to be cute or clever with `Deref` and `DerefMut` impls. They're really only appropriate for smart pointer types, which can only be implemented within the standard library for now as smart pointer types currently require unstable features and compiler magic to work. If we want functionality and behavior similar to `Deref` and `DerefMut` then what we're actually probably looking for is `AsRef` and `AsMut` which we'll get to later.\n\n本节的主旨即是使读者领会为什么不要自作聪明地实现 `Deref` 和 `DerefMut` 特性。这类特性确仅适合于智能指针类的类型，目前来讲标准库中的智能指针的实现，确需要这样的不稳定特性以及一些编译器魔法才能工作。如果我们确需要一些类似于`Deref` 和 `DerefMut` 的特性，不妨使用 `AsRef` 和 `AsMut` 特性。我们将在后面的章节中对这类特性做出说明。\n\n\n\n#### Index & IndexMut\n\n预备知识\n- [Self](#self)\n- [Methods](#methods)\n- [Associated Types](#associated-types)\n- [Generic Parameters](#generic-parameters)\n- [Generic Types vs Associated Types](#generic-types-vs-associated-types)\n- [Subtraits & Supertraits](#subtraits--supertraits)\n- [Sized](#sized)\n\n```rust\ntrait Index<Idx: ?Sized> {\n    type Output: ?Sized;\n    fn index(&self, index: Idx) -> &Self::Output;\n}\n\ntrait IndexMut<Idx>: Index<Idx> where Idx: ?Sized {\n    fn index_mut(&mut self, index: Idx) -> &mut Self::Output;\n}\n```\n\n> We can index `[]` into `Index<T, Output = U>` types with `T` values and the index operation will return `&U` values. For syntax sugar, the compiler auto inserts a deref operator `*` in front of any value returned from an index operation:\n\n对于实现 `Index<T, Output = U>` 的类型，我们可以使用 `[]` 索引算符对 `T` 类型的值索引 `&U` 类型的值。作为语法糖，编译器也会为索引操作返回的值自动添加一个 `*` 解引用算符。\n\n```rust\nfn main() {\n    // Vec<i32> impls Index<usize, Output = i32> so\n    // indexing Vec<i32> should produce &i32s and yet...\n    // 鉴于 Vec<i32> 实现了 Index<usize, Output = i32>\n    // 所以对 Vec<i32> 的索引应当返回 &i32 类型的值，但是。。。\n    let vec = vec![1, 2, 3, 4, 5];\n    let num_ref: &i32 = vec[0]; // ❌ expected &i32 found i32\n    \n    // above line actually desugars to\n    // 以上代码等价于\n    let num_ref: &i32 = *vec[0]; // ❌ expected &i32 found i32\n\n    // both of these alternatives work\n    // 以下是建议使用的一对形式\n    let num: i32 = vec[0]; // ✅\n    let num_ref: &i32 = &vec[0]; // ✅\n}\n```\n\n> It's kinda confusing at first, because it seems like the `Index` trait does not follow its own method signature, but really it's just questionable syntax sugar.\n\n令人困惑的是，似乎 `Index` 特性没有遵循它自己的方法签名，但其实真正有问题的是语法糖。\n\n> Since `Idx` is a generic type the `Index` trait can be implemented many times for a given type, and in the case of `Vec<T>` not only can we index into it using `usize` but we can also index into its using `Range<usize>`s to get slices.\n\n鉴于 `Idx` 是泛型类型，`Index` 特性对多个给定类型可以多次实现。并且对于 `Vec<T>` ，我们不仅可以对 `usize` 索引，还可以对 `Range<usize>` 索引得到切片。\n\n```rust\nfn main() {\n    let vec = vec![1, 2, 3, 4, 5];\n    assert_eq!(&vec[..], &[1, 2, 3, 4, 5]); // ✅\n    assert_eq!(&vec[1..], &[2, 3, 4, 5]); // ✅\n    assert_eq!(&vec[..4], &[1, 2, 3, 4]); // ✅\n    assert_eq!(&vec[1..4], &[2, 3, 4]); // ✅\n}\n```\n\n> To show off how we might impl `Index` ourselves here's a fun example which shows how we can use a newtype and the `Index` trait to impl wrapping indexes and negative indexes on a `Vec`:\n\n为了展示如何自己实现 `Index` 特性，以下是一个有趣的例子，它设计了一个 `Vec` 的包装结构，其使得循环索引和负数索引成为可能：\n\n```rust\nuse std::ops::Index;\n\nstruct WrappingIndex<T>(Vec<T>);\n\nimpl<T> Index<usize> for WrappingIndex<T> {\n    type Output = T;\n    fn index(&self, index: usize) -> &T {\n        &self.0[index % self.0.len()]\n    }\n}\n\nimpl<T> Index<i128> for WrappingIndex<T> {\n    type Output = T;\n    fn index(&self, index: i128) -> &T {\n        let self_len = self.0.len() as i128;\n        let idx = (((index % self_len) + self_len) % self_len) as usize;\n        &self.0[idx]\n    }\n}\n\n#[test] // ✅\nfn indexes() {\n    let wrapping_vec = WrappingIndex(vec![1, 2, 3]);\n    assert_eq!(1, wrapping_vec[0_usize]);\n    assert_eq!(2, wrapping_vec[1_usize]);\n    assert_eq!(3, wrapping_vec[2_usize]);\n}\n\n#[test] // ✅\nfn wrapping_indexes() {\n    let wrapping_vec = WrappingIndex(vec![1, 2, 3]);\n    assert_eq!(1, wrapping_vec[3_usize]);\n    assert_eq!(2, wrapping_vec[4_usize]);\n    assert_eq!(3, wrapping_vec[5_usize]);\n}\n\n#[test] // ✅\nfn neg_indexes() {\n    let wrapping_vec = WrappingIndex(vec![1, 2, 3]);\n    assert_eq!(1, wrapping_vec[-3_i128]);\n    assert_eq!(2, wrapping_vec[-2_i128]);\n    assert_eq!(3, wrapping_vec[-1_i128]);\n}\n\n#[test] // ✅\nfn wrapping_neg_indexes() {\n    let wrapping_vec = WrappingIndex(vec![1, 2, 3]);\n    assert_eq!(1, wrapping_vec[-6_i128]);\n    assert_eq!(2, wrapping_vec[-5_i128]);\n    assert_eq!(3, wrapping_vec[-4_i128]);\n}\n```\n\n> There's no requirement that the `Idx` type has to be a number type or a `Range`, it could be an enum! Here's an example using basketball positions to index into a basketball team to retrieve players on the team:\n\n`Idx` 的类型并不非得是数字类型或 `Range` 类型，甚至还可以是枚举！例如我们可以在一支篮球队中，对打什么位置索引从而得到队伍里打这个位置的队员：\n\n```rust\nuse std::ops::Index;\n\nenum BasketballPosition {\n    PointGuard,\n    ShootingGuard,\n    Center,\n    PowerForward,\n    SmallForward,\n}\n\nstruct BasketballPlayer {\n    name: &'static str,\n    position: BasketballPosition,\n}\n\nstruct BasketballTeam {\n    point_guard: BasketballPlayer,\n    shooting_guard: BasketballPlayer,\n    center: BasketballPlayer,\n    power_forward: BasketballPlayer,\n    small_forward: BasketballPlayer,\n}\n\nimpl Index<BasketballPosition> for BasketballTeam {\n    type Output = BasketballPlayer;\n    fn index(&self, position: BasketballPosition) -> &BasketballPlayer {\n        match position {\n            BasketballPosition::PointGuard => &self.point_guard,\n            BasketballPosition::ShootingGuard => &self.shooting_guard,\n            BasketballPosition::Center => &self.center,\n            BasketballPosition::PowerForward => &self.power_forward,\n            BasketballPosition::SmallForward => &self.small_forward,\n        }\n    }\n}\n```\n\n\n\n#### Drop\n\n预备知识\n- [Self](#self)\n- [Methods](#methods)\n\n```rust\ntrait Drop {\n    fn drop(&mut self);\n}\n```\n\n> If a type impls `Drop` then `drop` will be called on the type when it goes out of scope but before it's destroyed. We will rarely need to impl this for our types but a good example of where it's useful is if a type holds on to some external resources which needs to be cleaned up when the type is destroyed.\n\n对于实现 `Drop` 特性的类型，在该类型脱离作用域并销毁前，其 `drop` 方法会被调用。通常，不必为我们的类型实现这一特性，除非该类型持有某种外部的资源，且该资源需要显式释放。\n\n> There's a `BufWriter` type in the standard library that allows us to buffer writes to `Write` types. However, what if the `BufWriter` gets destroyed before the content in its buffer has been flushed to the underlying `Write` type? Thankfully that's not possible! The `BufWriter` impls the `Drop` trait so that `flush` is always called on it whenever it goes out of scope!\n\n标准库中的 `BufWriter` 类型允许我们对向 `Write` 类型写入的时候进行缓存。显然，当 `BufWriter` 销毁前应当把缓存的内容写入 `Writer` 实例，这就是 `Drop` 所允许我们做到的！对于实现了 `Drop` 的 `BufWriter` 来说，其实例在销毁前会总会调用 `flush` 方法。\n\n```rust\nimpl<W: Write> Drop for BufWriter<W> {\n    fn drop(&mut self) {\n        self.flush_buf();\n    }\n}\n```\n\n> Also, `Mutex`s in Rust don't have `unlock()` methods because they don't need them! Calling `lock()` on a `Mutex` returns a `MutexGuard` which automatically unlocks the `Mutex` when it goes out of scope thanks to its `Drop` impl:\n\n并且，在 Rust 中 `Mutex` 类型之所以没有 `unlock()` 方法，就是因为它完全不需要！鉴于 `Drop` 特性的实现，调用 `Mutex` 的 `lock()` 方法返回的 `MutexGuard` 类型，在脱离作用域时会自动地释放 `Mutex` 。\n\n```rust\nimpl<T: ?Sized> Drop for MutexGuard<'_, T> {\n    fn drop(&mut self) {\n        unsafe {\n            self.lock.inner.raw_unlock();\n        }\n    }\n}\n```\n\n> In general, if you're impling an abstraction over some resource that needs to be cleaned up after use then that's a great reason to make use of the `Drop` trait.\n\n简而言之，如果你正在设计某种需要显示释放的资源的抽象包装，那么这正是 `Drop` 特性大显神威的地方。\n\n\n\n## 转换特性 Conversion Traits\n\n\n\n### From & Into\n\n预备知识\n- [Self](#self)\n- [Functions](#functions)\n- [Methods](#methods)\n- [Generic Parameters](#generic-parameters)\n- [Generic Blanket Impls](#generic-blanket-impls)\n\n```rust\ntrait From<T> {\n    fn from(T) -> Self;\n}\n```\n\n> `From<T>` types allow us to convert `T` into `Self`.\n\n实现 `From<T>` 特性的类型允许我们从 `T` 类型转换到自身的类型 `Self` 。\n\n```rust\ntrait Into<T> {\n    fn into(self) -> T;\n}\n```\n\n> `Into<T>` types allow us to convert `Self` into `T`.\n\n实现 `Into<T>` 特性的类型允许我们从自身的类型 `Self` 转换到 `T` 类型。\n\n> These traits are two different sides of the same coin. We can only impl `From<T>` for our types because the `Into<T>` impl is automatically provided by this generic blanket impl:\n\n这是一对恰好相反的特性，如同一枚硬币的两面。注意，我们只能手动实现 `From<T>` 特性，而不能手动实现 `Into<T>` 特性，因为 `Into<T>` 特性已经被一揽子泛型实现所自动实现。\n\n```rust\nimpl<T, U> Into<U> for T\nwhere\n    U: From<T>,\n{\n    fn into(self) -> U {\n        U::from(self)\n    }\n}\n```\n\n> The reason both traits exist is because it allows us to write trait bounds on generic types slightly differently:\n\n这两个特性同时存在的一个好处在于，我们可以在为泛型类型添加约束的时候，使用两种稍有不同的记号：\n\n```rust\nfn function<T>(t: T)\nwhere\n    // these bounds are equivalent\n    // 以下两种记号等价\n    T: From<i32>,\n    i32: Into<T>\n{\n    // these examples are equivalent\n    // 以下两种记号等价\n    let example: T = T::from(0);\n    let example: T = 0.into();\n}\n```\n\n> There are no hard rules about when to use one or the other, so go with whatever makes the most sense for each situation. Now let's look at some example impls on `Point`:\n\n对于具体使用哪种记号并无一定之规，请根据实际情况做出最恰当的选择。接下来我们看看 `Point` 类型的例子：\n\n```rust\nstruct Point {\n    x: i32,\n    y: i32,\n}\n\nimpl From<(i32, i32)> for Point {\n    fn from((x, y): (i32, i32)) -> Self {\n        Point { x, y }\n    }\n}\n\nimpl From<[i32; 2]> for Point {\n    fn from([x, y]: [i32; 2]) -> Self {\n        Point { x, y }\n    }\n}\n\nfn example() {\n    // using From\n    let origin = Point::from((0, 0));\n    let origin = Point::from([0, 0]);\n\n    // using Into\n    let origin: Point = (0, 0).into();\n    let origin: Point = [0, 0].into();\n}\n```\n\n> The impl is not symmetric, so if we'd like to convert `Point`s into tuples and arrays we have to explicitly add those as well:\n\n这样的转换并不是对称的，如果我们想将 `Point` 转换为元组或数组，那么我们需要显式地编写相应的代码：\n\n```rust\nstruct Point {\n    x: i32,\n    y: i32,\n}\n\nimpl From<(i32, i32)> for Point {\n    fn from((x, y): (i32, i32)) -> Self {\n        Point { x, y }\n    }\n}\n\nimpl From<Point> for (i32, i32) {\n    fn from(Point { x, y }: Point) -> Self {\n        (x, y)\n    }\n}\n\nimpl From<[i32; 2]> for Point {\n    fn from([x, y]: [i32; 2]) -> Self {\n        Point { x, y }\n    }\n}\n\nimpl From<Point> for [i32; 2] {\n    fn from(Point { x, y }: Point) -> Self {\n        [x, y]\n    }\n}\n\nfn example() {\n    // from (i32, i32) into Point\n    let point = Point::from((0, 0));\n    let point: Point = (0, 0).into();\n\n    // from Point into (i32, i32)\n    let tuple = <(i32, i32)>::from(point);\n    let tuple: (i32, i32) = point.into();\n\n    // from [i32; 2] into Point\n    let point = Point::from([0, 0]);\n    let point: Point = [0, 0].into();\n\n    // from Point into [i32; 2]\n    let array = <[i32; 2]>::from(point);\n    let array: [i32; 2] = point.into();\n}\n```\n\n> A popular use of `From<T>` is to trim down boilerplate code. Let's say we add a `Triangle` type to our program which contains three `Point`s, here's some of the many ways we can construct it:\n\n借由 `From<T>` 特性，我们可以省却大量编写模板代码的麻烦。例如，我们现在具有一个包含三个 `Point` 的类型 `Triangle` 类型，以下是构造该类型的几种办法：\n\n```rust\nstruct Point {\n    x: i32,\n    y: i32,\n}\n\nimpl Point {\n    fn new(x: i32, y: i32) -> Point {\n        Point { x, y }\n    }\n}\n\nimpl From<(i32, i32)> for Point {\n    fn from((x, y): (i32, i32)) -> Point {\n        Point { x, y }\n    }\n}\n\nstruct Triangle {\n    p1: Point,\n    p2: Point,\n    p3: Point,\n}\n\nimpl Triangle {\n    fn new(p1: Point, p2: Point, p3: Point) -> Triangle {\n        Triangle { p1, p2, p3 }\n    }\n}\n\nimpl<P> From<[P; 3]> for Triangle\nwhere\n    P: Into<Point>\n{\n    fn from([p1, p2, p3]: [P; 3]) -> Triangle {\n        Triangle {\n            p1: p1.into(),\n            p2: p2.into(),\n            p3: p3.into(),\n        }\n    }\n}\n\nfn example() {\n    // manual construction\n    let triangle = Triangle {\n        p1: Point {\n            x: 0,\n            y: 0,\n        },\n        p2: Point {\n            x: 1,\n            y: 1,\n        },\n        p3: Point {\n            x: 2,\n            y: 2,\n        },\n    };\n\n    // using Point::new\n    let triangle = Triangle {\n        p1: Point::new(0, 0),\n        p2: Point::new(1, 1),\n        p3: Point::new(2, 2),\n    };\n\n    // using From<(i32, i32)> for Point\n    let triangle = Triangle {\n        p1: (0, 0).into(),\n        p2: (1, 1).into(),\n        p3: (2, 2).into(),\n    };\n\n    // using Triangle::new + From<(i32, i32)> for Point\n    let triangle = Triangle::new(\n        (0, 0).into(),\n        (1, 1).into(),\n        (2, 2).into(),\n    );\n\n    // using From<[Into<Point>; 3]> for Triangle\n    let triangle: Triangle = [\n        (0, 0),\n        (1, 1),\n        (2, 2),\n    ].into();\n}\n```\n\n> There are no rules for when, how, or why we should impl `From<T>` for our types so it's up to us to use our best judgement for every situation.\n\n对于 `From<T>` 特性的使用并无一定之规，运用你的智慧明智地使用它吧！\n\n> One popular use of `Into<T>` is to make functions which need owned values generic over whether they take owned or borrowed values:\n\n使用 `Into<T>` 特性的一个神奇之处在于，对于那些本来只能接受特定类型参数的函数，现在你可以有更多不同的选择：\n\n```rust\nstruct Person {\n    name: String,\n}\n\nimpl Person {\n    // accepts:\n    // - String\n    fn new1(name: String) -> Person {\n        Person { name }\n    }\n\n    // accepts:\n    // - String\n    // - &String\n    // - &str\n    // - Box<str>\n    // - Cow<'_, str>\n    // - char\n    // since all of the above types can be converted into String\n    fn new2<N: Into<String>>(name: N) -> Person {\n        Person { name: name.into() }\n    }\n}\n```\n\n\n\n## 错误处理 Error Handling\n\n> The best time to talk about error handling and the `Error` trait is after going over `Display`, `Debug`, `Any`, and `From` but before getting to `TryFrom` hence why the **Error Handling** section awkwardly bisects the **Conversion Traits** section.\n\n讲解错误处理与 `Error` 特性的最佳时机，莫过于在 `Display` ， `Debug` ， `Any` 和 `From` 之后， `TryFrom` 之前，这就是为什么我要将 **错误处理** 这一节硬塞在 **转换特性** 这一章里。\n\n### Error\n\n预备知识\n- [Self](#self)\n- [Methods](#methods)\n- [Default Impls](#default-impls)\n- [Generic Blanket Impls](#generic-blanket-impls)\n- [Subtraits & Supertraits](#subtraits--supertraits)\n- [Trait Objects](#trait-objects)\n- [Display & ToString](#display--tostring)\n- [Debug](#debug)\n- [Any](#any)\n- [From & Into](#from--into)\n\n```rust\ntrait Error: Debug + Display {\n    // provided default impls\n    // 提供默认实现\n    fn source(&self) -> Option<&(dyn Error + 'static)>;\n    fn backtrace(&self) -> Option<&Backtrace>;\n    fn description(&self) -> &str;\n    fn cause(&self) -> Option<&dyn Error>;\n}\n```\n\n> In Rust errors are returned, not thrown. Let's look at some examples.\n\n在 Rust 中，错误是被返回的，而不是被抛出的。让我们看看下面的例子：\n\n> Since dividing integer types by zero panics if we wanted to make our program safer and more explicit we could impl a `safe_div` function which returns a `Result` instead like this:\n\n由于整数的除零操作会导致 panic ，为了程序的健壮性，我们显式地实现了安全的 `safe_div` 除法函数，它的返回值是 `Result` ：\n\n```rust\nuse std::fmt;\nuse std::error;\n\n#[derive(Debug, PartialEq)]\nstruct DivByZero;\n\nimpl fmt::Display for DivByZero {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        write!(f, \"division by zero error\")\n    }\n}\n\nimpl error::Error for DivByZero {}\n\nfn safe_div(numerator: i32, denominator: i32) -> Result<i32, DivByZero> {\n    if denominator == 0 {\n        return Err(DivByZero);\n    }\n    Ok(numerator / denominator)\n}\n\n#[test] // ✅\nfn test_safe_div() {\n    assert_eq!(safe_div(8, 2), Ok(4));\n    assert_eq!(safe_div(5, 0), Err(DivByZero));\n}\n```\n\n> Since errors are returned and not thrown they must be explicitly handled, and if the current function cannot handle an error it should propagate it up to the caller. The most idiomatic way to propagate errors is to use the `?` operator, which is just syntax sugar for the now deprecated `try!` macro which simply does this:\n\n由于错误是被返回的，而不是被抛出的，它们必须被显式地处理。如果当前函数没有处理该错误的能力，那么该错误应当原路返回到上一级调用函数。最慣用的返回错误的方法是使用 `?` 算符，它是现在已经过时的 `try!` 宏的语法糖：\n\n```rust\nmacro_rules! try {\n    ($expr:expr) => {\n        match $expr {\n            // if Ok just unwrap the value\n            // 正常情况下直接解除 Result 的包装\n            Ok(val) => val,\n            // if Err map the err value using From and return\n            // 否则将该错误进行适当转换后，返回到上级调用函数\n            Err(err) => {\n                return Err(From::from(err));\n            }\n        }\n    };\n}\n```\n\n> If we wanted to write a function which reads a file into a `String` we could write it like this, propagating the `io::Error`s using `?` everywhere they can appear:\n\n例如，如果我们的函数其功能是将文件读为一个 `String` ，那么使用 `?` 算符来将可能的错误 `io::Error` 返回给上级调用函数就很方便：\n\n```rust\nuse std::io::Read;\nuse std::path::Path;\nuse std::io;\nuse std::fs::File;\n\nfn read_file_to_string(path: &Path) -> Result<String, io::Error> {\n    let mut file = File::open(path)?; // ⬆️ io::Error\n    let mut contents = String::new();\n    file.read_to_string(&mut contents)?; // ⬆️ io::Error\n    Ok(contents)\n}\n```\n\n> But let's say the file we're reading is actually a list of numbers and we want to sum them together, we'd update our function like this:\n\n又例如，如果我们的文件是一系列数字，我们想将它们加在一起，可以这样编写代码：\n\n```rust\nuse std::io::Read;\nuse std::path::Path;\nuse std::io;\nuse std::fs::File;\n\nfn sum_file(path: &Path) -> Result<i32, /* What to put here? */> {\n                                        // 这里填写什么类型好呢？\n    let mut file = File::open(path)?; // ⬆️ io::Error\n    let mut contents = String::new();\n    file.read_to_string(&mut contents)?; // ⬆️ io::Error\n    let mut sum = 0;\n    for line in contents.lines() {\n        sum += line.parse::<i32>()?; // ⬆️ ParseIntError\n    }\n    Ok(sum)\n}\n```\n\n> But what's the error type of our `Result` now? It can return either an `io::Error` or a `ParseIntError`. We're going to look at three approaches for solving this problem, starting with the most quick & dirty way and finishing with the most robust way.\n\n现在 `Rusult` 的类型又如何？该函数内部可能产生 `io::Error` 或 `ParseIntError` 两种错误。我们将介绍三种解决此类问题的方法，从最简单但不优雅的方法，到最健壮的方法：\n\n> The first approach is recognizing that all types which impl `Error` also impl `Display` so we can map all the errors to `String`s and use `String` as our error type:\n\n方法一，我们注意到，所有实现了 `Error` 的类型同时也实现了 `Display` ，因此我们可以将错误映射到 `String` 并以此为错误类型：\n\n```rust\nuse std::fs::File;\nuse std::io;\nuse std::io::Read;\nuse std::path::Path;\n\nfn sum_file(path: &Path) -> Result<i32, String> {\n    let mut file = File::open(path)\n        .map_err(|e| e.to_string())?; // ⬆️ io::Error -> String\n    let mut contents = String::new();\n    file.read_to_string(&mut contents)\n        .map_err(|e| e.to_string())?; // ⬆️ io::Error -> String\n    let mut sum = 0;\n    for line in contents.lines() {\n        sum += line.parse::<i32>()\n            .map_err(|e| e.to_string())?; // ⬆️ ParseIntError -> String\n    }\n    Ok(sum)\n}\n```\n\n> The obvious downside of stringifying every error is that we throw away type information which makes it harder for the caller to handle the errors.\n\n此方法的明显缺点在于，由于我们将所有的错误都序列化了，以至于丢弃了该错误的类型信息，这对于上级调用函数错误处理来讲，就不是那么方便了。\n\n> One nonobvious upside to the above approach is we can customize the strings to provide more context-specific information. For example, `ParseIntError` usually stringifies to `\"invalid digit found in string\"` which is very vague and doesn't mention what the invalid string is or what integer type it was trying to parse into. If we were debugging this problem that error message would almost be useless. However we can make it significantly better by providing all the context relevant information ourselves:\n\n但此方法也有一个不明显的优点，那就是我们可以使用自定义的字符串，来提供丰富的上下文错误信息。例如，`ParseIntError` 通常序列化为 `\"invalid digit found in string\"` 这样模棱两可的文本，既没有提及无效的字符串是什么，也没有提及它要转换到什么样的数字类型。这样的信息对于我们调试程序来讲几乎没有什么帮助。不过我们可以提供更有意义的，且上下文相关的信息来明显改善这一点：\n\n```rust\nsum += line.parse::<i32>()\n    .map_err(|_| format!(\"failed to parse {} into i32\", line))?;\n```\n\n> The second approach takes advantage of this generic blanket impl from the standard library:\n\n方法二，利用标准库的一揽子泛型实现：\n\n```rust\nimpl<E: error::Error> From<E> for Box<dyn error::Error>;\n```\n\n> Which means that any `Error` type can be implicitly converted into a `Box<dyn error::Error>` by the `?` operator, so we can set to error type to `Box<dyn error::Error>` in the `Result` return type of any function which produces errors and the `?` operator will do the rest of the work for us:\n\n所有实现了 `Error` 特性的类型都可以隐式地使用 `?` 转换为 `Box<dyn error::Error>` 类型。所以我们可以将 `Rusult` 的错误类型设为 `Box<dyn error::Error>` 类型，然后 `?` 算符会帮我们实现这一隐式转换。\n\n```rust\nuse std::fs::File;\nuse std::io::Read;\nuse std::path::Path;\nuse std::error;\n\nfn sum_file(path: &Path) -> Result<i32, Box<dyn error::Error>> {\n    let mut file = File::open(path)?; // ⬆️ io::Error -> Box<dyn error::Error>\n    let mut contents = String::new();\n    file.read_to_string(&mut contents)?; // ⬆️ io::Error -> Box<dyn error::Error>\n    let mut sum = 0;\n    for line in contents.lines() {\n        sum += line.parse::<i32>()?; // ⬆️ ParseIntError -> Box<dyn error::Error>\n    }\n    Ok(sum)\n}\n```\n\n> While being more concise, this seems to suffer from the same downside of the previous approach by throwing away type information. This is mostly true, but if the caller is aware of the impl details of our function they can still handle the different errors types using the `downcast_ref()` method on `error::Error` which works the same as it does on `dyn Any` types:\n\n这看起来似乎有与第一种方法一样的缺点，丢弃了错误的类型信息。有时确实如此，但倘若上级调用函数知悉该函数的实现细节，那么它仍然可以通过 `error::Error` 特性的 `downcast_ref()` 方法来分辨错误的具体类型，这与实现了 `dyn Any` 特性的类型是一样的：\n\n```rust\nfn handle_sum_file_errors(path: &Path) {\n    match sum_file(path) {\n        Ok(sum) => println!(\"the sum is {}\", sum),\n        Err(err) => {\n            if let Some(e) = err.downcast_ref::<io::Error>() {\n                // handle io::Error\n            } else if let Some(e) = err.downcast_ref::<ParseIntError>() {\n                // handle ParseIntError\n            } else {\n                // we know sum_file can only return one of the\n                // above errors so this branch is unreachable\n                // 由于我们知道该函数只能返回以上两种错误，\n                // 所以这一选择肢一般是不可能执行的\n                unreachable!();\n            }\n        }\n    }\n}\n```\n\n> The third approach, which is the most robust and type-safe way to aggregate these different errors would be to build our own custom error type using an enum:\n\n方法三，处理错误的最健壮和类型安全的方法，是通过枚举来构建我们自己的错误类型：\n\n```rust\nuse std::num::ParseIntError;\nuse std::fs::File;\nuse std::io;\nuse std::io::Read;\nuse std::path::Path;\nuse std::error;\nuse std::fmt;\n\n#[derive(Debug)]\nenum SumFileError {\n    Io(io::Error),\n    Parse(ParseIntError),\n}\n\nimpl From<io::Error> for SumFileError {\n    fn from(err: io::Error) -> Self {\n        SumFileError::Io(err)\n    }\n}\n\nimpl From<ParseIntError> for SumFileError {\n    fn from(err: ParseIntError) -> Self {\n        SumFileError::Parse(err)\n    }\n}\n\nimpl fmt::Display for SumFileError {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        match self {\n            SumFileError::Io(err) => write!(f, \"sum file error: {}\", err),\n            SumFileError::Parse(err) => write!(f, \"sum file error: {}\", err),\n        }\n    }\n}\n\nimpl error::Error for SumFileError {\n    // the default impl for this method always returns None\n    // but we can now override it to make it way more useful!\n    // 在默认实现中，该方法总是返回 None ，现在重写它！\n    fn source(&self) -> Option<&(dyn error::Error + 'static)> {\n        Some(match self {\n            SumFileError::Io(err) => err,\n            SumFileError::Parse(err) => err,\n        })\n    }\n}\n\nfn sum_file(path: &Path) -> Result<i32, SumFileError> {\n    let mut file = File::open(path)?; // ⬆️ io::Error -> SumFileError\n    let mut contents = String::new();\n    file.read_to_string(&mut contents)?; // ⬆️ io::Error -> SumFileError\n    let mut sum = 0;\n    for line in contents.lines() {\n        sum += line.parse::<i32>()?; // ⬆️ ParseIntError -> SumFileError\n    }\n    Ok(sum)\n}\n\nfn handle_sum_file_errors(path: &Path) {\n    match sum_file(path) {\n        Ok(sum) => println!(\"the sum is {}\", sum),\n        Err(SumFileError::Io(err)) => {\n            // handle io::Error\n        },\n        Err(SumFileError::Parse(err)) => {\n            // handle ParseIntError\n        },\n    }\n}\n```\n\n\n\n## 转换特性深入 Conversion Traits Continued\n\n\n\n### TryFrom & TryInto\n\n预备知识\n- [Self](#self)\n- [Functions](#functions)\n- [Methods](#methods)\n- [Associated Types](#associated-types)\n- [Generic Parameters](#generic-parameters)\n- [Generic Types vs Associated Types](#generic-types-vs-associated-types)\n- [Generic Blanket Impls](#generic-blanket-impls)\n- [From & Into](#from--into)\n- [Error](#error)\n\n> `TryFrom` and `TryInto` are the fallible versions of `From` and `Into`.\n\n`TryFrom` 和 `TryInto` 是可能失败版本的 `From` 和 `Into` 。\n\n```rust\ntrait TryFrom<T> {\n    type Error;\n    fn try_from(value: T) -> Result<Self, Self::Error>;\n}\n\ntrait TryInto<T> {\n    type Error;\n    fn try_into(self) -> Result<T, Self::Error>;\n}\n```\n\n> Similarly to `Into` we cannot impl `TryInto` because its impl is provided by this generic blanket impl:\n\n与 `Into` 相似地，我们不能手动实现 `TryInto` ，因为它已经为一揽子泛型实现所提供。\n\n```rust\nimpl<T, U> TryInto<U> for T\nwhere\n    U: TryFrom<T>,\n{\n    type Error = U::Error;\n\n    fn try_into(self) -> Result<U, U::Error> {\n        U::try_from(self)\n    }\n}\n```\n\n> Let's say that in the context of our program it doesn't make sense for `Point`s to have `x` and `y` values that are less than `-1000` or greater than `1000`. This is how we'd rewrite our earlier `From` impls using `TryFrom` to signal to the users of our type that this conversion can now fail:\n\n例如，我们的程序要求 `Point` 的 `x` 和 `y` 的值必须要处于 `-1000` 到 `1000` 之间，相较于 `From` ，使用 `TryFrom` 可以告知上级调用者，某些转换可能失败了。\n\n```rust\nuse std::convert::TryFrom;\nuse std::error;\nuse std::fmt;\n\nstruct Point {\n    x: i32,\n    y: i32,\n}\n\n#[derive(Debug)]\nstruct OutOfBounds;\n\nimpl fmt::Display for OutOfBounds {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        write!(f, \"out of bounds\")\n    }\n}\n\nimpl error::Error for OutOfBounds {}\n\n// now fallible\n// TryFrom 的转换允许失败\nimpl TryFrom<(i32, i32)> for Point {\n    type Error = OutOfBounds;\n    fn try_from((x, y): (i32, i32)) -> Result<Point, OutOfBounds> {\n        if x.abs() > 1000 || y.abs() > 1000 {\n            return Err(OutOfBounds);\n        }\n        Ok(Point { x, y })\n    }\n}\n\n// still infallible\n// From 的转换不允许失败\nimpl From<Point> for (i32, i32) {\n    fn from(Point { x, y }: Point) -> Self {\n        (x, y)\n    }\n}\n```\n\n> And here's the refactored `TryFrom<[TryInto<Point>; 3]>` impl for `Triangle`:\n\n现在，我们对 `Triangle` 使用 `TryFrom<[TryInto<Point>; 3]>` 进行重构：\n\n```rust\nuse std::convert::{TryFrom, TryInto};\nuse std::error;\nuse std::fmt;\n\nstruct Point {\n    x: i32,\n    y: i32,\n}\n\n#[derive(Debug)]\nstruct OutOfBounds;\n\nimpl fmt::Display for OutOfBounds {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        write!(f, \"out of bounds\")\n    }\n}\n\nimpl error::Error for OutOfBounds {}\n\nimpl TryFrom<(i32, i32)> for Point {\n    type Error = OutOfBounds;\n    fn try_from((x, y): (i32, i32)) -> Result<Self, Self::Error> {\n        if x.abs() > 1000 || y.abs() > 1000 {\n            return Err(OutOfBounds);\n        }\n        Ok(Point { x, y })\n    }\n}\n\nstruct Triangle {\n    p1: Point,\n    p2: Point,\n    p3: Point,\n}\n\nimpl<P> TryFrom<[P; 3]> for Triangle\nwhere\n    P: TryInto<Point>,\n{\n    type Error = P::Error;\n    fn try_from([p1, p2, p3]: [P; 3]) -> Result<Self, Self::Error> {\n        Ok(Triangle {\n            p1: p1.try_into()?,\n            p2: p2.try_into()?,\n            p3: p3.try_into()?,\n        })\n    }\n}\n\nfn example() -> Result<Triangle, OutOfBounds> {\n    let t: Triangle = [(0, 0), (1, 1), (2, 2)].try_into()?;\n    Ok(t)\n}\n```\n\n\n\n### FromStr\n\n预备知识\n- [Self](#self)\n- [Functions](#functions)\n- [Associated Types](#associated-types)\n- [Error](#error)\n- [TryFrom & TryInto](#tryfrom--tryinto)\n\n```rust\ntrait FromStr {\n    type Err;\n    fn from_str(s: &str) -> Result<Self, Self::Err>;\n}\n```\n\n> `FromStr` types allow performing a fallible conversion from `&str` into `Self`. The idiomatic way to use `FromStr` is to call the `.parse()` method on `&str`s:\n\n实现 `FromStr` 特性的类型允许可失败地从 `&str` 转换至 `Self` 。使用这一特性的慣用方式是，调用 `&str` 实例的 `.parse()` 方法：\n\n```rust\nuse std::str::FromStr;\n\nfn example<T: FromStr>(s: &'static str) {\n    // these are all equivalent\n    // 以下方法互相等价\n    let t: Result<T, _> = FromStr::from_str(s);\n    let t = T::from_str(s);\n    let t: Result<T, _> = s.parse();\n    let t = s.parse::<T>(); // most idiomatic\n                            // 最慣用的使用方式\n}\n```\n\n> Example impl for `Point`:\n\n下例为 `Point` 实现了 `FromStr` 特性：\n\n```rust\nuse std::error;\nuse std::fmt;\nuse std::iter::Enumerate;\nuse std::num::ParseIntError;\nuse std::str::{Chars, FromStr};\n\n#[derive(Debug, Eq, PartialEq)]\nstruct Point {\n    x: i32,\n    y: i32,\n}\n\nimpl Point {\n    fn new(x: i32, y: i32) -> Self {\n        Point { x, y }\n    }\n}\n\n#[derive(Debug, PartialEq)]\nstruct ParsePointError;\n\nimpl fmt::Display for ParsePointError {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        write!(f, \"failed to parse point\")\n    }\n}\n\nimpl From<ParseIntError> for ParsePointError {\n    fn from(_e: ParseIntError) -> Self {\n        ParsePointError\n    }\n}\n\nimpl error::Error for ParsePointError {}\n\nimpl FromStr for Point {\n    type Err = ParsePointError;\n\n    fn from_str(s: &str) -> Result<Self, Self::Err> {\n        let is_num = |(_, c): &(usize, char)| matches!(c, '0'..='9' | '-');\n        let isnt_num = |t: &(_, _)| !is_num(t);\n\n        let get_num =\n            |char_idxs: &mut Enumerate<Chars<'_>>| -> Result<(usize, usize), ParsePointError> {\n                let (start, _) = char_idxs\n                    .skip_while(isnt_num)\n                    .next()\n                    .ok_or(ParsePointError)?;\n                let (end, _) = char_idxs\n                    .skip_while(is_num)\n                    .next()\n                    .ok_or(ParsePointError)?;\n                Ok((start, end))\n            };\n\n        let mut char_idxs = s.chars().enumerate();\n        let (x_start, x_end) = get_num(&mut char_idxs)?;\n        let (y_start, y_end) = get_num(&mut char_idxs)?;\n\n        let x = s[x_start..x_end].parse::<i32>()?;\n        let y = s[y_start..y_end].parse::<i32>()?;\n\n        Ok(Point { x, y })\n    }\n}\n\n#[test] // ✅\nfn pos_x_y() {\n    let p = \"(4, 5)\".parse::<Point>();\n    assert_eq!(p, Ok(Point::new(4, 5)));\n}\n\n#[test] // ✅\nfn neg_x_y() {\n    let p = \"(-6, -2)\".parse::<Point>();\n    assert_eq!(p, Ok(Point::new(-6, -2)));\n}\n\n#[test] // ✅\nfn not_a_point() {\n    let p = \"not a point\".parse::<Point>();\n    assert_eq!(p, Err(ParsePointError));\n}\n```\n\n> `FromStr` has the same signature as `TryFrom<&str>`. It doesn't matter which one we impl for a type first as long as we forward the impl to the other one. Here's a `TryFrom<&str>` impl for `Point` assuming it already has a `FromStr` impl:\n\n`FromStr` 与 `TryFrom<&str>` 具有相同的函数签名。先实现哪个特性无关紧要，因为我们可以利用先实现的特性实现后实现的特性。例如，我们假定 `Point` 类型已经实现了 `FromStr` 特性，再来实现 `TryFrom<&str>` 特性：\n\n```rust\nimpl TryFrom<&str> for Point {\n    type Error = <Point as FromStr>::Err;\n    fn try_from(s: &str) -> Result<Point, Self::Error> {\n        <Point as FromStr>::from_str(s)\n    }\n}\n```\n\n\n### AsRef & AsMut\n\n预备知识\n- [Self](#self)\n- [Methods](#methods)\n- [Sized](#sized)\n- [Generic Parameters](#generic-parameters)\n- [Sized](#sized)\n- [Deref & DerefMut](#deref--derefmut)\n\n```rust\ntrait AsRef<T: ?Sized> {\n    fn as_ref(&self) -> &T;\n}\n\ntrait AsMut<T: ?Sized> {\n    fn as_mut(&mut self) -> &mut T;\n}\n```\n\n> `AsRef` is for cheap reference to reference conversions. However, one of the most common ways it's used is to make functions generic over whether they take ownership or not:\n\n`AsRef` 特性的存在很大程度上便捷了引用转换，其最常见的使用是为函数的引用类型的参数的传入提供方便：\n\n```rust\n// accepts:\n//  - &str\n//  - &String\nfn takes_str(s: &str) {\n    // use &str\n}\n\n// accepts:\n//  - &str\n//  - &String\n//  - String\nfn takes_asref_str<S: AsRef<str>>(s: S) {\n    let s: &str = s.as_ref();\n    // use &str\n}\n\nfn example(slice: &str, borrow: &String, owned: String) {\n    takes_str(slice);\n    takes_str(borrow);\n    takes_str(owned); // ❌\n    takes_asref_str(slice);\n    takes_asref_str(borrow);\n    takes_asref_str(owned); // ✅\n}\n```\n\n> The other most common use-case is returning a reference to inner private data wrapped by a type which protects some invariant. A good example from the standard library is `String` which is just a wrapper around `Vec<u8>`:\n\n另外一个常见的使用是，返回一个包装类型的内部私有数据的引用（该类型用于保证内部私有数据的不变性）。标准库中的 `String` 就是对 `Vec<u8>` 的这样一种包装：\n\n```rust\nstruct String {\n    vec: Vec<u8>,\n}\n```\n\n> This inner `Vec` cannot be made public because if it was people could mutate any byte and break the `String`'s valid UTF-8 encoding. However, it's safe to expose an immutable read-only reference to the inner byte array, hence this impl:\n\n之所以不公开内部的 `Vec` 数据，是因为一旦允许用户随意修改内部数据，就有可能破环 `String` 有效的 UTF-8 编码。但是，对外开放一个只读的字节数组的引用是安全的，所以有如下实现：\n\n```rust\nimpl AsRef<[u8]> for String;\n```\n\n> Generally, it often only makes sense to impl `AsRef` for a type if it wraps some other type to either provide additional functionality around the inner type or protect some invariant on the inner type.\n\n通常来讲我们不对类型实现 `AsRef` 特性，除非该类型包装了其它类型以提供额外的功能，或是对内部类型提供了不变性的保护。\n\n> Let's examine a example of bad `AsRef` impls:\n\n以下是实现 `AsRef` 特性的一个反例：\n\n```rust\nstruct User {\n    name: String,\n    age: u32,\n}\n\nimpl AsRef<String> for User {\n    fn as_ref(&self) -> &String {\n        &self.name\n    }\n}\n\nimpl AsRef<u32> for User {\n    fn as_ref(&self) -> &u32 {\n        &self.age\n    }\n}\n```\n\n> This works and kinda makes sense at first, but quickly falls apart if we add more members to `User`:\n\n乍看起来这似乎有几分道理，但是当我们对 `User` 类型添加新的成员时，缺点就暴露出来了：\n\n```rust\nstruct User {\n    name: String,\n    email: String,\n    age: u32,\n    height: u32,\n}\n\nimpl AsRef<String> for User {\n    fn as_ref(&self) -> &String {\n        // uh, do we return name or email here?\n        // 既然我们要返回一个字符串引用，那具体应该返回什么呢？\n        // name 和 email 都是字符串，如何选择呢？\n        // 出于返回类型的限制，似乎我们也难以返回一个混合的字符串。\n    }\n}\n\nimpl AsRef<u32> for User {\n    fn as_ref(&self) -> &u32 {\n        // uh, do we return age or height here?\n        // 如上同理\n    }\n}\n```\n\n> A `User` is composed of `String`s and `u32`s but it's not really the same thing as a `String` or a `u32`. Even if we had much more specific types:\n\n`User` 类型由多个 `String` 和 `u32` 类型的成员所组成，但我们也不能说 `User` 是 `String` 或 `u32` 吧？即便由更加具体的类型来构造也不行：\n\n```rust\nstruct User {\n    name: Name,\n    email: Email,\n    age: Age,\n    height: Height,\n}\n```\n\n> It wouldn't make much sense to impl `AsRef` for any of those because `AsRef` is for cheap reference to reference conversions between semantically equivalent things, and `Name`, `Email`, `Age`, and `Height` by themselves are not the same thing as a `User`.\n\n对于 `User` 这样的类型来讲，实现 `AsRef` 特性并没有什么太多意义。因为 `AsRef` 的存在仅是为了做一种最简单的引用转换，这种转换最好存在于语义上相类似的事务之间。`Name`，`Email`，`Age` 和 `Height` 其本身和 `User` 就不是一回事，在逻辑上谈不上转换。\n\n> A good example where we would impl `AsRef` would be if we introduced a new type `Moderator` that just wrapped a `User` and added some moderation specific privileges:\n\n下例展示了 `AsRef` 特性的正确用法，我们实现了一个新的类型 `Moderator`，它仅仅是包装了 `User` 类型，并添加了对其权限的一些控制：\n\n```rust\nstruct User {\n    name: String,\n    age: u32,\n}\n\n// unfortunately the standard library cannot provide\n// a generic blanket impl to save us from this boilerplate\n// 不幸的是，标准库并没有提供相应的一揽子泛型实现，我们不得不手动实现\nimpl AsRef<User> for User {\n    fn as_ref(&self) -> &User {\n        self\n    }\n}\n\nenum Privilege {\n    BanUsers,\n    EditPosts,\n    DeletePosts,\n}\n\n// although Moderators have some special\n// privileges they are still regular Users\n// and should be able to do all the same stuff\n// 尽管主持人类具有一些特殊的权限，\n// 但其仍然是普通的用户\n// 所有用户类能做到的主持人类也应能做到\nstruct Moderator {\n    user: User,\n    privileges: Vec<Privilege>\n}\n\nimpl AsRef<Moderator> for Moderator {\n    fn as_ref(&self) -> &Moderator {\n        self\n    }\n}\n\nimpl AsRef<User> for Moderator {\n    fn as_ref(&self) -> &User {\n        &self.user\n    }\n}\n\n// this should be callable with Users\n// and Moderators (who are also Users)\n// 这个函数的参数可以是 User 也可以是 Moderator\n// （ Moderator 也是 User ）\nfn create_post<U: AsRef<User>>(u: U) {\n    let user = u.as_ref();\n    // etc\n}\n\nfn example(user: User, moderator: Moderator) {\n    create_post(&user);\n    create_post(&moderator); // ✅\n}\n```\n\n> This works because `Moderator`s are just `User`s. Here's the example from the `Deref` section except using `AsRef` instead:\n\n之所以可以这样做，是因为 `Moderator` 就是 `User` 。下例是将 `Deref` 一节中的例子使用 `AsRef` 做出替代：\n\n```rust\nuse std::convert::AsRef;\n\nstruct Human {\n    health_points: u32,\n}\n\nimpl AsRef<Human> for Human {\n    fn as_ref(&self) -> &Human {\n        self\n    }\n}\n\nenum Weapon {\n    Spear,\n    Axe,\n    Sword,\n}\n\n// a Soldier is just a Human with a Weapon\n// 士兵是手持武器的人类\nstruct Soldier {\n    human: Human,\n    weapon: Weapon,\n}\n\nimpl AsRef<Soldier> for Soldier {\n    fn as_ref(&self) -> &Soldier {\n        self\n    }\n}\n\nimpl AsRef<Human> for Soldier {\n    fn as_ref(&self) -> &Human {\n        &self.human\n    }\n}\n\nenum Mount {\n    Horse,\n    Donkey,\n    Cow,\n}\n\n// a Knight is just a Soldier with a Mount\n// 骑士是胯骑坐骑的士兵\nstruct Knight {\n    soldier: Soldier,\n    mount: Mount,\n}\n\nimpl AsRef<Knight> for Knight {\n    fn as_ref(&self) -> &Knight {\n        self\n    }\n}\n\nimpl AsRef<Soldier> for Knight {\n    fn as_ref(&self) -> &Soldier {\n        &self.soldier\n    }\n}\n\nimpl AsRef<Human> for Knight {\n    fn as_ref(&self) -> &Human {\n        &self.soldier.human\n    }\n}\n\nenum Spell {\n    MagicMissile,\n    FireBolt,\n    ThornWhip,\n}\n\n// a Mage is just a Human who can cast Spells\n// 法师是口诵咒语的人类\nstruct Mage {\n    human: Human,\n    spells: Vec<Spell>,\n}\n\nimpl AsRef<Mage> for Mage {\n    fn as_ref(&self) -> &Mage {\n        self\n    }\n}\n\nimpl AsRef<Human> for Mage {\n    fn as_ref(&self) -> &Human {\n        &self.human\n    }\n}\n\nenum Staff {\n    Wooden,\n    Metallic,\n    Plastic,\n}\n\n// a Wizard is just a Mage with a Staff\n// 巫师是腰别法宝的法师\nstruct Wizard {\n    mage: Mage,\n    staff: Staff,\n}\n\nimpl AsRef<Wizard> for Wizard {\n    fn as_ref(&self) -> &Wizard {\n        self\n    }\n}\n\nimpl AsRef<Mage> for Wizard {\n    fn as_ref(&self) -> &Mage {\n        &self.mage\n    }\n}\n\nimpl AsRef<Human> for Wizard {\n    fn as_ref(&self) -> &Human {\n        &self.mage.human\n    }\n}\n\nfn borrows_human<H: AsRef<Human>>(human: H) {}\nfn borrows_soldier<S: AsRef<Soldier>>(soldier: S) {}\nfn borrows_knight<K: AsRef<Knight>>(knight: K) {}\nfn borrows_mage<M: AsRef<Mage>>(mage: M) {}\nfn borrows_wizard<W: AsRef<Wizard>>(wizard: W) {}\n\nfn example(human: Human, soldier: Soldier, knight: Knight, mage: Mage, wizard: Wizard) {\n    // all types can be used as Humans\n    borrows_human(&human);\n    borrows_human(&soldier);\n    borrows_human(&knight);\n    borrows_human(&mage);\n    borrows_human(&wizard);\n    // Knights can be used as Soldiers\n    borrows_soldier(&soldier);\n    borrows_soldier(&knight);\n    // Wizards can be used as Mages\n    borrows_mage(&mage);\n    borrows_mage(&wizard);\n    // Knights & Wizards passed as themselves\n    borrows_knight(&knight);\n    borrows_wizard(&wizard);\n}\n```\n\n> `Deref` didn't work in the prior version of the example above because deref coercion is an implicit conversion between types which leaves room for people to mistakenly formulate the wrong ideas and expectations for how it will behave. `AsRef` works above because it makes the conversion between types explicit and there's no room leftover to develop any wrong ideas or expectations.\n\n之所以 `Deref` 在上例之前的版本中不可使用，是因为自动解引用是一种隐式的转换，这就为程序员错误地使用留下了巨大的空间。\n\n而 `AsRef` 在上例中可以使用，是因为其实现的转换是显式的，这样很大程度上就消除了犯错误的空间。\n\n\n\n### Borrow & BorrowMut\n\n预备知识\n- [Self](#self)\n- [Methods](#methods)\n- [Generic Parameters](#generic-parameters)\n- [Subtraits & Supertraits](#subtraits--supertraits)\n- [Sized](#sized)\n- [AsRef & AsMut](#asref--asmut)\n- [PartialEq & Eq](#partialeq--eq)\n- [Hash](#hash)\n- [PartialOrd & Ord](#partialord--ord)\n\n```rust\ntrait Borrow<Borrowed> \nwhere\n    Borrowed: ?Sized, \n{\n    fn borrow(&self) -> &Borrowed;\n}\n\ntrait BorrowMut<Borrowed>: Borrow<Borrowed> \nwhere\n    Borrowed: ?Sized, \n{\n    fn borrow_mut(&mut self) -> &mut Borrowed;\n}\n```\n\n> These traits were invented to solve the very specific problem of looking up `String` keys in `HashSet`s, `HashMap`s, `BTreeSet`s, and `BTreeMap`s using `&str` values.\n\n这类特性存在的意义旨在于解决特定领域的问题，例如在 `Hashset`，`HashMap`，`BTreeSet`，`BtreeMap` 中使用 `&str` 查询 `String` 类型的键。\n\n> We can view `Borrow<T>` and `BorrowMut<T>` as stricter versions of `AsRef<T>` and `AsMut<T>`, where the returned reference `&T` has equivalent `Eq`, `Hash`, and `Ord` impls to `Self`. This is more easily explained with a commented example:\n\n我们可以将 `Borrow<T>` 和 `BorrowMut<T>` 视作 `AsRef<T>` 和 `AsMut<T>` 的严格版本，其返回的引用 `&T` 具有与 `Self` 相同的 `Eq`，`Hash` 和 `Ord` 的实现。这一点在下例的注释中得到很好的解释：\n\n```rust\nuse std::borrow::Borrow;\nuse std::hash::Hasher;\nuse std::collections::hash_map::DefaultHasher;\nuse std::hash::Hash;\n\nfn get_hash<T: Hash>(t: T) -> u64 {\n    let mut hasher = DefaultHasher::new();\n    t.hash(&mut hasher);\n    hasher.finish()\n}\n\nfn asref_example<Owned, Ref>(owned1: Owned, owned2: Owned)\nwhere\n    Owned: Eq + Ord + Hash + AsRef<Ref>,\n    Ref: Eq + Ord + Hash\n{\n    let ref1: &Ref = owned1.as_ref();\n    let ref2: &Ref = owned2.as_ref();\n    \n    // refs aren't required to be equal if owned types are equal\n    // 值相等，不意味着其引用一定相等\n    assert_eq!(owned1 == owned2, ref1 == ref2); // ❌\n    \n    let owned1_hash = get_hash(&owned1);\n    let owned2_hash = get_hash(&owned2);\n    let ref1_hash = get_hash(&ref1);\n    let ref2_hash = get_hash(&ref2);\n    \n    // ref hashes aren't required to be equal if owned type hashes are equal\n    // 值的哈希值相等，其引用不一定相等\n    assert_eq!(owned1_hash == owned2_hash, ref1_hash == ref2_hash); // ❌\n    \n    // ref comparisons aren't required to match owned type comparisons\n    // 值的比较，与其引用的比较没有必然联系\n    assert_eq!(owned1.cmp(&owned2), ref1.cmp(&ref2)); // ❌\n}\n\nfn borrow_example<Owned, Borrowed>(owned1: Owned, owned2: Owned)\nwhere\n    Owned: Eq + Ord + Hash + Borrow<Borrowed>,\n    Borrowed: Eq + Ord + Hash\n{\n    let borrow1: &Borrowed = owned1.borrow();\n    let borrow2: &Borrowed = owned2.borrow();\n    \n    // borrows are required to be equal if owned types are equal\n    // 值相等，借用值也必须相等\n    assert_eq!(owned1 == owned2, borrow1 == borrow2); // ✅\n    \n    let owned1_hash = get_hash(&owned1);\n    let owned2_hash = get_hash(&owned2);\n    let borrow1_hash = get_hash(&borrow1);\n    let borrow2_hash = get_hash(&borrow2);\n    \n    // borrow hashes are required to be equal if owned type hashes are equal\n    // 值的哈希值相等，借用值的哈希值也必须相等\n    assert_eq!(owned1_hash == owned2_hash, borrow1_hash == borrow2_hash); // ✅\n    \n    // borrow comparisons are required to match owned type comparisons\n    // 值的比较，与借用值的比较必须步调一致\n    assert_eq!(owned1.cmp(&owned2), borrow1.cmp(&borrow2)); // ✅\n}\n```\n\n> It's good to be aware of these traits and understand why they exist since it helps demystify some of the methods on `HashSet`, `HashMap`, `BTreeSet`, and `BTreeMap` but it's very rare that we would ever need to impl these traits for any of our types because it's very rare that we would ever need create a pair of types where one is the \"borrowed\" version of the other in the first place. If we have some `T` then `&T` will get the job done 99.99% of the time, and `T: Borrow<T>` is already implemented for all `T` because of a generic blanket impl, so we don't need to manually impl it and we don't need to create some `U` such that `T: Borrow<U>`.\n\n\n理解这类特性存在的意义，有助于我们揭开 `HashSet`，`HashMap`，`BTreeSet` 和 `BTreeMap` 中某些方法的实现的神秘面纱。但是在实际应用中，几乎没有什么地方需要我们去实现这样的特性，因为再难找到一个需要我们对一个值再创造一个“借用”版本的类型的场景了。对于某种类型 `T` ，`&T` 就能解决 99.9% 的问题了，且 `T: Borrow<T>` 已经被一揽子泛型实现对 `T` 实现了，所以我们无需手动实现它，也无需去实现某种的对 `U` 有 `T: Borrow<U>` 了。\n\n\n### ToOwned\n\n预备知识\n- [Self](#self)\n- [Methods](#methods)\n- [Default Impls](#default-impls)\n- [Clone](#clone)\n- [Borrow & BorrowMut](#borrow--borrowmut)\n\n```rust\ntrait ToOwned {\n    type Owned: Borrow<Self>;\n    fn to_owned(&self) -> Self::Owned;\n    \n    // provided default impls\n    // 提供默认实现\n    fn clone_into(&self, target: &mut Self::Owned);\n}\n```\n\n> `ToOwned` is a more generic version of `Clone`. `Clone` allows us to take a `&T` and turn it into an `T` but `ToOwned` allows us to take a `&Borrowed` and turn it into a `Owned` where `Owned: Borrow<Borrowed>`.\n\n`ToOwned` 特性是 `Clone` 特性的泛型版本。 `Clone` 特性允许我们由 `&T` 类型得到 `T` 类型，而 `ToOwned` 特性允许我们由 `&Borrow` 类型得到 `Owned` 类型，其中 `Owned: Borrow<Borrowed>` 。\n\n> In other words, we can't \"clone\" a `&str` into a `String`, or a `&Path` into a `PathBuf`, or an `&OsStr` into an `OsString`, since the `clone` method signature doesn't support this kind of cross-type cloning, and that's what `ToOwned` was made for.\n\n换句话讲，我们不能将 `&str` 克隆为 `String`，将 `&Path` 克隆为 `PathBuf` 或将 `&OsStr` 克隆为 `OsString` 。鉴于 `clone` 方法的签名不支持这样跨类型的克隆，这就是 `ToOwned` 特性存在的意义。\n\n> For similar reasons as `Borrow` and `BorrowMut`, it's good to be aware of this trait and understand why it exists but it's very rare we'll ever need to impl it for any of our types.\n\n与 `Borrow` 和 `BorrowMut` 相同地，理解此类特性存在的意义对我们或有帮助，但是鲜少需要我们手动为自己的类实现该特性。\n\n\n\n## 迭代特性 Iteration Traits\n\n\n\n### Iterator\n\n预备知识\n- [Self](#self)\n- [Methods](#methods)\n- [Associated Types](#associated-types)\n- [Default Impls](#default-impls)\n\n```rust\ntrait Iterator {\n    type Item;\n    fn next(&mut self) -> Option<Self::Item>;\n\n    // provided default impls\n    // 提供默认实现\n    fn size_hint(&self) -> (usize, Option<usize>);\n    fn count(self) -> usize;\n    fn last(self) -> Option<Self::Item>;\n    fn advance_by(&mut self, n: usize) -> Result<(), usize>;\n    fn nth(&mut self, n: usize) -> Option<Self::Item>;\n    fn step_by(self, step: usize) -> StepBy<Self>;\n    fn chain<U>(\n        self, \n        other: U\n    ) -> Chain<Self, <U as IntoIterator>::IntoIter>\n    where\n        U: IntoIterator<Item = Self::Item>;\n    fn zip<U>(self, other: U) -> Zip<Self, <U as IntoIterator>::IntoIter>\n    where\n        U: IntoIterator;\n    fn map<B, F>(self, f: F) -> Map<Self, F>\n    where\n        F: FnMut(Self::Item) -> B;\n    fn for_each<F>(self, f: F)\n    where\n        F: FnMut(Self::Item);\n    fn filter<P>(self, predicate: P) -> Filter<Self, P>\n    where\n        P: FnMut(&Self::Item) -> bool;\n    fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F>\n    where\n        F: FnMut(Self::Item) -> Option<B>;\n    fn enumerate(self) -> Enumerate<Self>;\n    fn peekable(self) -> Peekable<Self>;\n    fn skip_while<P>(self, predicate: P) -> SkipWhile<Self, P>\n    where\n        P: FnMut(&Self::Item) -> bool;\n    fn take_while<P>(self, predicate: P) -> TakeWhile<Self, P>\n    where\n        P: FnMut(&Self::Item) -> bool;\n    fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P>\n    where\n        P: FnMut(Self::Item) -> Option<B>;\n    fn skip(self, n: usize) -> Skip<Self>;\n    fn take(self, n: usize) -> Take<Self>;\n    fn scan<St, B, F>(self, initial_state: St, f: F) -> Scan<Self, St, F>\n    where\n        F: FnMut(&mut St, Self::Item) -> Option<B>;\n    fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F>\n    where\n        F: FnMut(Self::Item) -> U,\n        U: IntoIterator;\n    fn flatten(self) -> Flatten<Self>\n    where\n        Self::Item: IntoIterator;\n    fn fuse(self) -> Fuse<Self>;\n    fn inspect<F>(self, f: F) -> Inspect<Self, F>\n    where\n        F: FnMut(&Self::Item);\n    fn by_ref(&mut self) -> &mut Self;\n    fn collect<B>(self) -> B\n    where\n        B: FromIterator<Self::Item>;\n    fn partition<B, F>(self, f: F) -> (B, B)\n    where\n        F: FnMut(&Self::Item) -> bool,\n        B: Default + Extend<Self::Item>;\n    fn partition_in_place<'a, T, P>(self, predicate: P) -> usize\n    where\n        Self: DoubleEndedIterator<Item = &'a mut T>,\n        T: 'a,\n        P: FnMut(&T) -> bool;\n    fn is_partitioned<P>(self, predicate: P) -> bool\n    where\n        P: FnMut(Self::Item) -> bool;\n    fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R\n    where\n        F: FnMut(B, Self::Item) -> R,\n        R: Try<Ok = B>;\n    fn try_for_each<F, R>(&mut self, f: F) -> R\n    where\n        F: FnMut(Self::Item) -> R,\n        R: Try<Ok = ()>;\n    fn fold<B, F>(self, init: B, f: F) -> B\n    where\n        F: FnMut(B, Self::Item) -> B;\n    fn fold_first<F>(self, f: F) -> Option<Self::Item>\n    where\n        F: FnMut(Self::Item, Self::Item) -> Self::Item;\n    fn all<F>(&mut self, f: F) -> bool\n    where\n        F: FnMut(Self::Item) -> bool;\n    fn any<F>(&mut self, f: F) -> bool\n    where\n        F: FnMut(Self::Item) -> bool;\n    fn find<P>(&mut self, predicate: P) -> Option<Self::Item>\n    where\n        P: FnMut(&Self::Item) -> bool;\n    fn find_map<B, F>(&mut self, f: F) -> Option<B>\n    where\n        F: FnMut(Self::Item) -> Option<B>;\n    fn try_find<F, R>(\n        &mut self, \n        f: F\n    ) -> Result<Option<Self::Item>, <R as Try>::Error>\n    where\n        F: FnMut(&Self::Item) -> R,\n        R: Try<Ok = bool>;\n    fn position<P>(&mut self, predicate: P) -> Option<usize>\n    where\n        P: FnMut(Self::Item) -> bool;\n    fn rposition<P>(&mut self, predicate: P) -> Option<usize>\n    where\n        Self: ExactSizeIterator + DoubleEndedIterator,\n        P: FnMut(Self::Item) -> bool;\n    fn max(self) -> Option<Self::Item>\n    where\n        Self::Item: Ord;\n    fn min(self) -> Option<Self::Item>\n    where\n        Self::Item: Ord;\n    fn max_by_key<B, F>(self, f: F) -> Option<Self::Item>\n    where\n        F: FnMut(&Self::Item) -> B,\n        B: Ord;\n    fn max_by<F>(self, compare: F) -> Option<Self::Item>\n    where\n        F: FnMut(&Self::Item, &Self::Item) -> Ordering;\n    fn min_by_key<B, F>(self, f: F) -> Option<Self::Item>\n    where\n        F: FnMut(&Self::Item) -> B,\n        B: Ord;\n    fn min_by<F>(self, compare: F) -> Option<Self::Item>\n    where\n        F: FnMut(&Self::Item, &Self::Item) -> Ordering;\n    fn rev(self) -> Rev<Self>\n    where\n        Self: DoubleEndedIterator;\n    fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB)\n    where\n        Self: Iterator<Item = (A, B)>,\n        FromA: Default + Extend<A>,\n        FromB: Default + Extend<B>;\n    fn copied<'a, T>(self) -> Copied<Self>\n    where\n        Self: Iterator<Item = &'a T>,\n        T: 'a + Copy;\n    fn cloned<'a, T>(self) -> Cloned<Self>\n    where\n        Self: Iterator<Item = &'a T>,\n        T: 'a + Clone;\n    fn cycle(self) -> Cycle<Self>\n    where\n        Self: Clone;\n    fn sum<S>(self) -> S\n    where\n        S: Sum<Self::Item>;\n    fn product<P>(self) -> P\n    where\n        P: Product<Self::Item>;\n    fn cmp<I>(self, other: I) -> Ordering\n    where\n        I: IntoIterator<Item = Self::Item>,\n        Self::Item: Ord;\n    fn cmp_by<I, F>(self, other: I, cmp: F) -> Ordering\n    where\n        F: FnMut(Self::Item, <I as IntoIterator>::Item) -> Ordering,\n        I: IntoIterator;\n    fn partial_cmp<I>(self, other: I) -> Option<Ordering>\n    where\n        I: IntoIterator,\n        Self::Item: PartialOrd<<I as IntoIterator>::Item>;\n    fn partial_cmp_by<I, F>(\n        self, \n        other: I, \n        partial_cmp: F\n    ) -> Option<Ordering>\n    where\n        F: FnMut(Self::Item, <I as IntoIterator>::Item) -> Option<Ordering>,\n        I: IntoIterator;\n    fn eq<I>(self, other: I) -> bool\n    where\n        I: IntoIterator,\n        Self::Item: PartialEq<<I as IntoIterator>::Item>;\n    fn eq_by<I, F>(self, other: I, eq: F) -> bool\n    where\n        F: FnMut(Self::Item, <I as IntoIterator>::Item) -> bool,\n        I: IntoIterator;\n    fn ne<I>(self, other: I) -> bool\n    where\n        I: IntoIterator,\n        Self::Item: PartialEq<<I as IntoIterator>::Item>;\n    fn lt<I>(self, other: I) -> bool\n    where\n        I: IntoIterator,\n        Self::Item: PartialOrd<<I as IntoIterator>::Item>;\n    fn le<I>(self, other: I) -> bool\n    where\n        I: IntoIterator,\n        Self::Item: PartialOrd<<I as IntoIterator>::Item>;\n    fn gt<I>(self, other: I) -> bool\n    where\n        I: IntoIterator,\n        Self::Item: PartialOrd<<I as IntoIterator>::Item>;\n    fn ge<I>(self, other: I) -> bool\n    where\n        I: IntoIterator,\n        Self::Item: PartialOrd<<I as IntoIterator>::Item>;\n    fn is_sorted(self) -> bool\n    where\n        Self::Item: PartialOrd<Self::Item>;\n    fn is_sorted_by<F>(self, compare: F) -> bool\n    where\n        F: FnMut(&Self::Item, &Self::Item) -> Option<Ordering>;\n    fn is_sorted_by_key<F, K>(self, f: F) -> bool\n    where\n        F: FnMut(Self::Item) -> K,\n        K: PartialOrd<K>;\n}\n```\n\n> `Iterator<Item = T>` types can be iterated and will produce `T` types. There's no `IteratorMut` trait. Each `Iterator` impl can specify whether it returns immutable references, mutable references, or owned values via the `Item` associated type.\n\n实现 `Iterator<Item = T>` 的类型可以迭代产生 `T` 类型。注意：并不存在 `IteratorMut` 类型，因为可以通过在实现 `Iterator` 特性时指定 `Item` 关联类型，来选择其返回的是不可变引用、可变引用还是自有值。\n\n| `Vec<T>` 方法 | 返回类型 |\n|-----------------|-------------------|\n| `.iter()` | `Iterator<Item = &T>` |\n| `.iter_mut()` | `Iterator<Item = &mut T>` |\n| `.into_iter()` | `Iterator<Item = T>` |\n\n> Something that is not immediately obvious to beginner Rustaceans but that intermediate Rustaceans take for granted is that most types are not their own iterators. If a type is iterable we almost always impl some custom iterator type which iterates over it rather than trying to make it iterate over itself:\n\n对于 Rust 的初学者而言可能有些费解，但是对于中级学习者而言则是顺理成章的一件事是 —— 绝大多数类型并不是自己的迭代器。这意味着，如果某种类型是可迭代的，那么应当实现某种额外的迭代器类型去迭代它，而不是让它自己迭代自己。\n\n```rust\nstruct MyType {\n    items: Vec<String>\n}\n\nimpl MyType {\n    fn iter(&self) -> impl Iterator<Item = &String> {\n        MyTypeIterator {\n            index: 0,\n            items: &self.items\n        }\n    }\n}\n\nstruct MyTypeIterator<'a> {\n    index: usize,\n    items: &'a Vec<String>\n}\n\nimpl<'a> Iterator for MyTypeIterator<'a> {\n    type Item = &'a String;\n    fn next(&mut self) -> Option<Self::Item> {\n        if self.index >= self.items.len() {\n            None\n        } else {\n            let item = &self.items[self.index];\n            self.index += 1;\n            Some(item)\n        }\n    }\n}\n```\n\n> For the sake of teaching the above example shows how to impl an `Iterator` from scratch but the idiomatic solution in this situation would be to just defer to `Vec`'s `iter` method:\n\n出于教学的原因，我们在上例中从头手动实现了一个迭代器。而在这种情况下，最慣用的做法是直接调用 `Vec` 的 `iter` 方法。\n\n```rust\nstruct MyType {\n    items: Vec<String>\n}\n\nimpl MyType {\n    fn iter(&self) -> impl Iterator<Item = &String> {\n        self.items.iter()\n    }\n}\n```\n\n> Also this is a good generic blanket impl to be aware of:\n\n另外，最好了解这个一揽子泛型实现：\n\n```rust\nimpl<I: Iterator + ?Sized> Iterator for &mut I;\n```\n\n> It says that any mutable reference to an iterator is also an iterator. This is useful to know because it allows us to use iterator methods with `self` receivers as if they had `&mut self` receivers.\n\n任何迭代器的可变引用也是一个迭代器。了解这样的性质有助于我们理解，为什么可以将迭代器的某些参数为 `self` 的方法当作具有 `&mut self` 参数的方法来使用。\n\n> As an example, imagine we have a function which processes an iterator of more than three items, but the first step of the function is to take out the first three items of the iterator and process them separately before iterating over the remaining items, here's how a beginner may attempt to write this function:\n\n举个例子，想象我们有这样一个函数，它处理一个具有三个以上值的迭代器，这个函数首先要取得该迭代器的前三个值并分别地处理他们，然后再依次迭代剩余的值。初学者可能会这样实现该函数：\n\n```rust\nfn example<I: Iterator<Item = i32>>(mut iter: I) {\n    let first3: Vec<i32> = iter.take(3).collect();\n    for item in iter { // ❌ iter consumed in line above\n                       // ❌ iter 在上一行就已经被消耗掉了\n        // process remaining items\n        // 处理剩余的值\n    }\n}\n```\n\n> Well that's annoying. The `take` method has a `self` receiver so it seems like we cannot call it without consuming the whole iterator! Here's what a naive refactor of the above code might look like:\n\n糟糕，`take` 方法具有 `self` 参数，这意味着我们不能在不消耗掉整个迭代器的前提下调用该方法。以下可能是一个初学者的改进：\n\n```rust\nfn example<I: Iterator<Item = i32>>(mut iter: I) {\n    let first3: Vec<i32> = vec![\n        iter.next().unwrap(),\n        iter.next().unwrap(),\n        iter.next().unwrap(),\n    ];\n    for item in iter { // ✅\n        // process remaining items\n        // 处理剩余的值\n    }\n}\n```\n\n> Which is okay. However, the idiomatic refactor is actually:\n\n这是可行的，但是慣用的改进方式莫过于：\n\n```rust\nfn example<I: Iterator<Item = i32>>(mut iter: I) {\n    let first3: Vec<i32> = iter.by_ref().take(3).collect();\n    for item in iter { // ✅\n        // process remaining items\n        // 处理剩余的值\n    }\n}\n```\n\n> Not very easy to discover. But anyway, now we know.\n\n这真是一个很隐蔽的方法，但是被我们抓到了。\n\n> Also, there are no rules or conventions on what can or cannot be an iterator. If the type impls `Iterator` then it's an iterator. Some creative examples from the standard library:\n\n同样，对于什么可以是迭代器，什么不可以是，并无一定之规。实现了 `Iterator` 特性的就是迭代器。而在标准库中，确有一些具有创造性的用例：\n\n```rust\nuse std::sync::mpsc::channel;\nuse std::thread;\n\nfn paths_can_be_iterated(path: &Path) {\n    for part in path {\n        // iterate over parts of a path\n        // 迭代 path 的不同部分\n    }\n}\n\nfn receivers_can_be_iterated() {\n    let (send, recv) = channel();\n\n    thread::spawn(move || {\n        send.send(1).unwrap();\n        send.send(2).unwrap();\n        send.send(3).unwrap();\n    });\n\n    for received in recv {\n        // iterate over received values\n        // 迭代接收到的值\n    }\n}\n```\n\n\n\n### IntoIterator\n\n预备知识\n- [Self](#self)\n- [Methods](#methods)\n- [Associated Types](#associated-types)\n- [Iterator](#iterator)\n\n```rust\ntrait IntoIterator \nwhere\n    <Self::IntoIter as Iterator>::Item == Self::Item, \n{\n    type Item;\n    type IntoIter: Iterator;\n    fn into_iter(self) -> Self::IntoIter;\n}\n```\n\n> `IntoIterator` types can be converted into iterators, hence the name. The `into_iter` method is called on a type when it's used within a `for-in` loop:\n\n闻弦歌而知雅意，实现 `IntoIterator` 特性的类型可以被转换为迭代器。当用于 `for-in` 循环时，将自动调用该类型的 `into_iter` 方法.\n\n```rust\n// vec = Vec<T>\nfor v in vec {} // v = T\n\n// above line desugared\n// 以上代码等价于\nfor v in vec.into_iter() {}\n```\n\n> Not only does `Vec` impl `IntoIterator` but so does `&Vec` and `&mut Vec` if we'd like to iterate over immutable or mutable references instead of owned values, respectively.\n\n不仅 `Vec` 实现了 `IntoIterator` 特性，`&Vec` 与 `&mut Vec` 同样如此。因此我们可以相应的对可变与不可变的引用，以及自有值进行迭代。\n\n```rust\n// vec = Vec<T>\nfor v in &vec {} // v = &T\n\n// above example desugared\n// 以上代码等价于\nfor v in (&vec).into_iter() {}\n\n// vec = Vec<T>\nfor v in &mut vec {} // v = &mut T\n\n// above example desugared\n// 以上代码等价于\nfor v in (&mut vec).into_iter() {}\n```\n\n\n\n### FromIterator\n\n预备知识\n- [Self](#self)\n- [Functions](#functions)\n- [Generic Parameters](#generic-parameters)\n- [Iterator](#iterator)\n- [IntoIterator](#intoiterator)\n\n```rust\ntrait FromIterator<A> {\n    fn from_iter<T>(iter: T) -> Self\n    where\n        T: IntoIterator<Item = A>;\n}\n```\n\n> `FromIterator` types can be created from an iterator, hence the name. `FromIterator` is most commonly and idiomatically used by calling the `collect` method on `Iterator`:\n\n顾叶落而晓秋至，实现 `FromIterator` 特性的类型可以由迭代器而构造。`FromIterator` 特性最常见和最慣用的使用方法是调用 `Iterator` 的 `collect` 方法：\n\n```rust\nfn collect<B>(self) -> B\nwhere\n    B: FromIterator<Self::Item>;\n```\n\n> Example of collecting an `Iterator<Item = char>` into a `String`:\n\n下例展示了如何将 `Iterator<Item = char>` 迭代器的值收集为 `String` ：\n\n```rust\nfn filter_letters(string: &str) -> String {\n    string.chars().filter(|c| c.is_alphabetic()).collect()\n}\n```\n\n> All the collections in the standard library impl `IntoIterator` and `FromIterator` so that makes it easier to convert between them:\n\n标准库中的全部集合类型都实现了 `IntoIterator` 和 `FromIterator` 特性，所以在它们之间进行转换是很方便的：\n\n```rust\nuse std::collections::{BTreeSet, HashMap, HashSet, LinkedList};\n\n// String -> HashSet<char>\nfn unique_chars(string: &str) -> HashSet<char> {\n    string.chars().collect()\n}\n\n// Vec<T> -> BTreeSet<T>\nfn ordered_unique_items<T: Ord>(vec: Vec<T>) -> BTreeSet<T> {\n    vec.into_iter().collect()\n}\n\n// HashMap<K, V> -> LinkedList<(K, V)>\nfn entry_list<K, V>(map: HashMap<K, V>) -> LinkedList<(K, V)> {\n    map.into_iter().collect()\n}\n\n// and countless more possible examples\n// 还有数不胜数的例子\n```\n\n\n\n## 输入输出特性 I/O Traits\n\n\n\n### Read & Write\n\n预备知识\n- [Self](#self)\n- [Methods](#methods)\n- [Scope](#scope)\n- [Generic Blanket Impls](#generic-blanket-impls)\n\n```rust\ntrait Read {\n    fn read(&mut self, buf: &mut [u8]) -> Result<usize>;\n\n    // provided default impls\n    // 提供默认实现\n    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> Result<usize>;\n    fn is_read_vectored(&self) -> bool;\n    unsafe fn initializer(&self) -> Initializer;\n    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize>;\n    fn read_to_string(&mut self, buf: &mut String) -> Result<usize>;\n    fn read_exact(&mut self, buf: &mut [u8]) -> Result<()>;\n    fn by_ref(&mut self) -> &mut Self\n    where\n        Self: Sized;\n    fn bytes(self) -> Bytes<Self>\n    where\n        Self: Sized;\n    fn chain<R: Read>(self, next: R) -> Chain<Self, R>\n    where\n        Self: Sized;\n    fn take(self, limit: u64) -> Take<Self>\n    where\n        Self: Sized;\n}\n\ntrait Write {\n    fn write(&mut self, buf: &[u8]) -> Result<usize>;\n    fn flush(&mut self) -> Result<()>;\n\n    // provided default impls\n    // 提供默认实现\n    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> Result<usize>;\n    fn is_write_vectored(&self) -> bool;\n    fn write_all(&mut self, buf: &[u8]) -> Result<()>;\n    fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> Result<()>;\n    fn write_fmt(&mut self, fmt: Arguments<'_>) -> Result<()>;\n    fn by_ref(&mut self) -> &mut Self\n    where\n        Self: Sized;\n}\n```\n\n> Generic blanket impls worth knowing:\n\n值得关注的一揽子泛型实现：\n\n```rust\nimpl<R: Read + ?Sized> Read for &mut R;\nimpl<W: Write + ?Sized> Write for &mut W;\n```\n\n> These say that any mutable reference to a `Read` type is also `Read`, and same with `Write`. This is useful to know because it allows us to use any method with a `self` receiver as if it had a `&mut self` receiver. We already went over how to do this and why it's useful in the `Iterator` trait section so I'm not going to repeat it again here.\n\n对于任何实现了 `Read` 特性的类型，其可变的引用类型也实现了 `Read` 特性。`Write` 也是如此。知晓这一点有助于我们理解为什么，对于具有 `self` 参数的函数可以如同那些具有 `&mut self` 参数的函数一般使用。鉴于我们已经在 `Iterator` 特性一节中做出了相近的说明，对此我不再赘述。\n\n> I'd like to point out that `&[u8]` impls `Read` and that `Vec<u8>` impls `Write` so we can easily unit test our file handling functions using `String`s which are trivial to convert to `&[u8]` and from `Vec<u8>`:\n\n我特别指出的是，在 `&[u8]` 实现 `Read` 的同时，`Vec<u8>` 实现了 `Write`，因此我们可以很方便地使用 `String` 来对我们的文件处理函数进行单元测试，因为它可以轻易地转换到 `&[u8]` 和转换自 `Vec<u8>` 。\n\n```rust\nuse std::path::Path;\nuse std::fs::File;\nuse std::io::Read;\nuse std::io::Write;\nuse std::io;\n\n// function we want to test\n// 欲要测试此函数\nfn uppercase<R: Read, W: Write>(mut read: R, mut write: W) -> Result<(), io::Error> {\n    let mut buffer = String::new();\n    read.read_to_string(&mut buffer)?;\n    let uppercase = buffer.to_uppercase();\n    write.write_all(uppercase.as_bytes())?;\n    write.flush()?;\n    Ok(())\n}\n\n// in actual program we'd pass Files\n// 实际使用中我们传入文件\nfn example(in_path: &Path, out_path: &Path) -> Result<(), io::Error> {\n    let in_file = File::open(in_path)?;\n    let out_file = File::open(out_path)?;\n    uppercase(in_file, out_file)\n}\n\n\n// however in unit tests we can use Strings!\n// 但是在单元测试中我们使用 String !\n#[test] // ✅\nfn example_test() {\n    let in_file: String = \"i am screaming\".into();\n    let mut out_file: Vec<u8> = Vec::new();\n    uppercase(in_file.as_bytes(), &mut out_file).unwrap();\n    let out_result = String::from_utf8(out_file).unwrap();\n    assert_eq!(out_result, \"I AM SCREAMING\");\n}\n```\n\n\n\n## 结语 Conclusion\n\n> We learned a lot together! Too much in fact. This is us now:\n\n我们真是学习了太多！太多了！可能这就是我们现在的样子：\n\n![rust standard library traits](../../../assets/jason-jarvis-stdlib-traits.png)\n\n_该漫画的创作者: [The Jenkins Comic](https://thejenkinscomic.wordpress.com/2020/05/06/memory/)_\n\n\n\n## 讨论 Discuss\n\n> Discuss this article on\n\n可以在如下地点讨论本文\n- [Github](https://github.com/pretzelhammer/rust-blog/discussions)\n- [learnrust subreddit](https://www.reddit.com/r/learnrust/comments/ml9shl/tour_of_rusts_standard_library_traits/)\n- [official Rust users forum](https://users.rust-lang.org/t/blog-post-tour-of-rusts-standard-library-traits/57974)\n- [Twitter](https://twitter.com/pretzelhammer/status/1379561720176336902)\n- [lobste.rs](https://lobste.rs/s/g27ezp/tour_rust_s_standard_library_traits)\n- [rust subreddit](https://www.reddit.com/r/rust/comments/mmrao0/tour_of_rusts_standard_library_traits/)\n\n\n## 更多资料 Further Reading\n\n- [Sizedness in Rust](../../sizedness-in-rust.md)\n- [Rust 中常见的有关生命周期的误解](./common-rust-lifetime-misconceptions.md)\n- [2020 年的 Rust 学习指南](./learning-rust-in-2020.md)\n- [Learn Assembly with Entirely Too Many Brainfuck Compilers](../../too-many-brainfuck-compilers.md)\n\n\n\n## 翻译 Translation\n\n鉴于水平所限，\n\n难免出现翻译错误，\n\n如发现错误还请告知！\n\n\n\nskanfd 译\n\n2021年4月21日\n\n"
  },
  {
    "path": "posts/translations/zh-hans/why-blog.md",
    "content": "# 为什么写博客？\n\n_2020年 5月 2日 · #blogging_\n\n在学习 Rust 时我一直被几个概念所困扰，所以我尝试通过写 Markdown 组织我的想法。\n我很快便有了好几个 Markdown 文件。我想， _也许可以开始写博客？_ 但我意识到，\n_不行，我的小博客永远不会像 Niko Matsakis、Saoirse Shipwreckt、\nHuon Wilson、David Tolnay、Alexis Beingessner、Daniel Keep、Carl Fredrik Samson、\nAleksey Kladov、Amos Wegner、Pascal Hertleif、Dimitri Sabadie、\nDaniel Henry-Mantilla、\nSteve Klabnik、Jake Goulding 和 Carol Nichols 的那样出彩。_\n这个名单一点也不全面，还缺好几十个人呢！\n有好多比我聪明得多的人已经在写这一类东西了。但是，我有一个独特的优势：我很蠢。\n聪明人更倾向于写抽象文章给聪明人看。对于像我这样的傻瓜来说，\n市面上有一个巨大的空白，我打算把它填上。\n\n另外，这张图不错：\n\n![哇，两个蛋糕！](../../../assets/holy-shit-two-cakes.png)\n\n_作者：[stuffman](https://stuffman.tumblr.com/)_\n\n## 行，但为什么要放到 GitHub 仓库里而不是建一个网站？\n\n我是一个全栈网页网络开发人员，所以我对网站 _非常挑剔_ 。\n我致力于做一个 _完美的前端_ ，但是一点东西也没写出来。\n我知道有[无数静态网页生成器](https://www.staticgen.com/)把九成以上的工作都做完了，\n但我都试了一遍却一个也不喜欢。不是因为它们不好，实际上很多都不错，\n但我是个工匠，更喜欢自己动手。这是个问题，我知道。\n\n我差点放弃了我的这个想法，但后来我看见了 [Frank McSherry 的博客](https://github.com/frankmcsherry/blog)。\n哇！我怎么这么蠢，愣是没想到可以这样？不需要折腾一点前端！只要把文章放到 GitHub 上，\n别人就可以直接读了，无比简单。我喜欢这样。我决定也这么做，这样我就有时间写东西了。\n\n另：这个博客只有关于 Rust 的事，除了这篇文章没有任何个人的事。\n\n## 参阅\n\n- [Rust 中常见的有关生命周期的误解](./../../common-rust-lifetime-misconceptions.md)\n- [Rust 标准库特性指南](./tour-of-rusts-standard-library-traits.md)\n- [Sizedness in Rust](./../../sizedness-in-rust.md)\n- [RESTful API in Sync & Async Rust](./../../restful-api-in-sync-and-async-rust.md)\n- [2020 年的 Rust 学习指南](./learning-rust-in-2020.md)\n- [Learn Assembly with Entirely Too Many Brainfuck Compilers](./../../too-many-brainfuck-compilers.md)\n"
  },
  {
    "path": "posts/why-blog.md",
    "content": "# Why blog?\n\n_02 May 2020 · #blogging_\n\nWhile learning Rust I was struggling with certain concepts so I tried to organize my thoughts by writing them down in markdown files and I soon had several markdown files. I thought _\"Maybe I should start a blog?\"_ but then I realized _\"I probably shouldn't, my posts will never be as good as anything written on Rust by Niko Matsakis, Saoirse Shipwreckt, Huon Wilson, David Tolnay, Alexis Beingessner, Daniel Keep, Carl Fredrik Samson, Aleksey Kladov, Amos Wegner, Pascal Hertleif, Dimitri Sabadie, Daniel Henry-Mantilla, Steve Klabnik, Jake Goulding, or Carol Nichols\"_. That list isn't even exhaustive, there's easily dozens of people I left out! There's lots of super smart people who are already writing about Rust. However, I have one unique advantage that none of those people have: I'm dumb. Super smart people tend to write super smart articles that only other super smart people understand. There's a gap in the market for us dummies, and it's that gap I intend to fill with my writing.\n\nAlso I saw this comic which was pretty encouraging:\n\n![holy shit two cakes](../assets/holy-shit-two-cakes.png)\n\n_Artist credit: [stuffman](https://stuffman.tumblr.com/)_\n\n## Yeah but why is your blog a github repo and not a website?\n\nI'm a full-stack webdev by trade so I'm _super nitpicky_ when it comes to websites. I get lost in the technical details of trying to build _the perfect website_ that I spend zero time actually writing any content. I know there are [hundreds of static site generators](https://www.staticgen.com/) that do 90%+ of the technical work for you but I've tried those in the past and wasn't satisfied with them. That's not because they're bad tools, a lot of them are excellent tools, it's just that I'm a craftsman and not happy with something unless I made it with my own two hands. It's a problem, I know.\n\nI was almost about to give up on my blog idea but that's when I ran across [Frank McSherry's blog](https://github.com/frankmcsherry/blog). Wow, how come I've never thought of doing that? You don't have to build, deploy, or render anything! You push the markdown files to github and people can just read them on github. It's so simple. I love it. I decided to take this approach for my own blog so that I could focus all of my productive energy into actually writing good content.\n\nOne small final note: I plan to focus this blog entirely around Rust. Aside from this initial post I don't intend to use this blog to post about personal things.\n\n\n\n## Further Reading\n\n- [Common Rust Lifetime Misconceptions](./common-rust-lifetime-misconceptions.md)\n- [Tour of Rust's Standard Library Traits](./tour-of-rusts-standard-library-traits.md)\n- [Beginner's Guide to Concurrent Programming: Coding a Multithreaded Chat Server using Tokio](./chat-server.md)\n- [Learning Rust in 2024](./learning-rust-in-2024.md)\n- [Using Rust in Non-Rust Servers to Improve Performance](./rust-in-non-rust-servers.md)\n- [Sizedness in Rust](./sizedness-in-rust.md)\n- [RESTful API in Sync & Async Rust](./restful-api-in-sync-and-async-rust.md)\n- [Learn Assembly with Entirely Too Many Brainfuck Compilers](./too-many-brainfuck-compilers.md)\n\n\n\n## Notifications\n\nGet notified when a new blog post gets published by\n- Subscribing to this repo's [releases RSS feed](https://github.com/pretzelhammer/rust-blog/releases.atom) or\n- Watching this repo's releases (click `Watch` → click `Custom` → select `Releases` → click `Apply`)\n"
  },
  {
    "path": "readme.md",
    "content": "# pretzelhammer's Rust blog 🦀\n\nI write educational content for Rust beginners and Rust advanced beginners.\n\nHere are my posts in reverse chronological order.\n\n| Year | Title | Popularity | Translations |\n|-|-|-|-|\n| 2024 | [Using Rust in Non-Rust Servers to Improve Performance](./posts/rust-in-non-rust-servers.md) | 🔥🔥 | [中文](./posts/translations/zh-hans/rust-in-non-rust-servers.md) |\n| 2024 | [Learning Rust in 2024](./posts/learning-rust-in-2024.md) | 🔥🔥🔥 | [中文](./posts/translations/zh-hans/learning-rust-in-2024.md) |\n| 2024 | [Beginner's Guide to Concurrent Programming: Coding a Multithreaded Chat Server using Tokio](./posts/chat-server.md) | 🔥🔥 | [中文](./posts/translations/zh-hans/chat-server.md) |\n| 2021 | [RESTful API in Sync & Async Rust](./posts/restful-api-in-sync-and-async-rust.md) | 🔥 | - |\n| 2021 | [Tour of Rust's Standard Library Traits](./posts/tour-of-rusts-standard-library-traits.md) | 🔥🔥🔥 |[中文](./posts/translations/zh-hans/tour-of-rusts-standard-library-traits.md) |\n| 2020 | [Learn Assembly with Entirely Too Many Brainfuck Compilers](./posts/too-many-brainfuck-compilers.md) | 🔥 | - |\n| 2020 | [Sizedness in Rust](./posts/sizedness-in-rust.md) | 🔥🔥 | [中文](./posts/translations/zh-hans/sizedness-in-rust.md) |\n| 2020 | [Common Rust Lifetime Misconceptions](./posts/common-rust-lifetime-misconceptions.md) | 🔥🔥🔥🔥 | [中文](./posts/translations/zh-hans/common-rust-lifetime-misconceptions.md) · [日本語](./posts/translations/jp/common-rust-lifetime-misconceptions.md) · [русский](./posts/translations/rus/common-rust-lifetime-misconceptions.md) |\n| 2020 | [Learning Rust in 2020](./posts/learning-rust-in-2020.md) | 🔥🔥 | [中文](./posts/translations/zh-hans/learning-rust-in-2020.md) |\n| 2020 | [Why blog?](./posts/why-blog.md) | - | [中文](./posts/translations/zh-hans/why-blog.md) · [Türkçe](./posts/translations/tr/why-blog.md)  |\n\nNote: translations are community-maintained.\n\n## Notifications\n\nGet notified when a new blog post gets published by\n- Subscribing to this repo's [releases RSS feed](https://github.com/pretzelhammer/rust-blog/releases.atom) or\n- Watching this repo's releases (click `Watch` → click `Custom` → select `Releases` → click `Apply`)\n\n## Feedback\n\nIf you have any feedback please feel welcome to [open an issue](https://github.com/pretzelhammer/rust-blog/issues/new) on this repo. I accept pull requests for minor fixes like typos and grammar.\n\n## Translations\n\nIf you wanna translate a blog post into another language that's awesome! Please feel free to fork this repo and promote your translation however you like. I also accept pull requests for translations if you'd like to host your translation on my blog directly.\n\n## Licensing\n\nTo be compatible with [Rust](https://github.com/rust-lang/rust), all code examples in this blog are licensed under [Apache License Version 2.0](./license-apache) or [MIT License](./license-mit), at your option.\n\nI'd like to retain exclusive rights to the English version of the posts themselves, but as mentioned above if you translate a post into another language you're welcome to promote your translations however you like.\n"
  }
]