{"action":"created","comment":{"url":"https://api.github.com/repos/rust-lang/rust/pulls/comments/147560327","pull_request_review_id":72677564,"id":147560327,"diff_hunk":"@@ -9,231 +9,472 @@\n // except according to those terms.\n \n use abi::FnType;\n-use adt;\n use common::*;\n-use machine;\n+use rustc::hir;\n use rustc::ty::{self, Ty, TypeFoldable};\n-use rustc::ty::layout::LayoutTyper;\n+use rustc::ty::layout::{self, Align, LayoutOf, Size, TyLayout};\n+use rustc_back::PanicStrategy;\n use trans_item::DefPathBasedNames;\n use type_::Type;\n \n-use syntax::ast;\n+use std::fmt::Write;\n \n-pub fn fat_ptr_base_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> Type {\n-    match ty.sty {\n-        ty::TyRef(_, ty::TypeAndMut { ty: t, .. }) |\n-        ty::TyRawPtr(ty::TypeAndMut { ty: t, .. }) if !ccx.shared().type_is_sized(t) => {\n-            in_memory_type_of(ccx, t).ptr_to()\n+fn uncached_llvm_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,\n+                                layout: TyLayout<'tcx>,\n+                                defer: &mut Option<(Type, TyLayout<'tcx>)>)\n+                                -> Type {\n+    match layout.abi {\n+        layout::Abi::Scalar(_) => bug!(\"handled elsewhere\"),\n+        layout::Abi::Vector => {\n+            return Type::vector(&layout.field(ccx, 0).llvm_type(ccx),\n+                                layout.fields.count() as u64);\n         }\n-        ty::TyAdt(def, _) if def.is_box() => {\n-            in_memory_type_of(ccx, ty.boxed_ty()).ptr_to()\n+        layout::Abi::ScalarPair(..) => {\n+            return Type::struct_(ccx, &[\n+                layout.scalar_pair_element_llvm_type(ccx, 0),\n+                layout.scalar_pair_element_llvm_type(ccx, 1),\n+            ], false);\n         }\n-        _ => bug!(\"expected fat ptr ty but got {:?}\", ty)\n+        layout::Abi::Uninhabited |\n+        layout::Abi::Aggregate { .. } => {}\n     }\n-}\n \n-pub fn unsized_info_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> Type {\n-    let unsized_part = ccx.tcx().struct_tail(ty);\n-    match unsized_part.sty {\n-        ty::TyStr | ty::TyArray(..) | ty::TySlice(_) => {\n-            Type::uint_from_ty(ccx, ast::UintTy::Us)\n+    let name = match layout.ty.sty {\n+        ty::TyClosure(..) |\n+        ty::TyGenerator(..) |\n+        ty::TyAdt(..) |\n+        ty::TyDynamic(..) |\n+        ty::TyStr => {\n+            let mut name = String::with_capacity(32);\n+            let printer = DefPathBasedNames::new(ccx.tcx(), true, true);\n+            printer.push_type_name(layout.ty, &mut name);\n+            match (&layout.ty.sty, &layout.variants) {\n+                (&ty::TyAdt(def, _), &layout::Variants::Single { index }) => {\n+                    if def.is_enum() && !def.variants.is_empty() {\n+                        write!(&mut name, \"::{}\", def.variants[index].name).unwrap();\n+                    }\n+                }\n+                _ => {}\n+            }\n+            Some(name)\n+        }\n+        _ => None\n+    };\n+\n+    match layout.fields {\n+        layout::FieldPlacement::Union(_) => {\n+            let size = layout.size.bytes();\n+            let abi_align = layout.align.abi();\n+            assert_eq!(size % abi_align, 0);\n+            let elem_ty = Type::for_abi_align(ccx, layout.align);\n+            let fill = Type::array(&elem_ty, size / abi_align);\n+            match name {\n+                None => {\n+                    Type::struct_(ccx, &[fill], layout.is_packed())\n+                }\n+                Some(ref name) => {\n+                    let mut llty = Type::named_struct(ccx, name);\n+                    llty.set_struct_body(&[fill], layout.is_packed());\n+                    llty\n+                }\n+            }\n+        }\n+        layout::FieldPlacement::Array { count, .. } => {\n+            Type::array(&layout.field(ccx, 0).llvm_type(ccx), count)\n+        }\n+        layout::FieldPlacement::Arbitrary { .. } => {\n+            match name {\n+                None => {\n+                    Type::struct_(ccx, &struct_llfields(ccx, layout), layout.is_packed())\n+                }\n+                Some(ref name) => {\n+                    let llty = Type::named_struct(ccx, name);\n+                    *defer = Some((llty, layout));\n+                    llty\n+                }\n+            }\n         }\n-        ty::TyDynamic(..) => Type::vtable_ptr(ccx),\n-        _ => bug!(\"Unexpected tail in unsized_info_ty: {:?} for ty={:?}\",\n-                          unsized_part, ty)\n     }\n }\n \n-pub fn immediate_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {\n-    if t.is_bool() {\n-        Type::i1(cx)\n+fn struct_llfields<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,\n+                             layout: TyLayout<'tcx>) -> Vec<Type> {\n+    debug!(\"struct_llfields: {:#?}\", layout);\n+    let field_count = layout.fields.count();\n+\n+    let mut offset = Size::from_bytes(0);\n+    let mut result: Vec<Type> = Vec::with_capacity(1 + field_count * 2);\n+    for i in layout.fields.index_by_increasing_offset() {\n+        let field = layout.field(ccx, i);\n+        let target_offset = layout.fields.offset(i as usize);\n+        debug!(\"struct_llfields: {}: {:?} offset: {:?} target_offset: {:?}\",\n+            i, field, offset, target_offset);\n+        assert!(target_offset >= offset);\n+        let padding = target_offset - offset;\n+        result.push(Type::array(&Type::i8(ccx), padding.bytes()));\n+        debug!(\"    padding before: {:?}\", padding);\n+\n+        result.push(field.llvm_type(ccx));\n+\n+        if layout.is_packed() {\n+            assert_eq!(padding.bytes(), 0);\n+        } else {\n+            assert!(field.align.abi() <= layout.align.abi(),\n+                    \"non-packed type has field with larger align ({}): {:#?}\",\n+                    field.align.abi(), layout);\n+        }\n+\n+        offset = target_offset + field.size;\n+    }\n+    if !layout.is_unsized() && field_count > 0 {\n+        if offset > layout.size {\n+            bug!(\"layout: {:#?} stride: {:?} offset: {:?}\",\n+                 layout, layout.size, offset);\n+        }\n+        let padding = layout.size - offset;\n+        debug!(\"struct_llfields: pad_bytes: {:?} offset: {:?} stride: {:?}\",\n+               padding, offset, layout.size);\n+        result.push(Type::array(&Type::i8(ccx), padding.bytes()));\n+        assert!(result.len() == 1 + field_count * 2);\n     } else {\n-        type_of(cx, t)\n+        debug!(\"struct_llfields: offset: {:?} stride: {:?}\",\n+               offset, layout.size);\n     }\n-}\n \n-/// Get the LLVM type corresponding to a Rust type, i.e. `rustc::ty::Ty`.\n-/// This is the right LLVM type for an alloca containing a value of that type,\n-/// and the pointee of an Lvalue Datum (which is always a LLVM pointer).\n-/// For unsized types, the returned type is a fat pointer, thus the resulting\n-/// LLVM type for a `Trait` Lvalue is `{ i8*, void(i8*)** }*`, which is a double\n-/// indirection to the actual data, unlike a `i8` Lvalue, which is just `i8*`.\n-/// This is needed due to the treatment of immediate values, as a fat pointer\n-/// is too large for it to be placed in SSA value (by our rules).\n-/// For the raw type without far pointer indirection, see `in_memory_type_of`.\n-pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> Type {\n-    let ty = if !cx.shared().type_is_sized(ty) {\n-        cx.tcx().mk_imm_ptr(ty)\n-    } else {\n-        ty\n-    };\n-    in_memory_type_of(cx, ty)\n+    result\n }\n \n-/// Get the LLVM type corresponding to a Rust type, i.e. `rustc::ty::Ty`.\n-/// This is the right LLVM type for a field/array element of that type,\n-/// and is the same as `type_of` for all Sized types.\n-/// Unsized types, however, are represented by a \"minimal unit\", e.g.\n-/// `[T]` becomes `T`, while `str` and `Trait` turn into `i8` - this\n-/// is useful for indexing slices, as `&[T]`'s data pointer is `T*`.\n-/// If the type is an unsized struct, the regular layout is generated,\n-/// with the inner-most trailing unsized field using the \"minimal unit\"\n-/// of that field's type - this is useful for taking the address of\n-/// that field and ensuring the struct has the right alignment.\n-/// For the LLVM type of a value as a whole, see `type_of`.\n-pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {\n-    // Check the cache.\n-    if let Some(&llty) = cx.lltypes().borrow().get(&t) {\n-        return llty;\n+impl<'a, 'tcx> CrateContext<'a, 'tcx> {\n+    pub fn align_of(&self, ty: Ty<'tcx>) -> Align {\n+        self.layout_of(ty).align\n     }\n \n-    debug!(\"type_of {:?}\", t);\n+    pub fn size_of(&self, ty: Ty<'tcx>) -> Size {\n+        self.layout_of(ty).size\n+    }\n \n-    assert!(!t.has_escaping_regions(), \"{:?} has escaping regions\", t);\n+    pub fn size_and_align_of(&self, ty: Ty<'tcx>) -> (Size, Align) {\n+        self.layout_of(ty).size_and_align()\n+    }\n+}\n+\n+#[derive(Copy, Clone, PartialEq, Eq)]\n+pub enum PointerKind {\n+    /// Most general case, we know no restrictions to tell LLVM.\n+    Shared,\n \n-    // Replace any typedef'd types with their equivalent non-typedef\n-    // type. This ensures that all LLVM nominal types that contain\n-    // Rust types are defined as the same LLVM types.  If we don't do\n-    // this then, e.g. `Option<{myfield: bool}>` would be a different\n-    // type than `Option<myrec>`.\n-    let t_norm = cx.tcx().erase_regions(&t);\n+    /// `&T` where `T` contains no `UnsafeCell`, is `noalias` and `readonly`.\n+    Frozen,\n+\n+    /// `&mut T`, when we know `noalias` is safe for LLVM.\n+    UniqueBorrowed,\n+\n+    /// `Box<T>`, unlike `UniqueBorrowed`, it also has `noalias` on returns.\n+    UniqueOwned\n+}\n \n-    if t != t_norm {\n-        let llty = in_memory_type_of(cx, t_norm);\n-        debug!(\"--> normalized {:?} to {:?} llty={:?}\", t, t_norm, llty);\n-        cx.lltypes().borrow_mut().insert(t, llty);\n-        return llty;\n+#[derive(Copy, Clone)]\n+pub struct LlvmPointee {\n+    pub size: Size,\n+    pub align: Align,\n+    pub safe: Option<PointerKind>,\n+}\n+\n+pub trait LayoutLlvmExt<'tcx> {\n+    fn is_llvm_immediate(&self) -> bool;\n+    fn is_llvm_scalar_pair<'a>(&self) -> bool;\n+    fn llvm_type<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> Type;\n+    fn immediate_llvm_type<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> Type;\n+    fn scalar_pair_element_llvm_type<'a>(&self, ccx: &CrateContext<'a, 'tcx>,\n+                                         index: usize) -> Type;\n+    fn over_align(&self) -> Option<Align>;\n+    fn llvm_field_index(&self, index: usize) -> u64;\n+    fn llvm_pointee<'a>(&self, ccx: &CrateContext<'a, 'tcx>, offset: Size) -> Option<LlvmPointee>;","path":"src/librustc_trans/type_of.rs","position":254,"original_position":254,"commit_id":"22e41a4a68652200d102818c9f61f538e79cffa7","original_commit_id":"72f0c6f063d38a154d2ddf907ad946c813a07b31","user":{"login":"eddyb","id":77424,"avatar_url":"https://avatars2.githubusercontent.com/u/77424?v=4","gravatar_id":"","url":"https://api.github.com/users/eddyb","html_url":"https://github.com/eddyb","followers_url":"https://api.github.com/users/eddyb/followers","following_url":"https://api.github.com/users/eddyb/following{/other_user}","gists_url":"https://api.github.com/users/eddyb/gists{/gist_id}","starred_url":"https://api.github.com/users/eddyb/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/eddyb/subscriptions","organizations_url":"https://api.github.com/users/eddyb/orgs","repos_url":"https://api.github.com/users/eddyb/repos","events_url":"https://api.github.com/users/eddyb/events{/privacy}","received_events_url":"https://api.github.com/users/eddyb/received_events","type":"User","site_admin":false},"body":"It returns information we only use for LLVM.","created_at":"2017-10-28T17:52:30Z","updated_at":"2017-10-28T17:52:30Z","html_url":"https://github.com/rust-lang/rust/pull/45225#discussion_r147560327","pull_request_url":"https://api.github.com/repos/rust-lang/rust/pulls/45225","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/rust-lang/rust/pulls/comments/147560327"},"html":{"href":"https://github.com/rust-lang/rust/pull/45225#discussion_r147560327"},"pull_request":{"href":"https://api.github.com/repos/rust-lang/rust/pulls/45225"}},"in_reply_to_id":147005915},"pull_request":{"url":"https://api.github.com/repos/rust-lang/rust/pulls/45225","id":146104553,"html_url":"https://github.com/rust-lang/rust/pull/45225","diff_url":"https://github.com/rust-lang/rust/pull/45225.diff","patch_url":"https://github.com/rust-lang/rust/pull/45225.patch","issue_url":"https://api.github.com/repos/rust-lang/rust/issues/45225","number":45225,"state":"open","locked":false,"title":"Refactor type memory layouts and ABIs, to be more general and easier to optimize.","user":{"login":"eddyb","id":77424,"avatar_url":"https://avatars2.githubusercontent.com/u/77424?v=4","gravatar_id":"","url":"https://api.github.com/users/eddyb","html_url":"https://github.com/eddyb","followers_url":"https://api.github.com/users/eddyb/followers","following_url":"https://api.github.com/users/eddyb/following{/other_user}","gists_url":"https://api.github.com/users/eddyb/gists{/gist_id}","starred_url":"https://api.github.com/users/eddyb/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/eddyb/subscriptions","organizations_url":"https://api.github.com/users/eddyb/orgs","repos_url":"https://api.github.com/users/eddyb/repos","events_url":"https://api.github.com/users/eddyb/events{/privacy}","received_events_url":"https://api.github.com/users/eddyb/received_events","type":"User","site_admin":false},"body":"To combat combinatorial explosion, type layouts are now described through 3 orthogonal properties:\r\n* `Variants` describes the plurality of sum types (where applicable)\r\n  * `Single` is for one inhabited/active variant, including all C `struct`s and `union`s\r\n  * `Tagged` has its variants discriminated by an integer tag, including C `enum`s\r\n  * `NicheFilling` uses otherwise-invalid values (\"niches\") for all but one of its inhabited variants\r\n* `FieldPlacement` describes the number and memory offsets of fields (if any)\r\n  * `Union` has all its fields at offset `0`\r\n  * `Array` has offsets that are a multiple of its `stride`; guarantees all fields have one type\r\n  * `Arbitrary` records all the field offsets, which can be out-of-order\r\n* `Abi` describes how values of the type should be passed around, including for FFI\r\n  * `Uninhabited` corresponds to no values, associated with unreachable control-flow\r\n  * `Scalar` is ABI-identical to its only integer/floating-point/pointer \"scalar component\"\r\n  * `ScalarPair` has two \"scalar components\", but only applies to the Rust ABI\r\n  * `Vector` is for SIMD vectors, typically `#[repr(simd)]` `struct`s in Rust\r\n  * `Aggregate` has arbitrary contents, including all non-transparent C `struct`s and `union`s\r\n\r\nSize optimizations implemented so far:\r\n* ignoring uninhabited variants (i.e. containing uninhabited fields), e.g.:\r\n  * `Option<!>` is 0 bytes\r\n  * `Result<T, !>` has the same size as `T`\r\n* using arbitrary niches, not just `0`, to represent a data-less variant, e.g.:\r\n  * `Option<bool>`, `Option<Option<bool>>`, `Option<Ordering>` are all 1 byte\r\n  * `Option<char>` is 4 bytes\r\n* using a range of niches to represent *multiple* data-less variants, e.g.:\r\n  * `enum E { A(bool), B, C, D }` is 1 byte\r\n\r\nCode generation now takes advantage of `Scalar` and `ScalarPair` to, in more cases, pass around scalar components as immediates instead of indirectly, through pointers into temporary memory, while avoiding LLVM's \"first-class aggregates\", and there's more untapped potential here.\r\n\r\nCloses #44426, fixes #5977, fixes #14540, fixes #43278.","created_at":"2017-10-12T02:34:06Z","updated_at":"2017-10-28T17:52:30Z","closed_at":null,"merged_at":null,"merge_commit_sha":"59dcaf471f6b6bdbf3ab676768e1a0d75c2daf80","assignee":{"login":"arielb1","id":1830974,"avatar_url":"https://avatars1.githubusercontent.com/u/1830974?v=4","gravatar_id":"","url":"https://api.github.com/users/arielb1","html_url":"https://github.com/arielb1","followers_url":"https://api.github.com/users/arielb1/followers","following_url":"https://api.github.com/users/arielb1/following{/other_user}","gists_url":"https://api.github.com/users/arielb1/gists{/gist_id}","starred_url":"https://api.github.com/users/arielb1/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/arielb1/subscriptions","organizations_url":"https://api.github.com/users/arielb1/orgs","repos_url":"https://api.github.com/users/arielb1/repos","events_url":"https://api.github.com/users/arielb1/events{/privacy}","received_events_url":"https://api.github.com/users/arielb1/received_events","type":"User","site_admin":false},"assignees":[{"login":"arielb1","id":1830974,"avatar_url":"https://avatars1.githubusercontent.com/u/1830974?v=4","gravatar_id":"","url":"https://api.github.com/users/arielb1","html_url":"https://github.com/arielb1","followers_url":"https://api.github.com/users/arielb1/followers","following_url":"https://api.github.com/users/arielb1/following{/other_user}","gists_url":"https://api.github.com/users/arielb1/gists{/gist_id}","starred_url":"https://api.github.com/users/arielb1/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/arielb1/subscriptions","organizations_url":"https://api.github.com/users/arielb1/orgs","repos_url":"https://api.github.com/users/arielb1/repos","events_url":"https://api.github.com/users/arielb1/events{/privacy}","received_events_url":"https://api.github.com/users/arielb1/received_events","type":"User","site_admin":false}],"requested_reviewers":[],"milestone":null,"commits_url":"https://api.github.com/repos/rust-lang/rust/pulls/45225/commits","review_comments_url":"https://api.github.com/repos/rust-lang/rust/pulls/45225/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/45225/comments","statuses_url":"https://api.github.com/repos/rust-lang/rust/statuses/22e41a4a68652200d102818c9f61f538e79cffa7","head":{"label":"eddyb:trans-abi","ref":"trans-abi","sha":"22e41a4a68652200d102818c9f61f538e79cffa7","user":{"login":"eddyb","id":77424,"avatar_url":"https://avatars2.githubusercontent.com/u/77424?v=4","gravatar_id":"","url":"https://api.github.com/users/eddyb","html_url":"https://github.com/eddyb","followers_url":"https://api.github.com/users/eddyb/followers","following_url":"https://api.github.com/users/eddyb/following{/other_user}","gists_url":"https://api.github.com/users/eddyb/gists{/gist_id}","starred_url":"https://api.github.com/users/eddyb/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/eddyb/subscriptions","organizations_url":"https://api.github.com/users/eddyb/orgs","repos_url":"https://api.github.com/users/eddyb/repos","events_url":"https://api.github.com/users/eddyb/events{/privacy}","received_events_url":"https://api.github.com/users/eddyb/received_events","type":"User","site_admin":false},"repo":{"id":13473977,"name":"rust","full_name":"eddyb/rust","owner":{"login":"eddyb","id":77424,"avatar_url":"https://avatars2.githubusercontent.com/u/77424?v=4","gravatar_id":"","url":"https://api.github.com/users/eddyb","html_url":"https://github.com/eddyb","followers_url":"https://api.github.com/users/eddyb/followers","following_url":"https://api.github.com/users/eddyb/following{/other_user}","gists_url":"https://api.github.com/users/eddyb/gists{/gist_id}","starred_url":"https://api.github.com/users/eddyb/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/eddyb/subscriptions","organizations_url":"https://api.github.com/users/eddyb/orgs","repos_url":"https://api.github.com/users/eddyb/repos","events_url":"https://api.github.com/users/eddyb/events{/privacy}","received_events_url":"https://api.github.com/users/eddyb/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/eddyb/rust","description":"a safe, concurrent, practical language","fork":true,"url":"https://api.github.com/repos/eddyb/rust","forks_url":"https://api.github.com/repos/eddyb/rust/forks","keys_url":"https://api.github.com/repos/eddyb/rust/keys{/key_id}","collaborators_url":"https://api.github.com/repos/eddyb/rust/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/eddyb/rust/teams","hooks_url":"https://api.github.com/repos/eddyb/rust/hooks","issue_events_url":"https://api.github.com/repos/eddyb/rust/issues/events{/number}","events_url":"https://api.github.com/repos/eddyb/rust/events","assignees_url":"https://api.github.com/repos/eddyb/rust/assignees{/user}","branches_url":"https://api.github.com/repos/eddyb/rust/branches{/branch}","tags_url":"https://api.github.com/repos/eddyb/rust/tags","blobs_url":"https://api.github.com/repos/eddyb/rust/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/eddyb/rust/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/eddyb/rust/git/refs{/sha}","trees_url":"https://api.github.com/repos/eddyb/rust/git/trees{/sha}","statuses_url":"https://api.github.com/repos/eddyb/rust/statuses/{sha}","languages_url":"https://api.github.com/repos/eddyb/rust/languages","stargazers_url":"https://api.github.com/repos/eddyb/rust/stargazers","contributors_url":"https://api.github.com/repos/eddyb/rust/contributors","subscribers_url":"https://api.github.com/repos/eddyb/rust/subscribers","subscription_url":"https://api.github.com/repos/eddyb/rust/subscription","commits_url":"https://api.github.com/repos/eddyb/rust/commits{/sha}","git_commits_url":"https://api.github.com/repos/eddyb/rust/git/commits{/sha}","comments_url":"https://api.github.com/repos/eddyb/rust/comments{/number}","issue_comment_url":"https://api.github.com/repos/eddyb/rust/issues/comments{/number}","contents_url":"https://api.github.com/repos/eddyb/rust/contents/{+path}","compare_url":"https://api.github.com/repos/eddyb/rust/compare/{base}...{head}","merges_url":"https://api.github.com/repos/eddyb/rust/merges","archive_url":"https://api.github.com/repos/eddyb/rust/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/eddyb/rust/downloads","issues_url":"https://api.github.com/repos/eddyb/rust/issues{/number}","pulls_url":"https://api.github.com/repos/eddyb/rust/pulls{/number}","milestones_url":"https://api.github.com/repos/eddyb/rust/milestones{/number}","notifications_url":"https://api.github.com/repos/eddyb/rust/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/eddyb/rust/labels{/name}","releases_url":"https://api.github.com/repos/eddyb/rust/releases{/id}","deployments_url":"https://api.github.com/repos/eddyb/rust/deployments","created_at":"2013-10-10T14:40:52Z","updated_at":"2017-06-28T17:08:59Z","pushed_at":"2017-10-28T16:18:48Z","git_url":"git://github.com/eddyb/rust.git","ssh_url":"git@github.com:eddyb/rust.git","clone_url":"https://github.com/eddyb/rust.git","svn_url":"https://github.com/eddyb/rust","homepage":"http://www.rust-lang.org","size":328282,"stargazers_count":2,"watchers_count":2,"language":"Rust","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":2,"default_branch":"master"}},"base":{"label":"rust-lang:master","ref":"master","sha":"dce604a8fe85c22beb53d99c609d88e3a0ca9320","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":724712,"name":"rust","full_name":"rust-lang/rust","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/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}","deployments_url":"https://api.github.com/repos/rust-lang/rust/deployments","created_at":"2010-06-16T20:39:03Z","updated_at":"2017-10-28T13:27:14Z","pushed_at":"2017-10-28T17:51:27Z","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":"https://www.rust-lang.org","size":330228,"stargazers_count":24198,"watchers_count":24198,"language":"Rust","has_issues":true,"has_projects":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":4453,"mirror_url":null,"archived":false,"open_issues_count":3007,"forks":4453,"open_issues":3007,"watchers":24198,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/rust-lang/rust/pulls/45225"},"html":{"href":"https://github.com/rust-lang/rust/pull/45225"},"issue":{"href":"https://api.github.com/repos/rust-lang/rust/issues/45225"},"comments":{"href":"https://api.github.com/repos/rust-lang/rust/issues/45225/comments"},"review_comments":{"href":"https://api.github.com/repos/rust-lang/rust/pulls/45225/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/45225/commits"},"statuses":{"href":"https://api.github.com/repos/rust-lang/rust/statuses/22e41a4a68652200d102818c9f61f538e79cffa7"}},"author_association":"MEMBER"}}
{"actor":{"display_login":"eddyb"}}