{"action":"created","comment":{"url":"https://api.github.com/repos/rust-lang/rfcs/pulls/comments/179907905","pull_request_review_id":110246145,"id":179907905,"diff_hunk":"@@ -0,0 +1,700 @@\n+- Feature Name: delegation\n+- Start Date: 2018-04-06\n+- RFC PR: (leave this empty)\n+- Rust Issue: (leave this empty)\n+\n+# Summary\n+[summary]: #summary\n+\n+Syntax sugar for efficient code reuse via the composition pattern. Wrapper functions are generated for a struct, delegating most or all of a trait’s impl block to a member field that already implements the trait.\n+\n+\n+# Motivation\n+[motivation]: #motivation\n+\n+Let's consider some existing pieces of code:\n+```rust\n+// from rust/src/test/run-pass/dropck_legal_cycles.rs\n+impl<'a> Hash for H<'a> {\n+    fn hash<H: Hasher>(&self, state: &mut H) {\n+        self.name.hash(state)\n+    }\n+}\n+```\n+We can see a recurring pattern where the implementation of a method only consists in applying the same method to a subfield or more generally to an expression containing `self`. Those are examples of the well known [composition pattern][object_composition]. It has a lot of advantages, but unfortunately requires writing boilerplate code again and again. In a classical OOP language we could also have opted for inheritance for similar cases. Inheritance comes with its own bunch of problems and limitations but at least it allows a straightforward form of code reuse: any subclass implicitly imports the public methods of its superclass(es).\n+\n+One of the issues frequently mentioned when newcomers are learning Rust, is \"I can do this easily in OOP, but is it even possible in Rust? And how the heck do I do it?\" The lack of documentation/guides on this is a known issue and is being worked on, but it's not *just* a documentation issue.\n+\n+OOP is used to solve real problems and if we want people to choose Rust in any of the domains they proliferate in, we need good solutions for those problems. As @withoutboats said:\n+\n+> One aspect of inheritance-based polymorphism systems is that it is very easy to re-use code that has already been written as you are extending a system. The specific mechanism of re-use is connected to the more detrimental aspects of inheritance - the way it can result in ill-considered coupling and overly gregarious sharing of details which should be abstracted away.\n+> \n+> To avoid the pitfalls that many inheritance-based languages have fallen into, Rust has avoided that form of polymorphism entirely, preferring instead a combination of behaviorally constrained parametric polymorphism (traits and generics) and straightforward type composition.\n+> \n+> Avoiding inheritance has resulted in two major costs for users of Rust:\n+> \n+> - There are patterns enabled by inheritance which have no clean equivalent in Rust.\n+> - The forms of abstraction Rust suggests can result in more boilerplate and less convenient code re-use than inheritance.\n+> \n+> We've focused a lot of attention on resolving the first problem, which is what has driven the efforts around specialization and the like. But there hasn't been nearly as much attention at resolving the second problem. This RFC is aimed squarely at that problem, so thanks @contactomorph for considering that question.\n+\n+Efficient code reuse is about making us more productive, not just in terms of typing less, which is nice, but being able to clearly express *intent* in our code, making it easier to read, understand, refactor and prototype quickly. It also enables DRY and is in-line with the [2017 Roadmap](https://github.com/rust-lang/rust-roadmap): \n+\n+> In short, productivity should be a core value of Rust. By the end of 2017, let's try to earn the slogan: \n+> \n+> - Rust: fast, reliable, productive—pick three.\n+\n+Rust has no inheritance (yet) and as a result composition is an even more interesting pattern for factoring code than in other languages. In fact it is already used in many places. Some (approximate) figures:\n+\n+Project           | Occurences of \"delegating methods\" |\n+------------------| ---------------------------------- |\n+rust-lang/rust    | 845                                |\n+rust-lang/cargo   | 38                                 |\n+servo/servo       | 314                                |\n+\n+Functional programmers like @Centril love delegation and absolutely adore that they can do the following in Haskell with `{-# GeneralizedNewtypeDeriving #-}`:\n+\n+```haskell\n+newtype NormT m (a :: *) = NormT { _runNormT :: WriterT Unique m a }\n+  deriving ( Eq, Ord, Show, Read, Generic, Typeable\n+           , Functor, Applicative, Monad, MonadFix, MonadIO, MonadZip\n+           , Alternative, MonadPlus, MonadTrans, MFunctor, MMonad\n+           , MonadError e, MonadState s, MonadReader r\n+           , MonadWriter Unique )\n+```\n+\n+This is massive code reuse and not in any OOP language ^,-\n+\n+By providing syntax sugar for the composition pattern, it becomes a privileged tool for code reuse while being as terse as the inheritance-based equivalent. It could also enable ergonomic implementation of custom widgets in a pure Rust GUI library.\n+\n+Related discussions:\n+ \n+* [Initial pre-RFC][pre_rfc]\n+* [Reddit thread][comp_over_inh]\n+* [Initial RFC][initial_rfc]\n+* [Post-RFC design discussion][design_discussion]\n+* [Internals thread for this RFC][internals_thread]\n+\n+[pre_rfc]: https://internals.rust-lang.org/t/syntactic-sugar-for-delegation-of-implementation/2633\n+[comp_over_inh]: https://www.reddit.com/r/rust/comments/372mqw/how_do_i_composition_over_inheritance/\n+[object_composition]: https://en.wikipedia.org/wiki/Composition_over_inheritance\n+[initial_rfc]:\n+https://github.com/rust-lang/rfcs/pull/1406\n+[design_discussion]:\n+https://internals.rust-lang.org/t/3-weeks-to-delegation-please-help/5742\n+[internals_thread]: https://internals.rust-lang.org/t/new-rfc-for-delegation-anyone-interested-in-contributing/6644\n+\n+# Guide-level explanation\n+[guide]: #guide\n+\n+In Rust, we prefer composition over inheritence for code reuse. For common cases, we make this convenient with delegation syntax sugar.\n+\n+Whenever you have a struct `S` with a member field `f` of type `F` and `F` already implements a trait `TR`, you can delegate the implementation of `TR` for `S` to `f` using the keyword `delegate`:\n+\n+```rust\n+impl TR for S {\n+    delegate * to f;\n+}\n+```\n+\n+This is pure sugar, and does exactly the same thing as if you “manually delegated” all the items of `TR` like this:\n+\n+```rust\n+impl TR for S {\n+    type Item = <F as TR>::Item;\n+    // ...\n+    const MAX = <F as TR>::MAX;\n+    // ...\n+    fn foo(&self) -> u32 {\n+        self.f.foo()\n+    }\n+    fn bar(&self, x: u32, y: u32, z: u32) -> u32 {\n+        self.f.bar(x, y, z)\n+    }\n+    // ...\n+}\n+```\n+\n+To delegate most of a trait, rather than all of it, simply `delegate *` and then write the manual implementations for the items you don’t want to delegate.\n+\n+```rust\n+impl TR for S {\n+    delegate * to f;\n+\n+    fn foo(&self) -> u32 {\n+        42\n+    }\n+}\n+```\n+\n+Aside from the implementation of `foo()`, this has exactly the same meaning as the first example.\n+\n+If you only want to delegate specific items, rather than “all” or “most” items, then replace `*` with a comma-separated list of only the items you want to delegate. Since it’s possible for types and functions to have the same name, the items must be prefixed with `fn`, `const` and `type` as appropriate.\n+\n+```rust\n+impl TR for S {\n+    delegate fn foo, fn bar, const MAX, type Item\n+        to f;\n+}\n+```\n+\n+This also has the exact same meaning as the first example. While `to field_name;` is not required to be on a new line, this is the `rustfmt` default when delegating individual trait items, as it makes it easy to visually identify the field being delegated to.\n+\n+If you want to delegate some methods to one field and some to another, simply write multiple `delegate` statements:\n+\n+```rust\n+impl TR for S {\n+    delegate * to field_one;\n+    delegate fn foo, const MAX, type Item\n+        to field_two;\n+}\n+```\n+\n+This delegates `foo`, `MAX`, and `Item` to `field_two`. Everything else is delegated to `field_one`.\n+\n+In addition to \"regular\" structs with named fields, you can delegate to indexed fields on a tuple struct. This first field name is `0`, which we're used to writing as `self.0`:\n+\n+```rust\n+struct AddOnlyCounter(u32);\n+\n+impl AddOnlyCounter {\n+    fn new() -> Self {\n+        Self { 0 }\n+    }\n+}\n+\n+impl AddAssign for AddOnlyCounter {\n+    delegate * to 0;\n+}\n+```\n+\n+By using the _newtype pattern_, we _restrict_ the behaviour of the original type and only allow semantically valid methods/operations. If `AddOnlyCounter` is defined in another module, users can't break its guarantees, as the `u32` is private aka encapsulated.\n+\n+```rust\n+let counter = AddOnlyCounter::new();\n+\n+// this works:\n+counter += 1;\n+\n+// these are compile-time errors:\n+counter = 5;\n+counter -= 1;\n+counter.0 -= 1;\n+```\n+\n+\n+# Reference-level explanation\n+[reference]: #reference\n+\n+A delegation statement can only appear inside a trait impl block. Delegation inside inherent impls is left as a future extension.\n+\n+Delegation must be to a field on `Self`. Other kinds of implementer expressions are left as future extensions. This also means delegation can only be done on structs for now.\n+\n+There may be more than one delegation statement. For readability, `rustfmt` moves delegation statements to the top of an impl block.","path":"text/0000-delegation.md","position":193,"original_position":193,"commit_id":"a74616769541acff267f9c5845d447d0fb673bdc","original_commit_id":"a74616769541acff267f9c5845d447d0fb673bdc","user":{"login":"scottmcm","id":18526288,"avatar_url":"https://avatars2.githubusercontent.com/u/18526288?v=4","gravatar_id":"","url":"https://api.github.com/users/scottmcm","html_url":"https://github.com/scottmcm","followers_url":"https://api.github.com/users/scottmcm/followers","following_url":"https://api.github.com/users/scottmcm/following{/other_user}","gists_url":"https://api.github.com/users/scottmcm/gists{/gist_id}","starred_url":"https://api.github.com/users/scottmcm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/scottmcm/subscriptions","organizations_url":"https://api.github.com/users/scottmcm/orgs","repos_url":"https://api.github.com/users/scottmcm/repos","events_url":"https://api.github.com/users/scottmcm/events{/privacy}","received_events_url":"https://api.github.com/users/scottmcm/received_events","type":"User","site_admin":false},"body":"Perhaps justify _why_ this is more readable?  I can see an argument for `*`, but especially for single-method delegation, I'm not convinced.  Particularly in a case where I'm changing existing code to replace manual delegation with `delegate`, I'd expect rustfmt to leave the the item where it is so the diff is the obvious one.  And even in new code, I might be intentionally matching the order of the methods on the trait, for example.  (And more nit-picky, if it's going to move multiple, it would need to pick an order to put them in.)\r\n\r\nAlso, what's the semantics (since this is the reference section) of two `delegate * to` items?","created_at":"2018-04-07T04:16:49Z","updated_at":"2018-04-07T04:16:50Z","html_url":"https://github.com/rust-lang/rfcs/pull/2393#discussion_r179907905","pull_request_url":"https://api.github.com/repos/rust-lang/rfcs/pulls/2393","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/rust-lang/rfcs/pulls/comments/179907905"},"html":{"href":"https://github.com/rust-lang/rfcs/pull/2393#discussion_r179907905"},"pull_request":{"href":"https://api.github.com/repos/rust-lang/rfcs/pulls/2393"}}},"pull_request":{"url":"https://api.github.com/repos/rust-lang/rfcs/pulls/2393","id":179906197,"html_url":"https://github.com/rust-lang/rfcs/pull/2393","diff_url":"https://github.com/rust-lang/rfcs/pull/2393.diff","patch_url":"https://github.com/rust-lang/rfcs/pull/2393.patch","issue_url":"https://api.github.com/repos/rust-lang/rfcs/issues/2393","number":2393,"state":"open","locked":false,"title":"RFC: Delegation","user":{"login":"elahn","id":10919017,"avatar_url":"https://avatars0.githubusercontent.com/u/10919017?v=4","gravatar_id":"","url":"https://api.github.com/users/elahn","html_url":"https://github.com/elahn","followers_url":"https://api.github.com/users/elahn/followers","following_url":"https://api.github.com/users/elahn/following{/other_user}","gists_url":"https://api.github.com/users/elahn/gists{/gist_id}","starred_url":"https://api.github.com/users/elahn/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/elahn/subscriptions","organizations_url":"https://api.github.com/users/elahn/orgs","repos_url":"https://api.github.com/users/elahn/repos","events_url":"https://api.github.com/users/elahn/events{/privacy}","received_events_url":"https://api.github.com/users/elahn/received_events","type":"User","site_admin":false},"body":"Syntax sugar for efficient code reuse via the composition pattern. Wrapper functions are generated for a struct, delegating most or all of a trait’s impl block to a member field that already implements the trait.\r\n\r\n[Rendered](https://github.com/elahn/rfcs/blob/delegation2018/text/0000-delegation.md)\r\n\r\n### Please Note:\r\n\r\nThis RFC is a group effort from the Rust community. Whenever an issue is raised, please edit the [RFC draft](https://hackmd.io/ZUEHoEgwRF29hbcIyUXIiw?edit) to address it as best you can. \r\n\r\nIf the design needs to be bikeshedded, please do so [on this internals thread](https://internals.rust-lang.org/t/new-rfc-for-delegation-anyone-interested-in-contributing/6644).\r\n\r\nWhenever an issue or question has been resolved, [please submit a PR to this RFC](https://github.com/elahn/rfcs/tree/delegation2018).\r\n\r\n---------\r\n\r\nThank you, everyone for your contributions, they’ve been a big help. If we continue this collaborative style throughout the RFC process, I’ve no doubt we can address any concerns that arise and get this puppy accepted!","created_at":"2018-04-06T10:07:47Z","updated_at":"2018-04-07T04:16:50Z","closed_at":null,"merged_at":null,"merge_commit_sha":"41aee45e6c9934b907ce05e00f072ea349e71fc0","assignee":null,"assignees":[],"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/2393/commits","review_comments_url":"https://api.github.com/repos/rust-lang/rfcs/pulls/2393/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/2393/comments","statuses_url":"https://api.github.com/repos/rust-lang/rfcs/statuses/a74616769541acff267f9c5845d447d0fb673bdc","head":{"label":"elahn:delegation2018","ref":"delegation2018","sha":"a74616769541acff267f9c5845d447d0fb673bdc","user":{"login":"elahn","id":10919017,"avatar_url":"https://avatars0.githubusercontent.com/u/10919017?v=4","gravatar_id":"","url":"https://api.github.com/users/elahn","html_url":"https://github.com/elahn","followers_url":"https://api.github.com/users/elahn/followers","following_url":"https://api.github.com/users/elahn/following{/other_user}","gists_url":"https://api.github.com/users/elahn/gists{/gist_id}","starred_url":"https://api.github.com/users/elahn/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/elahn/subscriptions","organizations_url":"https://api.github.com/users/elahn/orgs","repos_url":"https://api.github.com/users/elahn/repos","events_url":"https://api.github.com/users/elahn/events{/privacy}","received_events_url":"https://api.github.com/users/elahn/received_events","type":"User","site_admin":false},"repo":{"id":80765713,"name":"rfcs","full_name":"elahn/rfcs","owner":{"login":"elahn","id":10919017,"avatar_url":"https://avatars0.githubusercontent.com/u/10919017?v=4","gravatar_id":"","url":"https://api.github.com/users/elahn","html_url":"https://github.com/elahn","followers_url":"https://api.github.com/users/elahn/followers","following_url":"https://api.github.com/users/elahn/following{/other_user}","gists_url":"https://api.github.com/users/elahn/gists{/gist_id}","starred_url":"https://api.github.com/users/elahn/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/elahn/subscriptions","organizations_url":"https://api.github.com/users/elahn/orgs","repos_url":"https://api.github.com/users/elahn/repos","events_url":"https://api.github.com/users/elahn/events{/privacy}","received_events_url":"https://api.github.com/users/elahn/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/elahn/rfcs","description":"RFCs for changes to Rust","fork":true,"url":"https://api.github.com/repos/elahn/rfcs","forks_url":"https://api.github.com/repos/elahn/rfcs/forks","keys_url":"https://api.github.com/repos/elahn/rfcs/keys{/key_id}","collaborators_url":"https://api.github.com/repos/elahn/rfcs/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/elahn/rfcs/teams","hooks_url":"https://api.github.com/repos/elahn/rfcs/hooks","issue_events_url":"https://api.github.com/repos/elahn/rfcs/issues/events{/number}","events_url":"https://api.github.com/repos/elahn/rfcs/events","assignees_url":"https://api.github.com/repos/elahn/rfcs/assignees{/user}","branches_url":"https://api.github.com/repos/elahn/rfcs/branches{/branch}","tags_url":"https://api.github.com/repos/elahn/rfcs/tags","blobs_url":"https://api.github.com/repos/elahn/rfcs/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/elahn/rfcs/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/elahn/rfcs/git/refs{/sha}","trees_url":"https://api.github.com/repos/elahn/rfcs/git/trees{/sha}","statuses_url":"https://api.github.com/repos/elahn/rfcs/statuses/{sha}","languages_url":"https://api.github.com/repos/elahn/rfcs/languages","stargazers_url":"https://api.github.com/repos/elahn/rfcs/stargazers","contributors_url":"https://api.github.com/repos/elahn/rfcs/contributors","subscribers_url":"https://api.github.com/repos/elahn/rfcs/subscribers","subscription_url":"https://api.github.com/repos/elahn/rfcs/subscription","commits_url":"https://api.github.com/repos/elahn/rfcs/commits{/sha}","git_commits_url":"https://api.github.com/repos/elahn/rfcs/git/commits{/sha}","comments_url":"https://api.github.com/repos/elahn/rfcs/comments{/number}","issue_comment_url":"https://api.github.com/repos/elahn/rfcs/issues/comments{/number}","contents_url":"https://api.github.com/repos/elahn/rfcs/contents/{+path}","compare_url":"https://api.github.com/repos/elahn/rfcs/compare/{base}...{head}","merges_url":"https://api.github.com/repos/elahn/rfcs/merges","archive_url":"https://api.github.com/repos/elahn/rfcs/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/elahn/rfcs/downloads","issues_url":"https://api.github.com/repos/elahn/rfcs/issues{/number}","pulls_url":"https://api.github.com/repos/elahn/rfcs/pulls{/number}","milestones_url":"https://api.github.com/repos/elahn/rfcs/milestones{/number}","notifications_url":"https://api.github.com/repos/elahn/rfcs/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/elahn/rfcs/labels{/name}","releases_url":"https://api.github.com/repos/elahn/rfcs/releases{/id}","deployments_url":"https://api.github.com/repos/elahn/rfcs/deployments","created_at":"2017-02-02T20:28:59Z","updated_at":"2018-04-06T09:16:50Z","pushed_at":"2018-04-06T22:42:44Z","git_url":"git://github.com/elahn/rfcs.git","ssh_url":"git@github.com:elahn/rfcs.git","clone_url":"https://github.com/elahn/rfcs.git","svn_url":"https://github.com/elahn/rfcs","homepage":"","size":5543,"stargazers_count":0,"watchers_count":0,"language":"Shell","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":1,"license":{"key":"other","name":"Other","spdx_id":null,"url":null},"forks":0,"open_issues":1,"watchers":0,"default_branch":"master"}},"base":{"label":"rust-lang:master","ref":"master","sha":"8bffc2fc5c0d6b25d101af69f18b9df9da7b134b","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-04-06T02:04:00Z","pushed_at":"2018-04-06T22:42:46Z","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":73964,"stargazers_count":1424,"watchers_count":1424,"language":"Shell","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":596,"mirror_url":null,"archived":false,"open_issues_count":723,"license":{"key":"other","name":"Other","spdx_id":null,"url":null},"forks":596,"open_issues":723,"watchers":1424,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/rust-lang/rfcs/pulls/2393"},"html":{"href":"https://github.com/rust-lang/rfcs/pull/2393"},"issue":{"href":"https://api.github.com/repos/rust-lang/rfcs/issues/2393"},"comments":{"href":"https://api.github.com/repos/rust-lang/rfcs/issues/2393/comments"},"review_comments":{"href":"https://api.github.com/repos/rust-lang/rfcs/pulls/2393/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/2393/commits"},"statuses":{"href":"https://api.github.com/repos/rust-lang/rfcs/statuses/a74616769541acff267f9c5845d447d0fb673bdc"}},"author_association":"NONE"}}
{"actor":{"display_login":"scottmcm"}}