{"action":"created","comment":{"url":"https://api.github.com/repos/rust-lang/rfcs/pulls/comments/166989098","pull_request_review_id":95138690,"id":166989098,"diff_hunk":"@@ -0,0 +1,720 @@\n+- Feature Name: `vendor_intrinsics`\n+- Start Date: 2018-02-04\n+- RFC PR: (leave this empty)\n+- Rust Issue: (leave this empty)\n+\n+# Summary\n+[summary]: #summary\n+\n+The purpose of this RFC is to provide a framework for SIMD to be used on stable\n+Rust. It proposes stabilizing x86-specific vendor intrinsics, but includes the\n+scaffolding for other platforms as well as a future portable SIMD design (to be\n+fleshed out in another RFC).\n+\n+# Motivation\n+[motivation]: #motivation\n+\n+Stable Rust today does not typically expose all of the capabilities of the\n+platform that you're running on. A notable gap in Rust's support includes SIMD\n+(single instruction multiple data) support. For example on x86 you don't\n+currently have explicit access to the 128, 256, and 512 bit registers on the\n+CPU. LLVM is in general an excellent optimizing compiler and often attempts to\n+make use of these registers (auto vectorizing code), but it unfortunately is\n+still somewhat limited and doesn't express the full power of the various SIMD\n+intrinsics.\n+\n+The goal of this RFC is to enable using SIMD intrinsics on stable Rust, and in\n+general provide a means to access the architecture-specific functionality of\n+each vendor. For example the AES intrinsics on x86 would also be made available\n+through this RFC, not only the SIMD-related AVX intrinsics.\n+\n+Note that this is certainly not the first discussion to broach the topic of SIMD\n+in Rust, but rather this has been an ongoing discussion for quite some time now!\n+For example the [simd crate][simd-crate] started [long ago][simd-start], we've\n+had [rfcs][simd-rfc], we've had a [lot][i1] of [discussions][i2] on internals,\n+and the [stdsimd] crate has been implemented.\n+\n+This RFC draws from much of the historical feedback and design that we've done\n+around SIMD in Rust and is targeted at providing path forward for using SIMD on\n+stable Rust while allowing the compiler to change in the future and retain a\n+stable interface.\n+\n+[simd-rfc]: https://github.com/rust-lang/rfcs/pull/1199\n+[simd-crate]: https://github.com/rust-lang-nursery/simd\n+[simd-start]: http://huonw.github.io/blog/2015/08/simd-in-rust/\n+[stdsimd]: https://github.com/rust-lang-nursery/stdsimd\n+[i1]: https://internals.rust-lang.org/t/getting-explicit-simd-on-stable-rust/4380\n+[i2]: https://internals.rust-lang.org/t/whats-the-next-step-towards-the-stabilization-of-simd/5867\n+\n+# Guide-level explanation\n+[guide-level-explanation]: #guide-level-explanation\n+\n+Let's say you've just heard about this fancy feature called \"auto vectorization\"\n+in LLVM and you want to take advantage of it. For example you've got a function\n+like this you'd like to make faster:\n+\n+```rust\n+pub fn foo(a: &[u8], b: &[u8], c: &mut [u8]) {\n+    for ((a, b), c) in a.iter().zip(b).zip(c) {\n+        *c = *a + *b;\n+    }\n+}\n+```\n+\n+When [inspecting the assembly][asm1] you notice that rustc is making use of the\n+`%xmmN` registers which you've read is related to SSE on your CPU. You know,\n+however, that your CPU supports up to AVX2 which has bigger registers, so you'd\n+like to get access to them!\n+\n+Your first solution to this problem is to compile with `-C\n+target-feature=+avx2`, and after that you see the `%ymmN` registers being used,\n+yay! Unfortunately though you're publishing this binary on CPUs which may not\n+actually have AVX2 as a feature, so you don't want to enable AVX2 for the entire\n+program. Instead what you can do is enable it for just this function:\n+\n+```rust\n+#[target_feature(enable = \"avx2\")]\n+pub unsafe fn foo(a: &[u8], b: &[u8], c: &mut [u8]) {\n+    for ((a, b), c) in a.iter().zip(b).zip(c) {\n+        *c = *a + *b;\n+    }\n+}\n+```\n+\n+And [sure enough][asm2] you see the `%ymmN` registers getting used in this\n+function! Note, however, that because you've explicitly enabled a feature you're\n+required to declare the function as `unsafe`, as specified in [RFC\n+2045][rfc2045] (although this requirement is likely to be relaxed in [RFC\n+2212][rfc2212]). This worked as a proof of concept but what you still need to do\n+is dispatch at runtime whether the local CPU that you're running on supports\n+AVX2 or not. Thankfully, though, libstd has a handy macro for this!\n+\n+[rfc2212]: https://github.com/rust-lang/rfcs/pull/2212\n+\n+```rust\n+pub fn foo(a: &[u8], b: &[u8], c: &mut [u8]) {\n+    // Note that this `unsafe` block is safe because we're testing\n+    // that the `avx2` feature is indeed available on our CPU.\n+    if cfg_feature_enabled!(\"avx2\") {\n+        unsafe { foo_avx2(a, b, c) }\n+    } else {\n+        foo_fallback(a, b, c)\n+    }\n+}\n+\n+#[target_feature(enable = \"avx2\")]\n+unsafe fn foo_avx2(a: &[u8], b: &[u8], c: &mut [u8]) {\n+    foo_fallback(a, b, c) // the function below is inlined here\n+}\n+\n+fn foo_fallback(a: &[u8], b: &[u8], c: &mut [u8]) {\n+    for ((a, b), c) in a.iter().zip(b).zip(c) {\n+        *c = *a + *b;\n+    }\n+}\n+```\n+\n+And [sure enough once again][asm3] we see that `foo` is dispatching at runtime\n+to the appropriate function, and only `foo_avx2` is using our `%ymmN` registers!\n+\n+[asm1]: https://play.rust-lang.org/?gist=36b253cd70840ea2ce6aad90418ec58b&version=nightly&mode=release\n+[asm2]: https://play.rust-lang.org/?gist=a31bdd3ce2b9a60e3317ccafb0133490&version=nightly&mode=release\n+[asm3]: https://play.rust-lang.org/?gist=cfce0743910291517aae3b15f70a7cbd&version=nightly&mode=release\n+[rfc2045]: https://github.com/rust-lang/rfcs/blob/master/text/2045-target-feature.md\n+\n+Ok great! At this point we've seen how to enable CPU features for\n+functions-at-a-time as well as how they could be used in a larger context to do\n+runtime dispatch to the most appropriate implementation. As we saw in the\n+motivation, however, we're just relying on LLVM to auto-vectorize here which\n+often isn't good enough or otherwise doesn't expose the functionality we want.\n+\n+For **explicit and guaranteed simd** on stable Rust you'll be using a new module\n+in the standard library, `std::vendor`. The `std::vendor` module is defined by\n+vendors, not us actually! For example Intel [publishes a list of\n+intrinsics][intel-intr] as does [ARM][arm-intr]. These exact functions and their\n+signatures will be available in `std::vendor` with types translated to Rust\n+(e.g. `int32_t` becomes `i32`). Vendor specific types like `__m128i` on Intel\n+will also live in `std::vendor`.\n+\n+For example let's say that we're writing a function that encodes a `&[u8]` in\n+ascii hex and we want to convert `&[1, 2]` to `\"0102\"`. The [stdsimd]\n+crate currently has this [as an example][hex-example], and let's take a look at\n+a few snippets from that.\n+\n+First up you'll see the dispatch routine like we wrote above:\n+\n+```rust\n+fn hex_encode<'a>(src: &[u8], dst: &'a mut [u8]) -> Result<&'a str, usize> {\n+    let len = src.len().checked_mul(2).unwrap();\n+    if dst.len() < len {\n+        return Err(len);\n+    }\n+\n+    #[cfg(any(target_arch = \"x86\", target_arch = \"x86_64\"))]\n+    {\n+        if cfg_feature_enabled!(\"avx2\") {\n+            return unsafe { hex_encode_avx2(src, dst) };\n+        }\n+        if cfg_feature_enabled!(\"sse4.1\") {\n+            return unsafe { hex_encode_sse41(src, dst) };\n+        }\n+    }\n+\n+    hex_encode_fallback(src, dst)\n+}\n+```\n+\n+Here we have some routine business about hex encoding in general, and then for\n+x86/x86\\_64 platforms we have optimized versions specifically for avx2 and\n+sse41. Using the `cfg_feature_enabled!` macro in libstd we saw above we'll\n+dispatch to the correct one at runtime.\n+\n+Taking a closer look at [`hex_encode_sse41`] we see that it starts out with a\n+bunch of weird looking function calls:\n+\n+```rust\n+let ascii_zero = _mm_set1_epi8(b'0' as i8);\n+let nines = _mm_set1_epi8(9);\n+let ascii_a = _mm_set1_epi8((b'a' - 9 - 1) as i8);\n+let and4bits = _mm_set1_epi8(0xf);\n+```\n+\n+As it turns out though, these are all Intel SIMD intrinsics! For example\n+[`_mm_set1_epi8`] is defined as creating an instance of `__m128i`, a 128-bit\n+integer register. The intrinsic specificall sets all bytes to the first\n+argument.\n+\n+These functions are all imported through `std::vendor::*` at the top of the\n+example (in this case `stdsimd::vendor::*`). We go on to use a bunch of these\n+intrinsics throughout the `hex_encode_sse41` function to actually do the hex\n+encoding.\n+\n+The example listed currently has some tests/benchmarks as well, and if we run\n+the benchmarks we'll see:\n+\n+```\n+test benches::large_default    ... bench:      73,432 ns/iter (+/- 12,526) = 14279 MB/s\n+test benches::large_fallback   ... bench:   1,711,030 ns/iter (+/- 286,642) = 612 MB/s\n+test benches::small_default    ... bench:          30 ns/iter (+/- 18) = 3900 MB/s\n+test benches::small_fallback   ... bench:         204 ns/iter (+/- 74) = 573 MB/s\n+test benches::x86::large_avx2  ... bench:      69,742 ns/iter (+/- 9,157) = 15035 MB/s\n+test benches::x86::large_sse41 ... bench:     108,463 ns/iter (+/- 70,250) = 9667 MB/s\n+test benches::x86::small_avx2  ... bench:          25 ns/iter (+/- 8) = 4680 MB/s\n+test benches::x86::small_sse41 ... bench:          25 ns/iter (+/- 14) = 4680 MB/s\n+```\n+\n+Or in other words, our runtime dispatch implementation (\"default\") is **20 times\n+faster** than the fallback implementation (no explicit SIMD). Furthermore the\n+AVX2 implementation is nearly 2x faster than the SSE4.1 implementation for large\n+inputs, and the SSE4.1 implementation is over 10x faster than the default\n+fallback as well.\n+\n+With `std::vendor` and `cfg_feature_enabled!` we've now written a program that's\n+20x faster on supported hardware, yet it also continues to run on older hardware\n+as well! Not bad for a few dozen lines on each function!\n+\n+[intel-intr]: https://software.intel.com/sites/landingpage/IntrinsicsGuide/#\n+[arm-intr]: https://developer.arm.com/technologies/neon/intrinsics\n+[hex-example]: https://github.com/rust-lang-nursery/stdsimd/blob/ee046e0419e4d5e8f742b138313eeefd603326b5/examples/hex.rs\n+[`hex_encode_sse41`]: https://github.com/rust-lang-nursery/stdsimd/blob/ee046e0419e4d5e8f742b138313eeefd603326b5/examples/hex.rs#L114-L160\n+[`_mm_set1_epi8`]: https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_set1_epi8&expand=4669\n+\n+---\n+\n+Note that this RFC is explicitly not attempting to stabilize/design a set of\n+\"portable simd operations\". The contents of `std::vendor` are platform specific\n+and provide no guarantees about portability. Efforts in the past, however, such\n+as with [simd.js] and the [simd crate][simd-crate] show that it's desirable and\n+useful to have a set of types which are usable across platforms.\n+\n+Furthermore LLVM does quite a good job with a portable `u32x4` type, for\n+example, in terms of platform support and speed on platforms that support it.\n+This RFC is not going to go too much into the details about these types, but\n+rather these guidelines will still hold:\n+\n+* The vendor intrinsics **will not** take portable types as arguments. For\n+  example `u32x4` and `__m128i` will be different types on x86. The two types,\n+  however, will be convertible between one another (either via transmutes or via\n+  explicit functions). This conversion will have zero run-time cost.\n+* The portable simd types will likely live in a module like `std::simd` rather\n+  than `std::vendor`.\n+\n+The design around these portable types are ongoing, however, and stay tuned for\n+an RFC for the `std::simd` module!\n+\n+[simd.js]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SIMD\n+\n+# Reference-level explanation\n+[reference-level-explanation]: #reference-level-explanation\n+\n+Stable SIMD in Rust ends up requiring a surprising number of both language and\n+library features to be productive. Thankfully, though, there's has been quite a\n+bit of experimentation over time with SIMD in Rust and we've gotten a lot of\n+good experience along the way! In this section, though, we'll be going into the\n+various features in detail.\n+\n+## The `#[target_feature]` Attribute\n+\n+The `#[target_feature]` attribute was specified in [RFC 2045][rfc2045] and\n+remains unchanged from that specification. As a quick recap it allows you to add\n+this attribute to functions:\n+\n+```rust\n+#[target_feature(enable = \"avx2\")]\n+```\n+\n+The only currently allowed key is `enable` (one day we may allow `disable`). The\n+string values accepted by `enable` will be separately stabilized but are likely\n+to be guided by vendor definitions. For example in Intel's [intrinsic\n+guide][intel-intr] it lists functions under \"AVX2\", so we're likely to stabilize\n+the name `avx2` for Rust.\n+\n+There's a good number of these features supported by the compiler today. It's\n+expected that when stabilizing other pieces of this RFC the names of the\n+following existing features for x86 will be stabilized:\n+\n+* `aes`\n+* `avx2`\n+* `avx`\n+* `bmi2`\n+* `bmi` - to be renamed to `bmi1`, the name Intel gives it\n+* `fma`\n+* `fxsr`\n+* `lzcnt`\n+* `popcnt`\n+* `rdrnd`\n+* `rdseed`\n+* `sse2`\n+* `sse3`\n+* `sse4.1`\n+* `sse4.2`\n+* `sse`\n+* `ssse3`\n+* `xsave`\n+* `xsavec`\n+* `xsaveopt`\n+* `xsaves`\n+\n+Note that AVX-512 names are missing from this list, but that's because we\n+haven't implemented any AVX-512 intrinsics yet. Those'll get stabilized on their\n+own once implemented. Additionally note that `mmx` is missing from this list.\n+For reasons discussed later, it's proposed that MMX types are omitted from the\n+first pass of stabilization. AMD also has some specific features supported\n+(`sse4a`, `tbm`), and so do ARM, MIPS, and PowerPC, but none of these feature\n+names a proposed for becoming stable in the first pass.\n+\n+## The `target_feature` value in `#[cfg]`\n+\n+In addition to enabling target features for a function the compiler will also\n+allow statically testing whether a particular target feature is enabled. This\n+corresponds to the `cfg_target_feature` feature today in rustc, and can be seen\n+via:\n+\n+```rust\n+#[cfg(target_feature = \"avx\")]\n+fn foo() {\n+    // implementation that can use `avx`\n+}\n+\n+#[cfg(not(target_feature = \"avx\"))]\n+fn foo() {\n+    // a fallback implementation\n+}\n+```\n+\n+Additionally this is also made available to `cfg!`:\n+\n+```rust\n+if cfg!(target_feature = \"avx\") {\n+    println!(\"this program was compiled with AVX support\");\n+}\n+```\n+\n+The `#[cfg]` attribute and `cfg!` macro statically resolve and **do not do\n+runtime dispatch**. Tweaking these functions is currently done via the `-C\n+target-feature` flag to the compiler. This flag to the compiler accepts a\n+similar set of strings to the ones specified above and is already \"stable\".\n+\n+## The `cfg_feature_enabled!` Macro\n+\n+One mode of operation with vendor intrinsics is to compile *part* of a program\n+with certain CPU features enabled but not the entire program. This way a\n+portable program can be compiled which runs across a broad range of hardware\n+which can still benefit from optimized implementations for particular hardware\n+at runtime.\n+\n+The crux of this support in libstd is this macro provided by libstd,\n+`cfg_feature_enabled!`. The macro will accept one argument, a string literal.\n+The string can be any feature passed to `#[target_feature(enable = ...)]` for\n+the platform you're compiling for. Finally, the macro will resolve to a `bool`\n+result.\n+\n+For example on x86 you could write:\n+\n+```rust\n+if cfg_feature_enabled!(\"sse4.1\") {\n+    println!(\"this cpu has sse4.1 features enabled!\");\n+}\n+```\n+\n+It would, however, be an error to write this on x86 cpus:\n+\n+```rust\n+cfg_feature_enabled!(\"neon\"); //~ ERROR: neon is an ARM feature, not x86\n+cfg_feature_enabled!(\"foo\"); //~ ERROR: unknown target feature for x86\n+```\n+\n+The macro is intended to be implemented in the `std` crate (**not** `core`) and\n+made available via the normal macro preludes. The implementation of this macro\n+is expected to be what [`stdsimd`][stdsimd] does today, notably:\n+\n+* The first time the macro is invoked all the local CPU features will be\n+  detected.\n+* The detected features will then be cached globally (currently in a bitset) for\n+  the rest of the execution of the program.","path":"text/0000-stable-simd.md","position":374,"original_position":374,"commit_id":"e8cf49ba4f32cfd396b72698ca35da17ef9a3a3e","original_commit_id":"e8cf49ba4f32cfd396b72698ca35da17ef9a3a3e","user":{"login":"gnzlbg","id":904614,"avatar_url":"https://avatars0.githubusercontent.com/u/904614?v=4","gravatar_id":"","url":"https://api.github.com/users/gnzlbg","html_url":"https://github.com/gnzlbg","followers_url":"https://api.github.com/users/gnzlbg/followers","following_url":"https://api.github.com/users/gnzlbg/following{/other_user}","gists_url":"https://api.github.com/users/gnzlbg/gists{/gist_id}","starred_url":"https://api.github.com/users/gnzlbg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gnzlbg/subscriptions","organizations_url":"https://api.github.com/users/gnzlbg/orgs","repos_url":"https://api.github.com/users/gnzlbg/repos","events_url":"https://api.github.com/users/gnzlbg/events{/privacy}","received_events_url":"https://api.github.com/users/gnzlbg/received_events","type":"User","site_admin":false},"body":"@petrochenkov The RFC only provides run-time support in `std`. Users of `core` should choose whatever run-time detection system fits their code. If they are writing user space code, they can choose a library that provides behavior similar to the run-time facilities in `std`. If they are writing kernel code, they will need something else, but they can built it on top of crates that already do `cpuid` queries like `cupid`.","created_at":"2018-02-08T16:24:20Z","updated_at":"2018-02-08T16:24:20Z","html_url":"https://github.com/rust-lang/rfcs/pull/2325#discussion_r166989098","pull_request_url":"https://api.github.com/repos/rust-lang/rfcs/pulls/2325","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/rust-lang/rfcs/pulls/comments/166989098"},"html":{"href":"https://github.com/rust-lang/rfcs/pull/2325#discussion_r166989098"},"pull_request":{"href":"https://api.github.com/repos/rust-lang/rfcs/pulls/2325"}},"in_reply_to_id":166912740},"pull_request":{"url":"https://api.github.com/repos/rust-lang/rfcs/pulls/2325","id":167749965,"html_url":"https://github.com/rust-lang/rfcs/pull/2325","diff_url":"https://github.com/rust-lang/rfcs/pull/2325.diff","patch_url":"https://github.com/rust-lang/rfcs/pull/2325.patch","issue_url":"https://api.github.com/repos/rust-lang/rfcs/issues/2325","number":2325,"state":"open","locked":false,"title":"Stable SIMD in Rust","user":{"login":"alexcrichton","id":64996,"avatar_url":"https://avatars1.githubusercontent.com/u/64996?v=4","gravatar_id":"","url":"https://api.github.com/users/alexcrichton","html_url":"https://github.com/alexcrichton","followers_url":"https://api.github.com/users/alexcrichton/followers","following_url":"https://api.github.com/users/alexcrichton/following{/other_user}","gists_url":"https://api.github.com/users/alexcrichton/gists{/gist_id}","starred_url":"https://api.github.com/users/alexcrichton/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alexcrichton/subscriptions","organizations_url":"https://api.github.com/users/alexcrichton/orgs","repos_url":"https://api.github.com/users/alexcrichton/repos","events_url":"https://api.github.com/users/alexcrichton/events{/privacy}","received_events_url":"https://api.github.com/users/alexcrichton/received_events","type":"User","site_admin":false},"body":"The purpose of this RFC is to provide a framework for SIMD to be used on stable\r\nRust. It proposes stabilizing x86-specific vendor intrinsics, but includes the\r\nscaffolding for other platforms as well as a future portable SIMD design (to be\r\nfleshed out in another RFC).\r\n\r\n[Rendered](https://github.com/alexcrichton/rfcs/blob/simd/text/0000-stable-simd.md)","created_at":"2018-02-07T16:56:25Z","updated_at":"2018-02-08T16:24:20Z","closed_at":null,"merged_at":null,"merge_commit_sha":"d817a73d91cf8c5979873414ad6b59d69e70e016","assignee":{"login":"alexcrichton","id":64996,"avatar_url":"https://avatars1.githubusercontent.com/u/64996?v=4","gravatar_id":"","url":"https://api.github.com/users/alexcrichton","html_url":"https://github.com/alexcrichton","followers_url":"https://api.github.com/users/alexcrichton/followers","following_url":"https://api.github.com/users/alexcrichton/following{/other_user}","gists_url":"https://api.github.com/users/alexcrichton/gists{/gist_id}","starred_url":"https://api.github.com/users/alexcrichton/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alexcrichton/subscriptions","organizations_url":"https://api.github.com/users/alexcrichton/orgs","repos_url":"https://api.github.com/users/alexcrichton/repos","events_url":"https://api.github.com/users/alexcrichton/events{/privacy}","received_events_url":"https://api.github.com/users/alexcrichton/received_events","type":"User","site_admin":false},"assignees":[{"login":"alexcrichton","id":64996,"avatar_url":"https://avatars1.githubusercontent.com/u/64996?v=4","gravatar_id":"","url":"https://api.github.com/users/alexcrichton","html_url":"https://github.com/alexcrichton","followers_url":"https://api.github.com/users/alexcrichton/followers","following_url":"https://api.github.com/users/alexcrichton/following{/other_user}","gists_url":"https://api.github.com/users/alexcrichton/gists{/gist_id}","starred_url":"https://api.github.com/users/alexcrichton/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alexcrichton/subscriptions","organizations_url":"https://api.github.com/users/alexcrichton/orgs","repos_url":"https://api.github.com/users/alexcrichton/repos","events_url":"https://api.github.com/users/alexcrichton/events{/privacy}","received_events_url":"https://api.github.com/users/alexcrichton/received_events","type":"User","site_admin":false}],"requested_reviewers":[],"requested_teams":[],"milestone":null,"commits_url":"https://api.github.com/repos/rust-lang/rfcs/pulls/2325/commits","review_comments_url":"https://api.github.com/repos/rust-lang/rfcs/pulls/2325/comments","review_comment_url":"https://api.github.com/repos/rust-lang/rfcs/pulls/comments{/number}","comments_url":"https://api.github.com/repos/rust-lang/rfcs/issues/2325/comments","statuses_url":"https://api.github.com/repos/rust-lang/rfcs/statuses/e8cf49ba4f32cfd396b72698ca35da17ef9a3a3e","head":{"label":"alexcrichton:simd","ref":"simd","sha":"e8cf49ba4f32cfd396b72698ca35da17ef9a3a3e","user":{"login":"alexcrichton","id":64996,"avatar_url":"https://avatars1.githubusercontent.com/u/64996?v=4","gravatar_id":"","url":"https://api.github.com/users/alexcrichton","html_url":"https://github.com/alexcrichton","followers_url":"https://api.github.com/users/alexcrichton/followers","following_url":"https://api.github.com/users/alexcrichton/following{/other_user}","gists_url":"https://api.github.com/users/alexcrichton/gists{/gist_id}","starred_url":"https://api.github.com/users/alexcrichton/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alexcrichton/subscriptions","organizations_url":"https://api.github.com/users/alexcrichton/orgs","repos_url":"https://api.github.com/users/alexcrichton/repos","events_url":"https://api.github.com/users/alexcrichton/events{/privacy}","received_events_url":"https://api.github.com/users/alexcrichton/received_events","type":"User","site_admin":false},"repo":{"id":17584422,"name":"rfcs","full_name":"alexcrichton/rfcs","owner":{"login":"alexcrichton","id":64996,"avatar_url":"https://avatars1.githubusercontent.com/u/64996?v=4","gravatar_id":"","url":"https://api.github.com/users/alexcrichton","html_url":"https://github.com/alexcrichton","followers_url":"https://api.github.com/users/alexcrichton/followers","following_url":"https://api.github.com/users/alexcrichton/following{/other_user}","gists_url":"https://api.github.com/users/alexcrichton/gists{/gist_id}","starred_url":"https://api.github.com/users/alexcrichton/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alexcrichton/subscriptions","organizations_url":"https://api.github.com/users/alexcrichton/orgs","repos_url":"https://api.github.com/users/alexcrichton/repos","events_url":"https://api.github.com/users/alexcrichton/events{/privacy}","received_events_url":"https://api.github.com/users/alexcrichton/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/alexcrichton/rfcs","description":"RFCs for changes to Rust","fork":true,"url":"https://api.github.com/repos/alexcrichton/rfcs","forks_url":"https://api.github.com/repos/alexcrichton/rfcs/forks","keys_url":"https://api.github.com/repos/alexcrichton/rfcs/keys{/key_id}","collaborators_url":"https://api.github.com/repos/alexcrichton/rfcs/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/alexcrichton/rfcs/teams","hooks_url":"https://api.github.com/repos/alexcrichton/rfcs/hooks","issue_events_url":"https://api.github.com/repos/alexcrichton/rfcs/issues/events{/number}","events_url":"https://api.github.com/repos/alexcrichton/rfcs/events","assignees_url":"https://api.github.com/repos/alexcrichton/rfcs/assignees{/user}","branches_url":"https://api.github.com/repos/alexcrichton/rfcs/branches{/branch}","tags_url":"https://api.github.com/repos/alexcrichton/rfcs/tags","blobs_url":"https://api.github.com/repos/alexcrichton/rfcs/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/alexcrichton/rfcs/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/alexcrichton/rfcs/git/refs{/sha}","trees_url":"https://api.github.com/repos/alexcrichton/rfcs/git/trees{/sha}","statuses_url":"https://api.github.com/repos/alexcrichton/rfcs/statuses/{sha}","languages_url":"https://api.github.com/repos/alexcrichton/rfcs/languages","stargazers_url":"https://api.github.com/repos/alexcrichton/rfcs/stargazers","contributors_url":"https://api.github.com/repos/alexcrichton/rfcs/contributors","subscribers_url":"https://api.github.com/repos/alexcrichton/rfcs/subscribers","subscription_url":"https://api.github.com/repos/alexcrichton/rfcs/subscription","commits_url":"https://api.github.com/repos/alexcrichton/rfcs/commits{/sha}","git_commits_url":"https://api.github.com/repos/alexcrichton/rfcs/git/commits{/sha}","comments_url":"https://api.github.com/repos/alexcrichton/rfcs/comments{/number}","issue_comment_url":"https://api.github.com/repos/alexcrichton/rfcs/issues/comments{/number}","contents_url":"https://api.github.com/repos/alexcrichton/rfcs/contents/{+path}","compare_url":"https://api.github.com/repos/alexcrichton/rfcs/compare/{base}...{head}","merges_url":"https://api.github.com/repos/alexcrichton/rfcs/merges","archive_url":"https://api.github.com/repos/alexcrichton/rfcs/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/alexcrichton/rfcs/downloads","issues_url":"https://api.github.com/repos/alexcrichton/rfcs/issues{/number}","pulls_url":"https://api.github.com/repos/alexcrichton/rfcs/pulls{/number}","milestones_url":"https://api.github.com/repos/alexcrichton/rfcs/milestones{/number}","notifications_url":"https://api.github.com/repos/alexcrichton/rfcs/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/alexcrichton/rfcs/labels{/name}","releases_url":"https://api.github.com/repos/alexcrichton/rfcs/releases{/id}","deployments_url":"https://api.github.com/repos/alexcrichton/rfcs/deployments","created_at":"2014-03-10T06:59:41Z","updated_at":"2018-02-07T18:18:42Z","pushed_at":"2018-02-07T18:22:13Z","git_url":"git://github.com/alexcrichton/rfcs.git","ssh_url":"git@github.com:alexcrichton/rfcs.git","clone_url":"https://github.com/alexcrichton/rfcs.git","svn_url":"https://github.com/alexcrichton/rfcs","homepage":"","size":5119,"stargazers_count":1,"watchers_count":1,"language":null,"has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":4,"mirror_url":null,"archived":false,"open_issues_count":1,"license":null,"forks":4,"open_issues":1,"watchers":1,"default_branch":"master"}},"base":{"label":"rust-lang:master","ref":"master","sha":"ab17693b6b45e1c9bdf05038b333fa66a502997a","user":{"login":"rust-lang","id":5430905,"avatar_url":"https://avatars1.githubusercontent.com/u/5430905?v=4","gravatar_id":"","url":"https://api.github.com/users/rust-lang","html_url":"https://github.com/rust-lang","followers_url":"https://api.github.com/users/rust-lang/followers","following_url":"https://api.github.com/users/rust-lang/following{/other_user}","gists_url":"https://api.github.com/users/rust-lang/gists{/gist_id}","starred_url":"https://api.github.com/users/rust-lang/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rust-lang/subscriptions","organizations_url":"https://api.github.com/users/rust-lang/orgs","repos_url":"https://api.github.com/users/rust-lang/repos","events_url":"https://api.github.com/users/rust-lang/events{/privacy}","received_events_url":"https://api.github.com/users/rust-lang/received_events","type":"Organization","site_admin":false},"repo":{"id":17527989,"name":"rfcs","full_name":"rust-lang/rfcs","owner":{"login":"rust-lang","id":5430905,"avatar_url":"https://avatars1.githubusercontent.com/u/5430905?v=4","gravatar_id":"","url":"https://api.github.com/users/rust-lang","html_url":"https://github.com/rust-lang","followers_url":"https://api.github.com/users/rust-lang/followers","following_url":"https://api.github.com/users/rust-lang/following{/other_user}","gists_url":"https://api.github.com/users/rust-lang/gists{/gist_id}","starred_url":"https://api.github.com/users/rust-lang/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rust-lang/subscriptions","organizations_url":"https://api.github.com/users/rust-lang/orgs","repos_url":"https://api.github.com/users/rust-lang/repos","events_url":"https://api.github.com/users/rust-lang/events{/privacy}","received_events_url":"https://api.github.com/users/rust-lang/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/rust-lang/rfcs","description":"RFCs for changes to Rust","fork":false,"url":"https://api.github.com/repos/rust-lang/rfcs","forks_url":"https://api.github.com/repos/rust-lang/rfcs/forks","keys_url":"https://api.github.com/repos/rust-lang/rfcs/keys{/key_id}","collaborators_url":"https://api.github.com/repos/rust-lang/rfcs/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/rust-lang/rfcs/teams","hooks_url":"https://api.github.com/repos/rust-lang/rfcs/hooks","issue_events_url":"https://api.github.com/repos/rust-lang/rfcs/issues/events{/number}","events_url":"https://api.github.com/repos/rust-lang/rfcs/events","assignees_url":"https://api.github.com/repos/rust-lang/rfcs/assignees{/user}","branches_url":"https://api.github.com/repos/rust-lang/rfcs/branches{/branch}","tags_url":"https://api.github.com/repos/rust-lang/rfcs/tags","blobs_url":"https://api.github.com/repos/rust-lang/rfcs/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/rust-lang/rfcs/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/rust-lang/rfcs/git/refs{/sha}","trees_url":"https://api.github.com/repos/rust-lang/rfcs/git/trees{/sha}","statuses_url":"https://api.github.com/repos/rust-lang/rfcs/statuses/{sha}","languages_url":"https://api.github.com/repos/rust-lang/rfcs/languages","stargazers_url":"https://api.github.com/repos/rust-lang/rfcs/stargazers","contributors_url":"https://api.github.com/repos/rust-lang/rfcs/contributors","subscribers_url":"https://api.github.com/repos/rust-lang/rfcs/subscribers","subscription_url":"https://api.github.com/repos/rust-lang/rfcs/subscription","commits_url":"https://api.github.com/repos/rust-lang/rfcs/commits{/sha}","git_commits_url":"https://api.github.com/repos/rust-lang/rfcs/git/commits{/sha}","comments_url":"https://api.github.com/repos/rust-lang/rfcs/comments{/number}","issue_comment_url":"https://api.github.com/repos/rust-lang/rfcs/issues/comments{/number}","contents_url":"https://api.github.com/repos/rust-lang/rfcs/contents/{+path}","compare_url":"https://api.github.com/repos/rust-lang/rfcs/compare/{base}...{head}","merges_url":"https://api.github.com/repos/rust-lang/rfcs/merges","archive_url":"https://api.github.com/repos/rust-lang/rfcs/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/rust-lang/rfcs/downloads","issues_url":"https://api.github.com/repos/rust-lang/rfcs/issues{/number}","pulls_url":"https://api.github.com/repos/rust-lang/rfcs/pulls{/number}","milestones_url":"https://api.github.com/repos/rust-lang/rfcs/milestones{/number}","notifications_url":"https://api.github.com/repos/rust-lang/rfcs/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/rust-lang/rfcs/labels{/name}","releases_url":"https://api.github.com/repos/rust-lang/rfcs/releases{/id}","deployments_url":"https://api.github.com/repos/rust-lang/rfcs/deployments","created_at":"2014-03-07T21:29:00Z","updated_at":"2018-02-08T08:09:05Z","pushed_at":"2018-02-07T18:22:16Z","git_url":"git://github.com/rust-lang/rfcs.git","ssh_url":"git@github.com:rust-lang/rfcs.git","clone_url":"https://github.com/rust-lang/rfcs.git","svn_url":"https://github.com/rust-lang/rfcs","homepage":"http://rust-lang.github.io/rfcs/","size":12395,"stargazers_count":1318,"watchers_count":1318,"language":"Shell","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":558,"mirror_url":null,"archived":false,"open_issues_count":751,"license":null,"forks":558,"open_issues":751,"watchers":1318,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/rust-lang/rfcs/pulls/2325"},"html":{"href":"https://github.com/rust-lang/rfcs/pull/2325"},"issue":{"href":"https://api.github.com/repos/rust-lang/rfcs/issues/2325"},"comments":{"href":"https://api.github.com/repos/rust-lang/rfcs/issues/2325/comments"},"review_comments":{"href":"https://api.github.com/repos/rust-lang/rfcs/pulls/2325/comments"},"review_comment":{"href":"https://api.github.com/repos/rust-lang/rfcs/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/rust-lang/rfcs/pulls/2325/commits"},"statuses":{"href":"https://api.github.com/repos/rust-lang/rfcs/statuses/e8cf49ba4f32cfd396b72698ca35da17ef9a3a3e"}},"author_association":"OWNER"}}
{"actor":{"display_login":"gnzlbg"}}