diff --git a/Cargo.lock b/Cargo.lock
index 157c1749c8782..a4e1ab6c1e4a8 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1660,7 +1660,7 @@ checksum = "3ca8957e71f04a205cb162508f9326aea04676c8dfd0711220190d6b83664f3f"
 dependencies = [
  "bitmaps",
  "rand_core 0.5.1",
- "rand_xoshiro",
+ "rand_xoshiro 0.4.0",
  "sized-chunks",
  "typenum",
  "version_check",
@@ -2256,7 +2256,7 @@ dependencies = [
  "libc",
  "log",
  "measureme",
- "rand 0.8.3",
+ "rand 0.8.4",
  "rustc-workspace-hack",
  "rustc_version",
  "shell-escape",
@@ -2852,9 +2852,9 @@ dependencies = [
 
 [[package]]
 name = "rand"
-version = "0.8.3"
+version = "0.8.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
+checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
 dependencies = [
  "libc",
  "rand_chacha 0.3.0",
@@ -2945,6 +2945,15 @@ dependencies = [
  "rand_core 0.5.1",
 ]
 
+[[package]]
+name = "rand_xoshiro"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa"
+dependencies = [
+ "rand_core 0.6.2",
+]
+
 [[package]]
 name = "rayon"
 version = "1.3.1"
@@ -4087,6 +4096,8 @@ dependencies = [
  "either",
  "gsgdt",
  "polonius-engine",
+ "rand 0.8.4",
+ "rand_xoshiro 0.6.0",
  "rustc-rayon-core",
  "rustc_apfloat",
  "rustc_arena",
@@ -5097,7 +5108,7 @@ checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
 dependencies = [
  "cfg-if 1.0.0",
  "libc",
- "rand 0.8.3",
+ "rand 0.8.4",
  "redox_syscall",
  "remove_dir_all",
  "winapi",
diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs
index 1c9c6834c100c..f0056cb79766a 100644
--- a/compiler/rustc_builtin_macros/src/format.rs
+++ b/compiler/rustc_builtin_macros/src/format.rs
@@ -1154,11 +1154,12 @@ pub fn expand_preparsed_format_args(
                     // account for `"` and account for raw strings `r#`
                     let padding = str_style.map(|i| i + 2).unwrap_or(1);
                     for sub in foreign::$kind::iter_subs(fmt_str, padding) {
-                        let trn = match sub.translate() {
-                            Some(trn) => trn,
+                        let (trn, success) = match sub.translate() {
+                            Ok(trn) => (trn, true),
+                            Err(Some(msg)) => (msg, false),
 
                             // If it has no translation, don't call it out specifically.
-                            None => continue,
+                            _ => continue,
                         };
 
                         let pos = sub.position();
@@ -1175,9 +1176,24 @@ pub fn expand_preparsed_format_args(
 
                         if let Some(inner_sp) = pos {
                             let sp = fmt_sp.from_inner(inner_sp);
-                            suggestions.push((sp, trn));
+
+                            if success {
+                                suggestions.push((sp, trn));
+                            } else {
+                                diag.span_note(
+                                    sp,
+                                    &format!("format specifiers use curly braces, and {}", trn),
+                                );
+                            }
                         } else {
-                            diag.help(&format!("`{}` should be written as `{}`", sub, trn));
+                            if success {
+                                diag.help(&format!("`{}` should be written as `{}`", sub, trn));
+                            } else {
+                                diag.note(&format!(
+                                    "`{}` should use curly braces, and {}",
+                                    sub, trn
+                                ));
+                            }
                         }
                     }
 
diff --git a/compiler/rustc_builtin_macros/src/format_foreign.rs b/compiler/rustc_builtin_macros/src/format_foreign.rs
index 0cc520e5bd1f0..bfddd7073ff2c 100644
--- a/compiler/rustc_builtin_macros/src/format_foreign.rs
+++ b/compiler/rustc_builtin_macros/src/format_foreign.rs
@@ -1,4 +1,4 @@
-pub mod printf {
+pub(crate) mod printf {
     use super::strcursor::StrCursor as Cur;
     use rustc_span::InnerSpan;
 
@@ -36,10 +36,10 @@ pub mod printf {
         ///
         /// This ignores cases where the substitution does not have an exact equivalent, or where
         /// the substitution would be unnecessary.
-        pub fn translate(&self) -> Option<String> {
+        pub fn translate(&self) -> Result<String, Option<String>> {
             match *self {
                 Substitution::Format(ref fmt) => fmt.translate(),
-                Substitution::Escape => None,
+                Substitution::Escape => Err(None),
             }
         }
     }
@@ -68,9 +68,9 @@ pub mod printf {
     impl Format<'_> {
         /// Translate this directive into an equivalent Rust formatting directive.
         ///
-        /// Returns `None` in cases where the `printf` directive does not have an exact Rust
+        /// Returns `Err` in cases where the `printf` directive does not have an exact Rust
         /// equivalent, rather than guessing.
-        pub fn translate(&self) -> Option<String> {
+        pub fn translate(&self) -> Result<String, Option<String>> {
             use std::fmt::Write;
 
             let (c_alt, c_zero, c_left, c_plus) = {
@@ -84,7 +84,12 @@ pub mod printf {
                         '0' => c_zero = true,
                         '-' => c_left = true,
                         '+' => c_plus = true,
-                        _ => return None,
+                        _ => {
+                            return Err(Some(format!(
+                                "the flag `{}` is unknown or unsupported",
+                                c
+                            )));
+                        }
                     }
                 }
                 (c_alt, c_zero, c_left, c_plus)
@@ -104,7 +109,9 @@ pub mod printf {
             let width = match self.width {
                 Some(Num::Next) => {
                     // NOTE: Rust doesn't support this.
-                    return None;
+                    return Err(Some(
+                        "you have to use a positional or named parameter for the width".to_string(),
+                    ));
                 }
                 w @ Some(Num::Arg(_)) => w,
                 w @ Some(Num::Num(_)) => w,
@@ -125,13 +132,21 @@ pub mod printf {
                 "p" => (Some(self.type_), false, true),
                 "g" => (Some("e"), true, false),
                 "G" => (Some("E"), true, false),
-                _ => return None,
+                _ => {
+                    return Err(Some(format!(
+                        "the conversion specifier `{}` is unknown or unsupported",
+                        self.type_
+                    )));
+                }
             };
 
             let (fill, width, precision) = match (is_int, width, precision) {
                 (true, Some(_), Some(_)) => {
                     // Rust can't duplicate this insanity.
-                    return None;
+                    return Err(Some(
+                        "width and precision cannot both be specified for integer conversions"
+                            .to_string(),
+                    ));
                 }
                 (true, None, Some(p)) => (Some("0"), Some(p), None),
                 (true, w, None) => (fill, w, None),
@@ -169,7 +184,17 @@ pub mod printf {
             s.push('{');
 
             if let Some(arg) = self.parameter {
-                write!(s, "{}", arg.checked_sub(1)?).ok()?;
+                match write!(
+                    s,
+                    "{}",
+                    match arg.checked_sub(1) {
+                        Some(a) => a,
+                        None => return Err(None),
+                    }
+                ) {
+                    Err(_) => return Err(None),
+                    _ => {}
+                }
             }
 
             if has_options {
@@ -199,12 +224,18 @@ pub mod printf {
                 }
 
                 if let Some(width) = width {
-                    width.translate(&mut s).ok()?;
+                    match width.translate(&mut s) {
+                        Err(_) => return Err(None),
+                        _ => {}
+                    }
                 }
 
                 if let Some(precision) = precision {
                     s.push('.');
-                    precision.translate(&mut s).ok()?;
+                    match precision.translate(&mut s) {
+                        Err(_) => return Err(None),
+                        _ => {}
+                    }
                 }
 
                 if let Some(type_) = type_ {
@@ -213,7 +244,7 @@ pub mod printf {
             }
 
             s.push('}');
-            Some(s)
+            Ok(s)
         }
     }
 
@@ -623,11 +654,11 @@ pub mod shell {
             }
         }
 
-        pub fn translate(&self) -> Option<String> {
+        pub fn translate(&self) -> Result<String, Option<String>> {
             match *self {
-                Substitution::Ordinal(n, _) => Some(format!("{{{}}}", n)),
-                Substitution::Name(n, _) => Some(format!("{{{}}}", n)),
-                Substitution::Escape(_) => None,
+                Substitution::Ordinal(n, _) => Ok(format!("{{{}}}", n)),
+                Substitution::Name(n, _) => Ok(format!("{{{}}}", n)),
+                Substitution::Escape(_) => Err(None),
             }
         }
     }
diff --git a/compiler/rustc_builtin_macros/src/format_foreign/printf/tests.rs b/compiler/rustc_builtin_macros/src/format_foreign/printf/tests.rs
index 33c54c9cee001..1336aab731674 100644
--- a/compiler/rustc_builtin_macros/src/format_foreign/printf/tests.rs
+++ b/compiler/rustc_builtin_macros/src/format_foreign/printf/tests.rs
@@ -3,7 +3,7 @@ use super::{iter_subs, parse_next_substitution as pns, Format as F, Num as N, Su
 macro_rules! assert_eq_pnsat {
     ($lhs:expr, $rhs:expr) => {
         assert_eq!(
-            pns($lhs).and_then(|(s, _)| s.translate()),
+            pns($lhs).and_then(|(s, _)| s.translate().ok()),
             $rhs.map(<String as From<&str>>::from)
         )
     };
@@ -98,7 +98,7 @@ fn test_parse() {
 #[test]
 fn test_iter() {
     let s = "The %d'th word %% is: `%.*s` %!\n";
-    let subs: Vec<_> = iter_subs(s, 0).map(|sub| sub.translate()).collect();
+    let subs: Vec<_> = iter_subs(s, 0).map(|sub| sub.translate().ok()).collect();
     assert_eq!(
         subs.iter().map(|ms| ms.as_ref().map(|s| &s[..])).collect::<Vec<_>>(),
         vec![Some("{}"), None, Some("{:.*}"), None]
diff --git a/compiler/rustc_builtin_macros/src/format_foreign/shell/tests.rs b/compiler/rustc_builtin_macros/src/format_foreign/shell/tests.rs
index ed8fe81dfcdd8..f5f82732f2034 100644
--- a/compiler/rustc_builtin_macros/src/format_foreign/shell/tests.rs
+++ b/compiler/rustc_builtin_macros/src/format_foreign/shell/tests.rs
@@ -3,7 +3,7 @@ use super::{parse_next_substitution as pns, Substitution as S};
 macro_rules! assert_eq_pnsat {
     ($lhs:expr, $rhs:expr) => {
         assert_eq!(
-            pns($lhs).and_then(|(f, _)| f.translate()),
+            pns($lhs).and_then(|(f, _)| f.translate().ok()),
             $rhs.map(<String as From<&str>>::from)
         )
     };
@@ -37,7 +37,7 @@ fn test_parse() {
 fn test_iter() {
     use super::iter_subs;
     let s = "The $0'th word $$ is: `$WORD` $!\n";
-    let subs: Vec<_> = iter_subs(s, 0).map(|sub| sub.translate()).collect();
+    let subs: Vec<_> = iter_subs(s, 0).map(|sub| sub.translate().ok()).collect();
     assert_eq!(
         subs.iter().map(|ms| ms.as_ref().map(|s| &s[..])).collect::<Vec<_>>(),
         vec![Some("{0}"), None, Some("{WORD}")]
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index 92199f611bad0..9b0e752689487 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -129,7 +129,8 @@ fn to_pass_builder_opt_level(cfg: config::OptLevel) -> llvm::PassBuilderOptLevel
 fn to_llvm_relocation_model(relocation_model: RelocModel) -> llvm::RelocModel {
     match relocation_model {
         RelocModel::Static => llvm::RelocModel::Static,
-        RelocModel::Pic => llvm::RelocModel::PIC,
+        // LLVM doesn't have a PIE relocation model, it represents PIE as PIC with an extra attribute.
+        RelocModel::Pic | RelocModel::Pie => llvm::RelocModel::PIC,
         RelocModel::DynamicNoPic => llvm::RelocModel::DynamicNoPic,
         RelocModel::Ropi => llvm::RelocModel::ROPI,
         RelocModel::Rwpi => llvm::RelocModel::RWPI,
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index 52a12b2fd81d8..7bdbec11d6033 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -195,11 +195,14 @@ pub unsafe fn create_module(
     let llvm_target = SmallCStr::new(&sess.target.llvm_target);
     llvm::LLVMRustSetNormalizedTarget(llmod, llvm_target.as_ptr());
 
-    if sess.relocation_model() == RelocModel::Pic {
+    let reloc_model = sess.relocation_model();
+    if matches!(reloc_model, RelocModel::Pic | RelocModel::Pie) {
         llvm::LLVMRustSetModulePICLevel(llmod);
         // PIE is potentially more effective than PIC, but can only be used in executables.
         // If all our outputs are executables, then we can relax PIC to PIE.
-        if sess.crate_types().iter().all(|ty| *ty == CrateType::Executable) {
+        if reloc_model == RelocModel::Pie
+            || sess.crate_types().iter().all(|ty| *ty == CrateType::Executable)
+        {
             llvm::LLVMRustSetModulePIELevel(llmod);
         }
     }
diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs
index 79bdace515832..c44cc6560563f 100644
--- a/compiler/rustc_codegen_llvm/src/lib.rs
+++ b/compiler/rustc_codegen_llvm/src/lib.rs
@@ -211,9 +211,16 @@ impl CodegenBackend for LlvmCodegenBackend {
         match req {
             PrintRequest::RelocationModels => {
                 println!("Available relocation models:");
-                for name in
-                    &["static", "pic", "dynamic-no-pic", "ropi", "rwpi", "ropi-rwpi", "default"]
-                {
+                for name in &[
+                    "static",
+                    "pic",
+                    "pie",
+                    "dynamic-no-pic",
+                    "ropi",
+                    "rwpi",
+                    "ropi-rwpi",
+                    "default",
+                ] {
                     println!("    {}", name);
                 }
                 println!();
diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs
index 34982f769d03a..b9022a391e6f1 100644
--- a/compiler/rustc_codegen_llvm/src/mono_item.rs
+++ b/compiler/rustc_codegen_llvm/src/mono_item.rs
@@ -143,6 +143,12 @@ impl CodegenCx<'ll, 'tcx> {
             return true;
         }
 
+        // With pie relocation model calls of functions defined in the translation
+        // unit can use copy relocations.
+        if self.tcx.sess.relocation_model() == RelocModel::Pie && !is_declaration {
+            return true;
+        }
+
         return false;
     }
 }
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 1c0442a231a58..43affdebbafa9 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -1490,9 +1490,13 @@ fn exec_linker(
 fn link_output_kind(sess: &Session, crate_type: CrateType) -> LinkOutputKind {
     let kind = match (crate_type, sess.crt_static(Some(crate_type)), sess.relocation_model()) {
         (CrateType::Executable, _, _) if sess.is_wasi_reactor() => LinkOutputKind::WasiReactorExe,
-        (CrateType::Executable, false, RelocModel::Pic) => LinkOutputKind::DynamicPicExe,
+        (CrateType::Executable, false, RelocModel::Pic | RelocModel::Pie) => {
+            LinkOutputKind::DynamicPicExe
+        }
         (CrateType::Executable, false, _) => LinkOutputKind::DynamicNoPicExe,
-        (CrateType::Executable, true, RelocModel::Pic) => LinkOutputKind::StaticPicExe,
+        (CrateType::Executable, true, RelocModel::Pic | RelocModel::Pie) => {
+            LinkOutputKind::StaticPicExe
+        }
         (CrateType::Executable, true, _) => LinkOutputKind::StaticNoPicExe,
         (_, true, _) => LinkOutputKind::StaticDylib,
         (_, false, _) => LinkOutputKind::DynamicDylib,
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 05b652fd5af2c..9c275b316c545 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -384,6 +384,16 @@ impl GenericArgs<'_> {
         self.args.iter().any(|arg| matches!(arg, GenericArg::Type(_)))
     }
 
+    pub fn has_err(&self) -> bool {
+        self.args.iter().any(|arg| match arg {
+            GenericArg::Type(ty) => matches!(ty.kind, TyKind::Err),
+            _ => false,
+        }) || self.bindings.iter().any(|arg| match arg.kind {
+            TypeBindingKind::Equality { ty } => matches!(ty.kind, TyKind::Err),
+            _ => false,
+        })
+    }
+
     #[inline]
     pub fn num_type_params(&self) -> usize {
         self.args.iter().filter(|arg| matches!(arg, GenericArg::Type(_))).count()
diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml
index b1fcc34bee1d7..d06c593d39481 100644
--- a/compiler/rustc_middle/Cargo.toml
+++ b/compiler/rustc_middle/Cargo.toml
@@ -32,3 +32,5 @@ chalk-ir = "0.55.0"
 smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
 rustc_session = { path = "../rustc_session" }
 rustc_type_ir = { path = "../rustc_type_ir" }
+rand = "0.8.4"
+rand_xoshiro = "0.6.0"
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index cfbbec374a172..b6aeb9122c3d3 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -24,6 +24,9 @@ use std::iter;
 use std::num::NonZeroUsize;
 use std::ops::Bound;
 
+use rand::{seq::SliceRandom, SeedableRng};
+use rand_xoshiro::Xoshiro128StarStar;
+
 pub fn provide(providers: &mut ty::query::Providers) {
     *providers =
         ty::query::Providers { layout_of, fn_abi_of_fn_ptr, fn_abi_of_instance, ..*providers };
@@ -324,6 +327,10 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
 
         let mut inverse_memory_index: Vec<u32> = (0..fields.len() as u32).collect();
 
+        // `ReprOptions.layout_seed` is a deterministic seed that we can use to
+        // randomize field ordering with
+        let mut rng = Xoshiro128StarStar::seed_from_u64(repr.field_shuffle_seed);
+
         let optimize = !repr.inhibit_struct_field_reordering_opt();
         if optimize {
             let end =
@@ -332,20 +339,35 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
             let field_align = |f: &TyAndLayout<'_>| {
                 if let Some(pack) = pack { f.align.abi.min(pack) } else { f.align.abi }
             };
-            match kind {
-                StructKind::AlwaysSized | StructKind::MaybeUnsized => {
-                    optimizing.sort_by_key(|&x| {
-                        // Place ZSTs first to avoid "interesting offsets",
-                        // especially with only one or two non-ZST fields.
-                        let f = &fields[x as usize];
-                        (!f.is_zst(), cmp::Reverse(field_align(f)))
-                    });
-                }
-                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]));
+
+            // If `-Z randomize-layout` was enabled for the type definition we can shuffle
+            // the field ordering to try and catch some code making assumptions about layouts
+            // we don't guarantee
+            if repr.can_randomize_type_layout() {
+                // Shuffle the ordering of the fields
+                optimizing.shuffle(&mut rng);
+
+            // Otherwise we just leave things alone and actually optimize the type's fields
+            } else {
+                match kind {
+                    StructKind::AlwaysSized | StructKind::MaybeUnsized => {
+                        optimizing.sort_by_key(|&x| {
+                            // Place ZSTs first to avoid "interesting offsets",
+                            // especially with only one or two non-ZST fields.
+                            let f = &fields[x as usize];
+                            (!f.is_zst(), cmp::Reverse(field_align(f)))
+                        });
+                    }
+
+                    StructKind::Prefixed(..) => {
+                        // Sort in ascending alignment so that the layout stays optimal
+                        // regardless of the prefix
+                        optimizing.sort_by_key(|&x| field_align(&fields[x as usize]));
+                    }
                 }
+
+                // FIXME(Kixiron): We can always shuffle fields within a given alignment class
+                //                 regardless of the status of `-Z randomize-layout`
             }
         }
 
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index b3ae76d987167..d04d1565fead7 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -1491,6 +1491,9 @@ bitflags! {
         const IS_LINEAR          = 1 << 3;
         // If true, don't expose any niche to type's context.
         const HIDE_NICHE         = 1 << 4;
+        // If true, the type's layout can be randomized using
+        // the seed stored in `ReprOptions.layout_seed`
+        const RANDOMIZE_LAYOUT   = 1 << 5;
         // Any of these flags being set prevent field reordering optimisation.
         const IS_UNOPTIMISABLE   = ReprFlags::IS_C.bits |
                                    ReprFlags::IS_SIMD.bits |
@@ -1505,6 +1508,14 @@ pub struct ReprOptions {
     pub align: Option<Align>,
     pub pack: Option<Align>,
     pub flags: ReprFlags,
+    /// The seed to be used for randomizing a type's layout
+    ///
+    /// Note: This could technically be a `[u8; 16]` (a `u128`) which would
+    /// be the "most accurate" hash as it'd encompass the item and crate
+    /// hash without loss, but it does pay the price of being larger.
+    /// Everything's a tradeoff, a `u64` seed should be sufficient for our
+    /// purposes (primarily `-Z randomize-layout`)
+    pub field_shuffle_seed: u64,
 }
 
 impl ReprOptions {
@@ -1513,6 +1524,11 @@ impl ReprOptions {
         let mut size = None;
         let mut max_align: Option<Align> = None;
         let mut min_pack: Option<Align> = None;
+
+        // Generate a deterministically-derived seed from the item's path hash
+        // to allow for cross-crate compilation to actually work
+        let field_shuffle_seed = tcx.def_path_hash(did).0.to_smaller_hash();
+
         for attr in tcx.get_attrs(did).iter() {
             for r in attr::find_repr_attrs(&tcx.sess, attr) {
                 flags.insert(match r {
@@ -1541,33 +1557,45 @@ impl ReprOptions {
             }
         }
 
+        // If `-Z randomize-layout` was enabled for the type definition then we can
+        // consider performing layout randomization
+        if tcx.sess.opts.debugging_opts.randomize_layout {
+            flags.insert(ReprFlags::RANDOMIZE_LAYOUT);
+        }
+
         // This is here instead of layout because the choice must make it into metadata.
         if !tcx.consider_optimizing(|| format!("Reorder fields of {:?}", tcx.def_path_str(did))) {
             flags.insert(ReprFlags::IS_LINEAR);
         }
-        ReprOptions { int: size, align: max_align, pack: min_pack, flags }
+
+        Self { int: size, align: max_align, pack: min_pack, flags, field_shuffle_seed }
     }
 
     #[inline]
     pub fn simd(&self) -> bool {
         self.flags.contains(ReprFlags::IS_SIMD)
     }
+
     #[inline]
     pub fn c(&self) -> bool {
         self.flags.contains(ReprFlags::IS_C)
     }
+
     #[inline]
     pub fn packed(&self) -> bool {
         self.pack.is_some()
     }
+
     #[inline]
     pub fn transparent(&self) -> bool {
         self.flags.contains(ReprFlags::IS_TRANSPARENT)
     }
+
     #[inline]
     pub fn linear(&self) -> bool {
         self.flags.contains(ReprFlags::IS_LINEAR)
     }
+
     #[inline]
     pub fn hide_niche(&self) -> bool {
         self.flags.contains(ReprFlags::HIDE_NICHE)
@@ -1594,9 +1622,17 @@ impl ReprOptions {
                 return true;
             }
         }
+
         self.flags.intersects(ReprFlags::IS_UNOPTIMISABLE) || self.int.is_some()
     }
 
+    /// Returns `true` if this type is valid for reordering and `-Z randomize-layout`
+    /// was enabled for its declaration crate
+    pub fn can_randomize_type_layout(&self) -> bool {
+        !self.inhibit_struct_field_reordering_opt()
+            && self.flags.contains(ReprFlags::RANDOMIZE_LAYOUT)
+    }
+
     /// Returns `true` if this `#[repr()]` should inhibit union ABI optimisations.
     pub fn inhibit_union_abi_opt(&self) -> bool {
         self.c()
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index d43528a1cf098..ee4e91ecb62b0 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -147,7 +147,7 @@ impl Inliner<'tcx> {
         self.check_mir_body(callsite, callee_body, callee_attrs)?;
 
         if !self.tcx.consider_optimizing(|| {
-            format!("Inline {:?} into {}", callee_body.span, callsite.callee)
+            format!("Inline {:?} into {:?}", callsite.callee, caller_body.source)
         }) {
             return Err("optimization fuel exhausted");
         }
diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs
index 953c6915068af..c7d080a80fe6f 100644
--- a/compiler/rustc_parse/src/parser/path.rs
+++ b/compiler/rustc_parse/src/parser/path.rs
@@ -495,20 +495,28 @@ impl<'a> Parser<'a> {
             None => {
                 let after_eq = eq.shrink_to_hi();
                 let before_next = self.token.span.shrink_to_lo();
-                self.struct_span_err(after_eq.to(before_next), "missing type to the right of `=`")
-                    .span_suggestion(
+                let mut err = self
+                    .struct_span_err(after_eq.to(before_next), "missing type to the right of `=`");
+                if matches!(self.token.kind, token::Comma | token::Gt) {
+                    err.span_suggestion(
                         self.sess.source_map().next_point(eq).to(before_next),
                         "to constrain the associated type, add a type after `=`",
                         " TheType".to_string(),
                         Applicability::HasPlaceholders,
-                    )
-                    .span_suggestion(
+                    );
+                    err.span_suggestion(
                         eq.to(before_next),
                         &format!("remove the `=` if `{}` is a type", ident),
                         String::new(),
                         Applicability::MaybeIncorrect,
                     )
-                    .emit();
+                } else {
+                    err.span_label(
+                        self.token.span,
+                        &format!("expected type, found {}", super::token_descr(&self.token)),
+                    )
+                };
+                return Err(err);
             }
         }
         Ok(self.mk_ty(span, ast::TyKind::Err))
@@ -572,6 +580,25 @@ impl<'a> Parser<'a> {
                     return self.recover_const_arg(start, err).map(Some);
                 }
             }
+        } else if self.eat_keyword_noexpect(kw::Const) {
+            // Detect and recover from the old, pre-RFC2000 syntax for const generics.
+            let mut err = self.struct_span_err(
+                start,
+                "expected lifetime, type, or constant, found keyword `const`",
+            );
+            if self.check_const_arg() {
+                err.span_suggestion_verbose(
+                    start.until(self.token.span),
+                    "the `const` keyword is only needed in the definition of the type",
+                    String::new(),
+                    Applicability::MaybeIncorrect,
+                );
+                err.emit();
+                GenericArg::Const(self.parse_const_arg()?)
+            } else {
+                let after_kw_const = self.token.span;
+                return self.recover_const_arg(after_kw_const, err).map(Some);
+            }
         } else {
             return Ok(None);
         };
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 8110afe75fa92..8ecb7a031ad81 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -1246,6 +1246,8 @@ options! {
         "enable queries of the dependency graph for regression testing (default: no)"),
     query_stats: bool = (false, parse_bool, [UNTRACKED],
         "print some statistics about the query system (default: no)"),
+    randomize_layout: bool = (false, parse_bool, [TRACKED],
+        "randomize the layout of types (default: no)"),
     relax_elf_relocations: Option<bool> = (None, parse_opt_bool, [TRACKED],
         "whether ELF relocations can be relaxed"),
     relro_level: Option<RelroLevel> = (None, parse_relro_level, [TRACKED],
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 87f9190114109..fbcc3bf2c4815 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -162,9 +162,6 @@ pub struct Session {
     /// Data about code being compiled, gathered during compilation.
     pub code_stats: CodeStats,
 
-    /// If `-zfuel=crate=n` is specified, `Some(crate)`.
-    optimization_fuel_crate: Option<String>,
-
     /// Tracks fuel info if `-zfuel=crate=n` is specified.
     optimization_fuel: Lock<OptimizationFuel>,
 
@@ -882,7 +879,7 @@ impl Session {
     /// This expends fuel if applicable, and records fuel if applicable.
     pub fn consider_optimizing<T: Fn() -> String>(&self, crate_name: &str, msg: T) -> bool {
         let mut ret = true;
-        if let Some(ref c) = self.optimization_fuel_crate {
+        if let Some((ref c, _)) = self.opts.debugging_opts.fuel {
             if c == crate_name {
                 assert_eq!(self.threads(), 1);
                 let mut fuel = self.optimization_fuel.lock();
@@ -1260,7 +1257,6 @@ pub fn build_session(
     let local_crate_source_file =
         local_crate_source_file.map(|path| file_path_mapping.map_prefix(path).0);
 
-    let optimization_fuel_crate = sopts.debugging_opts.fuel.as_ref().map(|i| i.0.clone());
     let optimization_fuel = Lock::new(OptimizationFuel {
         remaining: sopts.debugging_opts.fuel.as_ref().map_or(0, |i| i.1),
         out_of_fuel: false,
@@ -1311,7 +1307,6 @@ pub fn build_session(
             normalize_projection_ty: AtomicUsize::new(0),
         },
         code_stats: Default::default(),
-        optimization_fuel_crate,
         optimization_fuel,
         print_fuel,
         jobserver: jobserver::client(),
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index d18e5823cb80c..5276da1ba5a1c 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -288,6 +288,7 @@ impl ToJson for MergeFunctions {
 pub enum RelocModel {
     Static,
     Pic,
+    Pie,
     DynamicNoPic,
     Ropi,
     Rwpi,
@@ -301,6 +302,7 @@ impl FromStr for RelocModel {
         Ok(match s {
             "static" => RelocModel::Static,
             "pic" => RelocModel::Pic,
+            "pie" => RelocModel::Pie,
             "dynamic-no-pic" => RelocModel::DynamicNoPic,
             "ropi" => RelocModel::Ropi,
             "rwpi" => RelocModel::Rwpi,
@@ -315,6 +317,7 @@ impl ToJson for RelocModel {
         match *self {
             RelocModel::Static => "static",
             RelocModel::Pic => "pic",
+            RelocModel::Pie => "pie",
             RelocModel::DynamicNoPic => "dynamic-no-pic",
             RelocModel::Ropi => "ropi",
             RelocModel::Rwpi => "rwpi",
diff --git a/compiler/rustc_typeck/src/astconv/generics.rs b/compiler/rustc_typeck/src/astconv/generics.rs
index 27d76a6935904..456d3fe7b2f6a 100644
--- a/compiler/rustc_typeck/src/astconv/generics.rs
+++ b/compiler/rustc_typeck/src/astconv/generics.rs
@@ -600,7 +600,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     def_id,
                 )
                 .diagnostic()
-                .emit();
+                .emit_unless(gen_args.has_err());
 
                 false
             };
diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md
index 05384117ac175..4f8c4c66f8891 100644
--- a/src/doc/rustc/src/codegen-options/index.md
+++ b/src/doc/rustc/src/codegen-options/index.md
@@ -435,6 +435,10 @@ Equivalent to the "uppercase" `-fPIC` or `-fPIE` options in other compilers,
 depending on the produced crate types.  \
 This is the default model for majority of supported targets.
 
+- `pie` - position independent executable, relocatable code but without support for symbol
+interpositioning (replacing symbols by name using `LD_PRELOAD` and similar). Equivalent to the "uppercase" `-fPIE` option in other compilers. `pie`
+code cannot be linked into shared libraries (you'll get a linking error on attempt to do this).
+
 #### Special relocation models
 
 - `dynamic-no-pic` - relocatable external references, non-relocatable code.  \
diff --git a/src/test/assembly/pic-relocation-model.rs b/src/test/assembly/pic-relocation-model.rs
new file mode 100644
index 0000000000000..72471ffcdb0cb
--- /dev/null
+++ b/src/test/assembly/pic-relocation-model.rs
@@ -0,0 +1,35 @@
+// revisions: x64
+// assembly-output: emit-asm
+// [x64] compile-flags: --target x86_64-unknown-linux-gnu -Crelocation-model=pic
+// [x64] needs-llvm-components: x86
+
+
+#![feature(no_core, lang_items)]
+#![no_core]
+#![crate_type="rlib"]
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+// CHECK-LABEL: call_other_fn:
+// CHECK:       {{(jmpq|callq)}} *other_fn@GOTPCREL(%rip)
+#[no_mangle]
+pub fn call_other_fn() -> u8 {
+    unsafe {
+        other_fn()
+    }
+}
+
+// CHECK-LABEL: other_fn:
+// CHECK:       callq *foreign_fn@GOTPCREL(%rip)
+#[no_mangle]
+#[inline(never)]
+pub fn other_fn() -> u8 {
+    unsafe {
+        foreign_fn()
+    }
+}
+
+extern "C" {fn foreign_fn() -> u8;}
diff --git a/src/test/assembly/pie-relocation-model.rs b/src/test/assembly/pie-relocation-model.rs
new file mode 100644
index 0000000000000..e40797e038d4b
--- /dev/null
+++ b/src/test/assembly/pie-relocation-model.rs
@@ -0,0 +1,38 @@
+// revisions: x64
+// assembly-output: emit-asm
+// [x64] compile-flags: --target x86_64-unknown-linux-gnu -Crelocation-model=pie
+// [x64] needs-llvm-components: x86
+
+
+#![feature(no_core, lang_items)]
+#![no_core]
+#![crate_type="rlib"]
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+// CHECK-LABEL: call_other_fn:
+// With PIE local functions are called "directly".
+// CHECK:       {{(jmp|callq)}} other_fn
+#[no_mangle]
+pub fn call_other_fn() -> u8 {
+    unsafe {
+        other_fn()
+    }
+}
+
+// CHECK-LABEL: other_fn:
+// External functions are still called through GOT, since we don't know if the symbol
+// is defined in the binary or in the shared library.
+// CHECK:       callq *foreign_fn@GOTPCREL(%rip)
+#[no_mangle]
+#[inline(never)]
+pub fn other_fn() -> u8 {
+    unsafe {
+        foreign_fn()
+    }
+}
+
+extern "C" {fn foreign_fn() -> u8;}
diff --git a/src/test/codegen/pic-relocation-model.rs b/src/test/codegen/pic-relocation-model.rs
new file mode 100644
index 0000000000000..6e1d5a6c3f271
--- /dev/null
+++ b/src/test/codegen/pic-relocation-model.rs
@@ -0,0 +1,16 @@
+// compile-flags: -C relocation-model=pic
+
+#![crate_type = "rlib"]
+
+// CHECK: define i8 @call_foreign_fn()
+#[no_mangle]
+pub fn call_foreign_fn() -> u8 {
+    unsafe {
+        foreign_fn()
+    }
+}
+
+// CHECK: declare zeroext i8 @foreign_fn()
+extern "C" {fn foreign_fn() -> u8;}
+
+// CHECK: !{i32 7, !"PIC Level", i32 2}
diff --git a/src/test/codegen/pie-relocation-model.rs b/src/test/codegen/pie-relocation-model.rs
new file mode 100644
index 0000000000000..a843202a94f82
--- /dev/null
+++ b/src/test/codegen/pie-relocation-model.rs
@@ -0,0 +1,22 @@
+// compile-flags: -C relocation-model=pie
+// only-x86_64-unknown-linux-gnu
+
+#![crate_type = "rlib"]
+
+// With PIE we know local functions cannot be interpositioned, we can mark them
+// as dso_local.
+// CHECK: define dso_local i8 @call_foreign_fn()
+#[no_mangle]
+pub fn call_foreign_fn() -> u8 {
+    unsafe {
+        foreign_fn()
+    }
+}
+
+// External functions are still marked as non-dso_local, since we don't know if the symbol
+// is defined in the binary or in the shared library.
+// CHECK: declare zeroext i8 @foreign_fn()
+extern "C" {fn foreign_fn() -> u8;}
+
+// CHECK: !{i32 7, !"PIC Level", i32 2}
+// CHECK: !{i32 7, !"PIE Level", i32 2}
diff --git a/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-assoc.rs b/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-assoc.rs
new file mode 100644
index 0000000000000..99d8e9dea910d
--- /dev/null
+++ b/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-assoc.rs
@@ -0,0 +1,16 @@
+trait Foo<const N: usize> {
+    fn do_x(&self) -> [u8; N];
+}
+
+struct Bar;
+
+const T: usize = 42;
+
+impl Foo<const 3> for Bar {
+//~^ERROR expected lifetime, type, or constant, found keyword `const`
+    fn do_x(&self) -> [u8; 3] {
+        [0u8; 3]
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-assoc.stderr b/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-assoc.stderr
new file mode 100644
index 0000000000000..ddddd86ab9c06
--- /dev/null
+++ b/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-assoc.stderr
@@ -0,0 +1,14 @@
+error: expected lifetime, type, or constant, found keyword `const`
+  --> $DIR/issue-89013-no-assoc.rs:9:10
+   |
+LL | impl Foo<const 3> for Bar {
+   |          ^^^^^
+   |
+help: the `const` keyword is only needed in the definition of the type
+   |
+LL - impl Foo<const 3> for Bar {
+LL + impl Foo<3> for Bar {
+   | 
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-kw.rs b/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-kw.rs
new file mode 100644
index 0000000000000..19e0f38d320c4
--- /dev/null
+++ b/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-kw.rs
@@ -0,0 +1,17 @@
+trait Foo<const N: usize> {
+    fn do_x(&self) -> [u8; N];
+}
+
+struct Bar;
+
+const T: usize = 42;
+
+impl Foo<N = 3> for Bar {
+//~^ ERROR cannot constrain an associated constant to a value
+//~| ERROR associated type bindings are not allowed here
+    fn do_x(&self) -> [u8; 3] {
+        [0u8; 3]
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr b/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr
new file mode 100644
index 0000000000000..bbca92ad63a91
--- /dev/null
+++ b/src/test/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr
@@ -0,0 +1,18 @@
+error: cannot constrain an associated constant to a value
+  --> $DIR/issue-89013-no-kw.rs:9:10
+   |
+LL | impl Foo<N = 3> for Bar {
+   |          -^^^-
+   |          |   |
+   |          |   ...cannot be constrained to this value
+   |          this associated constant...
+
+error[E0229]: associated type bindings are not allowed here
+  --> $DIR/issue-89013-no-kw.rs:9:10
+   |
+LL | impl Foo<N = 3> for Bar {
+   |          ^^^^^ associated type not allowed here
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0229`.
diff --git a/src/test/ui/const-generics/parser-error-recovery/issue-89013-type.rs b/src/test/ui/const-generics/parser-error-recovery/issue-89013-type.rs
new file mode 100644
index 0000000000000..0ec6762b6e282
--- /dev/null
+++ b/src/test/ui/const-generics/parser-error-recovery/issue-89013-type.rs
@@ -0,0 +1,16 @@
+trait Foo<const N: usize> {
+    fn do_x(&self) -> [u8; N];
+}
+
+struct Bar;
+
+const T: usize = 42;
+
+impl Foo<N = type 3> for Bar {
+//~^ERROR missing type to the right of `=`
+    fn do_x(&self) -> [u8; 3] {
+        [0u8; 3]
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/parser-error-recovery/issue-89013-type.stderr b/src/test/ui/const-generics/parser-error-recovery/issue-89013-type.stderr
new file mode 100644
index 0000000000000..f0d0d90c774f8
--- /dev/null
+++ b/src/test/ui/const-generics/parser-error-recovery/issue-89013-type.stderr
@@ -0,0 +1,8 @@
+error: missing type to the right of `=`
+  --> $DIR/issue-89013-type.rs:9:13
+   |
+LL | impl Foo<N = type 3> for Bar {
+   |             ^---- expected type, found keyword `type`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/const-generics/parser-error-recovery/issue-89013.rs b/src/test/ui/const-generics/parser-error-recovery/issue-89013.rs
new file mode 100644
index 0000000000000..ca1158a2f6d16
--- /dev/null
+++ b/src/test/ui/const-generics/parser-error-recovery/issue-89013.rs
@@ -0,0 +1,18 @@
+trait Foo<const N: usize> {
+    fn do_x(&self) -> [u8; N];
+}
+
+struct Bar;
+
+const T: usize = 42;
+
+impl Foo<N = const 3> for Bar {
+//~^ ERROR expected lifetime, type, or constant, found keyword `const`
+//~| ERROR cannot constrain an associated constant to a value
+//~| ERROR associated type bindings are not allowed here
+    fn do_x(&self) -> [u8; 3] {
+        [0u8; 3]
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/parser-error-recovery/issue-89013.stderr b/src/test/ui/const-generics/parser-error-recovery/issue-89013.stderr
new file mode 100644
index 0000000000000..85379d3f06e4b
--- /dev/null
+++ b/src/test/ui/const-generics/parser-error-recovery/issue-89013.stderr
@@ -0,0 +1,30 @@
+error: expected lifetime, type, or constant, found keyword `const`
+  --> $DIR/issue-89013.rs:9:14
+   |
+LL | impl Foo<N = const 3> for Bar {
+   |              ^^^^^
+   |
+help: the `const` keyword is only needed in the definition of the type
+   |
+LL - impl Foo<N = const 3> for Bar {
+LL + impl Foo<N = 3> for Bar {
+   | 
+
+error: cannot constrain an associated constant to a value
+  --> $DIR/issue-89013.rs:9:10
+   |
+LL | impl Foo<N = const 3> for Bar {
+   |          -^^^^^^^^^-
+   |          |         |
+   |          |         ...cannot be constrained to this value
+   |          this associated constant...
+
+error[E0229]: associated type bindings are not allowed here
+  --> $DIR/issue-89013.rs:9:10
+   |
+LL | impl Foo<N = const 3> for Bar {
+   |          ^^^^^^^^^^^ associated type not allowed here
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0229`.
diff --git a/src/test/ui/fmt/issue-89173.rs b/src/test/ui/fmt/issue-89173.rs
new file mode 100644
index 0000000000000..96277d4d0d9d7
--- /dev/null
+++ b/src/test/ui/fmt/issue-89173.rs
@@ -0,0 +1,14 @@
+// Regression test for #89173: Make sure a helpful note is issued for
+// printf-style format strings using `*` to specify the width.
+
+fn main() {
+    let num = 0x0abcde;
+    let width = 6;
+    print!("%0*x", width, num);
+    //~^ ERROR: multiple unused formatting arguments
+    //~| NOTE: multiple missing formatting specifiers
+    //~| NOTE: argument never used
+    //~| NOTE: argument never used
+    //~| NOTE: format specifiers use curly braces, and you have to use a positional or named parameter for the width
+    //~| NOTE: printf formatting not supported
+}
diff --git a/src/test/ui/fmt/issue-89173.stderr b/src/test/ui/fmt/issue-89173.stderr
new file mode 100644
index 0000000000000..7b21e0a4fc896
--- /dev/null
+++ b/src/test/ui/fmt/issue-89173.stderr
@@ -0,0 +1,18 @@
+error: multiple unused formatting arguments
+  --> $DIR/issue-89173.rs:7:20
+   |
+LL |     print!("%0*x", width, num);
+   |            ------  ^^^^^  ^^^ argument never used
+   |            |       |
+   |            |       argument never used
+   |            multiple missing formatting specifiers
+   |
+note: format specifiers use curly braces, and you have to use a positional or named parameter for the width
+  --> $DIR/issue-89173.rs:7:13
+   |
+LL |     print!("%0*x", width, num);
+   |             ^^^^
+   = note: printf formatting not supported; see the documentation for `std::fmt`
+
+error: aborting due to previous error
+
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index 60703384e9e85..c1719a9ffe80c 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -167,6 +167,7 @@ const PERMITTED_DEPENDENCIES: &[&str] = &[
     "rand_hc",
     "rand_pcg",
     "rand_xorshift",
+    "rand_xoshiro",
     "redox_syscall",
     "regex",
     "regex-automata",