From 6b6cb7bda73f16ecd8e8755a13af93d64f284684 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Fri, 3 Apr 2020 23:00:47 +0200 Subject: [PATCH 1/6] Do not disable field reordering on enums with big discriminant The field are always re-ordered to minimize padding, regardless of the alignment of the discriminant --- src/librustc_middle/ty/layout.rs | 8 +++----- src/test/ui/type-sizes.rs | 25 +++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/librustc_middle/ty/layout.rs b/src/librustc_middle/ty/layout.rs index 520793c69fdd..5740f8cc091c 100644 --- a/src/librustc_middle/ty/layout.rs +++ b/src/librustc_middle/ty/layout.rs @@ -285,11 +285,7 @@ fn univariant_uninterned( let mut inverse_memory_index: Vec = (0..fields.len() as u32).collect(); - let mut optimize = !repr.inhibit_struct_field_reordering_opt(); - if let StructKind::Prefixed(_, align) = kind { - optimize &= align.bytes() == 1; - } - + let optimize = !repr.inhibit_struct_field_reordering_opt(); if optimize { let end = if let StructKind::MaybeUnsized = kind { fields.len() - 1 } else { fields.len() }; @@ -307,6 +303,8 @@ fn univariant_uninterned( }); } StructKind::Prefixed(..) => { + // Sort in ascending alignment so that the layout stay optimal + // regardless of the prefix optimizing.sort_by_key(|&x| field_align(&fields[x as usize])); } } diff --git a/src/test/ui/type-sizes.rs b/src/test/ui/type-sizes.rs index 1d332cc3bf7b..6a3f3c98f127 100644 --- a/src/test/ui/type-sizes.rs +++ b/src/test/ui/type-sizes.rs @@ -37,6 +37,29 @@ enum ReorderedEnum { B(u8, u16, u8), } +enum ReorderedEnum2 { + A(u8, u32, u8), + B(u16, u8, u16, u8), + + // 0x100 niche variants. + _00, _01, _02, _03, _04, _05, _06, _07, _08, _09, _0A, _0B, _0C, _0D, _0E, _0F, + _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _1A, _1B, _1C, _1D, _1E, _1F, + _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _2A, _2B, _2C, _2D, _2E, _2F, + _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _3A, _3B, _3C, _3D, _3E, _3F, + _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _4A, _4B, _4C, _4D, _4E, _4F, + _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _5A, _5B, _5C, _5D, _5E, _5F, + _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _6A, _6B, _6C, _6D, _6E, _6F, + _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _7A, _7B, _7C, _7D, _7E, _7F, + _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _8A, _8B, _8C, _8D, _8E, _8F, + _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, _9A, _9B, _9C, _9D, _9E, _9F, + _A0, _A1, _A2, _A3, _A4, _A5, _A6, _A7, _A8, _A9, _AA, _AB, _AC, _AD, _AE, _AF, + _B0, _B1, _B2, _B3, _B4, _B5, _B6, _B7, _B8, _B9, _BA, _BB, _BC, _BD, _BE, _BF, + _C0, _C1, _C2, _C3, _C4, _C5, _C6, _C7, _C8, _C9, _CA, _CB, _CC, _CD, _CE, _CF, + _D0, _D1, _D2, _D3, _D4, _D5, _D6, _D7, _D8, _D9, _DA, _DB, _DC, _DD, _DE, _DF, + _E0, _E1, _E2, _E3, _E4, _E5, _E6, _E7, _E8, _E9, _EA, _EB, _EC, _ED, _EE, _EF, + _F0, _F1, _F2, _F3, _F4, _F5, _F6, _F7, _F8, _F9, _FA, _FB, _FC, _FD, _FE, _FF, +} + enum EnumEmpty {} enum EnumSingle1 { @@ -104,6 +127,8 @@ pub fn main() { assert_eq!(size_of::(), 4 as usize); assert_eq!(size_of::(), 4); assert_eq!(size_of::(), 6); + assert_eq!(size_of::(), 8); + assert_eq!(size_of::(), 0); assert_eq!(size_of::(), 0); From 2b718e8d9ca6efdccf4d72647cb3d3101e15b7fa Mon Sep 17 00:00:00 2001 From: Trevor Spiteri Date: Sat, 4 Apr 2020 14:24:26 +0200 Subject: [PATCH 2/6] use ManuallyDrop instead of forget inside collections This commit changes some usage of mem::forget into mem::ManuallyDrop in some Vec, VecDeque, BTreeMap and Box methods. Before the commit, the generated IR for some of the methods was longer, and even after optimization, some unwinding artifacts were still present. --- src/liballoc/boxed.rs | 2 +- src/liballoc/collections/btree/map.rs | 16 ++++++++-------- src/liballoc/collections/vec_deque.rs | 11 +++++------ src/liballoc/raw_vec.rs | 16 +++++++--------- src/liballoc/vec.rs | 27 +++++++++++++-------------- 5 files changed, 34 insertions(+), 38 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 5406956a5288..db7420954a09 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -469,8 +469,8 @@ pub fn into_raw_non_null(b: Box) -> NonNull { #[inline] #[doc(hidden)] pub fn into_unique(b: Box) -> Unique { + let b = mem::ManuallyDrop::new(b); let mut unique = b.0; - mem::forget(b); // Box is kind-of a library type, but recognized as a "unique pointer" by // Stacked Borrows. This function here corresponds to "reborrowing to // a raw pointer", but there is no actual reborrow here -- so diff --git a/src/liballoc/collections/btree/map.rs b/src/liballoc/collections/btree/map.rs index bbeced1751d1..36770ee416cb 100644 --- a/src/liballoc/collections/btree/map.rs +++ b/src/liballoc/collections/btree/map.rs @@ -4,9 +4,10 @@ use core::hash::{Hash, Hasher}; use core::iter::{FromIterator, FusedIterator, Peekable}; use core::marker::PhantomData; +use core::mem::{self, ManuallyDrop}; use core::ops::Bound::{Excluded, Included, Unbounded}; use core::ops::{Index, RangeBounds}; -use core::{fmt, mem, ptr}; +use core::{fmt, ptr}; use super::node::{self, marker, ForceResult::*, Handle, InsertResult::*, NodeRef}; use super::search::{self, SearchResult::*}; @@ -190,9 +191,9 @@ fn clone_subtree<'a, K: Clone, V: Clone>( // We can't destructure subtree directly // because BTreeMap implements Drop let (subroot, sublength) = unsafe { + let subtree = ManuallyDrop::new(subtree); let root = ptr::read(&subtree.root); let length = subtree.length; - mem::forget(subtree); (root, length) }; @@ -1515,15 +1516,14 @@ impl IntoIterator for BTreeMap { type IntoIter = IntoIter; fn into_iter(self) -> IntoIter { - if self.root.is_none() { - mem::forget(self); + let me = ManuallyDrop::new(self); + if me.root.is_none() { return IntoIter { front: None, back: None, length: 0 }; } - let root1 = unsafe { unwrap_unchecked(ptr::read(&self.root)).into_ref() }; - let root2 = unsafe { unwrap_unchecked(ptr::read(&self.root)).into_ref() }; - let len = self.length; - mem::forget(self); + let root1 = unsafe { unwrap_unchecked(ptr::read(&me.root)).into_ref() }; + let root2 = unsafe { unwrap_unchecked(ptr::read(&me.root)).into_ref() }; + let len = me.length; IntoIter { front: Some(root1.first_leaf_edge()), diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index 94532521a906..c17a37c7bae1 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -12,7 +12,7 @@ use core::fmt; use core::hash::{Hash, Hasher}; use core::iter::{once, repeat_with, FromIterator, FusedIterator}; -use core::mem::{self, replace}; +use core::mem::{self, replace, ManuallyDrop}; use core::ops::Bound::{Excluded, Included, Unbounded}; use core::ops::{Index, IndexMut, RangeBounds, Try}; use core::ptr::{self, NonNull}; @@ -2898,12 +2898,12 @@ impl From> for VecDeque { /// This avoids reallocating where possible, but the conditions for that are /// strict, and subject to change, and so shouldn't be relied upon unless the /// `Vec` came from `From>` and hasn't been reallocated. - fn from(mut other: Vec) -> Self { + fn from(other: Vec) -> Self { unsafe { + let mut other = ManuallyDrop::new(other); let other_buf = other.as_mut_ptr(); let mut buf = RawVec::from_raw_parts(other_buf, other.capacity()); let len = other.len(); - mem::forget(other); // We need to extend the buf if it's not a power of two, too small // or doesn't have at least one free space @@ -2955,6 +2955,7 @@ fn from(mut other: VecDeque) -> Self { other.make_contiguous(); unsafe { + let other = ManuallyDrop::new(other); let buf = other.buf.ptr(); let len = other.len(); let cap = other.cap(); @@ -2962,9 +2963,7 @@ fn from(mut other: VecDeque) -> Self { if other.head != 0 { ptr::copy(buf.add(other.tail), buf, len); } - let out = Vec::from_raw_parts(buf, len, cap); - mem::forget(other); - out + Vec::from_raw_parts(buf, len, cap) } } } diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index 2bf40490e781..12e32fd9d352 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -3,7 +3,7 @@ use core::alloc::MemoryBlock; use core::cmp; -use core::mem::{self, MaybeUninit}; +use core::mem::{self, ManuallyDrop, MaybeUninit}; use core::ops::Drop; use core::ptr::{NonNull, Unique}; use core::slice; @@ -112,11 +112,10 @@ pub unsafe fn from_raw_parts(ptr: *mut T, capacity: usize) -> Self { } /// Converts a `Box<[T]>` into a `RawVec`. - pub fn from_box(mut slice: Box<[T]>) -> Self { + pub fn from_box(slice: Box<[T]>) -> Self { unsafe { - let result = RawVec::from_raw_parts(slice.as_mut_ptr(), slice.len()); - mem::forget(slice); - result + let mut slice = ManuallyDrop::new(slice); + RawVec::from_raw_parts(slice.as_mut_ptr(), slice.len()) } } } @@ -579,11 +578,10 @@ pub unsafe fn into_box(self, len: usize) -> Box<[MaybeUninit]> { "`len` must be smaller than or equal to `self.capacity()`" ); + let me = ManuallyDrop::new(self); // NOTE: not calling `capacity()` here; actually using the real `cap` field! - let slice = slice::from_raw_parts_mut(self.ptr() as *mut MaybeUninit, len); - let output = Box::from_raw(slice); - mem::forget(self); - output + let slice = slice::from_raw_parts_mut(me.ptr() as *mut MaybeUninit, len); + Box::from_raw(slice) } } diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 96a6399d0518..80574efe0627 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -66,7 +66,7 @@ use core::intrinsics::{arith_offset, assume}; use core::iter::{FromIterator, FusedIterator, TrustedLen}; use core::marker::PhantomData; -use core::mem; +use core::mem::{self, ManuallyDrop}; use core::ops::Bound::{Excluded, Included, Unbounded}; use core::ops::{self, Index, IndexMut, RangeBounds}; use core::ptr::{self, NonNull}; @@ -392,7 +392,7 @@ pub fn with_capacity(capacity: usize) -> Vec { /// ``` #[unstable(feature = "vec_into_raw_parts", reason = "new API", issue = "65816")] pub fn into_raw_parts(self) -> (*mut T, usize, usize) { - let mut me = mem::ManuallyDrop::new(self); + let mut me = ManuallyDrop::new(self); (me.as_mut_ptr(), me.len(), me.capacity()) } @@ -678,9 +678,9 @@ pub fn shrink_to(&mut self, min_capacity: usize) { pub fn into_boxed_slice(mut self) -> Box<[T]> { unsafe { self.shrink_to_fit(); - let buf = ptr::read(&self.buf); - let len = self.len(); - mem::forget(self); + let me = ManuallyDrop::new(self); + let buf = ptr::read(&me.buf); + let len = me.len(); buf.into_box(len).assume_init() } } @@ -1949,16 +1949,16 @@ impl IntoIterator for Vec { /// } /// ``` #[inline] - fn into_iter(mut self) -> IntoIter { + fn into_iter(self) -> IntoIter { unsafe { - let begin = self.as_mut_ptr(); + let mut me = ManuallyDrop::new(self); + let begin = me.as_mut_ptr(); let end = if mem::size_of::() == 0 { - arith_offset(begin as *const i8, self.len() as isize) as *const T + arith_offset(begin as *const i8, me.len() as isize) as *const T } else { - begin.add(self.len()) as *const T + begin.add(me.len()) as *const T }; - let cap = self.buf.capacity(); - mem::forget(self); + let cap = me.buf.capacity(); IntoIter { buf: NonNull::new_unchecked(begin), phantom: PhantomData, @@ -2081,9 +2081,8 @@ fn from_iter(iterator: IntoIter) -> Self { // has not been advanced at all. if iterator.buf.as_ptr() as *const _ == iterator.ptr { unsafe { - let vec = Vec::from_raw_parts(iterator.buf.as_ptr(), iterator.len(), iterator.cap); - mem::forget(iterator); - vec + let it = ManuallyDrop::new(iterator); + Vec::from_raw_parts(it.buf.as_ptr(), it.len(), it.cap) } } else { let mut vector = Vec::new(); From cd79400da7e6da5488b22e2a2eab24bcaff6aa95 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 31 Mar 2020 23:39:38 +0300 Subject: [PATCH 3/6] rustc_target: Rely on default value of `no_default_libraries` more --- src/librustc_target/spec/hermit_base.rs | 1 - src/librustc_target/spec/hermit_kernel_base.rs | 1 - src/librustc_target/spec/windows_base.rs | 1 - src/librustc_target/spec/windows_uwp_base.rs | 1 - 4 files changed, 4 deletions(-) diff --git a/src/librustc_target/spec/hermit_base.rs b/src/librustc_target/spec/hermit_base.rs index ee29d672b462..3f9dad689fd5 100644 --- a/src/librustc_target/spec/hermit_base.rs +++ b/src/librustc_target/spec/hermit_base.rs @@ -14,7 +14,6 @@ pub fn opts() -> TargetOptions { has_elf_tls: true, linker_is_gnu: true, pre_link_args, - no_default_libraries: true, panic_strategy: PanicStrategy::Abort, position_independent_executables: true, relocation_model: "static".to_string(), diff --git a/src/librustc_target/spec/hermit_kernel_base.rs b/src/librustc_target/spec/hermit_kernel_base.rs index 44d3ee671811..650219c21ac4 100644 --- a/src/librustc_target/spec/hermit_kernel_base.rs +++ b/src/librustc_target/spec/hermit_kernel_base.rs @@ -15,7 +15,6 @@ pub fn opts() -> TargetOptions { has_elf_tls: true, linker_is_gnu: true, pre_link_args, - no_default_libraries: true, panic_strategy: PanicStrategy::Abort, position_independent_executables: true, relocation_model: "static".to_string(), diff --git a/src/librustc_target/spec/windows_base.rs b/src/librustc_target/spec/windows_base.rs index 5f59ca8a5a31..34fcdf251b89 100644 --- a/src/librustc_target/spec/windows_base.rs +++ b/src/librustc_target/spec/windows_base.rs @@ -77,7 +77,6 @@ pub fn opts() -> TargetOptions { exe_suffix: ".exe".to_string(), staticlib_prefix: String::new(), staticlib_suffix: ".lib".to_string(), - no_default_libraries: true, target_family: Some("windows".to_string()), is_like_windows: true, allows_weak_linkage: false, diff --git a/src/librustc_target/spec/windows_uwp_base.rs b/src/librustc_target/spec/windows_uwp_base.rs index 3f7eb442bbc7..f19bd10dc0bb 100644 --- a/src/librustc_target/spec/windows_uwp_base.rs +++ b/src/librustc_target/spec/windows_uwp_base.rs @@ -43,7 +43,6 @@ pub fn opts() -> TargetOptions { exe_suffix: ".exe".to_string(), staticlib_prefix: "lib".to_string(), staticlib_suffix: ".a".to_string(), - no_default_libraries: true, target_family: Some("windows".to_string()), is_like_windows: true, allows_weak_linkage: false, From 106b30e86989cb4f201ef7a1b7fac7150b662b92 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 4 Apr 2020 16:23:43 +0300 Subject: [PATCH 4/6] macro_rules: `NtLifetime` cannot start with an identifier --- src/librustc_expand/mbe/macro_parser.rs | 2 +- src/test/ui/macros/issue-70446.rs | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/macros/issue-70446.rs diff --git a/src/librustc_expand/mbe/macro_parser.rs b/src/librustc_expand/mbe/macro_parser.rs index e868b7e36aac..5fb800972c78 100644 --- a/src/librustc_expand/mbe/macro_parser.rs +++ b/src/librustc_expand/mbe/macro_parser.rs @@ -768,7 +768,7 @@ fn may_begin_with(token: &Token, name: Name) -> bool { /// Checks whether the non-terminal may contain a single (non-keyword) identifier. fn may_be_ident(nt: &token::Nonterminal) -> bool { match *nt { - token::NtItem(_) | token::NtBlock(_) | token::NtVis(_) => false, + token::NtItem(_) | token::NtBlock(_) | token::NtVis(_) | token::NtLifetime(_) => false, _ => true, } } diff --git a/src/test/ui/macros/issue-70446.rs b/src/test/ui/macros/issue-70446.rs new file mode 100644 index 000000000000..407094d55ffe --- /dev/null +++ b/src/test/ui/macros/issue-70446.rs @@ -0,0 +1,13 @@ +// check-pass + +macro_rules! foo { + ($(: $p:path)? $(: $l:lifetime)? ) => { bar! {$(: $p)? $(: $l)? } }; +} + +macro_rules! bar { + ($(: $p:path)? $(: $l:lifetime)? ) => {}; +} + +foo! {: 'a } + +fn main() {} From 636076a89edd3e553775f159170991502761cbc0 Mon Sep 17 00:00:00 2001 From: Tshepang Lekhonkhobe Date: Sat, 4 Apr 2020 20:30:09 +0200 Subject: [PATCH 5/6] comment refers to removed type Was removed in 51938c61f6f1b26e463f9071716f543543486e72 --- src/librustc_driver/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index ccbce01d6c12..acf8f1adbc2e 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -136,7 +136,6 @@ pub fn diagnostics_registry() -> Registry { } // Parse args and run the compiler. This is the primary entry point for rustc. -// See comments on CompilerCalls below for details about the callbacks argument. // The FileLoader provides a way to load files from sources other than the file system. pub fn run_compiler( at_args: &[String], From edabceb4a3f0149323c381d5c75fe6957385addf Mon Sep 17 00:00:00 2001 From: Yoshua Wuyts Date: Fri, 3 Apr 2020 22:53:55 +0200 Subject: [PATCH 6/6] Add slice::fill --- src/libcore/slice/mod.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 2140a7be9efe..a257d73c0cca 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -23,6 +23,7 @@ // * The `raw` and `bytes` submodules. // * Boilerplate trait implementations. +use crate::borrow::Borrow; use crate::cmp; use crate::cmp::Ordering::{self, Equal, Greater, Less}; use crate::fmt; @@ -2145,6 +2146,29 @@ pub fn rotate_right(&mut self, k: usize) { } } + /// Fills `self` with elements by cloning `value`. + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_fill)] + /// + /// let mut buf = vec![0; 10]; + /// buf.fill(1); + /// assert_eq!(buf, vec![1; 10]); + /// ``` + #[unstable(feature = "slice_fill", issue = "70758")] + pub fn fill(&mut self, value: V) + where + V: Borrow, + T: Clone, + { + let value = value.borrow(); + for el in self { + el.clone_from(value) + } + } + /// Copies the elements from `src` into `self`. /// /// The length of `src` must be the same as `self`.