{"action":"created","comment":{"url":"https://api.github.com/repos/rust-lang/rfcs/pulls/comments/29965276","id":29965276,"diff_hunk":"@@ -0,0 +1,748 @@\n+- Feature Name: not applicable\n+- Start Date: 2015-05-04\n+- RFC PR: (leave this empty)\n+- Rust Issue: (leave this empty)\n+\n+# Summary\n+\n+This RFC proposes a comprehensive set of guidelines for which changes to\n+*stable* APIs are considered breaking from a semver perspective, and which are\n+not.  These guidelines are intended for both the standard library and for the\n+crates.io ecosystem.\n+\n+This does *not* mean that the standard library should be completely free to make\n+non-semver-breaking changes; there are sometimes still risks of ecosystem pain\n+that need to be taken into account. Rather, this RFC makes explicit an initial\n+set of changes that absolutely *cannot* be made without a semver bump.\n+\n+Along the way, it also discusses some interactions with potential language\n+features that can help mitigate pain for non-breaking changes.\n+\n+The RFC covers only API issues; other issues related to language features,\n+lints, type inference, command line arguments, Cargo, and so on are considered\n+out of scope.\n+\n+# Motivation\n+\n+Both Rust and its library ecosystem have adopted [semver](http://semver.org/), a\n+technique for versioning platforms/libraries partly in terms of the effect on\n+the code that uses them. In a nutshell, the versioning scheme has three components::\n+\n+1. **Major**: must be incremented for changes that break client code.\n+2. **Minor**: incremented for backwards-compatible feature additions.\n+3. **Patch**: incremented for backwards-compatible bug fixes.\n+\n+[Rust 1.0.0](http://blog.rust-lang.org/2015/02/13/Final-1.0-timeline.html) will\n+mark the beginning of our\n+[commitment to stability](http://blog.rust-lang.org/2014/10/30/Stability.html),\n+and from that point onward it will be important to be clear about what\n+constitutes a breaking change, in order for semver to play a meaningful role. As\n+we will see, this question is more subtle than one might think at first -- and\n+the simplest approach would make it effectively impossible to grow the standard\n+library.\n+\n+The goal of this RFC is to lay out a comprehensive policy for what *must* be\n+considered a breaking API change from the perspective of semver, along with some\n+guidance about non-semver-breaking changes.\n+\n+# Detailed design\n+\n+For clarity, in the rest of the RFC, we will use the following terms:\n+\n+* **Major change**: a change that requires a major semver bump.\n+* **Minor change**: a change that requires only a minor semver bump.\n+* **Breaking change**: a change that, *strictly speaking*, can cause downstream\n+  code to fail to compile.\n+\n+What we will see is that in Rust today, almost any change is technically a\n+breaking change. For example, given the way that globs currently work, *adding\n+any public item* to a library can break its clients (more on that later). But\n+not all breaking changes are equal.\n+\n+So, this RFC proposes that **all major changes are breaking, but not all breaking\n+changes are major.**\n+\n+## Overview\n+\n+### Principles of the policy\n+\n+The basic design of the policy is that **minor changes should require at most a\n+few local *annotations* to the code you are developing, and in principle no\n+changes to your dependencies.**\n+\n+In more detail:\n+\n+* Minor changes should require at most minor amounts of work upon upgrade. For\n+  example, changes that may require occasional type annotations or use of UFCS\n+  to disambiguate are not automatically \"major\" changes. (But in such cases, one\n+  must evaluate how widespread these \"minor\" changes are).\n+\n+* In principle, it should be possible to produce a version of the code for any\n+  dependencies that *will not break* when upgrading to a new minor\n+  revision. This goes hand-in-hand with the above bullet; as we will see, it's\n+  possible to save a fully \"elaborated\" version of upstream code that does not\n+  require any disambiguation. The \"in principle\" refers to the fact that getting\n+  there may require some additional tooling or language support, which this RFC\n+  outlines.\n+\n+That means that any breakage in a minor release must be very \"shallow\": it must\n+always be possible to locally fix the problem through some kind of\n+disambiguation *that could have been done in advance* (by using more explicit\n+forms) or other annotation (like disabling a lint). It means that minor changes\n+can never leave you in a state that requires breaking changes to your own code.\n+\n+**Although this general policy allows some (very limited) breakage in minor\n+releases, it is not a license to make these changes blindly**. The breakage that\n+this RFC permits, aside from being very simple to fix, is also unlikely to occur\n+often in practice. The RFC will discuss measures that should be employed in the\n+standard library to ensure that even these minor forms of breakage do not cause\n+widespread pain in the ecosystem.\n+\n+### Scope of the policy\n+\n+The policy laid out by this RFC applies to *stable*, *public* APIs in the\n+standard library. Eventually, stability attributes will be usable in external\n+libraries as well (this will require some design work), but for now public APIs\n+in external crates should be understood as de facto stable after the library\n+reaches 1.0.0 (per semver).\n+\n+## Policy by language feature\n+\n+Most of the policy is simplest to lay out with reference to specific language\n+features and the way that APIs using them can, and cannot, evolve in a minor\n+release.\n+\n+**Breaking changes are assumed to be major changes unless otherwise stated**.\n+The RFC covers many, but not all breaking changes that are major; it covers\n+*all* breaking changes that are considered minor.\n+\n+### Crates\n+\n+#### Major change: introducing `#[feature]` for the first time.\n+\n+Changing a crate from working on stable Rust to *requiring* a nightly is\n+considered a breaking change. Crate authors should consider using Cargo\n+\"features\" for their crate to make such use opt-in.\n+\n+#### Minor change: adding/removing crate dependencies.\n+\n+The author is not aware of any possible breakage in altering dependencies (which\n+is essentially private anyway).\n+\n+### Modules\n+\n+#### Major change: renaming/moving/removing any public items.\n+\n+Although renaming an item might seem like a minor change, according to the\n+general policy design this is not a permitted form of breakage: it's not\n+possible to annotate code in advance to avoid the breakage, nor is it possible\n+to prevent the breakage from affecting dependencies.\n+\n+Of course, much of the effect of renaming/moving/removing can be achieved by\n+instead using deprecation and `pub use`, and the standard library should not be\n+afraid to do so!In the long run, we should consider hiding at least some old\n+deprecated items from the docs, and could even consider putting out a major\n+version solely as a kind of \"garbage collection\" for long-deprecated APIs.\n+\n+#### Minor change: adding new public items.\n+\n+Note that adding new public items is currently a breaking change, due to glob\n+imports. For example, the following snippet of code will break if the `foo`\n+module introduces a public item called `bar`:\n+\n+```rust\n+use foo::*;\n+fn bar() { ... }\n+```\n+\n+The problem here is that glob imports currently do not allow any of their\n+imports to be shadowed by an explicitly-define item.\n+\n+There are two reasons this is considered a minor change by this RFC:\n+\n+1. The RFC also suggests permitting shadowing of a glob import by any explicit\n+   item. This has been the intended semantics of globs, but has not been\n+   implemented. The details are left to a future RFC, however.\n+\n+2. Even if that change were made, though, there is still the case where two glob\n+   imports conflict without any explicit definition \"covering\" them. This is\n+   permitted to produce an error under the principles of this RFC because the\n+   glob imports could have been written as more explicit (expanded) `use`\n+   statements. It is also plausible to do this expansion automatically for a\n+   crate's dependencies, to prevent breakage in the first place.\n+\n+### Structs\n+\n+See \"[Signatures in type definitions](#signatures-in-type-definitions)\" for some\n+general remarks about changes to the actual types in a `struct` definition.\n+\n+#### Major change: adding a private field when all current fields are public.\n+\n+This change has the effect of making external struct literals impossible to\n+write, which can break code irreparably.\n+\n+#### Major change: adding a public field when no private field exists.\n+\n+This change retains the ability to use struct literals, but it breaks existing\n+uses of such literals; it likewise breaks exhaustive matches against the struct.\n+\n+#### Minor change: adding or removing private fields when at least one already exists.\n+\n+No existing code could be relying on struct literals for the struct, nor on\n+exhaustively matching its contents, and client code will likewise be oblivious\n+to the addition of further private fields.\n+\n+For tuple structs, this is only a minor change if furthermore *all* fields are\n+currently private. (Tuple structs with mixtures of public and private fields are\n+bad practice in any case.)\n+\n+#### Minor change: going from a tuple struct with all private fields (with at least one field) to a normal struct, or vice versa.\n+\n+This is technically a breaking change:\n+\n+```rust\n+// in some other module:\n+pub struct Foo(SomeType);\n+\n+// in downstream code\n+let Foo(_) = foo;\n+```\n+\n+Changing `Foo` to a normal struct can break code that matches on it -- but there\n+is never any real reason to match on it in that circumstance, since you cannot\n+extract any fields or learn anything of interest about the struct.\n+\n+### Enums\n+\n+See \"[Signatures in type definitions](#signatures-in-type-definitions)\" for some\n+general remarks about changes to the actual types in an `enum` definition.\n+\n+#### Major change: adding new variants.\n+\n+Exhaustiveness checking means that a `match` that explicitly checks all the\n+variants for an `enum` will break if a new variant is added. It is not currently\n+possible to defend against this breakage in advance.\n+\n+A [postponed RFC](https://github.com/rust-lang/rfcs/pull/757) discusses a\n+language feature that allows an enum to be marked as \"extensible\", which\n+modifies the way that exhaustiveness checking is done and would make it possible\n+to extend the enum without breakage.\n+\n+#### Major change: adding new fields to a variant.\n+\n+If the enum is public, so is the full contents of all of its variants. As per\n+the rules for structs, this means it is not allowed to add any new fields (which\n+will automatically be public).\n+\n+If you wish to allow for this kind of extensibility, consider introducing a new,\n+explicit struct for the variant up front.\n+\n+### Traits\n+\n+#### Major change: adding a non-defaulted item.\n+\n+Adding any item without a default will immediately break all trait implementations.\n+\n+It's possible that in the future we will allow some kind of\n+\"[sealing](#sealed-traits)\" to say that a trait can only be used as a bound, not\n+to provide new implementations; such a trait *would* allow arbitrary items to be\n+added.\n+\n+#### Major change: any non-trivial change to item signatures.\n+\n+Because traits have both implementors and consumers, any change to the signature\n+of e.g. a method will affect at least one of the two parties. So, for example,\n+abstracting a concrete method to use generics instead might work fine for\n+clients of the trait, but would break existing implementors. (Note, as above,\n+the potential for \"sealed\" traits to alter this dynamic.)\n+\n+#### Minor change: adding a defaulted item.\n+\n+Adding a defaulted item is technically a breaking change:\n+\n+```rust\n+trait Trait1 {}\n+trait Trait2 {\n+    fn foo(&self);\n+}\n+\n+fn use_both<T: Trait1 + Trait2>(t: &T) {\n+    t.foo()\n+}\n+```\n+\n+If a `foo` method is added to `Trait1`, even with a default, it would cause a\n+dispatch ambiguity in `use_both`, since the call to `foo` could be referring to\n+either trait.\n+\n+(Note, however, that existing *implementations* of the trait are fine.)\n+\n+According to the basic principles of this RFC, such a change is minor: it is\n+always possible to annotate the call `t.foo()` to be more explicit *in advance*\n+using UFCS: `<Trait2>::foo(t)`. This kind of annotation could be done\n+automatically for code in dependencies (see\n+[Elaborated source](#elaborated-source)). And it would also be possible to\n+mitigate this problem by allowing\n+[method renaming on trait import](#trait-item-renaming).\n+\n+While the scenario of adding a defaulted method to a trait may seem somewhat\n+obscure, the exact same hazards arise with *implementing existing traits* (see\n+below), which is clearly vital to allow; we apply a similar policy to both.\n+\n+All that said, it is incumbent on library authors to ensure that such \"minor\"\n+changes are in fact minor in practice: if a conflict like `t.foo()` is likely to\n+arise at all often in downstream code, it would be advisable to explore a\n+different choice of names. More guidelines for the standard library are given\n+later on.\n+\n+#### Minor change: adding a defaulted type parameter.\n+\n+As with \"[Signatures in type definitions](#signatures-in-type-definitions)\",\n+traits are permitted to add new type parameters as long as defaults are provided\n+(which is backwards compatible).\n+\n+### Trait implementations\n+\n+#### Major change: implementing any \"fundamental\" trait.\n+\n+A [recent RFC](https://github.com/rust-lang/rfcs/pull/1023) introduced the idea\n+of \"fundamental\" traits which are so basic that *not* implementing such a trait\n+right off the bat is considered a promise that you will *never* implement the\n+trait. The `Sized` and `Fn` traits are examples.\n+\n+The coherence rules take advantage of fundamental traits in such a way that\n+*adding a new implementation of a fundamental trait to an existing type can\n+cause downstream breakage*. Thus, such impls are considered major changes.\n+\n+#### Minor change: implementing any non-fundamental trait.\n+\n+Unfortunately, implementing any existing trait can cause breakage:\n+\n+```rust\n+// Crate A\n+    pub trait Trait1 {\n+        fn foo(&self);\n+    }\n+\n+    pub struct Foo; // does not implement Trait1\n+\n+// Crate B\n+    use crateA::Trait1;\n+\n+    trait Trait2 {\n+        fn foo(&self);\n+    }\n+\n+    impl Trait2 for crateA::Foo { .. }\n+\n+    fn use_foo(f: &crateA::Foo) {\n+        f.foo()\n+    }\n+```\n+\n+If crate A adds an implementation of `Trait1` for `Foo`, the call to `f.foo()`\n+in crate B will yield a dispatch ambiguity (much like the one we saw for\n+defaulted items). Thus *technically implementing any existing trait is a\n+breaking change!* Completely prohibiting such a change is clearly a non-starter.\n+\n+However, as before, this kind of breakage is considered \"minor\" by the\n+principles of this RFC (see \"Adding a defaulted item\" above).\n+\n+### Inherent implementations\n+\n+#### Minor change: adding any inherent items.\n+\n+Adding an inherent item cannot lead to dispatch ambiguity, because inherent\n+items trump any trait items with the same name.\n+\n+However, introducing an inherent item *can* lead to breakage if the signature of\n+the item does not match that of an in scope, implemented trait:\n+\n+```rust\n+// Crate A\n+    pub struct Foo;\n+\n+// Crate B\n+    trait Trait {\n+        fn foo(&self);\n+    }\n+\n+    impl Trait for crateA::Foo { .. }\n+\n+    fn use_foo(f: &crateA::Foo) {\n+        f.foo()\n+   }\n+```\n+\n+If crate A adds a method:\n+\n+```rust\n+impl Foo {\n+    fn foo(&self, x: u8) { ... }\n+}\n+```\n+\n+then crate B would no longer compile, since dispatch would prefer the inherent\n+impl, which has the wrong type.\n+\n+Once more, this is considered a minor change, since UFCS can disambiguate (see\n+\"Adding a defaulted item\" above).\n+\n+It's worth noting, however, that if the signatures *did* happen to match then\n+the change would no longer cause a compilation error, but might silently change\n+runtime behavior. The case where the same method for the same type has\n+meaningfully different behavior is considered unlikely enough that the RFC is\n+willing to permit it to be labeled as a minor change -- and otherwise, inherent\n+methods could never be added after the fact.\n+\n+### Other items\n+\n+Most remaining items do not have any particularly unique items:\n+\n+* For type aliases, see \"[Signatures in type definitions](#signatures-in-type-definitions)\".\n+* For free functions, see \"[Signatures in functions](#signatures-in-functions)\".\n+\n+## Cross-cutting concerns\n+\n+### Behavioral changes\n+\n+This RFC is largely focused on API changes which may, in particular, cause\n+downstream code to stop compiling. But in some sense it is even more pernicious\n+to make a change that allows downstream code to continue compiling, but causes\n+its runtime behavior to break.\n+\n+This RFC does not attempt to provide a comprehensive policy on behavioral\n+changes, which would be extremely difficult. In general, APIs are expected to\n+provide explicit contracts for their behavior via documentation, and behavior\n+that is not part of this contract is permitted to change in minor\n+revisions. (Remember: this RFC is about setting a *minimum* bar for when major\n+version bumps are required.)\n+\n+This policy will likely require some revision over time, to become more explicit\n+and perhaps lay out some best practices.\n+\n+### Signatures in type definitions\n+\n+#### Major change: tightening bounds.\n+\n+Adding new constraints on existing type parameters is a breaking change, since\n+existing uses of the type definition can break. So the following is a major\n+change:\n+\n+```rust\n+// MAJOR CHANGE\n+\n+// Before\n+struct Foo<A> { .. }\n+\n+// After\n+struct Foo<A: Clone> { .. }\n+```\n+\n+#### Minor change: loosening bounds.\n+\n+Loosening bounds, on the other hand, cannot break code because when you\n+reference `Foo<A>`, you *do not learn anything about the bounds on `A`*. (This\n+is why you have to repeat any relevant bounds in `impl` blocks for `Foo`, for\n+example.) So the following is a minor change:\n+\n+```rust\n+// MINOR CHANGE\n+\n+// Before\n+struct Foo<A: Clone> { .. }\n+\n+// After\n+struct Foo<A> { .. }\n+```\n+\n+#### Minor change: adding defaulted type parameters.\n+\n+All existing references to a type/trait definition continue to compile and work\n+correctly after a new defaulted type parameter is added. So the following is\n+a minor change:\n+\n+```rust\n+// MINOR CHANGE\n+\n+// Before\n+struct Foo { .. }\n+\n+// After\n+struct Foo<A = u8> { .. }\n+```\n+\n+#### Minor change: generalizing to generics.\n+\n+A struct or enum field can change from a concrete type to a generic type\n+parameter, provided that the change results in an identical type for all\n+existing use cases. For example, the following change is permitted:\n+\n+```rust\n+// MINOR CHANGE\n+\n+// Before\n+struct Foo(pub u8);\n+\n+// After\n+struct Foo<T = u8>(pub T);\n+```\n+\n+because existing uses of `Foo` are shorthand for `Foo<u8>` which yields the\n+identical field type.\n+\n+On the other hand, the following is not permitted:\n+\n+```rust\n+// MAJOR CHANGE\n+\n+// Before\n+struct Foo<T = u8>(pub T, pub u8);\n+\n+// After\n+struct Foo<T = u8>(pub T, pub T);\n+```\n+\n+since there may be existing uses of `Foo` with a non-default type parameter\n+which would break as a result of the change.\n+\n+It's also permitted to change from a generic type to a more-generic one in a\n+minor revision:\n+\n+```rust\n+// MINOR CHANGE\n+\n+// Before\n+struct Foo<T>(pub T, pub T);\n+\n+// After\n+struct Foo<T, U = T>(pub T, pub U);\n+```\n+\n+since, again, all existing uses of the type `Foo<T>` will yield the same field\n+types as before.\n+\n+### Signatures in functions\n+\n+All of the changes mentioned below are considered major changes in the context\n+of trait methods, since they can break implementors.\n+\n+#### Major change: adding new arguments.\n+\n+At the moment, Rust does not provide defaulted arguments, so any change in arity\n+is a breaking change.\n+\n+#### Minor change: introducing a new type parameter.","path":"text/0000-api-evolution.md","position":535,"original_position":535,"commit_id":"e449a9c35c2aa647c2610b1da7633b6c92089632","original_commit_id":"e449a9c35c2aa647c2610b1da7633b6c92089632","user":{"login":"kballard","id":714,"avatar_url":"https://avatars.githubusercontent.com/u/714?v=3","gravatar_id":"","url":"https://api.github.com/users/kballard","html_url":"https://github.com/kballard","followers_url":"https://api.github.com/users/kballard/followers","following_url":"https://api.github.com/users/kballard/following{/other_user}","gists_url":"https://api.github.com/users/kballard/gists{/gist_id}","starred_url":"https://api.github.com/users/kballard/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kballard/subscriptions","organizations_url":"https://api.github.com/users/kballard/orgs","repos_url":"https://api.github.com/users/kballard/repos","events_url":"https://api.github.com/users/kballard/events{/privacy}","received_events_url":"https://api.github.com/users/kballard/received_events","type":"User","site_admin":false},"body":"@P1start I was referring to that first code snippet. With the second code snippet, the addition of a non-inferrable type parameter would of course be a breaking change, and I would expect anyone making such a change to provide a default value for the type parameter (or if they really don't want to, then to consider it a major version bump).","created_at":"2015-05-08T18:38:46Z","updated_at":"2015-05-08T18:38:46Z","html_url":"https://github.com/rust-lang/rfcs/pull/1105#discussion_r29965276","pull_request_url":"https://api.github.com/repos/rust-lang/rfcs/pulls/1105","_links":{"self":{"href":"https://api.github.com/repos/rust-lang/rfcs/pulls/comments/29965276"},"html":{"href":"https://github.com/rust-lang/rfcs/pull/1105#discussion_r29965276"},"pull_request":{"href":"https://api.github.com/repos/rust-lang/rfcs/pulls/1105"}}},"pull_request":{"url":"https://api.github.com/repos/rust-lang/rfcs/pulls/1105","id":34685817,"html_url":"https://github.com/rust-lang/rfcs/pull/1105","diff_url":"https://github.com/rust-lang/rfcs/pull/1105.diff","patch_url":"https://github.com/rust-lang/rfcs/pull/1105.patch","issue_url":"https://api.github.com/repos/rust-lang/rfcs/issues/1105","number":1105,"state":"open","locked":false,"title":"RFC: Policy on semver and API evolution","user":{"login":"aturon","id":709807,"avatar_url":"https://avatars.githubusercontent.com/u/709807?v=3","gravatar_id":"","url":"https://api.github.com/users/aturon","html_url":"https://github.com/aturon","followers_url":"https://api.github.com/users/aturon/followers","following_url":"https://api.github.com/users/aturon/following{/other_user}","gists_url":"https://api.github.com/users/aturon/gists{/gist_id}","starred_url":"https://api.github.com/users/aturon/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aturon/subscriptions","organizations_url":"https://api.github.com/users/aturon/orgs","repos_url":"https://api.github.com/users/aturon/repos","events_url":"https://api.github.com/users/aturon/events{/privacy}","received_events_url":"https://api.github.com/users/aturon/received_events","type":"User","site_admin":false},"body":"This RFC proposes a comprehensive set of guidelines for which changes to\r\n*stable* APIs are considered breaking from a semver perspective, and which are\r\nnot.  These guidelines are intended for both the standard library and for the\r\ncrates.io ecosystem.\r\n\r\nThis does *not* mean that the standard library should be completely free to make\r\nnon-semver-breaking changes; there are sometimes still risks of ecosystem pain\r\nthat need to be taken into account. Rather, this RFC makes explicit an initial\r\nset of changes that absolutely *cannot* be made without a semver bump.\r\n\r\nAlong the way, it also discusses some interactions with potential language\r\nfeatures that can help mitigate pain for non-breaking changes.\r\n\r\nThe RFC covers only API issues; other issues related to language features,\r\nlints, type inference, command line arguments, Cargo, and so on are considered\r\nout of scope.\r\n\r\n[Rendered](https://github.com/aturon/rfcs/blob/api-evolution/text/0000-api-evolution.md)","created_at":"2015-05-04T23:37:55Z","updated_at":"2015-05-08T18:38:46Z","closed_at":null,"merged_at":null,"merge_commit_sha":"1324d28e1d9d0e6792f75f96127948cced8598e4","assignee":{"login":"aturon","id":709807,"avatar_url":"https://avatars.githubusercontent.com/u/709807?v=3","gravatar_id":"","url":"https://api.github.com/users/aturon","html_url":"https://github.com/aturon","followers_url":"https://api.github.com/users/aturon/followers","following_url":"https://api.github.com/users/aturon/following{/other_user}","gists_url":"https://api.github.com/users/aturon/gists{/gist_id}","starred_url":"https://api.github.com/users/aturon/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aturon/subscriptions","organizations_url":"https://api.github.com/users/aturon/orgs","repos_url":"https://api.github.com/users/aturon/repos","events_url":"https://api.github.com/users/aturon/events{/privacy}","received_events_url":"https://api.github.com/users/aturon/received_events","type":"User","site_admin":false},"milestone":null,"commits_url":"https://api.github.com/repos/rust-lang/rfcs/pulls/1105/commits","review_comments_url":"https://api.github.com/repos/rust-lang/rfcs/pulls/1105/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/1105/comments","statuses_url":"https://api.github.com/repos/rust-lang/rfcs/statuses/e449a9c35c2aa647c2610b1da7633b6c92089632","head":{"label":"aturon:api-evolution","ref":"api-evolution","sha":"e449a9c35c2aa647c2610b1da7633b6c92089632","user":{"login":"aturon","id":709807,"avatar_url":"https://avatars.githubusercontent.com/u/709807?v=3","gravatar_id":"","url":"https://api.github.com/users/aturon","html_url":"https://github.com/aturon","followers_url":"https://api.github.com/users/aturon/followers","following_url":"https://api.github.com/users/aturon/following{/other_user}","gists_url":"https://api.github.com/users/aturon/gists{/gist_id}","starred_url":"https://api.github.com/users/aturon/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aturon/subscriptions","organizations_url":"https://api.github.com/users/aturon/orgs","repos_url":"https://api.github.com/users/aturon/repos","events_url":"https://api.github.com/users/aturon/events{/privacy}","received_events_url":"https://api.github.com/users/aturon/received_events","type":"User","site_admin":false},"repo":{"id":20423396,"name":"rfcs","full_name":"aturon/rfcs","owner":{"login":"aturon","id":709807,"avatar_url":"https://avatars.githubusercontent.com/u/709807?v=3","gravatar_id":"","url":"https://api.github.com/users/aturon","html_url":"https://github.com/aturon","followers_url":"https://api.github.com/users/aturon/followers","following_url":"https://api.github.com/users/aturon/following{/other_user}","gists_url":"https://api.github.com/users/aturon/gists{/gist_id}","starred_url":"https://api.github.com/users/aturon/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aturon/subscriptions","organizations_url":"https://api.github.com/users/aturon/orgs","repos_url":"https://api.github.com/users/aturon/repos","events_url":"https://api.github.com/users/aturon/events{/privacy}","received_events_url":"https://api.github.com/users/aturon/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/aturon/rfcs","description":"RFCs for changes to Rust","fork":true,"url":"https://api.github.com/repos/aturon/rfcs","forks_url":"https://api.github.com/repos/aturon/rfcs/forks","keys_url":"https://api.github.com/repos/aturon/rfcs/keys{/key_id}","collaborators_url":"https://api.github.com/repos/aturon/rfcs/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/aturon/rfcs/teams","hooks_url":"https://api.github.com/repos/aturon/rfcs/hooks","issue_events_url":"https://api.github.com/repos/aturon/rfcs/issues/events{/number}","events_url":"https://api.github.com/repos/aturon/rfcs/events","assignees_url":"https://api.github.com/repos/aturon/rfcs/assignees{/user}","branches_url":"https://api.github.com/repos/aturon/rfcs/branches{/branch}","tags_url":"https://api.github.com/repos/aturon/rfcs/tags","blobs_url":"https://api.github.com/repos/aturon/rfcs/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/aturon/rfcs/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/aturon/rfcs/git/refs{/sha}","trees_url":"https://api.github.com/repos/aturon/rfcs/git/trees{/sha}","statuses_url":"https://api.github.com/repos/aturon/rfcs/statuses/{sha}","languages_url":"https://api.github.com/repos/aturon/rfcs/languages","stargazers_url":"https://api.github.com/repos/aturon/rfcs/stargazers","contributors_url":"https://api.github.com/repos/aturon/rfcs/contributors","subscribers_url":"https://api.github.com/repos/aturon/rfcs/subscribers","subscription_url":"https://api.github.com/repos/aturon/rfcs/subscription","commits_url":"https://api.github.com/repos/aturon/rfcs/commits{/sha}","git_commits_url":"https://api.github.com/repos/aturon/rfcs/git/commits{/sha}","comments_url":"https://api.github.com/repos/aturon/rfcs/comments{/number}","issue_comment_url":"https://api.github.com/repos/aturon/rfcs/issues/comments{/number}","contents_url":"https://api.github.com/repos/aturon/rfcs/contents/{+path}","compare_url":"https://api.github.com/repos/aturon/rfcs/compare/{base}...{head}","merges_url":"https://api.github.com/repos/aturon/rfcs/merges","archive_url":"https://api.github.com/repos/aturon/rfcs/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/aturon/rfcs/downloads","issues_url":"https://api.github.com/repos/aturon/rfcs/issues{/number}","pulls_url":"https://api.github.com/repos/aturon/rfcs/pulls{/number}","milestones_url":"https://api.github.com/repos/aturon/rfcs/milestones{/number}","notifications_url":"https://api.github.com/repos/aturon/rfcs/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/aturon/rfcs/labels{/name}","releases_url":"https://api.github.com/repos/aturon/rfcs/releases{/id}","created_at":"2014-06-02T23:35:56Z","updated_at":"2015-01-17T17:42:40Z","pushed_at":"2015-05-07T15:46:57Z","git_url":"git://github.com/aturon/rfcs.git","ssh_url":"git@github.com:aturon/rfcs.git","clone_url":"https://github.com/aturon/rfcs.git","svn_url":"https://github.com/aturon/rfcs","homepage":"","size":2893,"stargazers_count":4,"watchers_count":4,"language":null,"has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":4,"default_branch":"master"}},"base":{"label":"rust-lang:master","ref":"master","sha":"92bc7a304843eaf3e553c2bbc94623a9a92a2aaf","user":{"login":"rust-lang","id":5430905,"avatar_url":"https://avatars.githubusercontent.com/u/5430905?v=3","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://avatars.githubusercontent.com/u/5430905?v=3","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}","created_at":"2014-03-07T21:29:00Z","updated_at":"2015-05-07T15:12:10Z","pushed_at":"2015-05-07T17:25:21Z","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":"","size":11289,"stargazers_count":333,"watchers_count":333,"language":null,"has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":199,"mirror_url":null,"open_issues_count":504,"forks":199,"open_issues":504,"watchers":333,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/rust-lang/rfcs/pulls/1105"},"html":{"href":"https://github.com/rust-lang/rfcs/pull/1105"},"issue":{"href":"https://api.github.com/repos/rust-lang/rfcs/issues/1105"},"comments":{"href":"https://api.github.com/repos/rust-lang/rfcs/issues/1105/comments"},"review_comments":{"href":"https://api.github.com/repos/rust-lang/rfcs/pulls/1105/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/1105/commits"},"statuses":{"href":"https://api.github.com/repos/rust-lang/rfcs/statuses/e449a9c35c2aa647c2610b1da7633b6c92089632"}}}}