about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/liballoc/boxed.rs2
-rw-r--r--src/liballoc/collections/btree/map.rs16
-rw-r--r--src/liballoc/collections/vec_deque.rs11
-rw-r--r--src/liballoc/raw_vec.rs25
-rw-r--r--src/liballoc/tests/vec.rs71
-rw-r--r--src/liballoc/vec.rs49
-rw-r--r--src/libcore/result.rs6
-rw-r--r--src/libcore/slice/mod.rs24
-rw-r--r--src/librustc_codegen_llvm/debuginfo/create_scope_map.rs2
-rw-r--r--src/librustc_codegen_llvm/debuginfo/metadata.rs15
-rw-r--r--src/librustc_codegen_llvm/debuginfo/mod.rs4
-rw-r--r--src/librustc_driver/lib.rs1
-rw-r--r--src/librustc_expand/mbe/macro_parser.rs2
-rw-r--r--src/librustc_interface/callbacks.rs1
-rw-r--r--src/librustc_middle/query/mod.rs4
-rw-r--r--src/librustc_middle/ty/instance.rs23
-rw-r--r--src/librustc_middle/ty/layout.rs8
-rw-r--r--src/librustc_middle/ty/mod.rs1
-rw-r--r--src/librustc_middle/ty/query/keys.rs11
-rw-r--r--src/librustc_mir/interpret/eval_context.rs52
-rw-r--r--src/librustc_mir/interpret/operand.rs2
-rw-r--r--src/librustc_mir/interpret/place.rs4
-rw-r--r--src/librustc_mir/interpret/terminator.rs1
-rw-r--r--src/librustc_target/spec/hermit_base.rs1
-rw-r--r--src/librustc_target/spec/hermit_kernel_base.rs1
-rw-r--r--src/librustc_target/spec/windows_base.rs1
-rw-r--r--src/librustc_target/spec/windows_uwp_base.rs1
-rw-r--r--src/librustc_ty/instance.rs8
-rw-r--r--src/librustc_ty/lib.rs1
-rw-r--r--src/test/ui/consts/const-eval/issue-70804-fn-subtyping.rs10
-rw-r--r--src/test/ui/macros/issue-70446.rs13
-rw-r--r--src/test/ui/type-sizes.rs25
32 files changed, 272 insertions, 124 deletions
diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs
index 5406956a528..db7420954a0 100644
--- a/src/liballoc/boxed.rs
+++ b/src/liballoc/boxed.rs
@@ -469,8 +469,8 @@ impl<T: ?Sized> Box<T> {
     #[inline]
     #[doc(hidden)]
     pub fn into_unique(b: Box<T>) -> Unique<T> {
+        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 bbeced1751d..36770ee416c 100644
--- a/src/liballoc/collections/btree/map.rs
+++ b/src/liballoc/collections/btree/map.rs
@@ -4,9 +4,10 @@ use core::fmt::Debug;
 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 @@ impl<K: Clone, V: Clone> Clone for BTreeMap<K, V> {
                             // 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<K, V> IntoIterator for BTreeMap<K, V> {
     type IntoIter = IntoIter<K, V>;
 
     fn into_iter(self) -> IntoIter<K, V> {
-        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 94532521a90..c17a37c7bae 100644
--- a/src/liballoc/collections/vec_deque.rs
+++ b/src/liballoc/collections/vec_deque.rs
@@ -12,7 +12,7 @@ use core::cmp::{self, Ordering};
 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<T> From<Vec<T>> for VecDeque<T> {
     /// 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<T>` came from `From<VecDeque<T>>` and hasn't been reallocated.
-    fn from(mut other: Vec<T>) -> Self {
+    fn from(other: Vec<T>) -> 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 @@ impl<T> From<VecDeque<T>> for Vec<T> {
         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 @@ impl<T> From<VecDeque<T>> for Vec<T> {
             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 2bf40490e78..7ac67870eb7 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 @@ impl<T> RawVec<T, Global> {
     }
 
     /// Converts a `Box<[T]>` into a `RawVec<T>`.
-    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())
         }
     }
 }
@@ -571,19 +570,21 @@ impl<T> RawVec<T, Global> {
     ///
     /// # Safety
     ///
-    /// `shrink_to_fit(len)` must be called immediately prior to calling this function. This
-    /// implies, that `len` must be smaller than or equal to `self.capacity()`.
+    /// * `len` must be greater than or equal to the most recently requested capacity, and
+    /// * `len` must be less than or equal to `self.capacity()`.
+    ///
+    /// Note, that the requested capacity and `self.capacity()` could differ, as
+    /// an allocator could overallocate and return a greater memory block than requested.
     pub unsafe fn into_box(self, len: usize) -> Box<[MaybeUninit<T>]> {
+        // Sanity-check one half of the safety requirement (we cannot check the other half).
         debug_assert!(
             len <= self.capacity(),
             "`len` must be smaller than or equal to `self.capacity()`"
         );
 
-        // NOTE: not calling `capacity()` here; actually using the real `cap` field!
-        let slice = slice::from_raw_parts_mut(self.ptr() as *mut MaybeUninit<T>, len);
-        let output = Box::from_raw(slice);
-        mem::forget(self);
-        output
+        let me = ManuallyDrop::new(self);
+        let slice = slice::from_raw_parts_mut(me.ptr() as *mut MaybeUninit<T>, len);
+        Box::from_raw(slice)
     }
 }
 
diff --git a/src/liballoc/tests/vec.rs b/src/liballoc/tests/vec.rs
index 831a42a4b3f..b63d81796f9 100644
--- a/src/liballoc/tests/vec.rs
+++ b/src/liballoc/tests/vec.rs
@@ -1350,17 +1350,26 @@ fn test_try_reserve_exact() {
 }
 
 #[test]
-fn test_stable_push_pop() {
+fn test_stable_pointers() {
+    /// Pull an element from the iterator, then drop it.
+    /// Useful to cover both the `next` and `drop` paths of an iterator.
+    fn next_then_drop<I: Iterator>(mut i: I) {
+        i.next().unwrap();
+        drop(i);
+    }
+
     // Test that, if we reserved enough space, adding and removing elements does not
     // invalidate references into the vector (such as `v0`).  This test also
     // runs in Miri, which would detect such problems.
-    let mut v = Vec::with_capacity(10);
+    let mut v = Vec::with_capacity(128);
     v.push(13);
 
-    // laundering the lifetime -- we take care that `v` does not reallocate, so that's okay.
-    let v0 = unsafe { &*(&v[0] as *const _) };
-
+    // Laundering the lifetime -- we take care that `v` does not reallocate, so that's okay.
+    let v0 = &mut v[0];
+    let v0 = unsafe { &mut *(v0 as *mut _) };
     // Now do a bunch of things and occasionally use `v0` again to assert it is still valid.
+
+    // Pushing/inserting and popping/removing
     v.push(1);
     v.push(2);
     v.insert(1, 1);
@@ -1368,6 +1377,58 @@ fn test_stable_push_pop() {
     v.remove(1);
     v.pop().unwrap();
     assert_eq!(*v0, 13);
+    v.push(1);
+    v.swap_remove(1);
+    assert_eq!(v.len(), 2);
+    v.swap_remove(1); // swap_remove the last element
+    assert_eq!(*v0, 13);
+
+    // Appending
+    v.append(&mut vec![27, 19]);
+    assert_eq!(*v0, 13);
+
+    // Extending
+    v.extend_from_slice(&[1, 2]);
+    v.extend(&[1, 2]); // `slice::Iter` (with `T: Copy`) specialization
+    v.extend(vec![2, 3]); // `vec::IntoIter` specialization
+    v.extend(std::iter::once(3)); // `TrustedLen` specialization
+    v.extend(std::iter::empty::<i32>()); // `TrustedLen` specialization with empty iterator
+    v.extend(std::iter::once(3).filter(|_| true)); // base case
+    v.extend(std::iter::once(&3)); // `cloned` specialization
+    assert_eq!(*v0, 13);
+
+    // Truncation
+    v.truncate(2);
+    assert_eq!(*v0, 13);
+
+    // Resizing
+    v.resize_with(v.len() + 10, || 42);
+    assert_eq!(*v0, 13);
+    v.resize_with(2, || panic!());
+    assert_eq!(*v0, 13);
+
+    // No-op reservation
+    v.reserve(32);
+    v.reserve_exact(32);
+    assert_eq!(*v0, 13);
+
+    // Partial draining
+    v.resize_with(10, || 42);
+    next_then_drop(v.drain(5..));
+    assert_eq!(*v0, 13);
+
+    // Splicing
+    v.resize_with(10, || 42);
+    next_then_drop(v.splice(5.., vec![1, 2, 3, 4, 5])); // empty tail after range
+    assert_eq!(*v0, 13);
+    next_then_drop(v.splice(5..8, vec![1])); // replacement is smaller than original range
+    assert_eq!(*v0, 13);
+    next_then_drop(v.splice(5..6, vec![1; 10].into_iter().filter(|_| true))); // lower bound not exact
+    assert_eq!(*v0, 13);
+
+    // Smoke test that would fire even outside Miri if an actual relocation happened.
+    *v0 -= 13;
+    assert_eq!(v[0], 0);
 }
 
 // https://github.com/rust-lang/rust/pull/49496 introduced specialization based on:
diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs
index 96a6399d051..a48e48d7da3 100644
--- a/src/liballoc/vec.rs
+++ b/src/liballoc/vec.rs
@@ -66,7 +66,7 @@ use core::hash::{self, Hash};
 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 @@ impl<T> Vec<T> {
     /// ```
     #[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 @@ impl<T> Vec<T> {
     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()
         }
     }
@@ -740,7 +740,8 @@ impl<T> Vec<T> {
             if len > self.len {
                 return;
             }
-            let s = self.get_unchecked_mut(len..) as *mut _;
+            let remaining_len = self.len - len;
+            let s = slice::from_raw_parts_mut(self.as_mut_ptr().add(len), remaining_len);
             self.len = len;
             ptr::drop_in_place(s);
         }
@@ -963,13 +964,15 @@ impl<T> Vec<T> {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn swap_remove(&mut self, index: usize) -> T {
+        let len = self.len();
+        assert!(index < len);
         unsafe {
             // We replace self[index] with the last element. Note that if the
-            // bounds check on hole succeeds there must be a last element (which
+            // bounds check above succeeds there must be a last element (which
             // can be self[index] itself).
-            let hole: *mut T = &mut self[index];
-            let last = ptr::read(self.get_unchecked(self.len - 1));
-            self.len -= 1;
+            let last = ptr::read(self.as_ptr().add(len - 1));
+            let hole: *mut T = self.as_mut_ptr().add(index);
+            self.set_len(len - 1);
             ptr::replace(hole, last)
         }
     }
@@ -1200,7 +1203,7 @@ impl<T> Vec<T> {
         } else {
             unsafe {
                 self.len -= 1;
-                Some(ptr::read(self.get_unchecked(self.len())))
+                Some(ptr::read(self.as_ptr().add(self.len())))
             }
         }
     }
@@ -1949,16 +1952,16 @@ impl<T> IntoIterator for Vec<T> {
     /// }
     /// ```
     #[inline]
-    fn into_iter(mut self) -> IntoIter<T> {
+    fn into_iter(self) -> IntoIter<T> {
         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::<T>() == 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,
@@ -2020,7 +2023,7 @@ where
                 let (lower, _) = iterator.size_hint();
                 let mut vector = Vec::with_capacity(lower.saturating_add(1));
                 unsafe {
-                    ptr::write(vector.get_unchecked_mut(0), element);
+                    ptr::write(vector.as_mut_ptr(), element);
                     vector.set_len(1);
                 }
                 vector
@@ -2081,9 +2084,8 @@ impl<T> SpecExtend<T, IntoIter<T>> for Vec<T> {
         // 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();
@@ -2123,8 +2125,9 @@ where
         self.reserve(slice.len());
         unsafe {
             let len = self.len();
+            let dst_slice = slice::from_raw_parts_mut(self.as_mut_ptr().add(len), slice.len());
+            dst_slice.copy_from_slice(slice);
             self.set_len(len + slice.len());
-            self.get_unchecked_mut(len..).copy_from_slice(slice);
         }
     }
 }
@@ -2145,7 +2148,7 @@ impl<T> Vec<T> {
                 self.reserve(lower.saturating_add(1));
             }
             unsafe {
-                ptr::write(self.get_unchecked_mut(len), element);
+                ptr::write(self.as_mut_ptr().add(len), element);
                 // NB can't overflow since we would have had to alloc the address space
                 self.set_len(len + 1);
             }
diff --git a/src/libcore/result.rs b/src/libcore/result.rs
index 0087b92f1f2..c7b5777a16e 100644
--- a/src/libcore/result.rs
+++ b/src/libcore/result.rs
@@ -521,14 +521,16 @@ impl<T, E> Result<T, E> {
         }
     }
 
-    /// Applies a function to the contained value (if any),
-    /// or returns the provided default (if not).
+    /// Applies a function to the contained value (if [`Ok`]),
+    /// or returns the provided default (if [`Err`]).
     ///
     /// Arguments passed to `map_or` are eagerly evaluated; if you are passing
     /// the result of a function call, it is recommended to use [`map_or_else`],
     /// which is lazily evaluated.
     ///
     /// [`map_or_else`]: #method.map_or_else
+    /// [`Ok`]: enum.Result.html#variant.Ok
+    /// [`Err`]: enum.Result.html#variant.Err
     ///
     /// # Examples
     ///
diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs
index 9be52e2dfb0..66aad324618 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 @@ impl<T> [T] {
         }
     }
 
+    /// 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<V>(&mut self, value: V)
+    where
+        V: Borrow<T>,
+        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`.
diff --git a/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs b/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs
index e2eae4ac427..7f47b61de3f 100644
--- a/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs
+++ b/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs
@@ -76,7 +76,7 @@ fn make_mir_scope(
     }
 
     let loc = cx.lookup_debug_loc(scope_data.span.lo());
-    let file_metadata = file_metadata(cx, &loc.file.name, debug_context.defining_crate);
+    let file_metadata = file_metadata(cx, &loc.file, debug_context.defining_crate);
 
     let scope_metadata = unsafe {
         Some(llvm::LLVMRustDIBuilderCreateLexicalBlock(
diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs
index 700f25d35bc..82cd8589327 100644
--- a/src/librustc_codegen_llvm/debuginfo/metadata.rs
+++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs
@@ -41,7 +41,7 @@ use rustc_middle::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt};
 use rustc_middle::{bug, span_bug};
 use rustc_session::config::{self, DebugInfo};
 use rustc_span::symbol::{Interner, Symbol};
-use rustc_span::{self, FileName, SourceFileHash, Span};
+use rustc_span::{self, SourceFile, SourceFileHash, Span};
 use rustc_target::abi::{Abi, Align, DiscriminantKind, HasDataLayout, Integer, LayoutOf};
 use rustc_target::abi::{Int, Pointer, F32, F64};
 use rustc_target::abi::{Primitive, Size, VariantIdx, Variants};
@@ -761,14 +761,13 @@ fn hex_encode(data: &[u8]) -> String {
 
 pub fn file_metadata(
     cx: &CodegenCx<'ll, '_>,
-    file_name: &FileName,
+    source_file: &SourceFile,
     defining_crate: CrateNum,
 ) -> &'ll DIFile {
-    debug!("file_metadata: file_name: {}, defining_crate: {}", file_name, defining_crate);
+    debug!("file_metadata: file_name: {}, defining_crate: {}", source_file.name, defining_crate);
 
-    let source_file = cx.sess().source_map().get_source_file(file_name);
-    let hash = source_file.as_ref().map(|f| &f.src_hash);
-    let file_name = Some(file_name.to_string());
+    let hash = Some(&source_file.src_hash);
+    let file_name = Some(source_file.name.to_string());
     let directory = if defining_crate == LOCAL_CRATE {
         Some(cx.sess().working_dir.0.to_string_lossy().to_string())
     } else {
@@ -2331,7 +2330,7 @@ pub fn create_global_var_metadata(cx: &CodegenCx<'ll, '_>, def_id: DefId, global
 
     let (file_metadata, line_number) = if !span.is_dummy() {
         let loc = cx.lookup_debug_loc(span.lo());
-        (file_metadata(cx, &loc.file.name, LOCAL_CRATE), loc.line)
+        (file_metadata(cx, &loc.file, LOCAL_CRATE), loc.line)
     } else {
         (unknown_file_metadata(cx), None)
     };
@@ -2440,6 +2439,6 @@ pub fn extend_scope_to_file(
     file: &rustc_span::SourceFile,
     defining_crate: CrateNum,
 ) -> &'ll DILexicalBlock {
-    let file_metadata = file_metadata(cx, &file.name, defining_crate);
+    let file_metadata = file_metadata(cx, &file, defining_crate);
     unsafe { llvm::LLVMRustDIBuilderCreateLexicalBlockFile(DIB(cx), scope_metadata, file_metadata) }
 }
diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs
index f04ac586504..37f502c56a6 100644
--- a/src/librustc_codegen_llvm/debuginfo/mod.rs
+++ b/src/librustc_codegen_llvm/debuginfo/mod.rs
@@ -249,7 +249,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         let def_id = instance.def_id();
         let containing_scope = get_containing_scope(self, instance);
         let loc = self.lookup_debug_loc(span.lo());
-        let file_metadata = file_metadata(self, &loc.file.name, def_id.krate);
+        let file_metadata = file_metadata(self, &loc.file, def_id.krate);
 
         let function_type_metadata = unsafe {
             let fn_signature = get_function_signature(self, fn_abi);
@@ -536,7 +536,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         span: Span,
     ) -> &'ll DIVariable {
         let loc = self.lookup_debug_loc(span.lo());
-        let file_metadata = file_metadata(self, &loc.file.name, dbg_context.defining_crate);
+        let file_metadata = file_metadata(self, &loc.file, dbg_context.defining_crate);
 
         let type_metadata = type_metadata(self, variable_type, span);
 
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index ccbce01d6c1..acf8f1adbc2 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],
diff --git a/src/librustc_expand/mbe/macro_parser.rs b/src/librustc_expand/mbe/macro_parser.rs
index e868b7e36aa..5fb800972c7 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/librustc_interface/callbacks.rs b/src/librustc_interface/callbacks.rs
index 88c3d0ec56f..913c67d045e 100644
--- a/src/librustc_interface/callbacks.rs
+++ b/src/librustc_interface/callbacks.rs
@@ -58,5 +58,4 @@ pub fn setup_callbacks() {
     rustc_span::SPAN_DEBUG.swap(&(span_debug as fn(_, &mut fmt::Formatter<'_>) -> _));
     rustc_hir::def_id::DEF_ID_DEBUG.swap(&(def_id_debug as fn(_, &mut fmt::Formatter<'_>) -> _));
     TRACK_DIAGNOSTICS.swap(&(track_diagnostic as fn(&_)));
-    rustc_middle::ty::RESOLVE_INSTANCE.swap(&(rustc_ty::instance::resolve_instance as _));
 }
diff --git a/src/librustc_middle/query/mod.rs b/src/librustc_middle/query/mod.rs
index 2ffbbfb1762..c26c043994f 100644
--- a/src/librustc_middle/query/mod.rs
+++ b/src/librustc_middle/query/mod.rs
@@ -1257,5 +1257,9 @@ rustc_queries! {
             eval_always
             desc { "looking up enabled feature gates" }
         }
+
+        query resolve_instance(key: (ty::ParamEnv<'tcx>, DefId, SubstsRef<'tcx>)) -> Option<ty::Instance<'tcx>> {
+            desc { "resolving instance `{:?}` `{:?}` with {:?}", key.1, key.2, key.0 }
+        }
     }
 }
diff --git a/src/librustc_middle/ty/instance.rs b/src/librustc_middle/ty/instance.rs
index 5d47a6e13f4..cf0222370f2 100644
--- a/src/librustc_middle/ty/instance.rs
+++ b/src/librustc_middle/ty/instance.rs
@@ -1,7 +1,6 @@
 use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use crate::ty::print::{FmtPrinter, Printer};
 use crate::ty::{self, SubstsRef, Ty, TyCtxt, TypeFoldable};
-use rustc_data_structures::AtomicRef;
 use rustc_hir::def::Namespace;
 use rustc_hir::def_id::{CrateNum, DefId};
 use rustc_hir::lang_items::DropInPlaceFnLangItem;
@@ -289,7 +288,9 @@ impl<'tcx> Instance<'tcx> {
         def_id: DefId,
         substs: SubstsRef<'tcx>,
     ) -> Option<Instance<'tcx>> {
-        (*RESOLVE_INSTANCE)(tcx, param_env, def_id, substs)
+        // All regions in the result of this query are erased, so it's
+        // fine to erase all of the input regions.
+        tcx.resolve_instance((tcx.erase_regions(&param_env), def_id, tcx.erase_regions(&substs)))
     }
 
     pub fn resolve_for_fn_ptr(
@@ -440,21 +441,3 @@ fn needs_fn_once_adapter_shim(
         (ty::ClosureKind::FnMut, _) | (ty::ClosureKind::FnOnce, _) => Err(()),
     }
 }
-
-fn resolve_instance_default(
-    _tcx: TyCtxt<'tcx>,
-    _param_env: ty::ParamEnv<'tcx>,
-    _def_id: DefId,
-    _substs: SubstsRef<'tcx>,
-) -> Option<Instance<'tcx>> {
-    unimplemented!()
-}
-
-pub static RESOLVE_INSTANCE: AtomicRef<
-    for<'tcx> fn(
-        TyCtxt<'tcx>,
-        ty::ParamEnv<'tcx>,
-        DefId,
-        SubstsRef<'tcx>,
-    ) -> Option<Instance<'tcx>>,
-> = AtomicRef::new(&(resolve_instance_default as _));
diff --git a/src/librustc_middle/ty/layout.rs b/src/librustc_middle/ty/layout.rs
index 520793c69fd..5740f8cc091 100644
--- a/src/librustc_middle/ty/layout.rs
+++ b/src/librustc_middle/ty/layout.rs
@@ -285,11 +285,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
 
         let mut inverse_memory_index: Vec<u32> = (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 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
                     });
                 }
                 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/librustc_middle/ty/mod.rs b/src/librustc_middle/ty/mod.rs
index 9b182333907..0ebd55a6c02 100644
--- a/src/librustc_middle/ty/mod.rs
+++ b/src/librustc_middle/ty/mod.rs
@@ -81,7 +81,6 @@ pub use self::context::{
     CtxtInterners, GeneratorInteriorTypeCause, GlobalCtxt, Lift, TypeckTables,
 };
 
-pub use self::instance::RESOLVE_INSTANCE;
 pub use self::instance::{Instance, InstanceDef};
 
 pub use self::trait_def::TraitDef;
diff --git a/src/librustc_middle/ty/query/keys.rs b/src/librustc_middle/ty/query/keys.rs
index a261e484a85..438e7ed4331 100644
--- a/src/librustc_middle/ty/query/keys.rs
+++ b/src/librustc_middle/ty/query/keys.rs
@@ -296,3 +296,14 @@ impl Key for (Symbol, u32, u32) {
         DUMMY_SP
     }
 }
+
+impl<'tcx> Key for (ty::ParamEnv<'tcx>, DefId, SubstsRef<'tcx>) {
+    type CacheSelector = DefaultCacheSelector;
+
+    fn query_crate(&self) -> CrateNum {
+        self.1.krate
+    }
+    fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
+        tcx.def_span(self.1)
+    }
+}
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index 10d3101ebb8..0b182d42287 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -14,11 +14,11 @@ use rustc_middle::mir::interpret::{
     sign_extend, truncate, AllocId, FrameInfo, GlobalId, InterpResult, Pointer, Scalar,
 };
 use rustc_middle::ty::layout::{self, TyAndLayout};
-use rustc_middle::ty::query::TyCtxtAt;
-use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
+use rustc_middle::ty::{
+    self, fold::BottomUpFolder, query::TyCtxtAt, subst::SubstsRef, Ty, TyCtxt, TypeFoldable,
+};
 use rustc_span::source_map::DUMMY_SP;
-use rustc_target::abi::{Abi, Align, HasDataLayout, LayoutOf, Size, TargetDataLayout};
+use rustc_target::abi::{Align, HasDataLayout, LayoutOf, Size, TargetDataLayout};
 
 use super::{
     Immediate, MPlaceTy, Machine, MemPlace, MemPlaceMeta, Memory, OpTy, Operand, Place, PlaceTy,
@@ -213,6 +213,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> LayoutOf for InterpCx<'mir, 'tcx, M> {
 /// Test if it is valid for a MIR assignment to assign `src`-typed place to `dest`-typed value.
 /// This test should be symmetric, as it is primarily about layout compatibility.
 pub(super) fn mir_assign_valid_types<'tcx>(
+    tcx: TyCtxt<'tcx>,
     src: TyAndLayout<'tcx>,
     dest: TyAndLayout<'tcx>,
 ) -> bool {
@@ -220,23 +221,42 @@ pub(super) fn mir_assign_valid_types<'tcx>(
         // Equal types, all is good.
         return true;
     }
-    // Type-changing assignments can happen for (at least) two reasons:
-    // - `&mut T` -> `&T` gets optimized from a reborrow to a mere assignment.
-    // - Subtyping is used. While all normal lifetimes are erased, higher-ranked lifetime
-    //   bounds are still around and can lead to type differences.
-    // There is no good way to check the latter, so we compare layouts instead -- but only
-    // for values with `Scalar`/`ScalarPair` abi.
-    // FIXME: Do something more accurate, type-based.
-    match &src.abi {
-        Abi::Scalar(..) | Abi::ScalarPair(..) => src.layout == dest.layout,
-        _ => false,
+    if src.layout != dest.layout {
+        // Layout differs, definitely not equal.
+        // We do this here because Miri would *do the wrong thing* if we allowed layout-changing
+        // assignments.
+        return false;
     }
+
+    // Type-changing assignments can happen for (at least) two reasons:
+    // 1. `&mut T` -> `&T` gets optimized from a reborrow to a mere assignment.
+    // 2. Subtyping is used. While all normal lifetimes are erased, higher-ranked types
+    //    with their late-bound lifetimes are still around and can lead to type differences.
+    // Normalize both of them away.
+    let normalize = |ty: Ty<'tcx>| {
+        ty.fold_with(&mut BottomUpFolder {
+            tcx,
+            // Normalize all references to immutable.
+            ty_op: |ty| match ty.kind {
+                ty::Ref(_, pointee, _) => tcx.mk_imm_ref(tcx.lifetimes.re_erased, pointee),
+                _ => ty,
+            },
+            // We just erase all late-bound lifetimes, but this is not fully correct (FIXME):
+            // lifetimes in invariant positions could matter (e.g. through associated types).
+            // We rely on the fact that layout was confirmed to be equal above.
+            lt_op: |_| tcx.lifetimes.re_erased,
+            // Leave consts unchanged.
+            ct_op: |ct| ct,
+        })
+    };
+    normalize(src.ty) == normalize(dest.ty)
 }
 
 /// Use the already known layout if given (but sanity check in debug mode),
 /// or compute the layout.
 #[cfg_attr(not(debug_assertions), inline(always))]
 pub(super) fn from_known_layout<'tcx>(
+    tcx: TyCtxt<'tcx>,
     known_layout: Option<TyAndLayout<'tcx>>,
     compute: impl FnOnce() -> InterpResult<'tcx, TyAndLayout<'tcx>>,
 ) -> InterpResult<'tcx, TyAndLayout<'tcx>> {
@@ -246,7 +266,7 @@ pub(super) fn from_known_layout<'tcx>(
             if cfg!(debug_assertions) {
                 let check_layout = compute()?;
                 assert!(
-                    mir_assign_valid_types(check_layout, known_layout),
+                    mir_assign_valid_types(tcx, check_layout, known_layout),
                     "expected type differs from actual type.\nexpected: {:?}\nactual: {:?}",
                     known_layout.ty,
                     check_layout.ty,
@@ -424,7 +444,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         // have to support that case (mostly by skipping all caching).
         match frame.locals.get(local).and_then(|state| state.layout.get()) {
             None => {
-                let layout = from_known_layout(layout, || {
+                let layout = from_known_layout(self.tcx.tcx, layout, || {
                     let local_ty = frame.body.local_decls[local].ty;
                     let local_ty =
                         self.subst_from_frame_and_normalize_erasing_regions(frame, local_ty);
diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs
index 12595e4e4d9..03614b2803f 100644
--- a/src/librustc_mir/interpret/operand.rs
+++ b/src/librustc_mir/interpret/operand.rs
@@ -529,7 +529,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             ty::ConstKind::Value(val_val) => val_val,
         };
         // Other cases need layout.
-        let layout = from_known_layout(layout, || self.layout_of(val.ty))?;
+        let layout = from_known_layout(self.tcx.tcx, layout, || self.layout_of(val.ty))?;
         let op = match val_val {
             ConstValue::ByRef { alloc, offset } => {
                 let id = self.tcx.alloc_map.lock().create_memory_alloc(alloc);
diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index ec299cdd213..716c7c7d933 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -868,7 +868,7 @@ where
         // We do NOT compare the types for equality, because well-typed code can
         // actually "transmute" `&mut T` to `&T` in an assignment without a cast.
         assert!(
-            mir_assign_valid_types(src.layout, dest.layout),
+            mir_assign_valid_types(self.tcx.tcx, src.layout, dest.layout),
             "type mismatch when copying!\nsrc: {:?},\ndest: {:?}",
             src.layout.ty,
             dest.layout.ty,
@@ -922,7 +922,7 @@ where
         src: OpTy<'tcx, M::PointerTag>,
         dest: PlaceTy<'tcx, M::PointerTag>,
     ) -> InterpResult<'tcx> {
-        if mir_assign_valid_types(src.layout, dest.layout) {
+        if mir_assign_valid_types(self.tcx.tcx, src.layout, dest.layout) {
             // Fast path: Just use normal `copy_op`
             return self.copy_op(src, dest);
         }
diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs
index 8ad743d2b8b..6ebe5b80370 100644
--- a/src/librustc_mir/interpret/terminator.rs
+++ b/src/librustc_mir/interpret/terminator.rs
@@ -75,7 +75,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             }
 
             Drop { location, target, unwind } => {
-                // FIXME(CTFE): forbid drop in const eval
                 let place = self.eval_place(location)?;
                 let ty = place.layout.ty;
                 trace!("TerminatorKind::drop: {:?}, type {}", location, ty);
diff --git a/src/librustc_target/spec/hermit_base.rs b/src/librustc_target/spec/hermit_base.rs
index ee29d672b46..3f9dad689fd 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 44d3ee67181..650219c21ac 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 5f59ca8a5a3..34fcdf251b8 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 3f7eb442bbc..f19bd10dc0b 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,
diff --git a/src/librustc_ty/instance.rs b/src/librustc_ty/instance.rs
index 677e373f2f4..955e2e36159 100644
--- a/src/librustc_ty/instance.rs
+++ b/src/librustc_ty/instance.rs
@@ -11,9 +11,7 @@ use log::debug;
 
 pub fn resolve_instance<'tcx>(
     tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    def_id: DefId,
-    substs: SubstsRef<'tcx>,
+    (param_env, def_id, substs): (ty::ParamEnv<'tcx>, DefId, SubstsRef<'tcx>),
 ) -> Option<Instance<'tcx>> {
     debug!("resolve(def_id={:?}, substs={:?})", def_id, substs);
     let result = if let Some(trait_def_id) = tcx.trait_of_item(def_id) {
@@ -199,3 +197,7 @@ fn resolve_associated_item<'tcx>(
         traits::VtableAutoImpl(..) | traits::VtableParam(..) | traits::VtableTraitAlias(..) => None,
     }
 }
+
+pub fn provide(providers: &mut ty::query::Providers<'_>) {
+    *providers = ty::query::Providers { resolve_instance, ..*providers };
+}
diff --git a/src/librustc_ty/lib.rs b/src/librustc_ty/lib.rs
index 04909b8b0c1..75e62e79640 100644
--- a/src/librustc_ty/lib.rs
+++ b/src/librustc_ty/lib.rs
@@ -25,4 +25,5 @@ pub fn provide(providers: &mut Providers<'_>) {
     common_traits::provide(providers);
     needs_drop::provide(providers);
     ty::provide(providers);
+    instance::provide(providers);
 }
diff --git a/src/test/ui/consts/const-eval/issue-70804-fn-subtyping.rs b/src/test/ui/consts/const-eval/issue-70804-fn-subtyping.rs
new file mode 100644
index 00000000000..59d46ea66c9
--- /dev/null
+++ b/src/test/ui/consts/const-eval/issue-70804-fn-subtyping.rs
@@ -0,0 +1,10 @@
+// check-pass
+#![feature(const_fn)]
+
+const fn nested(x: (for<'a> fn(&'a ()), String)) -> (fn(&'static ()), String) {
+    x
+}
+
+pub const TEST: (fn(&'static ()), String) = nested((|_x| (), String::new()));
+
+fn main() {}
diff --git a/src/test/ui/macros/issue-70446.rs b/src/test/ui/macros/issue-70446.rs
new file mode 100644
index 00000000000..407094d55ff
--- /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() {}
diff --git a/src/test/ui/type-sizes.rs b/src/test/ui/type-sizes.rs
index 1d332cc3bf7..6a3f3c98f12 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::<e3>(), 4 as usize);
     assert_eq!(size_of::<ReorderedStruct>(), 4);
     assert_eq!(size_of::<ReorderedEnum>(), 6);
+    assert_eq!(size_of::<ReorderedEnum2>(), 8);
+
 
     assert_eq!(size_of::<EnumEmpty>(), 0);
     assert_eq!(size_of::<EnumSingle1>(), 0);