{"action":"created","comment":{"url":"https://api.github.com/repos/rust-lang/rfcs/pulls/comments/185379160","pull_request_review_id":116737065,"id":185379160,"diff_hunk":"@@ -0,0 +1,411 @@\n+- Feature Name: Macro Expansion API for Proc Macros\n+- Start Date: 2018-01-26\n+- RFC PR: (leave this empty)\n+- Rust Issue: (leave this empty)\n+\n+# Summary\n+[summary]: #summary\n+\n+Add an API for procedural macros to expand macro calls in token streams. This will allow proc macros to handle unexpanded macro calls that are passed as inputs, as well as allow proc macros to access the results of macro calls that they construct themselves.\n+\n+# Motivation\n+[motivation]: #motivation\n+\n+There are a few places where proc macros may encounter unexpanded macros in their input even after [rust/pull/41029](https://github.com/rust-lang/rust/pull/41029) is merged:\n+\n+* In attribute and procedural macros:\n+\n+    ```rust\n+    #[my_attr_macro(x = a_macro_call!(...))]\n+    //                  ^^^^^^^^^^^^^^^^^^\n+    // This call isn't expanded before being passed to `my_attr_macro`, and can't be\n+    // since attr macros are passed raw token streams by design.\n+    struct X {...}\n+    ```\n+\n+    ```rust\n+    my_proc_macro!(concat!(\"hello\", \"world\"));\n+    //             ^^^^^^^^^^^^^^^^^^^^^^^^^\n+    // This call isn't expanded before being passed to `my_proc_macro`, and can't be\n+    // since proc macros are passed raw token streams by design.\n+    ```\n+\n+* In proc macros called with metavariables or token streams:\n+\n+    ```rust\n+    macro_rules! m {\n+        ($($x:tt)*) => {\n+            my_proc_macro!($($x)*);\n+        },\n+    }\n+\n+    m!(concat!(\"a\", \"b\", \"c\"));\n+    // ^^^^^^^^^^^^^^^^^^^^^^\n+    // This call isn't expanded before being passed to `my_proc_macro`, and can't be\n+    // because `m!` is declared to take a token tree, not a parsed expression that we know\n+    // how to expand.\n+    ```\n+\n+In these situations, proc macros need to either re-call the input macro call as part of their token output, or simply reject the input. If the proc macro needs to inspect the result of the macro call (for instance, to check or edit it, or to re-export a hygienic symbol defined in it), the author is currently unable to do so. This implies an additional place where a proc macro might encounter an unexpanded macro call, by _constructing_ it:\n+\n+* In a proc macro definition:\n+\n+    ```rust\n+    #[proc_macro]\n+    fn my_proc_macro(tokens: TokenStream) -> TokenStream {\n+        let token_args = extract_from(tokens);\n+    \n+        // These arguments are a token stream, but they will be passed to `another_macro!`\n+        // after being parsed as whatever `another_macro!` expects.\n+        //                                                  vvvvvvvvvv\n+        let other_tokens = some_other_crate::another_macro!(token_args);\n+        //                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n+        // This call gets expanded into whatever `another_macro` expects to be expanded\n+        // as. There is currently no way to get the resulting tokens without requiring the\n+        // macro result to compile in the same crate as `my_proc_macro`.\n+        ...\n+    }\n+    ```\n+\n+Giving proc macro authors the ability to handle these situations will allow proc macros to 'just work' in more contexts, and without surprising users who expect macro calls to interact well with more parts of the language. Additionally, supporting the 'proc macro definition' use case above allows proc macro authors to use macros from other crates _as macros_, rather than as proc macro definition functions.\n+\n+As a side note, allowing macro calls in built-in attributes would solve a few outstanding issues (see [rust-lang/rust#18849](https://github.com/rust-lang/rust/issues/18849) for an example). \n+\n+An older motivation to allow macro calls in attributes was to get `#[doc(include_str!(\"path/to/doc.txt\"))]` working, in order to provide an ergonomic way to keep documentation outside of Rust source files. This was eventually emulated by the accepted [RFC 1990](https://github.com/rust-lang/rfcs/pull/1990), indicating that macros in attributes could be used to solve problems at least important enough to go through the RFC process.\n+\n+# Guide-level explanation\n+[guide-level-explanation]: #guide-level-explanation\n+\n+## Macro Calls in Procedural Macros\n+\n+When implementing procedural macros you should account for the possibility that a user might provide a macro call in their input. For example, here's a silly proc macro that evaluates to the length of the string literal passed in.:\n+\n+```rust\n+extern crate syn;\n+#[macro_use]\n+extern crate quote;\n+\n+#[proc_macro]\n+fn string_length(tokens: TokenStream) -> TokenStream {\n+    let lit: syn::LitStr = syn::parse(tokens).unwrap();\n+    let len = str_lit.value().len();\n+    \n+    quote!(#len)\n+}\n+```\n+\n+If you call `string_length!` with something obviously wrong, like `string_length!(struct X)`, you'll get a parser error when `unwrap` gets called, which is expected. But what do you think happens if you call `string_length!(stringify!(struct X))`?\n+\n+It's reasonable to expect that `stringify!(struct X)` gets expanded and turned into a string literal `\"struct X\"`, before being passed to `string_length`. However, in order to give the most control to proc macro authors, Rust doesn't touch any of the ingoing tokens passed to a proc macro (**Note:** this doesn't strictly hold true for [proc _attribute_ macros](#macro-calls-in-attribute-macros)).\n+\n+Thankfully, there's an easy solution: the proc macro API offered by the compiler has methods for constructing and expanding macro calls. The `syn` crate uses these methods to provide an alternative to `parse`, called `parse_expand`. As the name suggests, `parse_expand` parses the input token stream while expanding and parsing any encountered macro calls. Indeed, replacing `parse` with `parse_expand` in our definition of `string_length` means it will handle input like `stringify!(struct X)` exactly as expected.\n+\n+As a utility, `parse_expand` uses sane expansion options for the most common case of macro calls in token stream inputs. It assumes:\n+\n+* The called macro, as well as any identifiers in its arguments, is in scope at the macro call site.\n+* The called macro should behave as though it were expanded in the source location.\n+\n+To understand what these assumptions mean, or how to expand a macro differently, check out the section on how [macro hygiene works](#spans-and-scopes) as well as the detailed [API overview](#api-overview).\n+\n+## Macro Calls in Attribute Macros\n+\n+Macro calls also show up in attribute macros. The situation is very similar to that of proc macros: `syn` offers `parse_meta_expand` in addition to `parse_meta`. This can be used to parse the attribute argument tokens, assuming your macro expects a normal meta-item and not some fancy custom token tree. For instance, the following behaves as expected:\n+\n+```rust\n+#[proc_macro_attribute]\n+fn my_attr_macro(attr: TokenStream, body: TokenStream) -> TokenStream {\n+    let meta: Syn::Meta = syn::parse_meta_expand(attr).unwrap();\n+    ...\n+}\n+```\n+\n+```rust\n+// Parses successfully: `my_attr_macro` behaves as though called with\n+// ``my_attr_macro(value = \"Hello, world!\")]\n+// struct X {...}\n+//                      vvvvvvvvvvvvvvvvvvvvvvvvvvvv\n+#[my_attr_macro(value = concat!(\"Hello, \", \"world!\"))]\n+struct X {...}\n+\n+// Parses unsuccessfully: the normal Rust syntax for meta items expects\n+// a literal, not an expression.\n+//                      vvvvvvvvvvvvvvvvvvvvvvvvv\n+#[my_attr_macro(value = println!(\"Hello, world!\"))]\n+struct Y {...}\n+```\n+\n+Of course, even if your attribute macro _does_ use a fancy token syntax, you can still use `parse_expand` to handle any macro calls you encounter.\n+\n+**Note:** Because the built-in attribute 'macro' `#[cfg]` is expanded and evaluated before body tokens are sent to an attribute macro, the compiler will also expand any other macros before then too for consistency. For instance, here `my_attr_macro!` will see `field: u32` instead of a call to `type_macro!`:\n+\n+```rust\n+macro_rules! type_macro {\n+    () => { u32 };\n+}\n+\n+#[my_attr_macro(...)]\n+struct X {\n+    field: type_macro!(),\n+}\n+```\n+\n+## Spans and Scopes\n+[guide-sshm]: guide-sshm\n+\n+**Note:** This isn't part of the proposed changes, but is useful for setting up the language for understanding proc macro expansion.\n+\n+If you're not familiar with how spans are used in token streams to track both line/column data and name resolution scopes, here is a refresher. Consider the following proc macro:\n+\n+```rust\n+#[macro_use]\n+extern crate quote;\n+\n+#[proc_macro]\n+fn my_hygienic_macro(tokens: TokenStream) -> TokenStream {\n+    quote! {            \n+        let mut x = 0;  // [Def]\n+        #tokens         // [Call]\n+        x += 1;         // [Def]\n+    }\n+}\n+```\n+\n+Each token in a `TokenStream` has a span, and that span tracks where the token is treated as being created - you'll see why we keep on saying \"treated as being created\" rather than just \"created\" [later](#unhygienic-scopes)!\n+\n+In the above code sample:\n+\n+* The tokens in lines marked `[Def]` have spans with scopes that indicate they should be treated as though they were defined here in the definition of `my_hygienic_macro`.\n+* The tokens in lines marked with `[Call]` keep their original spans and scopes, which in this case indicate they should be treated as though they were defined at the macro call site, wherever that is.\n+\n+Now let's see what happens when we use `my_hygienic_macro`:\n+\n+```rust\n+fn main() {\n+    my_hygienic_macro! {\n+        let mut x = 1;\n+        x += 2;\n+    };\n+    println!(x);\n+}\n+```\n+\n+After the call to `my_hygienic_macro!` in `main` is expanded, `main` looks something like this:\n+\n+```rust\n+fn main() {\n+    let mut x = 0; // 1. [Def]\n+    let mut x = 1; // 2. [Call]\n+    x += 2;        // 3. [Call]\n+    x += 1;        // 4. [Def]\n+    println!(x);   // 5. [Call]\n+}\n+```\n+\n+As you can see, the macro expansion has interleaved tokens provided by the caller (marked with `[Call]`) and tokens provided by the macro definition (marked with `[Def]`). \n+\n+Scopes are used to _resolve_ names. For example, in lines 3 and 5 the variable `x` is in the `[Call]` scope, and so will resolve to the variable declared in line 2. Similarly, in line 4 the variable `x` is in the `[Def]` scope, and so will resolve to the variable declared in line 1. Since the names in different _scopes_ resolve to different _variables_, this means mutating a variable in one scope doesn't mutate the variables in another, or shadow them, or interfere with name resolution. This is how Rust achieves macro hygiene!\n+\n+This doesn't just stop at variable names. The above principles apply to mods, structs, trait definition, trait method calls, macros - anything with a name which needs to be looked up.\n+\n+### Unhygienic Scopes\n+\n+Importantly, macro hygiene is _optional_: since we can manipulate the spans on tokens, we can change how a variable is resolved. For example:\n+\n+```rust\n+extern crate proc_macro;\n+#[macro_use]\n+extern crate quote;\n+\n+use proc_macro::Span;\n+\n+#[proc_macro]\n+fn my_unhygienic_macro(tokens: TokenStream) -> TokenStream {\n+    let hygienic = quote_spanned! { Span::def_site(),\n+        let mut x = 0; // [Def]\n+    };\n+    let unhygienic = quote_spanned! { Span::call_site(),\n+        x += 1;        // [Call]\n+    };\n+    quote! {\n+        #hygienic      // [Def]\n+        #tokens        // [Call]\n+        #unhygienic    // [Call]\n+    }\n+}\n+```\n+\n+If we call `my_unhygienic_macro` instead of `my_hygienic_macro` in `main` as before, the result is:\n+\n+```rust\n+fn main() {\n+    let mut x = 0; // 1. [Def]\n+    let mut x = 1; // 2. [Call], from main\n+    x += 2;        // 3. [Call], from main\n+    x += 1;        // 4. [Call], from my_unhygienic_macro\n+    println!(x);   // 5. [Call]\n+}\n+```\n+\n+By changing the scope of the span of the tokens on line 4 (using `quote_spanned` instead of `quote`), that instance of `x` will resolve to the one defined on line 2 instead of line 1. In fact, the variable actually declared by our macro on line 1 is never used.\n+\n+This trick has a few uses, such as 'exporting' a name to the caller of the macro. If hygiene was not optional, any new functions or modules you created in a macro would only be resolvable in the same macro.\n+\n+There are also some interesting [examples](https://github.com/dtolnay/syn/blob/030787c71b4cfb2764bccbbd2bf0e8d8497d46ef/examples/heapsize2/heapsize_derive/src/lib.rs#L65) of how this gets used to resolve method calls on traits declared in `[Def]`, but called with variables from `[Call]`.\n+\n+## API Overview\n+\n+The full API provided by `proc_macro` and used by `syn` is more flexible than suggested by the use of `parse_expand` and `parse_meta_expand` above. To begin, `proc_macro` defines a struct, `MacroCall`, with the following interface:\n+\n+```rust\n+struct MacroCall {...};\n+\n+impl MacroCall {\n+    fn new_proc(path: TokenStream, args: TokenStream) -> Self;\n+    \n+    fn new_attr(path: TokenStream, args: TokenStream, body: TokenStream) -> Self;\n+    \n+    fn call_from(self, from: Span) -> Self;\n+    \n+    fn expand(self) -> Result<TokenStream, Diagnostic>;\n+}\n+```\n+\n+The functions `new_proc` and `new_attr` create a procedural macro call and an attribute macro call, respectively. Both expect `path` to parse as a [path](https://docs.rs/syn/0.12/syn/struct.Path.html) like `println` or `::std::println`. The scope of the spans of `path` are used to resolve the macro definition. This is unlikely to work unless all the tokens have the same scope.\n+","path":"text/0000-proc-macro-expansion-api.md","position":274,"original_position":274,"commit_id":"1e0ace1ec32122d19ada884272330539ba7b4627","original_commit_id":"1e0ace1ec32122d19ada884272330539ba7b4627","user":{"login":"nrc","id":762626,"avatar_url":"https://avatars0.githubusercontent.com/u/762626?v=4","gravatar_id":"","url":"https://api.github.com/users/nrc","html_url":"https://github.com/nrc","followers_url":"https://api.github.com/users/nrc/followers","following_url":"https://api.github.com/users/nrc/following{/other_user}","gists_url":"https://api.github.com/users/nrc/gists{/gist_id}","starred_url":"https://api.github.com/users/nrc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nrc/subscriptions","organizations_url":"https://api.github.com/users/nrc/orgs","repos_url":"https://api.github.com/users/nrc/repos","events_url":"https://api.github.com/users/nrc/events{/privacy}","received_events_url":"https://api.github.com/users/nrc/received_events","type":"User","site_admin":false},"body":"Overall, I really like the idea of using a Builder API - it keeps things simple and is future-proof","created_at":"2018-05-02T02:06:31Z","updated_at":"2018-05-02T02:06:35Z","html_url":"https://github.com/rust-lang/rfcs/pull/2320#discussion_r185379160","pull_request_url":"https://api.github.com/repos/rust-lang/rfcs/pulls/2320","author_association":"OWNER","_links":{"self":{"href":"https://api.github.com/repos/rust-lang/rfcs/pulls/comments/185379160"},"html":{"href":"https://github.com/rust-lang/rfcs/pull/2320#discussion_r185379160"},"pull_request":{"href":"https://api.github.com/repos/rust-lang/rfcs/pulls/2320"}}},"pull_request":{"url":"https://api.github.com/repos/rust-lang/rfcs/pulls/2320","id":166688342,"html_url":"https://github.com/rust-lang/rfcs/pull/2320","diff_url":"https://github.com/rust-lang/rfcs/pull/2320.diff","patch_url":"https://github.com/rust-lang/rfcs/pull/2320.patch","issue_url":"https://api.github.com/repos/rust-lang/rfcs/issues/2320","number":2320,"state":"open","locked":false,"title":"RFC: Add macro expansion API to proc macros","user":{"login":"pierzchalski","id":1725294,"avatar_url":"https://avatars1.githubusercontent.com/u/1725294?v=4","gravatar_id":"","url":"https://api.github.com/users/pierzchalski","html_url":"https://github.com/pierzchalski","followers_url":"https://api.github.com/users/pierzchalski/followers","following_url":"https://api.github.com/users/pierzchalski/following{/other_user}","gists_url":"https://api.github.com/users/pierzchalski/gists{/gist_id}","starred_url":"https://api.github.com/users/pierzchalski/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pierzchalski/subscriptions","organizations_url":"https://api.github.com/users/pierzchalski/orgs","repos_url":"https://api.github.com/users/pierzchalski/repos","events_url":"https://api.github.com/users/pierzchalski/events{/privacy}","received_events_url":"https://api.github.com/users/pierzchalski/received_events","type":"User","site_admin":false},"body":"[Rendered](https://github.com/pierzchalski/rfcs/blob/macro-expansion-api/text/0000-proc-macro-expansion-api.md)\r\n\r\nCC @nrc, @nikomatsakis ","created_at":"2018-02-02T00:20:53Z","updated_at":"2018-05-02T02:06:35Z","closed_at":null,"merged_at":null,"merge_commit_sha":"830df8df22ec7ea7b8f30557d012ada37982c4b6","assignee":{"login":"nrc","id":762626,"avatar_url":"https://avatars0.githubusercontent.com/u/762626?v=4","gravatar_id":"","url":"https://api.github.com/users/nrc","html_url":"https://github.com/nrc","followers_url":"https://api.github.com/users/nrc/followers","following_url":"https://api.github.com/users/nrc/following{/other_user}","gists_url":"https://api.github.com/users/nrc/gists{/gist_id}","starred_url":"https://api.github.com/users/nrc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nrc/subscriptions","organizations_url":"https://api.github.com/users/nrc/orgs","repos_url":"https://api.github.com/users/nrc/repos","events_url":"https://api.github.com/users/nrc/events{/privacy}","received_events_url":"https://api.github.com/users/nrc/received_events","type":"User","site_admin":false},"assignees":[{"login":"nrc","id":762626,"avatar_url":"https://avatars0.githubusercontent.com/u/762626?v=4","gravatar_id":"","url":"https://api.github.com/users/nrc","html_url":"https://github.com/nrc","followers_url":"https://api.github.com/users/nrc/followers","following_url":"https://api.github.com/users/nrc/following{/other_user}","gists_url":"https://api.github.com/users/nrc/gists{/gist_id}","starred_url":"https://api.github.com/users/nrc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nrc/subscriptions","organizations_url":"https://api.github.com/users/nrc/orgs","repos_url":"https://api.github.com/users/nrc/repos","events_url":"https://api.github.com/users/nrc/events{/privacy}","received_events_url":"https://api.github.com/users/nrc/received_events","type":"User","site_admin":false}],"requested_reviewers":[],"requested_teams":[],"labels":[{"id":211667886,"url":"https://api.github.com/repos/rust-lang/rfcs/labels/T-lang","name":"T-lang","color":"bfd4f2","default":false}],"milestone":null,"commits_url":"https://api.github.com/repos/rust-lang/rfcs/pulls/2320/commits","review_comments_url":"https://api.github.com/repos/rust-lang/rfcs/pulls/2320/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/2320/comments","statuses_url":"https://api.github.com/repos/rust-lang/rfcs/statuses/1e0ace1ec32122d19ada884272330539ba7b4627","head":{"label":"pierzchalski:macro-expansion-api","ref":"macro-expansion-api","sha":"1e0ace1ec32122d19ada884272330539ba7b4627","user":{"login":"pierzchalski","id":1725294,"avatar_url":"https://avatars1.githubusercontent.com/u/1725294?v=4","gravatar_id":"","url":"https://api.github.com/users/pierzchalski","html_url":"https://github.com/pierzchalski","followers_url":"https://api.github.com/users/pierzchalski/followers","following_url":"https://api.github.com/users/pierzchalski/following{/other_user}","gists_url":"https://api.github.com/users/pierzchalski/gists{/gist_id}","starred_url":"https://api.github.com/users/pierzchalski/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pierzchalski/subscriptions","organizations_url":"https://api.github.com/users/pierzchalski/orgs","repos_url":"https://api.github.com/users/pierzchalski/repos","events_url":"https://api.github.com/users/pierzchalski/events{/privacy}","received_events_url":"https://api.github.com/users/pierzchalski/received_events","type":"User","site_admin":false},"repo":{"id":116890303,"name":"rfcs","full_name":"pierzchalski/rfcs","owner":{"login":"pierzchalski","id":1725294,"avatar_url":"https://avatars1.githubusercontent.com/u/1725294?v=4","gravatar_id":"","url":"https://api.github.com/users/pierzchalski","html_url":"https://github.com/pierzchalski","followers_url":"https://api.github.com/users/pierzchalski/followers","following_url":"https://api.github.com/users/pierzchalski/following{/other_user}","gists_url":"https://api.github.com/users/pierzchalski/gists{/gist_id}","starred_url":"https://api.github.com/users/pierzchalski/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pierzchalski/subscriptions","organizations_url":"https://api.github.com/users/pierzchalski/orgs","repos_url":"https://api.github.com/users/pierzchalski/repos","events_url":"https://api.github.com/users/pierzchalski/events{/privacy}","received_events_url":"https://api.github.com/users/pierzchalski/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/pierzchalski/rfcs","description":"RFCs for changes to Rust","fork":true,"url":"https://api.github.com/repos/pierzchalski/rfcs","forks_url":"https://api.github.com/repos/pierzchalski/rfcs/forks","keys_url":"https://api.github.com/repos/pierzchalski/rfcs/keys{/key_id}","collaborators_url":"https://api.github.com/repos/pierzchalski/rfcs/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/pierzchalski/rfcs/teams","hooks_url":"https://api.github.com/repos/pierzchalski/rfcs/hooks","issue_events_url":"https://api.github.com/repos/pierzchalski/rfcs/issues/events{/number}","events_url":"https://api.github.com/repos/pierzchalski/rfcs/events","assignees_url":"https://api.github.com/repos/pierzchalski/rfcs/assignees{/user}","branches_url":"https://api.github.com/repos/pierzchalski/rfcs/branches{/branch}","tags_url":"https://api.github.com/repos/pierzchalski/rfcs/tags","blobs_url":"https://api.github.com/repos/pierzchalski/rfcs/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/pierzchalski/rfcs/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/pierzchalski/rfcs/git/refs{/sha}","trees_url":"https://api.github.com/repos/pierzchalski/rfcs/git/trees{/sha}","statuses_url":"https://api.github.com/repos/pierzchalski/rfcs/statuses/{sha}","languages_url":"https://api.github.com/repos/pierzchalski/rfcs/languages","stargazers_url":"https://api.github.com/repos/pierzchalski/rfcs/stargazers","contributors_url":"https://api.github.com/repos/pierzchalski/rfcs/contributors","subscribers_url":"https://api.github.com/repos/pierzchalski/rfcs/subscribers","subscription_url":"https://api.github.com/repos/pierzchalski/rfcs/subscription","commits_url":"https://api.github.com/repos/pierzchalski/rfcs/commits{/sha}","git_commits_url":"https://api.github.com/repos/pierzchalski/rfcs/git/commits{/sha}","comments_url":"https://api.github.com/repos/pierzchalski/rfcs/comments{/number}","issue_comment_url":"https://api.github.com/repos/pierzchalski/rfcs/issues/comments{/number}","contents_url":"https://api.github.com/repos/pierzchalski/rfcs/contents/{+path}","compare_url":"https://api.github.com/repos/pierzchalski/rfcs/compare/{base}...{head}","merges_url":"https://api.github.com/repos/pierzchalski/rfcs/merges","archive_url":"https://api.github.com/repos/pierzchalski/rfcs/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/pierzchalski/rfcs/downloads","issues_url":"https://api.github.com/repos/pierzchalski/rfcs/issues{/number}","pulls_url":"https://api.github.com/repos/pierzchalski/rfcs/pulls{/number}","milestones_url":"https://api.github.com/repos/pierzchalski/rfcs/milestones{/number}","notifications_url":"https://api.github.com/repos/pierzchalski/rfcs/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/pierzchalski/rfcs/labels{/name}","releases_url":"https://api.github.com/repos/pierzchalski/rfcs/releases{/id}","deployments_url":"https://api.github.com/repos/pierzchalski/rfcs/deployments","created_at":"2018-01-10T01:12:57Z","updated_at":"2018-01-10T01:13:01Z","pushed_at":"2018-02-06T00:19:30Z","git_url":"git://github.com/pierzchalski/rfcs.git","ssh_url":"git@github.com:pierzchalski/rfcs.git","clone_url":"https://github.com/pierzchalski/rfcs.git","svn_url":"https://github.com/pierzchalski/rfcs","homepage":"http://rust-lang.github.io/rfcs/","size":10301,"stargazers_count":0,"watchers_count":0,"language":"Shell","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":{"key":"other","name":"Other","spdx_id":null,"url":null},"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"rust-lang:master","ref":"master","sha":"96dce82064dc229df9a17b573d5c6ff4e95fa8e1","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-05-02T01:18:42Z","pushed_at":"2018-05-01T23:54:34Z","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":114702,"stargazers_count":1460,"watchers_count":1460,"language":"Shell","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":613,"mirror_url":null,"archived":false,"open_issues_count":705,"license":{"key":"other","name":"Other","spdx_id":null,"url":null},"forks":613,"open_issues":705,"watchers":1460,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/rust-lang/rfcs/pulls/2320"},"html":{"href":"https://github.com/rust-lang/rfcs/pull/2320"},"issue":{"href":"https://api.github.com/repos/rust-lang/rfcs/issues/2320"},"comments":{"href":"https://api.github.com/repos/rust-lang/rfcs/issues/2320/comments"},"review_comments":{"href":"https://api.github.com/repos/rust-lang/rfcs/pulls/2320/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/2320/commits"},"statuses":{"href":"https://api.github.com/repos/rust-lang/rfcs/statuses/1e0ace1ec32122d19ada884272330539ba7b4627"}},"author_association":"NONE"}}
{"actor":{"display_login":"nrc"}}