From 88b5e945e01a4599c60ac406d4949cd0329935cb Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 20 Aug 2019 17:51:54 +0200 Subject: [PATCH 01/21] Make <*const/mut T>::offset_from `const fn` --- src/libcore/intrinsics.rs | 4 + src/libcore/ptr/mod.rs | 18 ++++- src/librustc_codegen_llvm/intrinsic.rs | 19 ++++- src/librustc_mir/interpret/intrinsics.rs | 56 +++++++++++++- src/librustc_mir/transform/qualify_consts.rs | 1 + src/librustc_typeck/check/intrinsic.rs | 2 + src/test/ui/consts/offset_from_ub.rs | 44 +++++++++++ src/test/ui/consts/offset_from_ub.stderr | 81 ++++++++++++++++++++ src/test/ui/consts/offset_of.rs | 39 ++++++++++ src/test/ui/offset_from.rs | 15 ++++ 10 files changed, 276 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/consts/offset_from_ub.rs create mode 100644 src/test/ui/consts/offset_from_ub.stderr create mode 100644 src/test/ui/consts/offset_of.rs create mode 100644 src/test/ui/offset_from.rs diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index b240d059114eb..bae7ae2884f90 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -1339,6 +1339,10 @@ extern "rust-intrinsic" { /// Emits a `!nontemporal` store according to LLVM (see their docs). /// Probably will never become stable. pub fn nontemporal_store(ptr: *mut T, val: T); + + /// See documentation of `<*const T>::offset_from` for details. + #[cfg(not(bootstrap))] + pub fn ptr_offset_from(ptr: *const T, base: *const T) -> isize; } // Some functions are defined here because they accidentally got made diff --git a/src/libcore/ptr/mod.rs b/src/libcore/ptr/mod.rs index 13ccc9b252a77..a7adaa6a5097a 100644 --- a/src/libcore/ptr/mod.rs +++ b/src/libcore/ptr/mod.rs @@ -1286,7 +1286,22 @@ impl *const T { /// } /// ``` #[unstable(feature = "ptr_offset_from", issue = "41079")] + #[cfg(not(bootstrap))] + #[rustc_const_unstable(feature = "const_ptr_offset_from")] #[inline] + pub const unsafe fn offset_from(self, origin: *const T) -> isize where T: Sized { + let pointee_size = mem::size_of::(); + let ok = 0 < pointee_size && pointee_size <= isize::max_value() as usize; + // assert that the pointee size is valid in a const eval compatible way + // FIXME: do this with a real assert at some point + [()][(!ok) as usize]; + intrinsics::ptr_offset_from(self, origin) + } + + #[unstable(feature = "ptr_offset_from", issue = "41079")] + #[inline] + #[cfg(bootstrap)] + /// bootstrap pub unsafe fn offset_from(self, origin: *const T) -> isize where T: Sized { let pointee_size = mem::size_of::(); assert!(0 < pointee_size && pointee_size <= isize::max_value() as usize); @@ -2013,8 +2028,9 @@ impl *mut T { /// } /// ``` #[unstable(feature = "ptr_offset_from", issue = "41079")] + #[rustc_const_unstable(feature = "const_ptr_offset_from")] #[inline] - pub unsafe fn offset_from(self, origin: *const T) -> isize where T: Sized { + pub const unsafe fn offset_from(self, origin: *const T) -> isize where T: Sized { (self as *const T).offset_from(origin) } diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index b7a410c3760cd..e940a42be7dea 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -19,6 +19,7 @@ use rustc::mir::interpret::GlobalId; use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; use rustc::hir; use syntax::ast::{self, FloatTy}; +use rustc_target::abi::HasDataLayout; use rustc_codegen_ssa::traits::*; @@ -694,6 +695,23 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { return; } + "ptr_offset_from" => { + let ty = substs.type_at(0); + let pointee_size = self.layout_of(ty).size; + + // This is the same sequence that Clang emits for pointer subtraction. + // It can be neither `nsw` nor `nuw` because the input is treated as + // unsigned but then the output is treated as signed, so neither works. + let a = args[0].immediate(); + let b = args[1].immediate(); + let a = self.ptrtoint(a, self.type_isize()); + let b = self.ptrtoint(b, self.type_isize()); + let d = self.sub(a, b); + let pointee_size = self.const_usize(pointee_size.bytes()); + // this is where the signed magic happens (notice the `s` in `exactsdiv`) + self.exactsdiv(d, pointee_size) + } + _ => bug!("unknown intrinsic '{}'", name), }; @@ -1218,7 +1236,6 @@ fn generic_simd_intrinsic( // The `fn simd_bitmask(vector) -> unsigned integer` intrinsic takes a // vector mask and returns an unsigned integer containing the most // significant bit (MSB) of each lane. - use rustc_target::abi::HasDataLayout; // If the vector has less than 8 lanes, an u8 is returned with zeroed // trailing bits. diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index 5fc23b4a69ec5..a04bf7c0f1a18 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -12,7 +12,7 @@ use rustc::mir::BinOp; use rustc::mir::interpret::{InterpResult, Scalar, GlobalId, ConstValue}; use super::{ - Machine, PlaceTy, OpTy, InterpCx, + Machine, PlaceTy, OpTy, InterpCx, ImmTy, }; mod type_name; @@ -236,6 +236,34 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let result = Scalar::from_uint(truncated_bits, layout.size); self.write_scalar(result, dest)?; } + + "ptr_offset_from" => { + let a = self.read_immediate(args[0])?.to_scalar()?.to_ptr()?; + let b = self.read_immediate(args[1])?.to_scalar()?.to_ptr()?; + if a.alloc_id != b.alloc_id { + throw_ub_format!( + "ptr_offset_from cannot compute offset of pointers into different \ + allocations.", + ); + } + let usize_layout = self.layout_of(self.tcx.types.usize)?; + let a_offset = ImmTy::from_uint(a.offset.bytes(), usize_layout); + let b_offset = ImmTy::from_uint(b.offset.bytes(), usize_layout); + let (val, overflowed, _) = self.overflowing_binary_op( + BinOp::Sub, a_offset, b_offset, + )?; + if overflowed { + throw_ub_format!( + "second argument to `ptr_offset_from` must be smaller than first", + ); + } + let pointee_layout = self.layout_of(substs.type_at(0))?; + let isize_layout = self.layout_of(self.tcx.types.isize)?; + let val = ImmTy::from_scalar(val, isize_layout); + let size = ImmTy::from_int(pointee_layout.size.bytes(), isize_layout); + self.exact_div(val, size, dest)?; + } + "transmute" => { self.copy_op_transmute(args[0], dest)?; } @@ -340,4 +368,30 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { return Ok(false); } } + + pub fn exact_div( + &mut self, + a: ImmTy<'tcx, M::PointerTag>, + b: ImmTy<'tcx, M::PointerTag>, + dest: PlaceTy<'tcx, M::PointerTag>, + ) -> InterpResult<'tcx> { + // Performs an exact division, resulting in undefined behavior where + // `x % y != 0` or `y == 0` or `x == T::min_value() && y == -1`. + // First, check x % y != 0. + if self.binary_op(BinOp::Rem, a, b)?.to_bits()? != 0 { + // Then, check if `b` is -1, which is the "min_value / -1" case. + let minus1 = Scalar::from_int(-1, dest.layout.size); + let b = b.to_scalar().unwrap(); + if b == minus1 { + throw_ub_format!("exact_div: result of dividing MIN by -1 cannot be represented") + } else { + throw_ub_format!( + "exact_div: {} cannot be divided by {} without remainder", + a.to_scalar().unwrap(), + b, + ) + } + } + self.binop_ignore_overflow(BinOp::Div, a, b, dest) + } } diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 387540655f07b..ec9c7a73de735 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -560,6 +560,7 @@ impl Qualif for IsNotPromotable { | "transmute" | "simd_insert" | "simd_extract" + | "ptr_offset_from" => return true, _ => {} diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index aeb2c40e2ef83..0ebdc0672fcb1 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -307,6 +307,8 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem) { (1, vec![param(0), param(0)], tcx.intern_tup(&[param(0), tcx.types.bool])), + "ptr_offset_from" => + (1, vec![ tcx.mk_imm_ptr(param(0)), tcx.mk_imm_ptr(param(0)) ], tcx.types.isize), "unchecked_div" | "unchecked_rem" | "exact_div" => (1, vec![param(0), param(0)], param(0)), "unchecked_shl" | "unchecked_shr" | diff --git a/src/test/ui/consts/offset_from_ub.rs b/src/test/ui/consts/offset_from_ub.rs new file mode 100644 index 0000000000000..07e1be0480cde --- /dev/null +++ b/src/test/ui/consts/offset_from_ub.rs @@ -0,0 +1,44 @@ +#![feature(const_raw_ptr_deref)] +#![feature(const_ptr_offset_from)] +#![feature(ptr_offset_from)] + +#[repr(C)] +struct Struct { + data: u8, + field: u8, +} + +pub const DIFFERENT_ALLOC: usize = { + //~^ NOTE + let uninit = std::mem::MaybeUninit::::uninit(); + let base_ptr: *const Struct = &uninit as *const _ as *const Struct; + let uninit2 = std::mem::MaybeUninit::::uninit(); + let field_ptr: *const Struct = &uninit2 as *const _ as *const Struct; + let offset = unsafe { field_ptr.offset_from(base_ptr) }; + offset as usize +}; + +pub const NOT_PTR: usize = { + //~^ NOTE + unsafe { (42 as *const u8).offset_from(&5u8) as usize } +}; + +pub const NOT_MULTIPLE_OF_SIZE: usize = { + //~^ NOTE + let data = [5u8, 6, 7]; + let base_ptr = data.as_ptr(); + let field_ptr = &data[1] as *const u8 as *const u16; + let offset = unsafe { field_ptr.offset_from(base_ptr as *const u16) }; + offset as usize +}; + +pub const OVERFLOW: usize = { + //~^ NOTE + let uninit = std::mem::MaybeUninit::::uninit(); + let base_ptr: *const Struct = &uninit as *const _ as *const Struct; + let field_ptr = unsafe { &(*base_ptr).field as *const u8 }; + let offset = unsafe { (base_ptr as *const u8).offset_from(field_ptr) }; + offset as usize +}; + +fn main() {} diff --git a/src/test/ui/consts/offset_from_ub.stderr b/src/test/ui/consts/offset_from_ub.stderr new file mode 100644 index 0000000000000..12185ab5ccda9 --- /dev/null +++ b/src/test/ui/consts/offset_from_ub.stderr @@ -0,0 +1,81 @@ +error: any use of this value will cause an error + --> $SRC_DIR/libcore/ptr/mod.rs:LL:COL + | +LL | intrinsics::ptr_offset_from(self, origin) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | ptr_offset_from cannot compute offset of pointers into different allocations. + | inside call to `std::ptr::::offset_from` at $DIR/offset_from_ub.rs:17:27 + | + ::: $DIR/offset_from_ub.rs:11:1 + | +LL | / pub const DIFFERENT_ALLOC: usize = { +LL | | +LL | | let uninit = std::mem::MaybeUninit::::uninit(); +LL | | let base_ptr: *const Struct = &uninit as *const _ as *const Struct; +... | +LL | | offset as usize +LL | | }; + | |__- + | + = note: `#[deny(const_err)]` on by default + +error: any use of this value will cause an error + --> $SRC_DIR/libcore/ptr/mod.rs:LL:COL + | +LL | intrinsics::ptr_offset_from(self, origin) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | a memory access tried to interpret some bytes as a pointer + | inside call to `std::ptr::::offset_from` at $DIR/offset_from_ub.rs:23:14 + | + ::: $DIR/offset_from_ub.rs:21:1 + | +LL | / pub const NOT_PTR: usize = { +LL | | +LL | | unsafe { (42 as *const u8).offset_from(&5u8) as usize } +LL | | }; + | |__- + +error: any use of this value will cause an error + --> $SRC_DIR/libcore/ptr/mod.rs:LL:COL + | +LL | intrinsics::ptr_offset_from(self, origin) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | exact_div: 1 cannot be divided by 2 without remainder + | inside call to `std::ptr::::offset_from` at $DIR/offset_from_ub.rs:31:27 + | + ::: $DIR/offset_from_ub.rs:26:1 + | +LL | / pub const NOT_MULTIPLE_OF_SIZE: usize = { +LL | | +LL | | let data = [5u8, 6, 7]; +LL | | let base_ptr = data.as_ptr(); +... | +LL | | offset as usize +LL | | }; + | |__- + +error: any use of this value will cause an error + --> $SRC_DIR/libcore/ptr/mod.rs:LL:COL + | +LL | intrinsics::ptr_offset_from(self, origin) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | second argument to `ptr_offset_from` must be smaller than first + | inside call to `std::ptr::::offset_from` at $DIR/offset_from_ub.rs:40:27 + | + ::: $DIR/offset_from_ub.rs:35:1 + | +LL | / pub const OVERFLOW: usize = { +LL | | +LL | | let uninit = std::mem::MaybeUninit::::uninit(); +LL | | let base_ptr: *const Struct = &uninit as *const _ as *const Struct; +... | +LL | | offset as usize +LL | | }; + | |__- + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/consts/offset_of.rs b/src/test/ui/consts/offset_of.rs new file mode 100644 index 0000000000000..7b5b4a77d9ae3 --- /dev/null +++ b/src/test/ui/consts/offset_of.rs @@ -0,0 +1,39 @@ +// run-pass + +#![feature(const_raw_ptr_deref)] +#![feature(const_ptr_offset_from)] +#![feature(ptr_offset_from)] + +struct Struct { + field: (), +} + +#[repr(C)] +struct Struct2 { + data: u8, + field: u8, +} + +pub const OFFSET: usize = { + let uninit = std::mem::MaybeUninit::::uninit(); + let base_ptr: *const Struct = &uninit as *const _ as *const Struct; + // The following statement is UB (taking the address of an uninitialized field). + // Const eval doesn't detect this right now, but it may stop compiling at some point + // in the future. + let field_ptr = unsafe { &(*base_ptr).field as *const () as *const u8 }; + let offset = unsafe { field_ptr.offset_from(base_ptr as *const u8) }; + offset as usize +}; + +pub const OFFSET_2: usize = { + let uninit = std::mem::MaybeUninit::::uninit(); + let base_ptr: *const Struct2 = &uninit as *const _ as *const Struct2; + let field_ptr = unsafe { &(*base_ptr).field as *const u8 }; + let offset = unsafe { field_ptr.offset_from(base_ptr as *const u8) }; + offset as usize +}; + +fn main() { + assert_eq!(OFFSET, 0); + assert_eq!(OFFSET_2, 1); +} diff --git a/src/test/ui/offset_from.rs b/src/test/ui/offset_from.rs new file mode 100644 index 0000000000000..cbbb2adf15f91 --- /dev/null +++ b/src/test/ui/offset_from.rs @@ -0,0 +1,15 @@ +// run-pass + +#![feature(ptr_offset_from)] + +fn main() { + let mut a = [0; 5]; + let ptr1: *mut i32 = &mut a[1]; + let ptr2: *mut i32 = &mut a[3]; + unsafe { + assert_eq!(ptr2.offset_from(ptr1), 2); + assert_eq!(ptr1.offset_from(ptr2), -2); + assert_eq!(ptr1.offset(2), ptr2); + assert_eq!(ptr2.offset(-2), ptr1); + } +} From 4a51801c394337a64850788c18cbf86c4cbfb35f Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 18 Oct 2019 12:21:09 +0200 Subject: [PATCH 02/21] Use dedicated method for getting the type size Co-Authored-By: Nikita Popov --- src/librustc_codegen_llvm/intrinsic.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index e940a42be7dea..6c0728d7a07a6 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -697,7 +697,7 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { "ptr_offset_from" => { let ty = substs.type_at(0); - let pointee_size = self.layout_of(ty).size; + let pointee_size = self.size_of(ty); // This is the same sequence that Clang emits for pointer subtraction. // It can be neither `nsw` nor `nuw` because the input is treated as From 94a6d4b1b88135bf0dc7b24f23b47eaad50d5ea5 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 18 Oct 2019 12:24:05 +0200 Subject: [PATCH 03/21] Adjust const eval code to reflect `offset_from` docs --- src/librustc_mir/interpret/intrinsics.rs | 7 +----- .../consts/{offset_of.rs => offset_from.rs} | 8 +++++++ src/test/ui/consts/offset_from_ub.rs | 9 -------- src/test/ui/consts/offset_from_ub.stderr | 22 +------------------ 4 files changed, 10 insertions(+), 36 deletions(-) rename src/test/ui/consts/{offset_of.rs => offset_from.rs} (77%) diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index a04bf7c0f1a18..a2b901029ec54 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -249,14 +249,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let usize_layout = self.layout_of(self.tcx.types.usize)?; let a_offset = ImmTy::from_uint(a.offset.bytes(), usize_layout); let b_offset = ImmTy::from_uint(b.offset.bytes(), usize_layout); - let (val, overflowed, _) = self.overflowing_binary_op( + let (val, _overflowed, _) = self.overflowing_binary_op( BinOp::Sub, a_offset, b_offset, )?; - if overflowed { - throw_ub_format!( - "second argument to `ptr_offset_from` must be smaller than first", - ); - } let pointee_layout = self.layout_of(substs.type_at(0))?; let isize_layout = self.layout_of(self.tcx.types.isize)?; let val = ImmTy::from_scalar(val, isize_layout); diff --git a/src/test/ui/consts/offset_of.rs b/src/test/ui/consts/offset_from.rs similarity index 77% rename from src/test/ui/consts/offset_of.rs rename to src/test/ui/consts/offset_from.rs index 7b5b4a77d9ae3..4d6800681889c 100644 --- a/src/test/ui/consts/offset_of.rs +++ b/src/test/ui/consts/offset_from.rs @@ -33,7 +33,15 @@ pub const OFFSET_2: usize = { offset as usize }; +pub const OVERFLOW: isize = { + let uninit = std::mem::MaybeUninit::::uninit(); + let base_ptr: *const Struct2 = &uninit as *const _ as *const Struct2; + let field_ptr = unsafe { &(*base_ptr).field as *const u8 }; + unsafe { (base_ptr as *const u8).offset_from(field_ptr) } +}; + fn main() { assert_eq!(OFFSET, 0); assert_eq!(OFFSET_2, 1); + assert_eq!(OVERFLOW, -1); } diff --git a/src/test/ui/consts/offset_from_ub.rs b/src/test/ui/consts/offset_from_ub.rs index 07e1be0480cde..fedc1af7705a5 100644 --- a/src/test/ui/consts/offset_from_ub.rs +++ b/src/test/ui/consts/offset_from_ub.rs @@ -32,13 +32,4 @@ pub const NOT_MULTIPLE_OF_SIZE: usize = { offset as usize }; -pub const OVERFLOW: usize = { - //~^ NOTE - let uninit = std::mem::MaybeUninit::::uninit(); - let base_ptr: *const Struct = &uninit as *const _ as *const Struct; - let field_ptr = unsafe { &(*base_ptr).field as *const u8 }; - let offset = unsafe { (base_ptr as *const u8).offset_from(field_ptr) }; - offset as usize -}; - fn main() {} diff --git a/src/test/ui/consts/offset_from_ub.stderr b/src/test/ui/consts/offset_from_ub.stderr index 12185ab5ccda9..ad9695f2fc220 100644 --- a/src/test/ui/consts/offset_from_ub.stderr +++ b/src/test/ui/consts/offset_from_ub.stderr @@ -57,25 +57,5 @@ LL | | offset as usize LL | | }; | |__- -error: any use of this value will cause an error - --> $SRC_DIR/libcore/ptr/mod.rs:LL:COL - | -LL | intrinsics::ptr_offset_from(self, origin) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | second argument to `ptr_offset_from` must be smaller than first - | inside call to `std::ptr::::offset_from` at $DIR/offset_from_ub.rs:40:27 - | - ::: $DIR/offset_from_ub.rs:35:1 - | -LL | / pub const OVERFLOW: usize = { -LL | | -LL | | let uninit = std::mem::MaybeUninit::::uninit(); -LL | | let base_ptr: *const Struct = &uninit as *const _ as *const Struct; -... | -LL | | offset as usize -LL | | }; - | |__- - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors From 1c9d88900b2deb2268e302dd1859f707ec26237b Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 18 Oct 2019 16:57:19 +0200 Subject: [PATCH 04/21] Review nit Co-Authored-By: Ralf Jung --- src/librustc_mir/interpret/intrinsics.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index a2b901029ec54..e3d3ff70c4e8a 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -249,7 +249,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let usize_layout = self.layout_of(self.tcx.types.usize)?; let a_offset = ImmTy::from_uint(a.offset.bytes(), usize_layout); let b_offset = ImmTy::from_uint(b.offset.bytes(), usize_layout); - let (val, _overflowed, _) = self.overflowing_binary_op( + let (val, _overflowed, _ty) = self.overflowing_binary_op( BinOp::Sub, a_offset, b_offset, )?; let pointee_layout = self.layout_of(substs.type_at(0))?; From 3956c48f06791f407ffeecc8e88fb68b28662ffa Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 18 Oct 2019 19:58:28 +0200 Subject: [PATCH 05/21] Ignore a test on musl because its ui output differs --- src/test/ui/consts/offset_from_ub.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/test/ui/consts/offset_from_ub.rs b/src/test/ui/consts/offset_from_ub.rs index fedc1af7705a5..a233c24a7c52c 100644 --- a/src/test/ui/consts/offset_from_ub.rs +++ b/src/test/ui/consts/offset_from_ub.rs @@ -1,3 +1,6 @@ +// ingoring on musl because it's ui output hides libcore backtraces +// ignore-musl + #![feature(const_raw_ptr_deref)] #![feature(const_ptr_offset_from)] #![feature(ptr_offset_from)] From bf83ecf90eac14093b226d27ab74bc6eefcd550c Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Sat, 19 Oct 2019 13:12:18 +0200 Subject: [PATCH 06/21] Update ui output --- src/test/ui/consts/offset_from_ub.stderr | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/test/ui/consts/offset_from_ub.stderr b/src/test/ui/consts/offset_from_ub.stderr index ad9695f2fc220..1460170a108cb 100644 --- a/src/test/ui/consts/offset_from_ub.stderr +++ b/src/test/ui/consts/offset_from_ub.stderr @@ -5,9 +5,9 @@ LL | intrinsics::ptr_offset_from(self, origin) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | ptr_offset_from cannot compute offset of pointers into different allocations. - | inside call to `std::ptr::::offset_from` at $DIR/offset_from_ub.rs:17:27 + | inside call to `std::ptr::::offset_from` at $DIR/offset_from_ub.rs:20:27 | - ::: $DIR/offset_from_ub.rs:11:1 + ::: $DIR/offset_from_ub.rs:14:1 | LL | / pub const DIFFERENT_ALLOC: usize = { LL | | @@ -27,9 +27,9 @@ LL | intrinsics::ptr_offset_from(self, origin) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | a memory access tried to interpret some bytes as a pointer - | inside call to `std::ptr::::offset_from` at $DIR/offset_from_ub.rs:23:14 + | inside call to `std::ptr::::offset_from` at $DIR/offset_from_ub.rs:26:14 | - ::: $DIR/offset_from_ub.rs:21:1 + ::: $DIR/offset_from_ub.rs:24:1 | LL | / pub const NOT_PTR: usize = { LL | | @@ -44,9 +44,9 @@ LL | intrinsics::ptr_offset_from(self, origin) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | exact_div: 1 cannot be divided by 2 without remainder - | inside call to `std::ptr::::offset_from` at $DIR/offset_from_ub.rs:31:27 + | inside call to `std::ptr::::offset_from` at $DIR/offset_from_ub.rs:34:27 | - ::: $DIR/offset_from_ub.rs:26:1 + ::: $DIR/offset_from_ub.rs:29:1 | LL | / pub const NOT_MULTIPLE_OF_SIZE: usize = { LL | | From 1e2b711d308be714e6211c125b1a33ac1247f866 Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Sun, 20 Oct 2019 06:31:27 +0000 Subject: [PATCH 07/21] fix WASI sleep impl --- src/libstd/sys/wasi/thread.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libstd/sys/wasi/thread.rs b/src/libstd/sys/wasi/thread.rs index 28a504f197974..6ce41420284e5 100644 --- a/src/libstd/sys/wasi/thread.rs +++ b/src/libstd/sys/wasi/thread.rs @@ -31,10 +31,10 @@ impl Thread { let nanos = dur.as_nanos(); assert!(nanos <= u64::max_value() as u128); - const CLOCK_ID: wasi::Userdata = 0x0123_45678; + const USERDATA: wasi::Userdata = 0x0123_45678; let clock = wasi::raw::__wasi_subscription_u_clock_t { - identifier: CLOCK_ID, + identifier: 0, clock_id: wasi::CLOCK_MONOTONIC, timeout: nanos as u64, precision: 0, @@ -42,7 +42,7 @@ impl Thread { }; let in_ = [wasi::Subscription { - userdata: 0, + userdata: USERDATA, type_: wasi::EVENTTYPE_CLOCK, u: wasi::raw::__wasi_subscription_u { clock: clock }, }]; @@ -53,7 +53,7 @@ impl Thread { }; match (res, event) { (Ok(1), wasi::Event { - userdata: CLOCK_ID, + userdata: USERDATA, error: 0, type_: wasi::EVENTTYPE_CLOCK, .. From c290293cf291951825b10830df4bce3bc03aabef Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 16 Oct 2019 10:33:16 +1100 Subject: [PATCH 08/21] Derive `Rustc{En,De}codable` for `TokenStream`. `TokenStream` used to be a complex type, but it is now just a newtype around a `Lrc>`. Currently it uses custom encoding that discards the `IsJoint` and custom decoding that adds `NonJoint` back in for every token tree. This requires building intermediate `Vec`s. This commit makes `TokenStream` derive `Rustc{En,De}codable`. This simplifies the code, and avoids the creation of the intermediate vectors, saving up to 3% on various benchmarks. It also changes the AST JSON output in one test. --- src/libsyntax/tokenstream.rs | 17 ++--------------- src/test/ui/ast-json/ast-json-output.stdout | 2 +- 2 files changed, 3 insertions(+), 16 deletions(-) diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs index ac155556cdae2..0559f224f1f4b 100644 --- a/src/libsyntax/tokenstream.rs +++ b/src/libsyntax/tokenstream.rs @@ -19,7 +19,6 @@ use syntax_pos::{BytePos, Span, DUMMY_SP}; #[cfg(target_arch = "x86_64")] use rustc_data_structures::static_assert_size; use rustc_data_structures::sync::Lrc; -use rustc_serialize::{Decoder, Decodable, Encoder, Encodable}; use smallvec::{SmallVec, smallvec}; use std::{iter, mem}; @@ -136,7 +135,7 @@ impl TokenTree { /// The goal is for procedural macros to work with `TokenStream`s and `TokenTree`s /// instead of a representation of the abstract syntax tree. /// Today's `TokenTree`s can still contain AST via `token::Interpolated` for back-compat. -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug, Default, RustcEncodable, RustcDecodable)] pub struct TokenStream(pub Lrc>); pub type TreeAndJoint = (TokenTree, IsJoint); @@ -145,7 +144,7 @@ pub type TreeAndJoint = (TokenTree, IsJoint); #[cfg(target_arch = "x86_64")] static_assert_size!(TokenStream, 8); -#[derive(Clone, Copy, Debug, PartialEq)] +#[derive(Clone, Copy, Debug, PartialEq, RustcEncodable, RustcDecodable)] pub enum IsJoint { Joint, NonJoint @@ -460,18 +459,6 @@ impl Cursor { } } -impl Encodable for TokenStream { - fn encode(&self, encoder: &mut E) -> Result<(), E::Error> { - self.trees().collect::>().encode(encoder) - } -} - -impl Decodable for TokenStream { - fn decode(decoder: &mut D) -> Result { - Vec::::decode(decoder).map(|vec| vec.into_iter().collect()) - } -} - #[derive(Debug, Copy, Clone, PartialEq, RustcEncodable, RustcDecodable)] pub struct DelimSpan { pub open: Span, diff --git a/src/test/ui/ast-json/ast-json-output.stdout b/src/test/ui/ast-json/ast-json-output.stdout index 563885133a4c1..64c9f69311582 100644 --- a/src/test/ui/ast-json/ast-json-output.stdout +++ b/src/test/ui/ast-json/ast-json-output.stdout @@ -1 +1 @@ -{"module":{"inner":{"lo":0,"hi":0},"items":[{"ident":{"name":"core","span":{"lo":0,"hi":0}},"attrs":[],"id":0,"kind":{"variant":"ExternCrate","fields":[null]},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"span":{"lo":0,"hi":0},"tokens":[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["extern",false]},"span":{"lo":0,"hi":0}}]},{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate",false]},"span":{"lo":0,"hi":0}}]},{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["core",false]},"span":{"lo":0,"hi":0}}]},{"variant":"Token","fields":[{"kind":"Semi","span":{"lo":0,"hi":0}}]}]}],"inline":true},"attrs":[],"span":{"lo":0,"hi":0}} +{"module":{"inner":{"lo":0,"hi":0},"items":[{"ident":{"name":"core","span":{"lo":0,"hi":0}},"attrs":[],"id":0,"kind":{"variant":"ExternCrate","fields":[null]},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"span":{"lo":0,"hi":0},"tokens":{"_field0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["extern",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["core",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":"Semi","span":{"lo":0,"hi":0}}]},"NonJoint"]]}}],"inline":true},"attrs":[],"span":{"lo":0,"hi":0}} From 87744841c81377b1f195ff171fb23c9ae3d40303 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 21 Oct 2019 11:36:52 +0200 Subject: [PATCH 09/21] Add option to disable keyboard shortcuts in docs --- src/librustdoc/html/render.rs | 1 + src/librustdoc/html/static/main.js | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 72a72e892814a..414c3137376a9 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1241,6 +1241,7 @@ fn settings(root_path: &str, suffix: &str) -> String { ("go-to-only-result", "Directly go to item in search if there is only one result", false), ("line-numbers", "Show line numbers on code examples", false), + ("disable-shortcuts", "Disable keyboard shortcuts", false), ]; format!( "

\ diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 17a940cc4c9f8..f0104c9156ded 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -79,6 +79,7 @@ function getSearchElement() { "derive", "traitalias"]; + var disableShortcuts = getCurrentValue("rustdoc-disable-shortcuts") !== "true"; var search_input = getSearchInput(); // On the search screen, so you remain on the last tab you opened. @@ -294,7 +295,7 @@ function getSearchElement() { function handleShortcut(ev) { // Don't interfere with browser shortcuts - if (ev.ctrlKey || ev.altKey || ev.metaKey) { + if (ev.ctrlKey || ev.altKey || ev.metaKey || disableShortcuts === true) { return; } From 3f1af9056d8b2bf7b90a657503cd03f8c0c2b538 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Mon, 21 Oct 2019 17:29:40 -0700 Subject: [PATCH 10/21] Code cleanups following up on #65576. This makes a few code cleanups to follow up on the review comments in https://github.com/rust-lang/rust/pull/65576. --- src/librustc_codegen_ssa/base.rs | 37 +++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index f4f3dd4d2d295..e8ffe868231a6 100644 --- a/src/librustc_codegen_ssa/base.rs +++ b/src/librustc_codegen_ssa/base.rs @@ -406,6 +406,8 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(cx: &' rust_main_def_id: DefId, use_start_lang_item: bool, ) { + // The entry function is either `int main(void)` or `int main(int argc, char **argv)`, + // depending on whether the target needs `argc` and `argv` to be passed in. let llfty = if cx.sess().target.target.options.main_needs_argc_argv { cx.type_func(&[cx.type_int(), cx.type_ptr_to(cx.type_i8p())], cx.type_int()) } else { @@ -440,19 +442,7 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(cx: &' bx.insert_reference_to_gdb_debug_scripts_section_global(); - let (arg_argc, arg_argv) = if cx.sess().target.target.options.main_needs_argc_argv { - // Params from native main() used as args for rust start function - let param_argc = bx.get_param(0); - let param_argv = bx.get_param(1); - let arg_argc = bx.intcast(param_argc, cx.type_isize(), true); - let arg_argv = param_argv; - (arg_argc, arg_argv) - } else { - // The Rust start function doesn't need argc and argv, so just pass zeros. - let arg_argc = bx.const_int(cx.type_int(), 0); - let arg_argv = bx.const_null(cx.type_ptr_to(cx.type_i8p())); - (arg_argc, arg_argv) - }; + let (arg_argc, arg_argv) = get_argc_argv(cx, &mut bx); let (start_fn, args) = if use_start_lang_item { let start_def_id = cx.tcx().require_lang_item(StartFnLangItem, None); @@ -477,6 +467,27 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(cx: &' } } +/// Obtain the `argc` and `argv` values to pass to the rust start function. +fn get_argc_argv<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( + cx: &'a Bx::CodegenCx, + bx: &mut Bx +) -> (Bx::Value, Bx::Value) +{ + if cx.sess().target.target.options.main_needs_argc_argv { + // Params from native `main()` used as args for rust start function + let param_argc = bx.get_param(0); + let param_argv = bx.get_param(1); + let arg_argc = bx.intcast(param_argc, cx.type_isize(), true); + let arg_argv = param_argv; + (arg_argc, arg_argv) + } else { + // The Rust start function doesn't need `argc` and `argv`, so just pass zeros. + let arg_argc = bx.const_int(cx.type_int(), 0); + let arg_argv = bx.const_null(cx.type_ptr_to(cx.type_i8p())); + (arg_argc, arg_argv) + } +} + pub const CODEGEN_WORKER_ID: usize = ::std::usize::MAX; pub fn codegen_crate( From 40f92b3b0595984f40aafd70ec4a5b9a3bdde47a Mon Sep 17 00:00:00 2001 From: yjhmelody <465402634@qq.com> Date: Tue, 22 Oct 2019 12:25:14 +0800 Subject: [PATCH 11/21] refactor maybe_append --- src/libsyntax/parse/parser.rs | 7 ------- src/libsyntax/parse/parser/item.rs | 10 ++++++++-- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 9cb410a8ae318..d4d2f42446bec 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -86,13 +86,6 @@ macro_rules! maybe_recover_from_interpolated_ty_qpath { } } -fn maybe_append(mut lhs: Vec, mut rhs: Option>) -> Vec { - if let Some(ref mut rhs) = rhs { - lhs.append(rhs); - } - lhs -} - #[derive(Debug, Clone, Copy, PartialEq)] enum PrevTokenKind { DocComment, diff --git a/src/libsyntax/parse/parser/item.rs b/src/libsyntax/parse/parser/item.rs index 0acfd1450d819..73bd80e2a21f7 100644 --- a/src/libsyntax/parse/parser/item.rs +++ b/src/libsyntax/parse/parser/item.rs @@ -10,7 +10,6 @@ use crate::ast::{Visibility, VisibilityKind, Mutability, FnHeader, ForeignItem, use crate::ast::{Ty, TyKind, Generics, GenericBounds, TraitRef, EnumDef, VariantData, StructField}; use crate::ast::{Mac, MacDelimiter, Block, BindingMode, FnDecl, MethodSig, SelfKind, Param}; use crate::parse::token; -use crate::parse::parser::maybe_append; use crate::tokenstream::{TokenTree, TokenStream}; use crate::symbol::{kw, sym}; use crate::source_map::{self, respan, Span}; @@ -416,10 +415,17 @@ impl<'a> Parser<'a> { ) -> PResult<'a, Option>> { let (ident, item, extra_attrs) = info; let span = lo.to(self.prev_span); - let attrs = maybe_append(attrs, extra_attrs); + let attrs = Self::maybe_append(attrs, extra_attrs); Ok(Some(self.mk_item(span, ident, item, vis, attrs))) } + fn maybe_append(mut lhs: Vec, mut rhs: Option>) -> Vec { + if let Some(ref mut rhs) = rhs { + lhs.append(rhs); + } + lhs + } + /// This is the fall-through for parsing items. fn parse_macro_use_or_failure( &mut self, From a239c8dfb29c20f29fc3b30959f654d41fb0dd7f Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Tue, 22 Oct 2019 17:00:47 +0900 Subject: [PATCH 12/21] Add test for issue-41366 --- src/test/ui/closures/issue-41366.rs | 13 +++++++++++++ src/test/ui/closures/issue-41366.stderr | 22 ++++++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 src/test/ui/closures/issue-41366.rs create mode 100644 src/test/ui/closures/issue-41366.stderr diff --git a/src/test/ui/closures/issue-41366.rs b/src/test/ui/closures/issue-41366.rs new file mode 100644 index 0000000000000..5cae0e76d1acb --- /dev/null +++ b/src/test/ui/closures/issue-41366.rs @@ -0,0 +1,13 @@ +trait T<'x> { + type V; +} + +impl<'g> T<'g> for u32 { + type V = u16; +} + +fn main() { + (&|_|()) as &dyn for<'x> Fn(>::V); + //~^ ERROR: type mismatch in closure arguments + //~| ERROR: type mismatch resolving +} diff --git a/src/test/ui/closures/issue-41366.stderr b/src/test/ui/closures/issue-41366.stderr new file mode 100644 index 0000000000000..91d26efbc4f35 --- /dev/null +++ b/src/test/ui/closures/issue-41366.stderr @@ -0,0 +1,22 @@ +error[E0631]: type mismatch in closure arguments + --> $DIR/issue-41366.rs:10:5 + | +LL | (&|_|()) as &dyn for<'x> Fn(>::V); + | ^^-----^ + | | | + | | found signature of `fn(_) -> _` + | expected signature of `for<'x> fn(>::V) -> _` + | + = note: required for the cast to the object type `dyn for<'x> std::ops::Fn(>::V)` + +error[E0271]: type mismatch resolving `for<'x> <[closure@$DIR/issue-41366.rs:10:7: 10:12] as std::ops::FnOnce<(>::V,)>>::Output == ()` + --> $DIR/issue-41366.rs:10:5 + | +LL | (&|_|()) as &dyn for<'x> Fn(>::V); + | ^^^^^^^^ expected bound lifetime parameter 'x, found concrete lifetime + | + = note: required for the cast to the object type `dyn for<'x> std::ops::Fn(>::V)` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0271`. From dd0f98bc3ebc08cd0bcff7e682b9aff9038921cd Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Tue, 22 Oct 2019 17:01:06 +0900 Subject: [PATCH 13/21] Add test for issue-51431 --- src/test/ui/asm/issue-51431.rs | 10 ++++++++++ src/test/ui/asm/issue-51431.stderr | 8 ++++++++ 2 files changed, 18 insertions(+) create mode 100644 src/test/ui/asm/issue-51431.rs create mode 100644 src/test/ui/asm/issue-51431.stderr diff --git a/src/test/ui/asm/issue-51431.rs b/src/test/ui/asm/issue-51431.rs new file mode 100644 index 0000000000000..d29c31fafc286 --- /dev/null +++ b/src/test/ui/asm/issue-51431.rs @@ -0,0 +1,10 @@ +// ignore-emscripten no asm! support + +#![feature(asm)] + +fn main() { + unsafe { + asm! {"mov $0,$1"::"0"("bx"),"1"(0x00)} + //~^ ERROR: invalid value for constraint in inline assembly + } +} diff --git a/src/test/ui/asm/issue-51431.stderr b/src/test/ui/asm/issue-51431.stderr new file mode 100644 index 0000000000000..132eea126d642 --- /dev/null +++ b/src/test/ui/asm/issue-51431.stderr @@ -0,0 +1,8 @@ +error[E0669]: invalid value for constraint in inline assembly + --> $DIR/issue-51431.rs:7:32 + | +LL | asm! {"mov $0,$1"::"0"("bx"),"1"(0x00)} + | ^^^^ + +error: aborting due to previous error + From 93fab980e3b6e02deeecf5168cd0f3745c698660 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Tue, 22 Oct 2019 17:01:32 +0900 Subject: [PATCH 14/21] Add test for issue-52437 --- src/test/ui/closures/issue-52437.rs | 5 +++++ src/test/ui/closures/issue-52437.stderr | 15 +++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 src/test/ui/closures/issue-52437.rs create mode 100644 src/test/ui/closures/issue-52437.stderr diff --git a/src/test/ui/closures/issue-52437.rs b/src/test/ui/closures/issue-52437.rs new file mode 100644 index 0000000000000..6ac5380a5aa23 --- /dev/null +++ b/src/test/ui/closures/issue-52437.rs @@ -0,0 +1,5 @@ +fn main() { + [(); &(&'static: loop { |x| {}; }) as *const _ as usize] + //~^ ERROR: invalid label name `'static` + //~| ERROR: type annotations needed +} diff --git a/src/test/ui/closures/issue-52437.stderr b/src/test/ui/closures/issue-52437.stderr new file mode 100644 index 0000000000000..e76f942e9ba57 --- /dev/null +++ b/src/test/ui/closures/issue-52437.stderr @@ -0,0 +1,15 @@ +error: invalid label name `'static` + --> $DIR/issue-52437.rs:2:13 + | +LL | [(); &(&'static: loop { |x| {}; }) as *const _ as usize] + | ^^^^^^^ + +error[E0282]: type annotations needed + --> $DIR/issue-52437.rs:2:30 + | +LL | [(); &(&'static: loop { |x| {}; }) as *const _ as usize] + | ^ consider giving this closure parameter a type + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0282`. From 768965a2a65277a59bf6fb8d37ee5fbcfa57dc8c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 22 Oct 2019 10:15:56 +0200 Subject: [PATCH 15/21] bring back some Debug instances for Miri --- src/librustc_mir/interpret/eval_context.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 2ab7c41bb787e..0ff350f0bab24 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -91,7 +91,7 @@ pub struct Frame<'mir, 'tcx, Tag=(), Extra=()> { pub extra: Extra, } -#[derive(Clone, Eq, PartialEq)] +#[derive(Clone, Eq, PartialEq, Debug)] pub enum StackPopCleanup { /// Jump to the next block in the caller, or cause UB if None (that's a function /// that may never return). Also store layout of return place so @@ -113,7 +113,7 @@ pub struct LocalState<'tcx, Tag=(), Id=AllocId> { } /// Current value of a local variable -#[derive(Clone, PartialEq, Eq)] +#[derive(Clone, PartialEq, Eq, Debug)] pub enum LocalValue { /// This local is not currently alive, and cannot be used at all. Dead, From fc5b48514ef6cc74a81686e71b7efe3659fcadb5 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 22 Oct 2019 10:18:38 +0200 Subject: [PATCH 16/21] add comments --- src/librustc_mir/interpret/eval_context.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 0ff350f0bab24..d929e958f05d0 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -91,7 +91,7 @@ pub struct Frame<'mir, 'tcx, Tag=(), Extra=()> { pub extra: Extra, } -#[derive(Clone, Eq, PartialEq, Debug)] +#[derive(Clone, Eq, PartialEq, Debug)] // Miri debug-prints these pub enum StackPopCleanup { /// Jump to the next block in the caller, or cause UB if None (that's a function /// that may never return). Also store layout of return place so @@ -113,7 +113,7 @@ pub struct LocalState<'tcx, Tag=(), Id=AllocId> { } /// Current value of a local variable -#[derive(Clone, PartialEq, Eq, Debug)] +#[derive(Clone, PartialEq, Eq, Debug)] // Miri debug-prints these pub enum LocalValue { /// This local is not currently alive, and cannot be used at all. Dead, From 7a85c430fb978717ee1433cf5bee756f40544e74 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Tue, 22 Oct 2019 17:01:49 +0900 Subject: [PATCH 17/21] Add test for issue-63496 --- src/test/ui/associated-const/issue-63496.rs | 9 ++++++++ .../ui/associated-const/issue-63496.stderr | 21 +++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 src/test/ui/associated-const/issue-63496.rs create mode 100644 src/test/ui/associated-const/issue-63496.stderr diff --git a/src/test/ui/associated-const/issue-63496.rs b/src/test/ui/associated-const/issue-63496.rs new file mode 100644 index 0000000000000..311c48b5e48c5 --- /dev/null +++ b/src/test/ui/associated-const/issue-63496.rs @@ -0,0 +1,9 @@ +trait A { + const C: usize; + + fn f() -> ([u8; A::C], [u8; A::C]); + //~^ ERROR: type annotations needed: cannot resolve + //~| ERROR: type annotations needed: cannot resolve +} + +fn main() {} diff --git a/src/test/ui/associated-const/issue-63496.stderr b/src/test/ui/associated-const/issue-63496.stderr new file mode 100644 index 0000000000000..70bb12de1fb72 --- /dev/null +++ b/src/test/ui/associated-const/issue-63496.stderr @@ -0,0 +1,21 @@ +error[E0283]: type annotations needed: cannot resolve `_: A` + --> $DIR/issue-63496.rs:4:21 + | +LL | const C: usize; + | --------------- required by `A::C` +LL | +LL | fn f() -> ([u8; A::C], [u8; A::C]); + | ^^^^ + +error[E0283]: type annotations needed: cannot resolve `_: A` + --> $DIR/issue-63496.rs:4:33 + | +LL | const C: usize; + | --------------- required by `A::C` +LL | +LL | fn f() -> ([u8; A::C], [u8; A::C]); + | ^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0283`. From 74db3e8a9e31adf0ed7b3e9f4e1093e6b6a40fc4 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 18 Oct 2019 21:22:41 +0300 Subject: [PATCH 18/21] rustc_metadata: use a table for super_predicates. --- src/librustc_metadata/decoder.rs | 14 ++++---------- src/librustc_metadata/encoder.rs | 23 +++++++++++++++-------- src/librustc_metadata/schema.rs | 13 ++++--------- 3 files changed, 23 insertions(+), 27 deletions(-) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index b8b0030244028..1ec7702af79d7 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -448,7 +448,7 @@ impl<'tcx> EntryKind<'tcx> { EntryKind::Mod(_) => DefKind::Mod, EntryKind::Variant(_) => DefKind::Variant, EntryKind::Trait(_) => DefKind::Trait, - EntryKind::TraitAlias(_) => DefKind::TraitAlias, + EntryKind::TraitAlias => DefKind::TraitAlias, EntryKind::Enum(..) => DefKind::Enum, EntryKind::MacroDef(_) => DefKind::Macro(MacroKind::Bang), EntryKind::ForeignType => DefKind::ForeignTy, @@ -575,7 +575,7 @@ impl<'a, 'tcx> CrateMetadata { data.is_marker, self.def_path_table.def_path_hash(item_id)) }, - EntryKind::TraitAlias(_) => { + EntryKind::TraitAlias => { ty::TraitDef::new(self.local_def_id(item_id), hir::Unsafety::Normal, false, @@ -680,13 +680,7 @@ impl<'a, 'tcx> CrateMetadata { item_id: DefIndex, tcx: TyCtxt<'tcx>, ) -> ty::GenericPredicates<'tcx> { - let super_predicates = match self.kind(item_id) { - EntryKind::Trait(data) => data.decode(self).super_predicates, - EntryKind::TraitAlias(data) => data.decode(self).super_predicates, - _ => bug!("def-index does not refer to trait or trait alias"), - }; - - super_predicates.decode((self, tcx)) + self.root.per_def.super_predicates.get(self, item_id).unwrap().decode((self, tcx)) } crate fn get_generics(&self, item_id: DefIndex, sess: &Session) -> ty::Generics { @@ -1118,7 +1112,7 @@ impl<'a, 'tcx> CrateMetadata { def_key.parent.and_then(|parent_index| { match self.kind(parent_index) { EntryKind::Trait(_) | - EntryKind::TraitAlias(_) => Some(self.local_def_id(parent_index)), + EntryKind::TraitAlias => Some(self.local_def_id(parent_index)), _ => None, } }) diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 6ae8c2fc6c694..79a7caa292b08 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -76,6 +76,7 @@ struct PerDefTables<'tcx> { generics: PerDefTable>, predicates: PerDefTable>>, predicates_defined_on: PerDefTable>>, + super_predicates: PerDefTable>>, mir: PerDefTable>>, promoted_mir: PerDefTable>>>, @@ -513,6 +514,7 @@ impl<'tcx> EncodeContext<'tcx> { generics: self.per_def.generics.encode(&mut self.opaque), predicates: self.per_def.predicates.encode(&mut self.opaque), predicates_defined_on: self.per_def.predicates_defined_on.encode(&mut self.opaque), + super_predicates: self.per_def.super_predicates.encode(&mut self.opaque), mir: self.per_def.mir.encode(&mut self.opaque), promoted_mir: self.per_def.promoted_mir.encode(&mut self.opaque), @@ -835,6 +837,11 @@ impl EncodeContext<'tcx> { self.tcx.predicates_defined_on(def_id)) } + fn encode_super_predicates(&mut self, def_id: DefId) { + debug!("EncodeContext::encode_super_predicates({:?})", def_id); + record!(self.per_def.super_predicates[def_id] <- self.tcx.super_predicates_of(def_id)); + } + fn encode_info_for_trait_item(&mut self, def_id: DefId) { debug!("EncodeContext::encode_info_for_trait_item({:?})", def_id); let tcx = self.tcx; @@ -1166,18 +1173,11 @@ impl EncodeContext<'tcx> { paren_sugar: trait_def.paren_sugar, has_auto_impl: self.tcx.trait_is_auto(def_id), is_marker: trait_def.is_marker, - super_predicates: self.lazy(tcx.super_predicates_of(def_id)), }; EntryKind::Trait(self.lazy(data)) } - hir::ItemKind::TraitAlias(..) => { - let data = TraitAliasData { - super_predicates: self.lazy(tcx.super_predicates_of(def_id)), - }; - - EntryKind::TraitAlias(self.lazy(data)) - } + hir::ItemKind::TraitAlias(..) => EntryKind::TraitAlias, hir::ItemKind::ExternCrate(_) | hir::ItemKind::Use(..) => bug!("cannot encode info for item {:?}", item), }); @@ -1269,6 +1269,13 @@ impl EncodeContext<'tcx> { } _ => {} // not *wrong* for other kinds of items, but not needed } + match item.kind { + hir::ItemKind::Trait(..) | + hir::ItemKind::TraitAlias(..) => { + self.encode_super_predicates(def_id); + } + _ => {} + } let mir = match item.kind { hir::ItemKind::Static(..) | hir::ItemKind::Const(..) => true, diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 96f35783278fa..b681078ee0d5d 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -243,6 +243,7 @@ crate struct LazyPerDefTables<'tcx> { pub generics: Lazy!(PerDefTable>), pub predicates: Lazy!(PerDefTable)>), pub predicates_defined_on: Lazy!(PerDefTable)>), + pub super_predicates: Lazy!(PerDefTable)>), pub mir: Lazy!(PerDefTable)>), pub promoted_mir: Lazy!(PerDefTable>)>), @@ -273,13 +274,13 @@ crate enum EntryKind<'tcx> { MacroDef(Lazy), Closure(Lazy!(ClosureData<'tcx>)), Generator(Lazy!(GeneratorData<'tcx>)), - Trait(Lazy!(TraitData<'tcx>)), + Trait(Lazy), Impl(Lazy!(ImplData<'tcx>)), Method(Lazy!(MethodData<'tcx>)), AssocType(AssocContainer), AssocOpaqueTy(AssocContainer), AssocConst(AssocContainer, ConstQualif, Lazy), - TraitAlias(Lazy!(TraitAliasData<'tcx>)), + TraitAlias, } /// Additional data for EntryKind::Const and EntryKind::AssocConst @@ -324,17 +325,11 @@ crate struct VariantData<'tcx> { } #[derive(RustcEncodable, RustcDecodable)] -crate struct TraitData<'tcx> { +crate struct TraitData { pub unsafety: hir::Unsafety, pub paren_sugar: bool, pub has_auto_impl: bool, pub is_marker: bool, - pub super_predicates: Lazy!(ty::GenericPredicates<'tcx>), -} - -#[derive(RustcEncodable, RustcDecodable)] -crate struct TraitAliasData<'tcx> { - pub super_predicates: Lazy!(ty::GenericPredicates<'tcx>), } #[derive(RustcEncodable, RustcDecodable)] From 66a025378025742a2a867287c4683e1209d15f65 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Tue, 22 Oct 2019 12:53:46 +0200 Subject: [PATCH 19/21] self-profiling: Remove module names from some event-ids in codegen backend. --- src/librustc_codegen_ssa/back/write.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index 8bc815f2c622e..762b50f1659cc 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -259,7 +259,7 @@ fn generate_lto_work( needs_thin_lto: Vec<(String, B::ThinBuffer)>, import_only_modules: Vec<(SerializedModule, WorkProduct)> ) -> Vec<(WorkItem, u64)> { - let _prof_timer = cgcx.prof.generic_activity("codegen_run_lto"); + let _prof_timer = cgcx.prof.generic_activity("codegen_generate_lto_work"); let (lto_modules, copy_jobs) = if !needs_fat_lto.is_empty() { assert!(needs_thin_lto.is_empty()); @@ -674,11 +674,11 @@ impl WorkItem { } } - pub fn name(&self) -> String { + fn profiling_event_id(&self) -> &'static str { match *self { - WorkItem::Optimize(ref m) => format!("optimize: {}", m.name), - WorkItem::CopyPostLtoArtifacts(ref m) => format!("copy post LTO artifacts: {}", m.name), - WorkItem::LTO(ref m) => format!("lto: {}", m.name()), + WorkItem::Optimize(_) => "codegen_module_optimize", + WorkItem::CopyPostLtoArtifacts(_) => "codegen_copy_artifacts_from_incr_cache", + WorkItem::LTO(_) => "codegen_module_perform_lto", } } } @@ -1587,7 +1587,7 @@ fn spawn_work( // as a diagnostic was already sent off to the main thread - just // surface that there was an error in this worker. bomb.result = { - let _prof_timer = cgcx.prof.generic_activity(&work.name()); + let _prof_timer = cgcx.prof.generic_activity(work.profiling_event_id()); execute_work_item(&cgcx, work).ok() }; }); From 7a80a11a83f1b00e750f3d1c235b67ef8ab70c29 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 18 Oct 2019 22:15:14 +0300 Subject: [PATCH 20/21] rustc_metadata: use a table for fn_sig. --- src/librustc_metadata/decoder.rs | 13 ++------ src/librustc_metadata/encoder.rs | 53 +++++++++++++++----------------- src/librustc_metadata/schema.rs | 32 ++++++++----------- 3 files changed, 38 insertions(+), 60 deletions(-) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 1ec7702af79d7..9c7b721fb7f63 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -458,7 +458,7 @@ impl<'tcx> EntryKind<'tcx> { EntryKind::Impl(_) | EntryKind::Field | EntryKind::Generator(_) | - EntryKind::Closure(_) => return None, + EntryKind::Closure => return None, }) } } @@ -1239,16 +1239,7 @@ impl<'a, 'tcx> CrateMetadata { } crate fn fn_sig(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> { - let sig = match self.kind(id) { - EntryKind::Fn(data) | - EntryKind::ForeignFn(data) => data.decode(self).sig, - EntryKind::Method(data) => data.decode(self).fn_data.sig, - EntryKind::Variant(data) | - EntryKind::Struct(data, _) => data.decode(self).ctor_sig.unwrap(), - EntryKind::Closure(data) => data.decode(self).sig, - _ => bug!(), - }; - sig.decode((self, tcx)) + self.root.per_def.fn_sig.get(self, id).unwrap().decode((self, tcx)) } #[inline] diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 79a7caa292b08..e3ad1c5e197b5 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -71,6 +71,7 @@ struct PerDefTables<'tcx> { deprecation: PerDefTable>, ty: PerDefTable>>, + fn_sig: PerDefTable>>, inherent_impls: PerDefTable>, variances: PerDefTable>, generics: PerDefTable>, @@ -509,6 +510,7 @@ impl<'tcx> EncodeContext<'tcx> { deprecation: self.per_def.deprecation.encode(&mut self.opaque), ty: self.per_def.ty.encode(&mut self.opaque), + fn_sig: self.per_def.fn_sig.encode(&mut self.opaque), inherent_impls: self.per_def.inherent_impls.encode(&mut self.opaque), variances: self.per_def.variances.encode(&mut self.opaque), generics: self.per_def.generics.encode(&mut self.opaque), @@ -637,13 +639,7 @@ impl EncodeContext<'tcx> { let data = VariantData { ctor_kind: variant.ctor_kind, discr: variant.discr, - // FIXME(eddyb) deduplicate these with `encode_enum_variant_ctor`. ctor: variant.ctor_def_id.map(|did| did.index), - ctor_sig: if variant.ctor_kind == CtorKind::Fn { - variant.ctor_def_id.map(|ctor_def_id| self.lazy(&tcx.fn_sig(ctor_def_id))) - } else { - None - }, }; let enum_id = tcx.hir().as_local_hir_id(enum_did).unwrap(); @@ -662,6 +658,11 @@ impl EncodeContext<'tcx> { self.encode_deprecation(def_id); self.encode_item_type(def_id); if variant.ctor_kind == CtorKind::Fn { + // FIXME(eddyb) encode signature only in `encode_enum_variant_ctor`. + if let Some(ctor_def_id) = variant.ctor_def_id { + record!(self.per_def.fn_sig[def_id] <- tcx.fn_sig(ctor_def_id)); + } + // FIXME(eddyb) is this ever used? self.encode_variances_of(def_id); } self.encode_generics(def_id); @@ -681,15 +682,11 @@ impl EncodeContext<'tcx> { let def_id = variant.ctor_def_id.unwrap(); debug!("EncodeContext::encode_enum_variant_ctor({:?})", def_id); + // FIXME(eddyb) encode only the `CtorKind` for constructors. let data = VariantData { ctor_kind: variant.ctor_kind, discr: variant.discr, ctor: Some(def_id.index), - ctor_sig: if variant.ctor_kind == CtorKind::Fn { - Some(self.lazy(tcx.fn_sig(def_id))) - } else { - None - } }; // Variant constructors have the same visibility as the parent enums, unless marked as @@ -708,6 +705,7 @@ impl EncodeContext<'tcx> { self.encode_deprecation(def_id); self.encode_item_type(def_id); if variant.ctor_kind == CtorKind::Fn { + record!(self.per_def.fn_sig[def_id] <- tcx.fn_sig(def_id)); self.encode_variances_of(def_id); } self.encode_generics(def_id); @@ -782,11 +780,6 @@ impl EncodeContext<'tcx> { ctor_kind: variant.ctor_kind, discr: variant.discr, ctor: Some(def_id.index), - ctor_sig: if variant.ctor_kind == CtorKind::Fn { - Some(self.lazy(tcx.fn_sig(def_id))) - } else { - None - } }; let struct_id = tcx.hir().as_local_hir_id(adt_def_id).unwrap(); @@ -813,6 +806,7 @@ impl EncodeContext<'tcx> { self.encode_deprecation(def_id); self.encode_item_type(def_id); if variant.ctor_kind == CtorKind::Fn { + record!(self.per_def.fn_sig[def_id] <- tcx.fn_sig(def_id)); self.encode_variances_of(def_id); } self.encode_generics(def_id); @@ -881,7 +875,6 @@ impl EncodeContext<'tcx> { asyncness: m_sig.header.asyncness, constness: hir::Constness::NotConst, param_names, - sig: self.lazy(tcx.fn_sig(def_id)), } } else { bug!() @@ -913,6 +906,7 @@ impl EncodeContext<'tcx> { ty::AssocKind::OpaqueTy => unreachable!(), } if trait_item.kind == ty::AssocKind::Method { + record!(self.per_def.fn_sig[def_id] <- tcx.fn_sig(def_id)); self.encode_variances_of(def_id); } self.encode_generics(def_id); @@ -959,7 +953,6 @@ impl EncodeContext<'tcx> { asyncness: sig.header.asyncness, constness: sig.header.constness, param_names: self.encode_fn_param_names_for_body(body), - sig: self.lazy(tcx.fn_sig(def_id)), } } else { bug!() @@ -980,6 +973,7 @@ impl EncodeContext<'tcx> { self.encode_deprecation(def_id); self.encode_item_type(def_id); if impl_item.kind == ty::AssocKind::Method { + record!(self.per_def.fn_sig[def_id] <- tcx.fn_sig(def_id)); self.encode_variances_of(def_id); } self.encode_generics(def_id); @@ -1088,7 +1082,6 @@ impl EncodeContext<'tcx> { asyncness: header.asyncness, constness: header.constness, param_names: self.encode_fn_param_names_for_body(body), - sig: self.lazy(tcx.fn_sig(def_id)), }; EntryKind::Fn(self.lazy(data)) @@ -1116,7 +1109,6 @@ impl EncodeContext<'tcx> { ctor_kind: variant.ctor_kind, discr: variant.discr, ctor, - ctor_sig: None, }), adt_def.repr) } hir::ItemKind::Union(..) => { @@ -1127,7 +1119,6 @@ impl EncodeContext<'tcx> { ctor_kind: variant.ctor_kind, discr: variant.discr, ctor: None, - ctor_sig: None, }), adt_def.repr) } hir::ItemKind::Impl(_, _, defaultness, ..) => { @@ -1232,6 +1223,9 @@ impl EncodeContext<'tcx> { hir::ItemKind::Impl(..) => self.encode_item_type(def_id), _ => {} } + if let hir::ItemKind::Fn(..) = item.kind { + record!(self.per_def.fn_sig[def_id] <- tcx.fn_sig(def_id)); + } self.encode_inherent_implementations(def_id); match item.kind { hir::ItemKind::Enum(..) | @@ -1328,10 +1322,12 @@ impl EncodeContext<'tcx> { fn encode_info_for_closure(&mut self, def_id: DefId) { debug!("EncodeContext::encode_info_for_closure({:?})", def_id); - let tables = self.tcx.typeck_tables_of(def_id); + // NOTE(eddyb) `tcx.type_of(def_id)` isn't used because it's fully generic, + // including on the signature, which is inferred in `typeck_tables_of. let hir_id = self.tcx.hir().as_local_hir_id(def_id).unwrap(); + let ty = self.tcx.typeck_tables_of(def_id).node_type(hir_id); - record!(self.per_def.kind[def_id] <- match tables.node_type(hir_id).kind { + record!(self.per_def.kind[def_id] <- match ty.kind { ty::Generator(def_id, ..) => { let layout = self.tcx.generator_layout(def_id); let data = GeneratorData { @@ -1340,11 +1336,7 @@ impl EncodeContext<'tcx> { EntryKind::Generator(self.lazy(data)) } - ty::Closure(def_id, substs) => { - let sig = substs.as_closure().sig(def_id, self.tcx); - let data = ClosureData { sig: self.lazy(sig) }; - EntryKind::Closure(self.lazy(data)) - } + ty::Closure(..) => EntryKind::Closure, _ => bug!("closure that is neither generator nor closure"), }); @@ -1352,6 +1344,9 @@ impl EncodeContext<'tcx> { record!(self.per_def.span[def_id] <- self.tcx.def_span(def_id)); record!(self.per_def.attributes[def_id] <- &self.tcx.get_attrs(def_id)[..]); self.encode_item_type(def_id); + if let ty::Closure(def_id, substs) = ty.kind { + record!(self.per_def.fn_sig[def_id] <- substs.as_closure().sig(def_id, self.tcx)); + } self.encode_generics(def_id); self.encode_optimized_mir(def_id); self.encode_promoted_mir(def_id); @@ -1560,7 +1555,6 @@ impl EncodeContext<'tcx> { asyncness: hir::IsAsync::NotAsync, constness: hir::Constness::NotConst, param_names: self.encode_fn_param_names(names), - sig: self.lazy(tcx.fn_sig(def_id)), }; EntryKind::ForeignFn(self.lazy(data)) } @@ -1576,6 +1570,7 @@ impl EncodeContext<'tcx> { self.encode_deprecation(def_id); self.encode_item_type(def_id); if let hir::ForeignItemKind::Fn(..) = nitem.kind { + record!(self.per_def.fn_sig[def_id] <- tcx.fn_sig(def_id)); self.encode_variances_of(def_id); } self.encode_generics(def_id); diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index b681078ee0d5d..03754c92252a3 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -238,6 +238,7 @@ crate struct LazyPerDefTables<'tcx> { pub deprecation: Lazy!(PerDefTable>), pub ty: Lazy!(PerDefTable)>), + pub fn_sig: Lazy!(PerDefTable)>), pub inherent_impls: Lazy!(PerDefTable>), pub variances: Lazy!(PerDefTable>), pub generics: Lazy!(PerDefTable>), @@ -265,18 +266,18 @@ crate enum EntryKind<'tcx> { OpaqueTy, Enum(ReprOptions), Field, - Variant(Lazy!(VariantData<'tcx>)), - Struct(Lazy!(VariantData<'tcx>), ReprOptions), - Union(Lazy!(VariantData<'tcx>), ReprOptions), - Fn(Lazy!(FnData<'tcx>)), - ForeignFn(Lazy!(FnData<'tcx>)), + Variant(Lazy), + Struct(Lazy, ReprOptions), + Union(Lazy, ReprOptions), + Fn(Lazy), + ForeignFn(Lazy), Mod(Lazy), MacroDef(Lazy), - Closure(Lazy!(ClosureData<'tcx>)), + Closure, Generator(Lazy!(GeneratorData<'tcx>)), Trait(Lazy), Impl(Lazy!(ImplData<'tcx>)), - Method(Lazy!(MethodData<'tcx>)), + Method(Lazy), AssocType(AssocContainer), AssocOpaqueTy(AssocContainer), AssocConst(AssocContainer, ConstQualif, Lazy), @@ -306,22 +307,18 @@ crate struct MacroDef { } #[derive(RustcEncodable, RustcDecodable)] -crate struct FnData<'tcx> { +crate struct FnData { pub asyncness: hir::IsAsync, pub constness: hir::Constness, pub param_names: Lazy<[ast::Name]>, - pub sig: Lazy!(ty::PolyFnSig<'tcx>), } #[derive(RustcEncodable, RustcDecodable)] -crate struct VariantData<'tcx> { +crate struct VariantData { pub ctor_kind: CtorKind, pub discr: ty::VariantDiscr, /// If this is unit or tuple-variant/struct, then this is the index of the ctor id. pub ctor: Option, - /// If this is a tuple struct or variant - /// ctor, this is its "function" signature. - pub ctor_sig: Option)>, } #[derive(RustcEncodable, RustcDecodable)] @@ -383,17 +380,12 @@ impl AssocContainer { } #[derive(RustcEncodable, RustcDecodable)] -crate struct MethodData<'tcx> { - pub fn_data: FnData<'tcx>, +crate struct MethodData { + pub fn_data: FnData, pub container: AssocContainer, pub has_self: bool, } -#[derive(RustcEncodable, RustcDecodable)] -crate struct ClosureData<'tcx> { - pub sig: Lazy!(ty::PolyFnSig<'tcx>), -} - #[derive(RustcEncodable, RustcDecodable)] crate struct GeneratorData<'tcx> { pub layout: mir::GeneratorLayout<'tcx>, From 371cc39b256d0fa5ec0da3193e0ec6f9377bd903 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sat, 19 Oct 2019 01:10:58 +0300 Subject: [PATCH 21/21] rustc_metadata: use a table for impl_trait_ref. --- src/librustc_metadata/decoder.rs | 4 ++-- src/librustc_metadata/encoder.rs | 8 +++++++- src/librustc_metadata/schema.rs | 7 ++++--- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 9c7b721fb7f63..1333e3fb3ce3e 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -711,7 +711,7 @@ impl<'a, 'tcx> CrateMetadata { } } - fn get_impl_data(&self, id: DefIndex) -> ImplData<'tcx> { + fn get_impl_data(&self, id: DefIndex) -> ImplData { match self.kind(id) { EntryKind::Impl(data) => data.decode(self), _ => bug!(), @@ -738,7 +738,7 @@ impl<'a, 'tcx> CrateMetadata { } crate fn get_impl_trait(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> Option> { - self.get_impl_data(id).trait_ref.map(|tr| tr.decode((self, tcx))) + self.root.per_def.impl_trait_ref.get(self, id).map(|tr| tr.decode((self, tcx))) } /// Iterates over all the stability attributes in the given crate. diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index e3ad1c5e197b5..0dc9f91ae00e1 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -72,6 +72,7 @@ struct PerDefTables<'tcx> { ty: PerDefTable>>, fn_sig: PerDefTable>>, + impl_trait_ref: PerDefTable>>, inherent_impls: PerDefTable>, variances: PerDefTable>, generics: PerDefTable>, @@ -511,6 +512,7 @@ impl<'tcx> EncodeContext<'tcx> { ty: self.per_def.ty.encode(&mut self.opaque), fn_sig: self.per_def.fn_sig.encode(&mut self.opaque), + impl_trait_ref: self.per_def.impl_trait_ref.encode(&mut self.opaque), inherent_impls: self.per_def.inherent_impls.encode(&mut self.opaque), variances: self.per_def.variances.encode(&mut self.opaque), generics: self.per_def.generics.encode(&mut self.opaque), @@ -1152,7 +1154,6 @@ impl EncodeContext<'tcx> { defaultness, parent_impl: parent, coerce_unsized_info, - trait_ref: trait_ref.map(|trait_ref| self.lazy(trait_ref)), }; EntryKind::Impl(self.lazy(data)) @@ -1226,6 +1227,11 @@ impl EncodeContext<'tcx> { if let hir::ItemKind::Fn(..) = item.kind { record!(self.per_def.fn_sig[def_id] <- tcx.fn_sig(def_id)); } + if let hir::ItemKind::Impl(..) = item.kind { + if let Some(trait_ref) = self.tcx.impl_trait_ref(def_id) { + record!(self.per_def.impl_trait_ref[def_id] <- trait_ref); + } + } self.encode_inherent_implementations(def_id); match item.kind { hir::ItemKind::Enum(..) | diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 03754c92252a3..ad39aa34fd5c8 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -239,6 +239,7 @@ crate struct LazyPerDefTables<'tcx> { pub ty: Lazy!(PerDefTable)>), pub fn_sig: Lazy!(PerDefTable)>), + pub impl_trait_ref: Lazy!(PerDefTable)>), pub inherent_impls: Lazy!(PerDefTable>), pub variances: Lazy!(PerDefTable>), pub generics: Lazy!(PerDefTable>), @@ -276,7 +277,7 @@ crate enum EntryKind<'tcx> { Closure, Generator(Lazy!(GeneratorData<'tcx>)), Trait(Lazy), - Impl(Lazy!(ImplData<'tcx>)), + Impl(Lazy), Method(Lazy), AssocType(AssocContainer), AssocOpaqueTy(AssocContainer), @@ -330,14 +331,14 @@ crate struct TraitData { } #[derive(RustcEncodable, RustcDecodable)] -crate struct ImplData<'tcx> { +crate struct ImplData { pub polarity: ty::ImplPolarity, pub defaultness: hir::Defaultness, pub parent_impl: Option, /// This is `Some` only for impls of `CoerceUnsized`. + // FIXME(eddyb) perhaps compute this on the fly if cheap enough? pub coerce_unsized_info: Option, - pub trait_ref: Option)>, }