[INFO] cloning repository https://github.com/pat11639/fake
[INFO] running `Command { std: "git" "-c" "credential.helper=" "-c" "credential.helper=/workspace/cargo-home/bin/git-credential-null" "clone" "--bare" "https://github.com/pat11639/fake" "/workspace/cache/git-repos/https%3A%2F%2Fgithub.com%2Fpat11639%2Ffake", kill_on_drop: false }`
[INFO] [stderr] Cloning into bare repository '/workspace/cache/git-repos/https%3A%2F%2Fgithub.com%2Fpat11639%2Ffake'...
[INFO] running `Command { std: "git" "rev-parse" "HEAD", kill_on_drop: false }`
[INFO] [stdout] a6a7d443555d4daaf58fcdd52bd9371786f7bc06
[INFO] testing pat11639/fake against nightly-2025-01-18+rustflags=-Zrandomize-layout for randomize-layout-2
[INFO] running `Command { std: "git" "clone" "/workspace/cache/git-repos/https%3A%2F%2Fgithub.com%2Fpat11639%2Ffake" "/workspace/builds/worker-6-tc2/source", kill_on_drop: false }`
[INFO] [stderr] Cloning into '/workspace/builds/worker-6-tc2/source'...
[INFO] [stderr] done.
[INFO] validating manifest of git repo https://github.com/pat11639/fake on toolchain nightly-2025-01-18
[INFO] running `Command { std: CARGO_HOME="/workspace/cargo-home" RUSTUP_HOME="/workspace/rustup-home" "/workspace/cargo-home/bin/cargo" "+nightly-2025-01-18" "metadata" "--manifest-path" "Cargo.toml" "--no-deps", kill_on_drop: false }`
[INFO] started tweaking git repo https://github.com/pat11639/fake
[INFO] finished tweaking git repo https://github.com/pat11639/fake
[INFO] tweaked toml for git repo https://github.com/pat11639/fake written to /workspace/builds/worker-6-tc2/source/Cargo.toml
[INFO] crate git repo https://github.com/pat11639/fake already has a lockfile, it will not be regenerated
[INFO] running `Command { std: CARGO_HOME="/workspace/cargo-home" RUSTUP_HOME="/workspace/rustup-home" "/workspace/cargo-home/bin/cargo" "+nightly-2025-01-18" "fetch" "--manifest-path" "Cargo.toml", kill_on_drop: false }`
[INFO] [stderr] warning: no edition set: defaulting to the 2015 edition while the latest is 2024
[INFO] running `Command { std: "docker" "create" "-v" "/var/lib/crater-agent-workspace/builds/worker-6-tc2/target:/opt/rustwide/target:rw,Z" "-v" "/var/lib/crater-agent-workspace/builds/worker-6-tc2/source:/opt/rustwide/workdir:ro,Z" "-v" "/var/lib/crater-agent-workspace/cargo-home:/opt/rustwide/cargo-home:ro,Z" "-v" "/var/lib/crater-agent-workspace/rustup-home:/opt/rustwide/rustup-home:ro,Z" "-e" "SOURCE_DIR=/opt/rustwide/workdir" "-e" "CARGO_TARGET_DIR=/opt/rustwide/target" "-e" "CARGO_HOME=/opt/rustwide/cargo-home" "-e" "RUSTUP_HOME=/opt/rustwide/rustup-home" "-w" "/opt/rustwide/workdir" "-m" "1610612736" "--user" "0:0" "--network" "none" "ghcr.io/rust-lang/crates-build-env/linux@sha256:819108c5571ea2e421544af4d832f968d213c87fbe3707a016657f43d2f853bc" "/opt/rustwide/cargo-home/bin/cargo" "+nightly-2025-01-18" "metadata" "--no-deps" "--format-version=1", kill_on_drop: false }`
[INFO] [stdout] f6bb7c042a12b9ae1bad12c68d8a9c16a3f568e13efb8a0117e95b8277b2fcc7
[INFO] running `Command { std: "docker" "start" "-a" "f6bb7c042a12b9ae1bad12c68d8a9c16a3f568e13efb8a0117e95b8277b2fcc7", kill_on_drop: false }`
[INFO] running `Command { std: "docker" "inspect" "f6bb7c042a12b9ae1bad12c68d8a9c16a3f568e13efb8a0117e95b8277b2fcc7", kill_on_drop: false }`
[INFO] running `Command { std: "docker" "rm" "-f" "f6bb7c042a12b9ae1bad12c68d8a9c16a3f568e13efb8a0117e95b8277b2fcc7", kill_on_drop: false }`
[INFO] [stdout] f6bb7c042a12b9ae1bad12c68d8a9c16a3f568e13efb8a0117e95b8277b2fcc7
[INFO] running `Command { std: "docker" "create" "-v" "/var/lib/crater-agent-workspace/builds/worker-6-tc2/target:/opt/rustwide/target:rw,Z" "-v" "/var/lib/crater-agent-workspace/builds/worker-6-tc2/source:/opt/rustwide/workdir:ro,Z" "-v" "/var/lib/crater-agent-workspace/cargo-home:/opt/rustwide/cargo-home:ro,Z" "-v" "/var/lib/crater-agent-workspace/rustup-home:/opt/rustwide/rustup-home:ro,Z" "-e" "SOURCE_DIR=/opt/rustwide/workdir" "-e" "CARGO_TARGET_DIR=/opt/rustwide/target" "-e" "CARGO_INCREMENTAL=0" "-e" "RUST_BACKTRACE=full" "-e" "RUSTFLAGS=--cap-lints=forbid -Zrandomize-layout" "-e" "RUSTDOCFLAGS=--cap-lints=forbid" "-e" "CARGO_HOME=/opt/rustwide/cargo-home" "-e" "RUSTUP_HOME=/opt/rustwide/rustup-home" "-w" "/opt/rustwide/workdir" "-m" "1610612736" "--user" "0:0" "--network" "none" "ghcr.io/rust-lang/crates-build-env/linux@sha256:819108c5571ea2e421544af4d832f968d213c87fbe3707a016657f43d2f853bc" "/opt/rustwide/cargo-home/bin/cargo" "+nightly-2025-01-18" "build" "--frozen" "--message-format=json", kill_on_drop: false }`
[INFO] [stdout] f18fdb8506fcfb182a0e7ff8acd6632d7c18644a0fa9aa88507d0f1616497747
[INFO] running `Command { std: "docker" "start" "-a" "f18fdb8506fcfb182a0e7ff8acd6632d7c18644a0fa9aa88507d0f1616497747", kill_on_drop: false }`
[INFO] [stderr] warning: no edition set: defaulting to the 2015 edition while the latest is 2024
[INFO] [stderr]    Compiling version_check v0.9.3
[INFO] [stderr]    Compiling libc v0.2.98
[INFO] [stderr]    Compiling proc-macro2 v1.0.27
[INFO] [stderr]    Compiling memchr v2.4.0
[INFO] [stderr]    Compiling autocfg v1.0.1
[INFO] [stderr]    Compiling glob v0.3.0
[INFO] [stderr]    Compiling unicode-width v0.1.8
[INFO] [stderr]    Compiling log v0.4.14
[INFO] [stderr]    Compiling regex-syntax v0.6.25
[INFO] [stderr]    Compiling vec_map v0.8.2
[INFO] [stderr]    Compiling ansi_term v0.11.0
[INFO] [stderr]    Compiling strsim v0.8.0
[INFO] [stderr]    Compiling termcolor v1.1.2
[INFO] [stderr]    Compiling libloading v0.7.0
[INFO] [stderr]    Compiling syn v1.0.73
[INFO] [stderr]    Compiling bindgen v0.56.0
[INFO] [stderr]    Compiling textwrap v0.11.0
[INFO] [stderr]    Compiling humantime v2.1.0
[INFO] [stderr]    Compiling shlex v0.1.1
[INFO] [stderr]    Compiling lazycell v1.3.0
[INFO] [stderr]    Compiling serde v1.0.126
[INFO] [stderr]    Compiling peeking_take_while v0.1.2
[INFO] [stderr]    Compiling rustc-hash v1.1.0
[INFO] [stderr]    Compiling nom v5.1.2
[INFO] [stderr]    Compiling proc-macro-error-attr v1.0.4
[INFO] [stderr]    Compiling pkg-config v0.3.19
[INFO] [stderr]    Compiling cc v1.0.69
[INFO] [stderr]    Compiling proc-macro-error v1.0.4
[INFO] [stderr]    Compiling ryu v1.0.5
[INFO] [stderr]    Compiling clang-sys v1.2.0
[INFO] [stderr]    Compiling num-traits v0.2.14
[INFO] [stderr]    Compiling miniz_oxide v0.4.4
[INFO] [stderr]    Compiling num-integer v0.1.44
[INFO] [stderr]    Compiling atty v0.2.14
[INFO] [stderr]    Compiling which v3.1.1
[INFO] [stderr]    Compiling clap v2.33.3
[INFO] [stderr]    Compiling crc32fast v1.2.1
[INFO] [stderr]    Compiling unicase v2.6.0
[INFO] [stderr]    Compiling serde_json v1.0.64
[INFO] [stderr]    Compiling serde_derive v1.0.126
[INFO] [stderr]    Compiling adler v1.0.2
[INFO] [stderr]    Compiling safemem v0.3.3
[INFO] [stderr]    Compiling quote v1.0.9
[INFO] [stderr]    Compiling aho-corasick v0.7.18
[INFO] [stderr]    Compiling line-wrap v0.1.1
[INFO] [stderr]    Compiling base64 v0.10.1
[INFO] [stderr]    Compiling humantime v1.3.0
[INFO] [stderr]    Compiling pulldown-cmark v0.8.0
[INFO] [stderr]    Compiling linked-hash-map v0.5.4
[INFO] [stderr]    Compiling xml-rs v0.8.3
[INFO] [stderr]    Compiling maud_htmlescape v0.17.0
[INFO] [stderr]    Compiling itoa v0.4.7
[INFO] [stderr]    Compiling walkdir v2.3.2
[INFO] [stderr]    Compiling yaml-rust v0.4.5
[INFO] [stderr]    Compiling time v0.1.44
[INFO] [stderr]    Compiling getopts v0.2.21
[INFO] [stderr]    Compiling flate2 v1.0.20
[INFO] [stderr]    Compiling cexpr v0.4.0
[INFO] [stderr]    Compiling chrono v0.4.19
[INFO] [stderr]    Compiling ordinal v0.2.3
[INFO] [stderr]    Compiling maud_macros v0.22.2
[INFO] [stderr]    Compiling regex v1.5.4
[INFO] [stderr]    Compiling maud v0.22.2
[INFO] [stderr]    Compiling plist v0.4.2
[INFO] [stderr]    Compiling bincode v1.3.3
[INFO] [stderr]    Compiling env_logger v0.8.4
[INFO] [stderr]    Compiling onig_sys v69.7.0
[INFO] [stderr]    Compiling onig v5.0.0
[INFO] [stderr]    Compiling syntect v3.3.0
[INFO] [stderr]    Compiling blogc v0.1.0 (/opt/rustwide/workdir)
[INFO] [stderr]     Finished `dev` profile [unoptimized + debuginfo] target(s) in 39.05s
[INFO] [stderr] warning: the following packages contain code that will be rejected by a future version of Rust: nom v5.1.2
[INFO] [stderr] note: to see what the problems were, use the option `--future-incompat-report`, or run `cargo report future-incompatibilities --id 1`
[INFO] running `Command { std: "docker" "inspect" "f18fdb8506fcfb182a0e7ff8acd6632d7c18644a0fa9aa88507d0f1616497747", kill_on_drop: false }`
[INFO] running `Command { std: "docker" "rm" "-f" "f18fdb8506fcfb182a0e7ff8acd6632d7c18644a0fa9aa88507d0f1616497747", kill_on_drop: false }`
[INFO] [stdout] f18fdb8506fcfb182a0e7ff8acd6632d7c18644a0fa9aa88507d0f1616497747
[INFO] running `Command { std: "docker" "create" "-v" "/var/lib/crater-agent-workspace/builds/worker-6-tc2/target:/opt/rustwide/target:rw,Z" "-v" "/var/lib/crater-agent-workspace/builds/worker-6-tc2/source:/opt/rustwide/workdir:ro,Z" "-v" "/var/lib/crater-agent-workspace/cargo-home:/opt/rustwide/cargo-home:ro,Z" "-v" "/var/lib/crater-agent-workspace/rustup-home:/opt/rustwide/rustup-home:ro,Z" "-e" "SOURCE_DIR=/opt/rustwide/workdir" "-e" "CARGO_TARGET_DIR=/opt/rustwide/target" "-e" "CARGO_INCREMENTAL=0" "-e" "RUST_BACKTRACE=full" "-e" "RUSTFLAGS=--cap-lints=forbid -Zrandomize-layout" "-e" "RUSTDOCFLAGS=--cap-lints=forbid" "-e" "CARGO_HOME=/opt/rustwide/cargo-home" "-e" "RUSTUP_HOME=/opt/rustwide/rustup-home" "-w" "/opt/rustwide/workdir" "-m" "1610612736" "--user" "0:0" "--network" "none" "ghcr.io/rust-lang/crates-build-env/linux@sha256:819108c5571ea2e421544af4d832f968d213c87fbe3707a016657f43d2f853bc" "/opt/rustwide/cargo-home/bin/cargo" "+nightly-2025-01-18" "test" "--frozen" "--no-run" "--message-format=json", kill_on_drop: false }`
[INFO] [stdout] b7cb53986fec94faffeac4eef14cb44bdb5373eb9eac6e928648759e9d3696fd
[INFO] running `Command { std: "docker" "start" "-a" "b7cb53986fec94faffeac4eef14cb44bdb5373eb9eac6e928648759e9d3696fd", kill_on_drop: false }`
[INFO] [stderr] warning: no edition set: defaulting to the 2015 edition while the latest is 2024
[INFO] [stderr]    Compiling blogc v0.1.0 (/opt/rustwide/workdir)
[INFO] [stderr]     Finished `test` profile [unoptimized + debuginfo] target(s) in 1.68s
[INFO] [stderr] warning: the following packages contain code that will be rejected by a future version of Rust: nom v5.1.2
[INFO] [stderr] note: to see what the problems were, use the option `--future-incompat-report`, or run `cargo report future-incompatibilities --id 1`
[INFO] running `Command { std: "docker" "inspect" "b7cb53986fec94faffeac4eef14cb44bdb5373eb9eac6e928648759e9d3696fd", kill_on_drop: false }`
[INFO] running `Command { std: "docker" "rm" "-f" "b7cb53986fec94faffeac4eef14cb44bdb5373eb9eac6e928648759e9d3696fd", kill_on_drop: false }`
[INFO] [stdout] b7cb53986fec94faffeac4eef14cb44bdb5373eb9eac6e928648759e9d3696fd
[INFO] running `Command { std: "docker" "create" "-v" "/var/lib/crater-agent-workspace/builds/worker-6-tc2/target:/opt/rustwide/target:rw,Z" "-v" "/var/lib/crater-agent-workspace/builds/worker-6-tc2/source:/opt/rustwide/workdir:ro,Z" "-v" "/var/lib/crater-agent-workspace/cargo-home:/opt/rustwide/cargo-home:ro,Z" "-v" "/var/lib/crater-agent-workspace/rustup-home:/opt/rustwide/rustup-home:ro,Z" "-e" "SOURCE_DIR=/opt/rustwide/workdir" "-e" "CARGO_TARGET_DIR=/opt/rustwide/target" "-e" "CARGO_INCREMENTAL=0" "-e" "RUST_BACKTRACE=full" "-e" "RUSTFLAGS=--cap-lints=forbid -Zrandomize-layout" "-e" "RUSTDOCFLAGS=--cap-lints=forbid" "-e" "CARGO_HOME=/opt/rustwide/cargo-home" "-e" "RUSTUP_HOME=/opt/rustwide/rustup-home" "-w" "/opt/rustwide/workdir" "-m" "1610612736" "--user" "0:0" "--network" "none" "ghcr.io/rust-lang/crates-build-env/linux@sha256:819108c5571ea2e421544af4d832f968d213c87fbe3707a016657f43d2f853bc" "/opt/rustwide/cargo-home/bin/cargo" "+nightly-2025-01-18" "test" "--frozen", kill_on_drop: false }`
[INFO] [stdout] 06e3ab65d55e33fbd8b884fa768186205a703c8caa232ac8877733d29998f9e0
[INFO] running `Command { std: "docker" "start" "-a" "06e3ab65d55e33fbd8b884fa768186205a703c8caa232ac8877733d29998f9e0", kill_on_drop: false }`
[INFO] [stderr] warning: no edition set: defaulting to the 2015 edition while the latest is 2024
[INFO] [stderr]     Finished `test` profile [unoptimized + debuginfo] target(s) in 0.12s
[INFO] [stderr] warning: the following packages contain code that will be rejected by a future version of Rust: nom v5.1.2
[INFO] [stderr] note: to see what the problems were, use the option `--future-incompat-report`, or run `cargo report future-incompatibilities --id 1`
[INFO] [stderr]      Running unittests src/lib.rs (/opt/rustwide/target/debug/deps/blog-046068d88437f0cc)
[INFO] [stdout] 
[INFO] [stdout] running 10 tests
[INFO] [stdout] test post::tests::it_returns_an_error_for_an_unexpected_filename ... ok
[INFO] [stdout] test post::tests::it_overrides_the_path_when_url_is_specified ... ok
[INFO] [stdout] test post_link::tests::it_returns_an_empty_array_of_links ... ok
[INFO] [stdout] test post::tests::it_renders_hard_coded_legacy_html_from_a_file ... ok
[INFO] [stdout] test post_link::tests::it_returns_a_valid_array_of_links ... ok
[INFO] [stdout] test post::tests::it_parses_the_title ... ok
[INFO] [stdout] test post::tests::it_parses_the_date ... ok
[INFO] [stdout] test post::tests::it_calculates_an_output_path_and_directory ... ok
[INFO] [stdout] test post_link::tests::it_returns_links_without_repeated_months ... ok
[INFO] [stdout] test post::tests::it_renders_html ... FAILED
[INFO] [stdout] 
[INFO] [stdout] failures:
[INFO] [stdout] 
[INFO] [stdout] ---- post::tests::it_renders_html stdout ----
[INFO] [stdout] 
[INFO] [stdout] thread 'post::tests::it_renders_html' panicked at src/post.rs:265:9:
[INFO] [stdout] assertion `left == right` failed
[INFO] [stdout]   left: "<div style=\"float: right; padding: 8px 0px 40px 30px; text-align: center; line-height:18px\">\n  <img src=\"http://patshaughnessy.net/assets/2018/1/18/dictionary.jpg\"><br/>\n  <i>Human languages have similar words with different<br/> shades of meaning. Some computer languages do too.<br/>\n  <small>(from: <a href=\"https://commons.wikimedia.org/wiki/File:ĸra_in_a_dictionary_(ubt).JPG\">Wikimedia Commons</a>)</small></i> \n</div>\n<p>This year I’ve decided to try to learn <a href=\"https://www.rust-lang.org\">Rust</a>. I’m\nfascinated by its ownership model for memory management; I’m curious what the\nclaims about safety are all about; and, I love how it incorporates ideas from\nthe functional programming world. But I haven’t gotten to all of that yet - I’m\njust getting started learning the basic syntax.</p>\n<p>Learning a computer language is just like learning a human language. You have\nto try to read and write it everyday, even if just for a few minutes. You need\nto get to know some native speakers. And there’s no way around it: You need to\nlearn the basic vocabulary of the language, word by word. To make things worse,\nour human languages usually have several  words that mean the same thing. Which\none should I use? Sometime only a native speaker will really know.</p>\n<p>This week I was reading about <span class=\"code\">if let</span> and <span\nclass=\"code\">match</span> in <a href=\"https://doc.rust-lang.org/book/second-edition/ch06-03-if-let.html\">The Rust Programming\nBook</a>\n(TRPL). I read that <span class=\"code\">if let</span> is really syntactic sugar\nfor <span class=\"code\">match</span>:</p>\n<div style=\"padding: 8px 0px 40px 30px; text-align: center; line-height:18px\">\n<img width=\"500\" src=\"http://patshaughnessy.net/assets/2018/1/18/trpl-quote.png\"/>\n</div>\n<p>This intrigued me. The phrase “syntactic sugar” implies the two code snippets\ndon’t only produce the same results, it means the compiler generates exactly\nthe same code in each case.</p>\n<p>Does the Rust compiler really generate exactly the same code for <span\nclass=\"code\">if let</span> as it does for <span class=\"code\">match</span>? Read\non to find out. Today I’ll start with a quick review of the syntax and meaning\nof <span class=\"code\">if let</span> and <span class=\"code\">match</span>. Then\nI’ll take a look at how Rust compiles <span class=\"code\">if let</span> and\n<span class=\"code\">match</span>, at what code it produces.</p>\n<h2>If Let Compares a Pattern with a Value</h2>\n<p>The idea behind <span class=\"code\">if let</span> is that it compares a pattern\nwith a value:</p>\n<img src=\"http://patshaughnessy.net/assets/2018/1/18/pattern-value.png\"/>\n<p>In this example <span class=\"code\">if let</span> compares the pattern <span\nclass=\"code\">Some(3)</span> with the value <span\nclass=\"code\">some_u8_value</span>. If there’s a match, <span class=\"code\">if\nlet</span> executes the <span class=\"code\">println!</span> code inside the\nblock.</p>\n<h2>If Let Also Assigns Values</h2>\n<p><span class=\"code\">if let</span> assigns a value at the same time, when the\npattern matches the value. This is the idea behind including the <span class=\"code\">let</span> keyword\nafter <span class=\"code\">if</span>. This is more apparent if I rewrite the example using a variable <span class=\"code\">i</span>\ninstead of 3. I'll also add a main function so I can execute the code:</p>\n<pre>\nfn main() {\n  let some_u8_value = Some(3u8);\n  if let Some(i) = some_u8_value {\n     println!(\"assigned {} to i\", i);\n  }\n}\n</pre>\n<p>When I saved this in a file called if-let.rs and ran it, I got:</p>\n<pre>\n$ rustc if-let.rs\n$ ./main\nAssigned 3 to i\n</pre>\n<p><span class=\"code\">if let</span> “unwrapped” the option structure, and assigned\nthe value 3 to the identifier <span class=\"code\">i</span>.</p>\n<h2>Match: If Let’s Big Brother</h2>\n<p>As TRPL explains, I could also have written this using the <span\nclass=\"code\">match</span> keyword, as follows:</p>\n<pre>\nfn main() {\n    let some_u8_value = Some(3u8);\n    match some_u8_value {\n        Some(i) => println!(\"Matched: {}\", i),\n        None => (),\n    }\n}\n</pre>\n<p>To write this all I had to do was move things around a bit in my <span\nclass=\"code\">if let</span> code snippet from above:</p>\n<img src=\"http://patshaughnessy.net/assets/2018/1/18/if-let-match.png\"/>\n<p>Because there was no else clause for the <span class=\"code\">if let</span>\nstatement, I used <span class=\"code\">None =&gt; ()</span> in match.</p>\n<p>Saving this code in match.rs and running it I got the same result:</p>\n<pre>\n$ rustc match.rs\n$ ./main\nMatched: 3\n</pre>\n<h2>Mid-Level IR (MIR)</h2>\n<p>I was curious though: If these two code snippets are entirely equivalent, then\nthe Rust compiler should generate <em>exactly the same executable program</em> when I\ncompile them. In theory, therefore, I should be able to compare the two\nexecutable binaries to test whether TRPL’s statement about syntactic sugar is\naccurate. But comparing binary executables might not work. Likely there are\ntimestamps or other ephemeral values encoded in the executable that would break\nthe comparison. I decided to look for an easier way to test the compiler’s\noutput.</p>\n<p>Then I came across mid-level intermediate representation (MIR), described <a href=\"https://blog.rust-lang.org/2016/04/19/MIR.html\">here\non the Rust blog</a>. MIR is an\ninternal text language the rust compiler produces when you include the\n<span class=\"code\">—emit-mir</span> flag, like this:</p>\n<pre>\n$ rustc --emit mir if-let.rs\n</pre>\n<p>With this option specified, rust generates a file called if-let.mir. Opening up\nthis file, I see:</p>\n<pre>\n// WARNING: This output format is intended for human consumers only\n// and is subject to change without notice. Knock yourself out.\nfn main() -> () {\n    let mut _0: ();                      // return pointer\n    scope 1 {\n        let _1: std::option::Option<u8>; // \"some_u8_value\" in scope 1 at src/if-let.rs:16:9: 16:22\n\netc…\n</pre>\n<p>“Knock yourself out;” now I’m really intrigued!</p>\n<h2>A First Look at MIR</h2>\n<p>I decided to compare the MIR text file the Rust compiler produced for the <span class=\"code\">if\nlet</span> snippet vs. the <span class=\"code\">match</span> snippet. If Rust\nconsiders <span class=\"code\">if let</span> to be syntactic sugar for <span\nclass=\"code\">match</span>, then the MIR representation of the two snippets\nshould be the same.</p>\n<p>But when I started reading the MIR code, I found the call to the <span\nclass=\"code\">println!</span> macro generated a lot of verbose text:</p>\n<pre>\nlet mut _3: isize;\nlet mut _4: ();\nlet mut _5: std::fmt::Arguments;\nlet mut _6: &[&str];\nlet mut _7: &[&str; 2];\nlet mut _8: &[&str; 2];\nlet mut _9: &[std::fmt::ArgumentV1];\nlet mut _10: &[std::fmt::ArgumentV1; 1];\nlet mut _11: &[std::fmt::ArgumentV1; 1];\nlet mut _12: [std::fmt::ArgumentV1; 1];\nlet mut _13: (&u8,);\nlet mut _14: &u8;\nlet mut _16: std::fmt::ArgumentV1;\nlet mut _17: &u8;\nlet mut _18: fn(&u8, &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error>;\n</pre>\n<p>All of this MIR pseudocode might confuse my comparison unnecessarily, so I\ndecided to simplify my <span class=\"code\">if let</span> example by removing the\n<span class=\"code\">println!</span> call entirely. I rewrote the <span\nclass=\"code\">if let</span> snippet like this (if-let.rs):</p>\n<pre>\nfn main() {\n    let some_u8_value = Some(3u8);\n    if let Some(i) = some_u8_value {\n        let _ = i;\n    }\n}\n</pre>\n<p>And the <span class=\"code\">match</span> snippet like this (match.rs):</p>\n<pre>\nfn main() {\n    let some_u8_value = Some(3u8);\n    match some_u8_value {\n        Some(i) => { let _ = i; }\n        None => ()\n    }\n}\n</pre>\n<p>I also noticed the MIR file contained many comments with line numbers:</p>\n<pre>\n_2 = ((_1 as Some).0: u8);       // scope 3 at if-let.rs:3:17: 3:18\nStorageLive(_5);                 // scope 3 at <print macros>:2:27: 2:58\nStorageLive(_6);                 // scope 3 at <println macros>:3:18: 3:43\n</pre>\n<p>I realized the line numbers would likely cause problems comparing one MIR file\nto another, so I removed all of the comments using sed:</p>\n<pre>\n$ rustc if-let.rs --emit mir\n$ cat if-let.mir | sed -e 's/\\/\\/.*$//' > if-let.mir.nocomments\n</pre>\n<p>This generates a new text file called if-let.mir.nocomments, which contains the\nsame content as if-let.mir, but with no comments. And this command processes\nthe match.rs file in the same way:</p>\n<pre>\n$ rustc match.rs --emit mir\n$ cat match.mir | sed -e 's/\\/\\/.*$//' > match.mir.nocomments\n</pre>\n<h2>Comparing MIR Files</h2>\n<p>Now I ran a simple diff command on the simplified MIR text files. If the\ncompiler considers <span class=\"code\">if let</span> to be exactly the same as\n<span class=\"code\">match</span> then there should be no difference, then the\noutput of diff should be empty.</p>\n<p>But running diff I saw:</p>\n<pre>\n$ diff if-let.mir.nocomments match.mir.nocomments\n19c19\n<         switchInt(_3) -> [1isize: bb2, otherwise: bb1];\n---\n>         switchInt(_3) -> [0isize: bb1, otherwise: bb2];\n</pre>\n<p>My two MIR files are <em>almost</em> identical; the MIR text Rust generates for <span\nclass=\"code\">if let</span> is exactly the same as the MIR text Rust generates\nfor <span class=\"code\">match</span>, except for line 19. I’ve <em>almost</em> proven\nthe hypothesis that <span class=\"code\">if let</span> is syntactic sugar for\n<span class=\"code\">match</span>, but not quite.</p>\n<p>Let’s take a close look at the MIR code around line 19 and try to understand\nwhat it means. Here’s a portion of if-let.mir.nocomments, produced by the Rust\ncompiler from my <span class=\"code\">if let</span> code above:</p>\n<pre>\nbb0: {\n    StorageLive(_1);\n    _1 = std::option::Option<u8>::Some(const 3u8,);\n    _3 = discriminant(_1);\n    switchInt(_3) -> [1isize: bb2, otherwise: bb1];\n}\n\nbb1: {\n    _0 = ();\n    goto -> bb3;\n}\n\nbb2: {\n    StorageLive(_2);\n    _2 = ((_1 as Some).0: u8);\n    _0 = ();\n    goto -> bb3;\n}\n</pre>\n<p>I don’t understand MIR syntax, but it’s not hard to guess what’s going on. Each\nof these “bb” blocks of code <span class=\"code\">{ … }</span> probably\nrepresents a logical piece of my program.</p>\n<p>The first block, <span class=\"code\">bb0</span>, seems to assign the value <span class=\"code\">Some(3)</span> to _1, and then calls\n<span class=\"code\">discriminant(_1)</span> and saves the “discriminant,” whatever that is, in _3.\nFinally, it tests whether the discriminant is 1. If the discriminant is 1 it\njumps to <span class=\"code\">bb2</span>, or otherwise to <span\nclass=\"code\">bb1</span>. So <span class=\"code\">bb0</span> likely represents the\n<span class=\"code\">if</span> portion of my <span class=\"code\">if let</span>\nsnippet, testing a condition:</p>\n<pre>\nif let Some(i) = some_u8_value\n</pre>\n<p>The <span class=\"code\">bb1</span> block saves <span class=\"code\">()</span> in <span\nclass=\"code\">_0</span> and jumps to <span class=\"code\">bb3</span>. This likely represents the\nmissing/default else clause of my <span class=\"code\">if let</span> statement.</p>\n<p>And the <span class=\"code\">bb2</span> block saves 3, the unwrapped value inside of <span class=\"code\">Some(3)</span>, in <span class=\"code\">_2</span> and\njumps to <span class=\"code\">bb3</span>. Probably <span class=\"code\">_2</span> is the variable <span class=\"code\">i</span>, and this block of MIR text\nrepresents the <span class=\"code\">let</span> portion of my <span\nclass=\"code\">if let</span> snippet:</p>\n<pre>\nlet Some(i) = some_u8_value\nlet _ = i;\n</pre>\n<p>Now let’s take a look at the <span class=\"code\">match</span> version, the contents of\nmatch.mir.nocomments. It’s entirely the same, except for the <span class=\"code\">switchInt</span> line:</p>\n<pre>\nbb0: {\n    StorageLive(_1);\n    _1 = std::option::Option<u8>::Some(const 3u8,);\n    _3 = discriminant(_1);\n    <b>switchInt(_3) -> [0isize: bb1, otherwise: bb2];</b>\n}\n</pre>\n<p>Reading this carefully, I saw that actually it does mean the same thing: If the\ndiscriminant is 0, Rust calls the <span class=\"code\">bb1</span> block, or\notherwise the <span class=\"code\">bb2</span> block.</p>\n<p>So, summarizing, the <span class=\"code\">if let</span> snippet ran this\npseudo-code:</p>\n<blockquote>\nIf the discriminant is 1, call bb1, else bb2.\n</blockquote>\n<p>…and the <span class=\"code\">match</span> snippet ran this pseudo-code:</p>\n<blockquote>\nIf the discriminant is 0, call bb2, else bb1.\n</blockquote>\n<p>So, in fact, the two versions use the same logic, assuming the value of\ndiscriminant is either 0 or 1. If discriminant = 0, Rust assumes the comparison\nwas true and executes the match clause; if discriminant = 1, Rust executes the\nelse clause.</p>\n<p>Clearly the discriminant function is crucial - when I have time next, I’ll\nexplore what discriminant means, where it’s implemented and how it works. Or if\nanyone from the Rust teams happens to read this, let us know.</p>\n"
[INFO] [stdout]  right: "<div style=\"float: right; padding: 8px 0px 40px 30px; text-align: center; line-height:18px\">\n  <img src=\"http://patshaughnessy.net/assets/2018/1/18/dictionary.jpg\"><br/>\n  <i>Human languages have similar words with different<br/> shades of meaning. Some computer languages do too.<br/>\n  <small>(from: <a href=\"https://commons.wikimedia.org/wiki/File:ĸra_in_a_dictionary_(ubt).JPG\">Wikimedia Commons</a>)</small></i> \n</div>\n<p>This year I’ve decided to try to learn <a href=\"https://www.rust-lang.org\">Rust</a>. I’m\nfascinated by its ownership model for memory management; I’m curious what the\nclaims about safety are all about; and, I love how it incorporates ideas from\nthe functional programming world. But I haven’t gotten to all of that yet - I’m\njust getting started learning the basic syntax.</p>\n<p>Learning a computer language is just like learning a human language. You have\nto try to read and write it everyday, even if just for a few minutes. You need\nto get to know some native speakers. And there’s no way around it: You need to\nlearn the basic vocabulary of the language, word by word. To make things worse,\nour human languages usually have several  words that mean the same thing. Which\none should I use? Sometime only a native speaker will really know.</p>\n<p>This week I was reading about <span class=\"code\">if let</span> and <span\nclass=\"code\">match</span> in <a href=\"https://doc.rust-lang.org/book/second-edition/ch06-03-if-let.html\">The Rust Programming\nBook</a>\n(TRPL). I read that <span class=\"code\">if let</span> is really syntactic sugar\nfor <span class=\"code\">match</span>:</p>\n<div style=\"padding: 8px 0px 40px 30px; text-align: center; line-height:18px\">\n<img width=\"500\" src=\"http://patshaughnessy.net/assets/2018/1/18/trpl-quote.png\"/>\n</div>\n<p>This intrigued me. The phrase “syntactic sugar” implies the two code snippets\ndon’t only produce the same results, it means the compiler generates exactly\nthe same code in each case.</p>\n<p>Does the Rust compiler really generate exactly the same code for <span\nclass=\"code\">if let</span> as it does for <span class=\"code\">match</span>? Read\non to find out. Today I’ll start with a quick review of the syntax and meaning\nof <span class=\"code\">if let</span> and <span class=\"code\">match</span>. Then\nI’ll take a look at how Rust compiles <span class=\"code\">if let</span> and\n<span class=\"code\">match</span>, at what code it produces.</p>\n<h2>If Let Compares a Pattern with a Value</h2>\n<p>The idea behind <span class=\"code\">if let</span> is that it compares a pattern\nwith a value:</p>\n<p><img src=\"http://patshaughnessy.net/assets/2018/1/18/pattern-value.png\"/></p>\n<p>In this example <span class=\"code\">if let</span> compares the pattern <span\nclass=\"code\">Some(3)</span> with the value <span\nclass=\"code\">some_u8_value</span>. If there’s a match, <span class=\"code\">if\nlet</span> executes the <span class=\"code\">println!</span> code inside the\nblock.</p>\n<h2>If Let Also Assigns Values</h2>\n<p><span class=\"code\">if let</span> assigns a value at the same time, when the\npattern matches the value. This is the idea behind including the <span class=\"code\">let</span> keyword\nafter <span class=\"code\">if</span>. This is more apparent if I rewrite the example using a variable <span class=\"code\">i</span>\ninstead of 3. I'll also add a main function so I can execute the code:</p>\n<pre>\nfn main() {\n  let some_u8_value = Some(3u8);\n  if let Some(i) = some_u8_value {\n     println!(\"assigned {} to i\", i);\n  }\n}\n</pre>\n<p>When I saved this in a file called if-let.rs and ran it, I got:</p>\n<pre>\n$ rustc if-let.rs\n$ ./main\nAssigned 3 to i\n</pre>\n<p><span class=\"code\">if let</span> “unwrapped” the option structure, and assigned\nthe value 3 to the identifier <span class=\"code\">i</span>.</p>\n<h2>Match: If Let’s Big Brother</h2>\n<p>As TRPL explains, I could also have written this using the <span\nclass=\"code\">match</span> keyword, as follows:</p>\n<pre>\nfn main() {\n    let some_u8_value = Some(3u8);\n    match some_u8_value {\n        Some(i) => println!(\"Matched: {}\", i),\n        None => (),\n    }\n}\n</pre>\n<p>To write this all I had to do was move things around a bit in my <span\nclass=\"code\">if let</span> code snippet from above:</p>\n<p><img src=\"http://patshaughnessy.net/assets/2018/1/18/if-let-match.png\"/></p>\n<p>Because there was no else clause for the <span class=\"code\">if let</span>\nstatement, I used <span class=\"code\">None =&gt; ()</span> in match.</p>\n<p>Saving this code in match.rs and running it I got the same result:</p>\n<pre>\n$ rustc match.rs\n$ ./main\nMatched: 3\n</pre>\n<h2>Mid-Level IR (MIR)</h2>\n<p>I was curious though: If these two code snippets are entirely equivalent, then\nthe Rust compiler should generate <em>exactly the same executable program</em> when I\ncompile them. In theory, therefore, I should be able to compare the two\nexecutable binaries to test whether TRPL’s statement about syntactic sugar is\naccurate. But comparing binary executables might not work. Likely there are\ntimestamps or other ephemeral values encoded in the executable that would break\nthe comparison. I decided to look for an easier way to test the compiler’s\noutput.</p>\n<p>Then I came across mid-level intermediate representation (MIR), described <a href=\"https://blog.rust-lang.org/2016/04/19/MIR.html\">here\non the Rust blog</a>. MIR is an\ninternal text language the rust compiler produces when you include the\n<span class=\"code\">—emit-mir</span> flag, like this:</p>\n<pre>\n$ rustc --emit mir if-let.rs\n</pre>\n<p>With this option specified, rust generates a file called if-let.mir. Opening up\nthis file, I see:</p>\n<pre>\n// WARNING: This output format is intended for human consumers only\n// and is subject to change without notice. Knock yourself out.\nfn main() -> () {\n    let mut _0: ();                      // return pointer\n    scope 1 {\n        let _1: std::option::Option<u8>; // \"some_u8_value\" in scope 1 at src/if-let.rs:16:9: 16:22\n\netc…\n</pre>\n<p>“Knock yourself out;” now I’m really intrigued!</p>\n<h2>A First Look at MIR</h2>\n<p>I decided to compare the MIR text file the Rust compiler produced for the <span class=\"code\">if\nlet</span> snippet vs. the <span class=\"code\">match</span> snippet. If Rust\nconsiders <span class=\"code\">if let</span> to be syntactic sugar for <span\nclass=\"code\">match</span>, then the MIR representation of the two snippets\nshould be the same.</p>\n<p>But when I started reading the MIR code, I found the call to the <span\nclass=\"code\">println!</span> macro generated a lot of verbose text:</p>\n<pre>\nlet mut _3: isize;\nlet mut _4: ();\nlet mut _5: std::fmt::Arguments;\nlet mut _6: &[&str];\nlet mut _7: &[&str; 2];\nlet mut _8: &[&str; 2];\nlet mut _9: &[std::fmt::ArgumentV1];\nlet mut _10: &[std::fmt::ArgumentV1; 1];\nlet mut _11: &[std::fmt::ArgumentV1; 1];\nlet mut _12: [std::fmt::ArgumentV1; 1];\nlet mut _13: (&u8,);\nlet mut _14: &u8;\nlet mut _16: std::fmt::ArgumentV1;\nlet mut _17: &u8;\nlet mut _18: fn(&u8, &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error>;\n</pre>\n<p>All of this MIR pseudocode might confuse my comparison unnecessarily, so I\ndecided to simplify my <span class=\"code\">if let</span> example by removing the\n<span class=\"code\">println!</span> call entirely. I rewrote the <span\nclass=\"code\">if let</span> snippet like this (if-let.rs):</p>\n<pre>\nfn main() {\n    let some_u8_value = Some(3u8);\n    if let Some(i) = some_u8_value {\n        let _ = i;\n    }\n}\n</pre>\n<p>And the <span class=\"code\">match</span> snippet like this (match.rs):</p>\n<pre>\nfn main() {\n    let some_u8_value = Some(3u8);\n    match some_u8_value {\n        Some(i) => { let _ = i; }\n        None => ()\n    }\n}\n</pre>\n<p>I also noticed the MIR file contained many comments with line numbers:</p>\n<pre>\n_2 = ((_1 as Some).0: u8);       // scope 3 at if-let.rs:3:17: 3:18\nStorageLive(_5);                 // scope 3 at <print macros>:2:27: 2:58\nStorageLive(_6);                 // scope 3 at <println macros>:3:18: 3:43\n</pre>\n<p>I realized the line numbers would likely cause problems comparing one MIR file\nto another, so I removed all of the comments using sed:</p>\n<pre>\n$ rustc if-let.rs --emit mir\n$ cat if-let.mir | sed -e 's/\\/\\/.*$//' > if-let.mir.nocomments\n</pre>\n<p>This generates a new text file called if-let.mir.nocomments, which contains the\nsame content as if-let.mir, but with no comments. And this command processes\nthe match.rs file in the same way:</p>\n<pre>\n$ rustc match.rs --emit mir\n$ cat match.mir | sed -e 's/\\/\\/.*$//' > match.mir.nocomments\n</pre>\n<h2>Comparing MIR Files</h2>\n<p>Now I ran a simple diff command on the simplified MIR text files. If the\ncompiler considers <span class=\"code\">if let</span> to be exactly the same as\n<span class=\"code\">match</span> then there should be no difference, then the\noutput of diff should be empty.</p>\n<p>But running diff I saw:</p>\n<pre>\n$ diff if-let.mir.nocomments match.mir.nocomments\n19c19\n<         switchInt(_3) -> [1isize: bb2, otherwise: bb1];\n---\n>         switchInt(_3) -> [0isize: bb1, otherwise: bb2];\n</pre>\n<p>My two MIR files are <em>almost</em> identical; the MIR text Rust generates for <span\nclass=\"code\">if let</span> is exactly the same as the MIR text Rust generates\nfor <span class=\"code\">match</span>, except for line 19. I’ve <em>almost</em> proven\nthe hypothesis that <span class=\"code\">if let</span> is syntactic sugar for\n<span class=\"code\">match</span>, but not quite.</p>\n<p>Let’s take a close look at the MIR code around line 19 and try to understand\nwhat it means. Here’s a portion of if-let.mir.nocomments, produced by the Rust\ncompiler from my <span class=\"code\">if let</span> code above:</p>\n<pre>\nbb0: {\n    StorageLive(_1);\n    _1 = std::option::Option<u8>::Some(const 3u8,);\n    _3 = discriminant(_1);\n    switchInt(_3) -> [1isize: bb2, otherwise: bb1];\n}\n\nbb1: {\n    _0 = ();\n    goto -> bb3;\n}\n\nbb2: {\n    StorageLive(_2);\n    _2 = ((_1 as Some).0: u8);\n    _0 = ();\n    goto -> bb3;\n}\n</pre>\n<p>I don’t understand MIR syntax, but it’s not hard to guess what’s going on. Each\nof these “bb” blocks of code <span class=\"code\">{ … }</span> probably\nrepresents a logical piece of my program.</p>\n<p>The first block, <span class=\"code\">bb0</span>, seems to assign the value <span class=\"code\">Some(3)</span> to _1, and then calls\n<span class=\"code\">discriminant(_1)</span> and saves the “discriminant,” whatever that is, in _3.\nFinally, it tests whether the discriminant is 1. If the discriminant is 1 it\njumps to <span class=\"code\">bb2</span>, or otherwise to <span\nclass=\"code\">bb1</span>. So <span class=\"code\">bb0</span> likely represents the\n<span class=\"code\">if</span> portion of my <span class=\"code\">if let</span>\nsnippet, testing a condition:</p>\n<pre>\nif let Some(i) = some_u8_value\n</pre>\n<p>The <span class=\"code\">bb1</span> block saves <span class=\"code\">()</span> in <span\nclass=\"code\">_0</span> and jumps to <span class=\"code\">bb3</span>. This likely represents the\nmissing/default else clause of my <span class=\"code\">if let</span> statement.</p>\n<p>And the <span class=\"code\">bb2</span> block saves 3, the unwrapped value inside of <span class=\"code\">Some(3)</span>, in <span class=\"code\">_2</span> and\njumps to <span class=\"code\">bb3</span>. Probably <span class=\"code\">_2</span> is the variable <span class=\"code\">i</span>, and this block of MIR text\nrepresents the <span class=\"code\">let</span> portion of my <span\nclass=\"code\">if let</span> snippet:</p>\n<pre>\nlet Some(i) = some_u8_value\nlet _ = i;\n</pre>\n<p>Now let’s take a look at the <span class=\"code\">match</span> version, the contents of\nmatch.mir.nocomments. It’s entirely the same, except for the <span class=\"code\">switchInt</span> line:</p>\n<pre>\nbb0: {\n    StorageLive(_1);\n    _1 = std::option::Option<u8>::Some(const 3u8,);\n    _3 = discriminant(_1);\n    <b>switchInt(_3) -> [0isize: bb1, otherwise: bb2];</b>\n}\n</pre>\n<p>Reading this carefully, I saw that actually it does mean the same thing: If the\ndiscriminant is 0, Rust calls the <span class=\"code\">bb1</span> block, or\notherwise the <span class=\"code\">bb2</span> block.</p>\n<p>So, summarizing, the <span class=\"code\">if let</span> snippet ran this\npseudo-code:</p>\n<blockquote>\nIf the discriminant is 1, call bb1, else bb2.\n</blockquote>\n<p>…and the <span class=\"code\">match</span> snippet ran this pseudo-code:</p>\n<blockquote>\nIf the discriminant is 0, call bb2, else bb1.\n</blockquote>\n<p>So, in fact, the two versions use the same logic, assuming the value of\ndiscriminant is either 0 or 1. If discriminant = 0, Rust assumes the comparison\nwas true and executes the match clause; if discriminant = 1, Rust executes the\nelse clause.</p>\n<p>Clearly the discriminant function is crucial - when I have time next, I’ll\nexplore what discriminant means, where it’s implemented and how it works. Or if\nanyone from the Rust teams happens to read this, let us know.</p>\n"
[INFO] [stdout] stack backtrace:
[INFO] [stdout]    0:     0x59c2c4fa9b4a - std::backtrace_rs::backtrace::libunwind::trace::hb059275cfc8d6126
[INFO] [stdout]                                at /rustc/6067b36314ab5eb2eb47cecc464545ba58e1ad24/library/std/src/../../backtrace/src/backtrace/libunwind.rs:116:5
[INFO] [stdout]    1:     0x59c2c4fa9b4a - std::backtrace_rs::backtrace::trace_unsynchronized::h2da071e4327ce3ee
[INFO] [stdout]                                at /rustc/6067b36314ab5eb2eb47cecc464545ba58e1ad24/library/std/src/../../backtrace/src/backtrace/mod.rs:66:5
[INFO] [stdout]    2:     0x59c2c4fa9b4a - std::sys::backtrace::_print_fmt::h842a1474e6f8d23f
[INFO] [stdout]                                at /rustc/6067b36314ab5eb2eb47cecc464545ba58e1ad24/library/std/src/sys/backtrace.rs:66:9
[INFO] [stdout]    3:     0x59c2c4fa9b4a - <std::sys::backtrace::BacktraceLock::print::DisplayBacktrace as core::fmt::Display>::fmt::h71a62eb3b9696b12
[INFO] [stdout]                                at /rustc/6067b36314ab5eb2eb47cecc464545ba58e1ad24/library/std/src/sys/backtrace.rs:39:26
[INFO] [stdout]    4:     0x59c2c4fd3c63 - core::fmt::rt::Argument::fmt::hdb6b616786b41dc1
[INFO] [stdout]                                at /rustc/6067b36314ab5eb2eb47cecc464545ba58e1ad24/library/core/src/fmt/rt.rs:177:76
[INFO] [stdout]    5:     0x59c2c4fd3c63 - core::fmt::write::h2cc1698af7e2d686
[INFO] [stdout]                                at /rustc/6067b36314ab5eb2eb47cecc464545ba58e1ad24/library/core/src/fmt/mod.rs:1440:21
[INFO] [stdout]    6:     0x59c2c4fa6113 - std::io::Write::write_fmt::hab1b4cd059a79022
[INFO] [stdout]                                at /rustc/6067b36314ab5eb2eb47cecc464545ba58e1ad24/library/std/src/io/mod.rs:1887:15
[INFO] [stdout]    7:     0x59c2c4fa9992 - std::sys::backtrace::BacktraceLock::print::h147fe35b4ea13b08
[INFO] [stdout]                                at /rustc/6067b36314ab5eb2eb47cecc464545ba58e1ad24/library/std/src/sys/backtrace.rs:42:9
[INFO] [stdout]    8:     0x59c2c4faaf6f - std::panicking::default_hook::{{closure}}::hbd44223dbdc0d208
[INFO] [stdout]                                at /rustc/6067b36314ab5eb2eb47cecc464545ba58e1ad24/library/std/src/panicking.rs:298:22
[INFO] [stdout]    9:     0x59c2c4faad88 - std::panicking::default_hook::h20f81eb0576efcec
[INFO] [stdout]                                at /rustc/6067b36314ab5eb2eb47cecc464545ba58e1ad24/library/std/src/panicking.rs:322:9
[INFO] [stdout]   10:     0x59c2c4c61fe3 - <alloc::boxed::Box<F,A> as core::ops::function::Fn<Args>>::call::hdb53814c496a4d34
[INFO] [stdout]                                at /rustc/6067b36314ab5eb2eb47cecc464545ba58e1ad24/library/alloc/src/boxed.rs:2027:9
[INFO] [stdout]   11:     0x59c2c4c61fe3 - test::test_main::{{closure}}::hc0a4963c59427c24
[INFO] [stdout]                                at /rustc/6067b36314ab5eb2eb47cecc464545ba58e1ad24/library/test/src/lib.rs:134:21
[INFO] [stdout]   12:     0x59c2c4faba63 - <alloc::boxed::Box<F,A> as core::ops::function::Fn<Args>>::call::h591b2225413a77e9
[INFO] [stdout]                                at /rustc/6067b36314ab5eb2eb47cecc464545ba58e1ad24/library/alloc/src/boxed.rs:2027:9
[INFO] [stdout]   13:     0x59c2c4faba63 - std::panicking::rust_panic_with_hook::h625eea43051b2edc
[INFO] [stdout]                                at /rustc/6067b36314ab5eb2eb47cecc464545ba58e1ad24/library/std/src/panicking.rs:839:13
[INFO] [stdout]   14:     0x59c2c4fab71a - std::panicking::begin_panic_handler::{{closure}}::h4f9159cfbc3f6bd3
[INFO] [stdout]                                at /rustc/6067b36314ab5eb2eb47cecc464545ba58e1ad24/library/std/src/panicking.rs:704:13
[INFO] [stdout]   15:     0x59c2c4faa049 - std::sys::backtrace::__rust_end_short_backtrace::h0390abce48353151
[INFO] [stdout]                                at /rustc/6067b36314ab5eb2eb47cecc464545ba58e1ad24/library/std/src/sys/backtrace.rs:168:18
[INFO] [stdout]   16:     0x59c2c4fab3ad - rust_begin_unwind
[INFO] [stdout]                                at /rustc/6067b36314ab5eb2eb47cecc464545ba58e1ad24/library/std/src/panicking.rs:695:5
[INFO] [stdout]   17:     0x59c2c4fd1f80 - core::panicking::panic_fmt::h9e7c637e9e5f29c9
[INFO] [stdout]                                at /rustc/6067b36314ab5eb2eb47cecc464545ba58e1ad24/library/core/src/panicking.rs:75:14
[INFO] [stdout]   18:     0x59c2c4fd2372 - core::panicking::assert_failed_inner::h538bec7c1374cd9c
[INFO] [stdout]   19:     0x59c2c4c146a2 - core::panicking::assert_failed::h88e82bda153b7423
[INFO] [stdout]                                at /rustc/6067b36314ab5eb2eb47cecc464545ba58e1ad24/library/core/src/panicking.rs:364:5
[INFO] [stdout]   20:     0x59c2c4bf199b - blog::post::tests::it_renders_html::h43b449b37ce39f05
[INFO] [stdout]                                at /opt/rustwide/workdir/src/post.rs:265:9
[INFO] [stdout]   21:     0x59c2c4bf1637 - blog::post::tests::it_renders_html::{{closure}}::hac03dd9298f1273c
[INFO] [stdout]                                at /opt/rustwide/workdir/src/post.rs:262:25
[INFO] [stdout]   22:     0x59c2c4bf4176 - core::ops::function::FnOnce::call_once::hd3b3fd8bd3597700
[INFO] [stdout]                                at /rustc/6067b36314ab5eb2eb47cecc464545ba58e1ad24/library/core/src/ops/function.rs:250:5
[INFO] [stdout]   23:     0x59c2c4c6773b - core::ops::function::FnOnce::call_once::he27718dfdd183f43
[INFO] [stdout]                                at /rustc/6067b36314ab5eb2eb47cecc464545ba58e1ad24/library/core/src/ops/function.rs:250:5
[INFO] [stdout]   24:     0x59c2c4c6773b - test::__rust_begin_short_backtrace::h4e84902998457a5d
[INFO] [stdout]                                at /rustc/6067b36314ab5eb2eb47cecc464545ba58e1ad24/library/test/src/lib.rs:632:18
[INFO] [stdout]   25:     0x59c2c4c66673 - test::run_test_in_process::{{closure}}::h7176fd18fc1feca0
[INFO] [stdout]                                at /rustc/6067b36314ab5eb2eb47cecc464545ba58e1ad24/library/test/src/lib.rs:655:60
[INFO] [stdout]   26:     0x59c2c4c66673 - <core::panic::unwind_safe::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once::hf79cff2a624d8cf7
[INFO] [stdout]                                at /rustc/6067b36314ab5eb2eb47cecc464545ba58e1ad24/library/core/src/panic/unwind_safe.rs:272:9
[INFO] [stdout]   27:     0x59c2c4c66673 - std::panicking::try::do_call::h3da0561d9ab99c25
[INFO] [stdout]                                at /rustc/6067b36314ab5eb2eb47cecc464545ba58e1ad24/library/std/src/panicking.rs:587:40
[INFO] [stdout]   28:     0x59c2c4c66673 - std::panicking::try::h41c9fa508bc61df6
[INFO] [stdout]                                at /rustc/6067b36314ab5eb2eb47cecc464545ba58e1ad24/library/std/src/panicking.rs:550:19
[INFO] [stdout]   29:     0x59c2c4c66673 - std::panic::catch_unwind::h6b3ff07bb5afad93
[INFO] [stdout]                                at /rustc/6067b36314ab5eb2eb47cecc464545ba58e1ad24/library/std/src/panic.rs:358:14
[INFO] [stdout]   30:     0x59c2c4c66673 - test::run_test_in_process::hc7253dd11b39b9f4
[INFO] [stdout]                                at /rustc/6067b36314ab5eb2eb47cecc464545ba58e1ad24/library/test/src/lib.rs:655:27
[INFO] [stdout]   31:     0x59c2c4c66673 - test::run_test::{{closure}}::hfb2007f8649c30bb
[INFO] [stdout]                                at /rustc/6067b36314ab5eb2eb47cecc464545ba58e1ad24/library/test/src/lib.rs:576:43
[INFO] [stdout]   32:     0x59c2c4c29755 - test::run_test::{{closure}}::h56a17aa7a282a9f4
[INFO] [stdout]                                at /rustc/6067b36314ab5eb2eb47cecc464545ba58e1ad24/library/test/src/lib.rs:606:41
[INFO] [stdout]   33:     0x59c2c4c29755 - std::sys::backtrace::__rust_begin_short_backtrace::hd2d2d2fb8e8c6aac
[INFO] [stdout]                                at /rustc/6067b36314ab5eb2eb47cecc464545ba58e1ad24/library/std/src/sys/backtrace.rs:152:18
[INFO] [stdout]   34:     0x59c2c4c2d03a - std::thread::Builder::spawn_unchecked_::{{closure}}::{{closure}}::h4faa3f9db6133423
[INFO] [stdout]                                at /rustc/6067b36314ab5eb2eb47cecc464545ba58e1ad24/library/std/src/thread/mod.rs:559:17
[INFO] [stdout]   35:     0x59c2c4c2d03a - <core::panic::unwind_safe::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once::hf2e855a36a4ea846
[INFO] [stdout]                                at /rustc/6067b36314ab5eb2eb47cecc464545ba58e1ad24/library/core/src/panic/unwind_safe.rs:272:9
[INFO] [stdout]   36:     0x59c2c4c2d03a - std::panicking::try::do_call::h2f73af3616c35465
[INFO] [stdout]                                at /rustc/6067b36314ab5eb2eb47cecc464545ba58e1ad24/library/std/src/panicking.rs:587:40
[INFO] [stdout]   37:     0x59c2c4c2d03a - std::panicking::try::hd1660ce9efadef5a
[INFO] [stdout]                                at /rustc/6067b36314ab5eb2eb47cecc464545ba58e1ad24/library/std/src/panicking.rs:550:19
[INFO] [stdout]   38:     0x59c2c4c2d03a - std::panic::catch_unwind::h5ee8d7823b8ca744
[INFO] [stdout]                                at /rustc/6067b36314ab5eb2eb47cecc464545ba58e1ad24/library/std/src/panic.rs:358:14
[INFO] [stdout]   39:     0x59c2c4c2d03a - std::thread::Builder::spawn_unchecked_::{{closure}}::h53c3a1894dce8407
[INFO] [stdout]                                at /rustc/6067b36314ab5eb2eb47cecc464545ba58e1ad24/library/std/src/thread/mod.rs:557:30
[INFO] [stdout]   40:     0x59c2c4c2d03a - core::ops::function::FnOnce::call_once{{vtable.shim}}::h048ce291ad4f62bf
[INFO] [stdout]                                at /rustc/6067b36314ab5eb2eb47cecc464545ba58e1ad24/library/core/src/ops/function.rs:250:5
[INFO] [stdout]   41:     0x59c2c4fb01cb - <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once::ha52bedf99a3b4981
[INFO] [stdout]                                at /rustc/6067b36314ab5eb2eb47cecc464545ba58e1ad24/library/alloc/src/boxed.rs:2013:9
[INFO] [stdout]   42:     0x59c2c4fb01cb - <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once::h567748934d80ccf8
[INFO] [stdout]                                at /rustc/6067b36314ab5eb2eb47cecc464545ba58e1ad24/library/alloc/src/boxed.rs:2013:9
[INFO] [stdout]   43:     0x59c2c4fb01cb - std::sys::pal::unix::thread::Thread::new::thread_start::h2d970728ae887adc
[INFO] [stdout]                                at /rustc/6067b36314ab5eb2eb47cecc464545ba58e1ad24/library/std/src/sys/pal/unix/thread.rs:106:17
[INFO] [stdout]   44:     0x7bea4b986ac3 - <unknown>
[INFO] [stdout]   45:     0x7bea4ba17a04 - clone
[INFO] [stdout]   46:                0x0 - <unknown>
[INFO] [stdout] 
[INFO] [stdout] 
[INFO] [stdout] failures:
[INFO] [stdout]     post::tests::it_renders_html
[INFO] [stdout] 
[INFO] [stdout] test result: FAILED. 9 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.12s
[INFO] [stdout] 
[INFO] [stderr] error: test failed, to rerun pass `--lib`
[INFO] running `Command { std: "docker" "inspect" "06e3ab65d55e33fbd8b884fa768186205a703c8caa232ac8877733d29998f9e0", kill_on_drop: false }`
[INFO] running `Command { std: "docker" "rm" "-f" "06e3ab65d55e33fbd8b884fa768186205a703c8caa232ac8877733d29998f9e0", kill_on_drop: false }`
[INFO] [stdout] 06e3ab65d55e33fbd8b884fa768186205a703c8caa232ac8877733d29998f9e0
