{"action":"created","comment":{"url":"https://api.github.com/repos/rust-lang/rust/pulls/comments/35445638","id":35445638,"diff_hunk":"@@ -0,0 +1,413 @@\n+% Wrapper Types\n+\n+// Alternate title: \"Choosing your Guarantees\"\n+\n+One important feature of Rust as language is that it lets us control the costs and guarantees\n+of a program.\n+\n+There are various &ldquo;wrapper type&rdquo; abstractions in the Rust standard library which embody a multitude\n+of tradeoffs between cost, ergonomics, and guarantees. Many let one choose between runtime and\n+compile time enforcement. This section will explain a few selected abstractions in detail.\n+\n+Before proceeding, it is highly recommended that one reads about [ownership][ownership] and\n+[borrowing][borrowing] in Rust.\n+\n+[ownership]: ownership.html\n+[borrowing]: references-and-borrowing.html\n+\n+# Basic pointer types\n+\n+## `Box<T>`\n+\n+[`Box<T>`][box] is an \"owned pointer\" or a \"box\". While it can hand out borrowed references to the\n+data, it is the only owner of the data. In particular, when something like the following occurs:\n+\n+```rust\n+let x = Box::new(1);\n+let y = x;\n+// x no longer accessible here\n+```\n+\n+Here, the box was _moved_ into `y`. As `x` no longer owns it, the compiler will no longer allow the\n+programmer to use `x` after this. A box can similarly be moved _out_ of a function by returning it.\n+\n+When a box (that hasn't been moved) goes out of scope, destructors are run. These destructors take\n+care of deallocating the inner data.\n+\n+This abstraction is a cheap abstraction for dynamic allocation. If you want to allocate some memory\n+on the heap and safely pass around a pointer to that memory, this is ideal. Note that you will only\n+be allowed to share borrowed references to this by the regular borrowing rules, checked at compile\n+time.\n+\n+[box]: ../std/boxed/struct.Box.html\n+\n+#### Interlude: `Copy`\n+\n+Move/ownership semantics are not special to `Box<T>`; it is a feature of all types which are not\n+`Copy`.\n+\n+A `Copy` type is one where all the data it logically encompasses (usually, owns) is part of its\n+stack representation[^2]. Most types containing pointers to other data are not `Copy`, since there\n+is additional data elsewhere, and simply copying the stack representation may accidentally share\n+ownership of that data in an unsafe manner.\n+\n+Types like `Vec<T>` and `String` which have data on the heap are also not `Copy`. Types\n+like primitive types and  often compositions of the same are `Copy`.\n+\n+`&T` and raw pointers _are_ `Copy`. Even though they do point to further data, they do not \"own\"\n+that data. Whereas `Box<T>` can be thought of as \"some data which happens to be dynamically\n+allocated\", `&T` is thought of as \"a borrowing reference to some data\". Even though both are\n+pointers, only the first is considered to be \"data\". Hence, a copy of the first should involve a\n+copy of the data (which is not part of its stack representation), but a copy of the second only\n+needs a copy of the reference. `&mut T` is not `Copy` because mutable aliases cannot be shared, and\n+`&mut T` \"owns\" the data it points to somewhat since it can mutate.\n+\n+Practically speaking, a type can be `Copy` if a copy of its stack representation doesn't violate\n+memory safety.\n+\n+[^2]: Here, \"stack representation\" means the actual data on the stack used by a value of this type (if it is held on the stack). For example, a `Vec<T>` has a stack representation of a pointer and two integers (length, capacity). While there is more data behind the indirection of the pointer, it is not part of the stack-held portion of the `Vec`. Looking at this a different way, a type is `Copy` if a `memcopy` of the data copies all the data owned by it.\n+\n+## `&T` and `&mut T` \n+\n+These are immutable and mutable references respectively. They follow the &lquo;read-write lock&rquo;\n+pattern, such that one may either have only one mutable reference to some data, or any number of\n+immutable ones, but not both. This guarantee is enforced at compile time, and has no visible cost at\n+runtime. In most cases these two pointer types suffice for sharing cheap references between sections\n+of code.\n+\n+These pointers cannot be copied in such a way that they outlive the lifetime associated with them.\n+\n+## `*const T` and `*mut T`\n+\n+These are C-like raw pointers with no lifetime or ownership attached to them. They just point to\n+some location in memory with no other restrictions. The only guarantee that these provide is that\n+they cannot be dereferenced except in code marked `unsafe`.\n+\n+These are useful when building safe, low cost abstractions like `Vec<T>`, but should be avoided in\n+safe code.\n+\n+## `Rc<T>`\n+\n+This is the first wrapper we will cover that has a runtime cost.\n+\n+[`Rc<T>`][rc] is a reference counted pointer. In other words, this lets us have multiple \"owning\"\n+pointers to the same data, and the data will be dropped (destructors will be run) when all pointers\n+are out of scope.\n+\n+Internally, it contains a shared \"reference count\" (also called \"refcount\"), which is incremented\n+each time the `Rc` is cloned, and decremented each time one of the `Rc`s goes out of scope. The main\n+responsibility of `Rc<T>` is to ensure that destructors are called for shared data.\n+\n+The internal data here is immutable, and if a cycle of references is created, the data will be\n+leaked. If we want data that doesn't leak when there are cycles, we need a garbage collector.\n+\n+// Should I link to rust-gc and rajan-bacon-cc here?\n+\n+#### Guarantees\n+\n+The main guarantee provided here is that the data will not be destroyed until all references to it\n+are out of scope.\n+\n+This should be used when we wish to dynamically allocate and share some data (read-only) between\n+various portions of yur program, where it is not certain which portion will finish using the pointer\n+last. It's a viable alternative to `&T` when `&T` is either impossible to statically check for\n+correctness, or creates extremely unergonomic code where the programmer does not wish to spend the\n+development cost of working with.\n+\n+This pointer is _not_ thread safe, and Rust will not let it be sent or shared with other threads.\n+This lets one avoid the cost of atomics in situations where they are unnecessary.\n+\n+There is a sister smart pointer to this one, `Weak<T>`. This is a non-owning, but also non-borrowed,\n+smart pointer. It is also similar to `&T`, but it is not restricted in lifetime&mdash;a `Weak<T>`\n+can be held on to forever. However, it is possible that an attempt to access the inner data may fail\n+and return `None`, since this can outlive the owned `Rc`s. This is useful for cyclic\n+data structures and other things.\n+\n+#### Cost\n+\n+As far as memory goes, `Rc<T>` is a single allocation, though it will allocate two extra words (i.e.\n+two `usize` values) as compared to a regular `Box<T>` (for \"strong\" and \"weak\" refcounts).\n+\n+`Rc<T>` has the computational cost of incrementing/decrementing the refcount whenever it is cloned\n+or goes out of scope respectively. Note that a clone will not do a deep copy, rather it will simply\n+increment the inner reference count and return a copy of the `Rc<T>`\n+\n+[rc]: ../std/rc/struct.Rc.html\n+\n+# Cell types\n+\n+&lquo;Cell&rquo;s provide interior mutability. In other words, they contain data which can be manipulated even\n+if the type cannot be obtained in a mutable form (for example, when it is behind an `&`-ptr or\n+`Rc<T>`).\n+\n+[The documentation for the `cell` module has a pretty good explanation for these][cell-mod].\n+\n+These types are _generally_ found in struct fields, but they may be found elsewhere too.\n+\n+## `Cell<T>`\n+\n+[`Cell<T>`][cell] is a type that provides zero-cost interior mutability, but only for `Copy` types.\n+Since the compiler knows that all the data owned by the contained value is on the stack, there's\n+no worry of leaking any data behind references (or worse!) by simply replacing the data.\n+\n+It is still possible to violate your own invariants using this wrapper, so be careful when using it.\n+If a field is wrapped in `Cell`, it's a nice indicator that the chunk of data is mutable and may not\n+stay the same between the time you first read it and when you intend to use it.\n+\n+\n+\n+```rust\n+let x = Cell::new(1);\n+let y = &x;\n+let z = &x;\n+x.set(2);\n+y.set(3);\n+z.set(4);\n+println!(\"{}\", x.get());\n+```\n+\n+Note that here we were able to mutate the same value from various immutable references.\n+\n+\n+This has the same runtime cost as the following:\n+\n+\n+```rust\n+let mut x = 1;\n+let y = &mut x;\n+let z = &mut x;\n+x = 2;\n+*y = 3;\n+*z = 4;\n+println!(\"{}\", x;\n+```\n+\n+but it has the added benefit of actually compiling successfully.\n+\n+\n+#### Guarantees\n+\n+This relaxes the \"no aliasing with mutability\" restriction in places where it's unnecessary.\n+However, this also relaxes the guarantees that the restriction provides; so if your invariants\n+depend on data stored within `Cell`, you should be careful.\n+\n+\n+This is useful for mutating primitives and other `Copy` types when there is no easy way of\n+doing it in line with the static rules of `&` and `&mut`.\n+\n+[Gábor Lehel][glaebhoerl] summed up the guarantees provided by `Cell` in a rather succinct manner:\n+\n+> The basic guarantee we need to ensure is that interior references can't be invalidated (left\n+> dangling) by mutation of the outer structure. (Think about references to the interiors of types\n+> like `Option`, `Box`, `Vec`, etc.) `&`, `&mut`, and Cell each make a different tradeoff here. `&`\n+> allows shared interior references but forbids mutation; `&mut` allows mutation xor interior\n+> references but not sharing; `Cell` allows shared mutability but not interior references.\n+\n+(Since `Cell` operates by copying, it can't create interior references)\n+\n+[glaebhoerl]: http://www.reddit.com/r/rust/comments/378tj6/blog_post_review_requested_container_types/crlfl74\n+\n+#### Cost\n+\n+There is no runtime cost to using `Cell<T>`, however if you are using it to wrap larger (`Copy`)\n+structs, it might be worthwhile to instead wrap individual fields in `Cell<T>` since each write is\n+otherwise a full copy of the struct.\n+\n+\n+## `RefCell<T>`\n+\n+[`RefCell<T>`][refcell] also provides interior mutability, but isn't restricted to `Copy` types.\n+\n+Instead, it has a runtime cost. `RefCell<T>` enforces the read-write lock pattern at runtime (it's\n+like a single-threaded mutex), unlike `&T`/`&mut T` which do so at compile time. This is done by the\n+`borrow()` and `borrow_mut()` functions, which modify an internal reference count and return smart\n+pointers which can be dereferenced immutably and mutably respectively. The refcount is restored when\n+the smart pointers go out of scope. With this system, we can dynamically ensure that there are never\n+any other borrows active when a mutable borrow is active. If the programmer attempts to make such a\n+borrow, the thread will panic.\n+\n+\n+```rust\n+let x = RefCell::new(vec![1,2,3,4]);\n+{\n+    println!(\"{:?}\", *x.borrow())\n+}\n+\n+{\n+    let my_ref = x.borrow_mut();\n+    my_ref.push(1);\n+}\n+\n+```\n+\n+Similar to `Cell`, this is mainly useful for situations where it's hard or impossible to satisfy the\n+borrow checker. Generally we know that such mutations won't happen in a nested form, but it's good\n+to check.\n+\n+For large, complicated programs, it becomes useful to put some things in `RefCell`s to make things\n+simpler. For example, a lot of the maps in [the `ctxt` struct][ctxt] in the rust compiler internals\n+are inside this wrapper. These are only modified once (during creation, which is not right after\n+initialization) or a couple of times in well-separated places. However, since this struct is\n+pervasively used everywhere, juggling mutable and immutable pointers would be hard (perhaps\n+impossible) and probably form a soup of `&`-ptrs which would be hard to extend. On the other hand,\n+the `RefCell` provides a cheap (not zero-cost) way of safely accessing these. In the future, if\n+someone adds some code that attempts to modify the cell when it's already borrowed, it will cause a\n+(usually deterministic) panic which can be traced back to the offending borrow.\n+\n+Similarly, in Servo's DOM there is a lot of mutation, most of which is local to a DOM type, but some\n+of which crisscrosses the DOM and modifies various things. Using `RefCell` and `Cell` to guard all\n+mutation lets us avoid worrying about mutability everywhere, and it simultaneously highlights the\n+places where mutation is _actually_ happening.\n+\n+Note that `RefCell` should be avoided if a mostly simple solution is possible with `&` pointers.\n+\n+\n+#### Guarantees\n+\n+`RefCell` relaxes the _static_ restrictions preventing aliased mutation, and replaces them with\n+_dynamic_ ones. As such the guarantees have not changed.\n+\n+#### Cost\n+\n+`RefCell` does not allocate, but it contains an additional \"borrow state\"\n+indicator (one word in size) along with the data.\n+\n+At runtime each borrow causes a modification/check of the refcount.\n+\n+[cell-mod]: ../std/cell/\n+[cell]: ../std/cell/struct.Cell.html\n+[refcell]: ../std/cell/struct.RefCell.html\n+[ctxt]: ../rustc/middle/ty/struct.ctxt.html\n+\n+# Synchronous types\n+\n+Many of the types above cannot be used in a threadsafe manner. Particularly, `Rc<T>` and\n+`RefCell<T>`, which both use non-atomic reference counts (_atomic_ reference counts are those which\n+can be incremented from multiple threads without causing a data race), cannot be used this way. This\n+makes them cheaper to use, but we need thread safe versions of these too. They exist, in the form of\n+`Arc<T>` and `Mutex<T>`/`RWLock<T>`\n+\n+Note that the non-threadsafe types _cannot_ be sent between threads, and this is checked at compile\n+time.\n+\n+There are many useful wrappers for concurrent programming in the [sync][sync] module, but only the\n+major ones will be covered below.\n+\n+[sync]: ../std/sync/index.html\n+\n+## `Arc<T>`\n+\n+[`Arc<T>`][arc] is just a version of `Rc<T>` that uses an atomic reference count (hence, \"Arc\").\n+This can be sent freely between threads.\n+\n+\n+\n+\n+C++'s `shared_ptr` is similar to `Arc`, however in the case of C++ the inner data is always mutable.\n+For semantics similar to that from C++, we should use `Arc<Mutex<T>>`, `Arc<RwLock<T>>`, or\n+`Arc<UnsafeCell<T>>`[^4] (`UnsafeCell<T>` is a cell type that can be used to hold any data and has\n+no runtime cost, but accessing it requires `unsafe` blocks). The last one should only be used if we\n+are certain that the usage won't cause any memory unsafety. Remember that writing to a struct is not\n+an atomic operation, and many functions like `vec.push()` can reallocate internally and cause unsafe\n+behavior, so even monotonicity may not be enough to justify `UnsafeCell`.\n+\n+\n+[^4]: `Arc<UnsafeCell<T>>` actually won't compile since `UnsafeCell<T>` isn't `Send` or `Sync`, but we can wrap it in a type and implement `Send`/`Sync` for it manually to get `Arc<Wrapper<T>>` where `Wrapper` is `struct Wrapper<T>(UnsafeCell<T>)`.\n+\n+#### Guarantees\n+\n+Like `Rc`, this provides the (thread safe) guarantee that the destructor for the internal data will\n+be run when the last `Arc` goes out of scope (barring any cycles).\n+\n+#### Cost\n+\n+This has the added cost of using atomics for changing the refcount (which will happen whenever it is\n+cloned or goes out of scope). When sharing data from an `Arc` in a single thread, it is preferable\n+to share `&` pointers whenever possible.\n+\n+[arc]: ../std/sync/struct.Arc.html\n+\n+## `Mutex<T>` and `RwLock<T>`\n+\n+[`Mutex<T>`][mutex] and [`RwLock<T>`][rwlock] provide mutual-exclusion via RAII guards (guards are\n+objects which maintain some state, like a lock, until their destructor is called). For both of\n+these, the mutex is opaque until we call `lock()` on it, at which point the thread will block\n+until a lock can be acquired, and then a guard will be returned. This guard can be used to access\n+the inner data (mutably), and the lock will be released when the guard goes out of scope.\n+\n+\n+```rust\n+{\n+    let guard = mutex.lock();\n+    // guard dereferences mutably to the inner type\n+    *guard += 1;\n+} // lock released when destructor runs\n+```\n+\n+\n+`RwLock` has the added benefit of being efficient for multiple reads. It is always safe to have\n+multiple readers to shared data as long as there are no writers; and `RwLock` lets readers acquire a\n+\"read lock\". Such locks can be acquired concurrently and are kept track of via a reference count.\n+Writers must obtain a \"write lock\" which can only be obtained when all readers have gone out of\n+scope.\n+\n+","path":"src/doc/trpl/choosing-guarantees.md","position":354,"original_position":354,"commit_id":"66c4b8d2ed70ba340fe1f407354ddabccd89e783","original_commit_id":"66c4b8d2ed70ba340fe1f407354ddabccd89e783","user":{"login":"steveklabnik","id":27786,"avatar_url":"https://avatars.githubusercontent.com/u/27786?v=3","gravatar_id":"","url":"https://api.github.com/users/steveklabnik","html_url":"https://github.com/steveklabnik","followers_url":"https://api.github.com/users/steveklabnik/followers","following_url":"https://api.github.com/users/steveklabnik/following{/other_user}","gists_url":"https://api.github.com/users/steveklabnik/gists{/gist_id}","starred_url":"https://api.github.com/users/steveklabnik/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/steveklabnik/subscriptions","organizations_url":"https://api.github.com/users/steveklabnik/orgs","repos_url":"https://api.github.com/users/steveklabnik/repos","events_url":"https://api.github.com/users/steveklabnik/events{/privacy}","received_events_url":"https://api.github.com/users/steveklabnik/received_events","type":"User","site_admin":false},"body":"extra \\n","created_at":"2015-07-24T17:32:17Z","updated_at":"2015-07-24T17:32:17Z","html_url":"https://github.com/rust-lang/rust/pull/26960#discussion_r35445638","pull_request_url":"https://api.github.com/repos/rust-lang/rust/pulls/26960","_links":{"self":{"href":"https://api.github.com/repos/rust-lang/rust/pulls/comments/35445638"},"html":{"href":"https://github.com/rust-lang/rust/pull/26960#discussion_r35445638"},"pull_request":{"href":"https://api.github.com/repos/rust-lang/rust/pulls/26960"}}},"pull_request":{"url":"https://api.github.com/repos/rust-lang/rust/pulls/26960","id":39742105,"html_url":"https://github.com/rust-lang/rust/pull/26960","diff_url":"https://github.com/rust-lang/rust/pull/26960.diff","patch_url":"https://github.com/rust-lang/rust/pull/26960.patch","issue_url":"https://api.github.com/repos/rust-lang/rust/issues/26960","number":26960,"state":"open","locked":false,"title":"Move wrapper types blog post into trpl","user":{"login":"Manishearth","id":1617736,"avatar_url":"https://avatars.githubusercontent.com/u/1617736?v=3","gravatar_id":"","url":"https://api.github.com/users/Manishearth","html_url":"https://github.com/Manishearth","followers_url":"https://api.github.com/users/Manishearth/followers","following_url":"https://api.github.com/users/Manishearth/following{/other_user}","gists_url":"https://api.github.com/users/Manishearth/gists{/gist_id}","starred_url":"https://api.github.com/users/Manishearth/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Manishearth/subscriptions","organizations_url":"https://api.github.com/users/Manishearth/orgs","repos_url":"https://api.github.com/users/Manishearth/repos","events_url":"https://api.github.com/users/Manishearth/events{/privacy}","received_events_url":"https://api.github.com/users/Manishearth/received_events","type":"User","site_admin":false},"body":"@steveklabnik had suggested I do this.\n\nThis needs much review -- I tried reducing the informal tone but there's room for improvement.\n\n\nr? @steveklabnik","created_at":"2015-07-11T07:36:23Z","updated_at":"2015-07-24T17:32:17Z","closed_at":null,"merged_at":null,"merge_commit_sha":"bf3b33ac9e3e6102d822c339b0fb37ab0c36468c","assignee":{"login":"steveklabnik","id":27786,"avatar_url":"https://avatars.githubusercontent.com/u/27786?v=3","gravatar_id":"","url":"https://api.github.com/users/steveklabnik","html_url":"https://github.com/steveklabnik","followers_url":"https://api.github.com/users/steveklabnik/followers","following_url":"https://api.github.com/users/steveklabnik/following{/other_user}","gists_url":"https://api.github.com/users/steveklabnik/gists{/gist_id}","starred_url":"https://api.github.com/users/steveklabnik/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/steveklabnik/subscriptions","organizations_url":"https://api.github.com/users/steveklabnik/orgs","repos_url":"https://api.github.com/users/steveklabnik/repos","events_url":"https://api.github.com/users/steveklabnik/events{/privacy}","received_events_url":"https://api.github.com/users/steveklabnik/received_events","type":"User","site_admin":false},"milestone":null,"commits_url":"https://api.github.com/repos/rust-lang/rust/pulls/26960/commits","review_comments_url":"https://api.github.com/repos/rust-lang/rust/pulls/26960/comments","review_comment_url":"https://api.github.com/repos/rust-lang/rust/pulls/comments{/number}","comments_url":"https://api.github.com/repos/rust-lang/rust/issues/26960/comments","statuses_url":"https://api.github.com/repos/rust-lang/rust/statuses/66c4b8d2ed70ba340fe1f407354ddabccd89e783","head":{"label":"Manishearth:wrapper-types","ref":"wrapper-types","sha":"66c4b8d2ed70ba340fe1f407354ddabccd89e783","user":{"login":"Manishearth","id":1617736,"avatar_url":"https://avatars.githubusercontent.com/u/1617736?v=3","gravatar_id":"","url":"https://api.github.com/users/Manishearth","html_url":"https://github.com/Manishearth","followers_url":"https://api.github.com/users/Manishearth/followers","following_url":"https://api.github.com/users/Manishearth/following{/other_user}","gists_url":"https://api.github.com/users/Manishearth/gists{/gist_id}","starred_url":"https://api.github.com/users/Manishearth/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Manishearth/subscriptions","organizations_url":"https://api.github.com/users/Manishearth/orgs","repos_url":"https://api.github.com/users/Manishearth/repos","events_url":"https://api.github.com/users/Manishearth/events{/privacy}","received_events_url":"https://api.github.com/users/Manishearth/received_events","type":"User","site_admin":false},"repo":{"id":18477516,"name":"rust","full_name":"Manishearth/rust","owner":{"login":"Manishearth","id":1617736,"avatar_url":"https://avatars.githubusercontent.com/u/1617736?v=3","gravatar_id":"","url":"https://api.github.com/users/Manishearth","html_url":"https://github.com/Manishearth","followers_url":"https://api.github.com/users/Manishearth/followers","following_url":"https://api.github.com/users/Manishearth/following{/other_user}","gists_url":"https://api.github.com/users/Manishearth/gists{/gist_id}","starred_url":"https://api.github.com/users/Manishearth/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Manishearth/subscriptions","organizations_url":"https://api.github.com/users/Manishearth/orgs","repos_url":"https://api.github.com/users/Manishearth/repos","events_url":"https://api.github.com/users/Manishearth/events{/privacy}","received_events_url":"https://api.github.com/users/Manishearth/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/Manishearth/rust","description":"a safe, concurrent, practical language","fork":true,"url":"https://api.github.com/repos/Manishearth/rust","forks_url":"https://api.github.com/repos/Manishearth/rust/forks","keys_url":"https://api.github.com/repos/Manishearth/rust/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Manishearth/rust/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Manishearth/rust/teams","hooks_url":"https://api.github.com/repos/Manishearth/rust/hooks","issue_events_url":"https://api.github.com/repos/Manishearth/rust/issues/events{/number}","events_url":"https://api.github.com/repos/Manishearth/rust/events","assignees_url":"https://api.github.com/repos/Manishearth/rust/assignees{/user}","branches_url":"https://api.github.com/repos/Manishearth/rust/branches{/branch}","tags_url":"https://api.github.com/repos/Manishearth/rust/tags","blobs_url":"https://api.github.com/repos/Manishearth/rust/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Manishearth/rust/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Manishearth/rust/git/refs{/sha}","trees_url":"https://api.github.com/repos/Manishearth/rust/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Manishearth/rust/statuses/{sha}","languages_url":"https://api.github.com/repos/Manishearth/rust/languages","stargazers_url":"https://api.github.com/repos/Manishearth/rust/stargazers","contributors_url":"https://api.github.com/repos/Manishearth/rust/contributors","subscribers_url":"https://api.github.com/repos/Manishearth/rust/subscribers","subscription_url":"https://api.github.com/repos/Manishearth/rust/subscription","commits_url":"https://api.github.com/repos/Manishearth/rust/commits{/sha}","git_commits_url":"https://api.github.com/repos/Manishearth/rust/git/commits{/sha}","comments_url":"https://api.github.com/repos/Manishearth/rust/comments{/number}","issue_comment_url":"https://api.github.com/repos/Manishearth/rust/issues/comments{/number}","contents_url":"https://api.github.com/repos/Manishearth/rust/contents/{+path}","compare_url":"https://api.github.com/repos/Manishearth/rust/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Manishearth/rust/merges","archive_url":"https://api.github.com/repos/Manishearth/rust/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Manishearth/rust/downloads","issues_url":"https://api.github.com/repos/Manishearth/rust/issues{/number}","pulls_url":"https://api.github.com/repos/Manishearth/rust/pulls{/number}","milestones_url":"https://api.github.com/repos/Manishearth/rust/milestones{/number}","notifications_url":"https://api.github.com/repos/Manishearth/rust/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Manishearth/rust/labels{/name}","releases_url":"https://api.github.com/repos/Manishearth/rust/releases{/id}","created_at":"2014-04-05T21:54:27Z","updated_at":"2015-02-23T09:02:42Z","pushed_at":"2015-07-23T08:11:37Z","git_url":"git://github.com/Manishearth/rust.git","ssh_url":"git@github.com:Manishearth/rust.git","clone_url":"https://github.com/Manishearth/rust.git","svn_url":"https://github.com/Manishearth/rust","homepage":"http://www.rust-lang.org","size":307391,"stargazers_count":0,"watchers_count":0,"language":"Rust","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":0,"default_branch":"master"}},"base":{"label":"rust-lang:master","ref":"master","sha":"d18eb74009924648cf8b6fe652f6ac4ab2a37718","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":724712,"name":"rust","full_name":"rust-lang/rust","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/rust","description":"A safe, concurrent, practical language.","fork":false,"url":"https://api.github.com/repos/rust-lang/rust","forks_url":"https://api.github.com/repos/rust-lang/rust/forks","keys_url":"https://api.github.com/repos/rust-lang/rust/keys{/key_id}","collaborators_url":"https://api.github.com/repos/rust-lang/rust/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/rust-lang/rust/teams","hooks_url":"https://api.github.com/repos/rust-lang/rust/hooks","issue_events_url":"https://api.github.com/repos/rust-lang/rust/issues/events{/number}","events_url":"https://api.github.com/repos/rust-lang/rust/events","assignees_url":"https://api.github.com/repos/rust-lang/rust/assignees{/user}","branches_url":"https://api.github.com/repos/rust-lang/rust/branches{/branch}","tags_url":"https://api.github.com/repos/rust-lang/rust/tags","blobs_url":"https://api.github.com/repos/rust-lang/rust/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/rust-lang/rust/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/rust-lang/rust/git/refs{/sha}","trees_url":"https://api.github.com/repos/rust-lang/rust/git/trees{/sha}","statuses_url":"https://api.github.com/repos/rust-lang/rust/statuses/{sha}","languages_url":"https://api.github.com/repos/rust-lang/rust/languages","stargazers_url":"https://api.github.com/repos/rust-lang/rust/stargazers","contributors_url":"https://api.github.com/repos/rust-lang/rust/contributors","subscribers_url":"https://api.github.com/repos/rust-lang/rust/subscribers","subscription_url":"https://api.github.com/repos/rust-lang/rust/subscription","commits_url":"https://api.github.com/repos/rust-lang/rust/commits{/sha}","git_commits_url":"https://api.github.com/repos/rust-lang/rust/git/commits{/sha}","comments_url":"https://api.github.com/repos/rust-lang/rust/comments{/number}","issue_comment_url":"https://api.github.com/repos/rust-lang/rust/issues/comments{/number}","contents_url":"https://api.github.com/repos/rust-lang/rust/contents/{+path}","compare_url":"https://api.github.com/repos/rust-lang/rust/compare/{base}...{head}","merges_url":"https://api.github.com/repos/rust-lang/rust/merges","archive_url":"https://api.github.com/repos/rust-lang/rust/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/rust-lang/rust/downloads","issues_url":"https://api.github.com/repos/rust-lang/rust/issues{/number}","pulls_url":"https://api.github.com/repos/rust-lang/rust/pulls{/number}","milestones_url":"https://api.github.com/repos/rust-lang/rust/milestones{/number}","notifications_url":"https://api.github.com/repos/rust-lang/rust/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/rust-lang/rust/labels{/name}","releases_url":"https://api.github.com/repos/rust-lang/rust/releases{/id}","created_at":"2010-06-16T20:39:03Z","updated_at":"2015-07-24T16:12:17Z","pushed_at":"2015-07-24T17:11:18Z","git_url":"git://github.com/rust-lang/rust.git","ssh_url":"git@github.com:rust-lang/rust.git","clone_url":"https://github.com/rust-lang/rust.git","svn_url":"https://github.com/rust-lang/rust","homepage":"http://www.rust-lang.org","size":651097,"stargazers_count":12720,"watchers_count":12720,"language":"Rust","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":2449,"mirror_url":null,"open_issues_count":2153,"forks":2449,"open_issues":2153,"watchers":12720,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/rust-lang/rust/pulls/26960"},"html":{"href":"https://github.com/rust-lang/rust/pull/26960"},"issue":{"href":"https://api.github.com/repos/rust-lang/rust/issues/26960"},"comments":{"href":"https://api.github.com/repos/rust-lang/rust/issues/26960/comments"},"review_comments":{"href":"https://api.github.com/repos/rust-lang/rust/pulls/26960/comments"},"review_comment":{"href":"https://api.github.com/repos/rust-lang/rust/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/rust-lang/rust/pulls/26960/commits"},"statuses":{"href":"https://api.github.com/repos/rust-lang/rust/statuses/66c4b8d2ed70ba340fe1f407354ddabccd89e783"}}}}