diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs
index 2704cb8d78538..c8f1e1dbb0151 100644
--- a/compiler/rustc_attr/src/builtin.rs
+++ b/compiler/rustc_attr/src/builtin.rs
@@ -454,6 +454,15 @@ pub fn find_crate_name(sess: &Session, attrs: &[Attribute]) -> Option<Symbol> {
     sess.first_attr_value_str_by_name(attrs, sym::crate_name)
 }
 
+#[derive(Clone, Debug)]
+pub struct Condition {
+    pub name: Symbol,
+    pub name_span: Span,
+    pub value: Option<Symbol>,
+    pub value_span: Option<Span>,
+    pub span: Span,
+}
+
 /// Tests if a cfg-pattern matches the cfg set
 pub fn cfg_matches(
     cfg: &ast::MetaItem,
@@ -462,70 +471,42 @@ pub fn cfg_matches(
     features: Option<&Features>,
 ) -> bool {
     eval_condition(cfg, sess, features, &mut |cfg| {
-        try_gate_cfg(cfg, sess, features);
-        let error = |span, msg| {
-            sess.span_diagnostic.span_err(span, msg);
-            true
-        };
-        if cfg.path.segments.len() != 1 {
-            return error(cfg.path.span, "`cfg` predicate key must be an identifier");
-        }
-        match &cfg.kind {
-            MetaItemKind::List(..) => {
-                error(cfg.span, "unexpected parentheses after `cfg` predicate key")
-            }
-            MetaItemKind::NameValue(lit) if !lit.kind.is_str() => {
-                handle_errors(
-                    sess,
-                    lit.span,
-                    AttrError::UnsupportedLiteral(
-                        "literal in `cfg` predicate value must be a string",
-                        lit.kind.is_bytestr(),
-                    ),
+        try_gate_cfg(cfg.name, cfg.span, sess, features);
+        if let Some(names_valid) = &sess.check_config.names_valid {
+            if !names_valid.contains(&cfg.name) {
+                sess.buffer_lint_with_diagnostic(
+                    UNEXPECTED_CFGS,
+                    cfg.span,
+                    lint_node_id,
+                    "unexpected `cfg` condition name",
+                    BuiltinLintDiagnostics::UnexpectedCfg((cfg.name, cfg.name_span), None),
                 );
-                true
             }
-            MetaItemKind::NameValue(..) | MetaItemKind::Word => {
-                let ident = cfg.ident().expect("multi-segment cfg predicate");
-                let name = ident.name;
-                let value = cfg.value_str();
-                if let Some(names_valid) = &sess.check_config.names_valid {
-                    if !names_valid.contains(&name) {
-                        sess.buffer_lint_with_diagnostic(
-                            UNEXPECTED_CFGS,
-                            cfg.span,
-                            lint_node_id,
-                            "unexpected `cfg` condition name",
-                            BuiltinLintDiagnostics::UnexpectedCfg((name, ident.span), None),
-                        );
-                    }
-                }
-                if let Some(value) = value {
-                    if let Some(values) = &sess.check_config.values_valid.get(&name) {
-                        if !values.contains(&value) {
-                            sess.buffer_lint_with_diagnostic(
-                                UNEXPECTED_CFGS,
-                                cfg.span,
-                                lint_node_id,
-                                "unexpected `cfg` condition value",
-                                BuiltinLintDiagnostics::UnexpectedCfg(
-                                    (name, ident.span),
-                                    Some((value, cfg.name_value_literal_span().unwrap())),
-                                ),
-                            );
-                        }
-                    }
+        }
+        if let Some(value) = cfg.value {
+            if let Some(values) = &sess.check_config.values_valid.get(&cfg.name) {
+                if !values.contains(&value) {
+                    sess.buffer_lint_with_diagnostic(
+                        UNEXPECTED_CFGS,
+                        cfg.span,
+                        lint_node_id,
+                        "unexpected `cfg` condition value",
+                        BuiltinLintDiagnostics::UnexpectedCfg(
+                            (cfg.name, cfg.name_span),
+                            cfg.value_span.map(|vs| (value, vs)),
+                        ),
+                    );
                 }
-                sess.config.contains(&(name, value))
             }
         }
+        sess.config.contains(&(cfg.name, cfg.value))
     })
 }
 
-fn try_gate_cfg(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Features>) {
-    let gate = find_gated_cfg(|sym| cfg.has_name(sym));
+fn try_gate_cfg(name: Symbol, span: Span, sess: &ParseSess, features: Option<&Features>) {
+    let gate = find_gated_cfg(|sym| sym == name);
     if let (Some(feats), Some(gated_cfg)) = (features, gate) {
-        gate_cfg(&gated_cfg, cfg.span, sess, feats);
+        gate_cfg(&gated_cfg, span, sess, feats);
     }
 }
 
@@ -563,11 +544,11 @@ pub fn eval_condition(
     cfg: &ast::MetaItem,
     sess: &ParseSess,
     features: Option<&Features>,
-    eval: &mut impl FnMut(&ast::MetaItem) -> bool,
+    eval: &mut impl FnMut(Condition) -> bool,
 ) -> bool {
     match cfg.kind {
         ast::MetaItemKind::List(ref mis) if cfg.name_or_empty() == sym::version => {
-            try_gate_cfg(cfg, sess, features);
+            try_gate_cfg(sym::version, cfg.span, sess, features);
             let (min_version, span) = match &mis[..] {
                 [NestedMetaItem::Literal(Lit { kind: LitKind::Str(sym, ..), span, .. })] => {
                     (sym, span)
@@ -649,6 +630,25 @@ pub fn eval_condition(
 
                     !eval_condition(mis[0].meta_item().unwrap(), sess, features, eval)
                 }
+                sym::target => {
+                    if let Some(features) = features && !features.cfg_target_compact {
+                        feature_err(
+                            sess,
+                            sym::cfg_target_compact,
+                            cfg.span,
+                            &"compact `cfg(target(..))` is experimental and subject to change"
+                        ).emit();
+                    }
+
+                    mis.iter().fold(true, |res, mi| {
+                        let mut mi = mi.meta_item().unwrap().clone();
+                        if let [seg, ..] = &mut mi.path.segments[..] {
+                            seg.ident.name = Symbol::intern(&format!("target_{}", seg.ident.name));
+                        }
+
+                        res & eval_condition(&mi, sess, features, eval)
+                    })
+                }
                 _ => {
                     struct_span_err!(
                         sess.span_diagnostic,
@@ -662,7 +662,32 @@ pub fn eval_condition(
                 }
             }
         }
-        ast::MetaItemKind::Word | ast::MetaItemKind::NameValue(..) => eval(cfg),
+        ast::MetaItemKind::Word | MetaItemKind::NameValue(..) if cfg.path.segments.len() != 1 => {
+            sess.span_diagnostic
+                .span_err(cfg.path.span, "`cfg` predicate key must be an identifier");
+            true
+        }
+        MetaItemKind::NameValue(ref lit) if !lit.kind.is_str() => {
+            handle_errors(
+                sess,
+                lit.span,
+                AttrError::UnsupportedLiteral(
+                    "literal in `cfg` predicate value must be a string",
+                    lit.kind.is_bytestr(),
+                ),
+            );
+            true
+        }
+        ast::MetaItemKind::Word | ast::MetaItemKind::NameValue(..) => {
+            let ident = cfg.ident().expect("multi-segment cfg predicate");
+            eval(Condition {
+                name: ident.name,
+                name_span: ident.span,
+                value: cfg.value_str(),
+                value_span: cfg.name_value_literal_span(),
+                span: cfg.span,
+            })
+        }
     }
 }
 
diff --git a/compiler/rustc_attr/src/lib.rs b/compiler/rustc_attr/src/lib.rs
index c95c1c40a34c2..c3f9f0cf3621f 100644
--- a/compiler/rustc_attr/src/lib.rs
+++ b/compiler/rustc_attr/src/lib.rs
@@ -4,6 +4,7 @@
 //! The goal is to move the definition of `MetaItem` and things that don't need to be in `syntax`
 //! to this crate.
 
+#![feature(let_chains)]
 #![feature(let_else)]
 
 #[macro_use]
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index 1956327dfaba4..5a02661513ca7 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -319,6 +319,8 @@ declare_features! (
     (active, cfg_sanitize, "1.41.0", Some(39699), None),
     /// Allows `cfg(target_abi = "...")`.
     (active, cfg_target_abi, "1.55.0", Some(80970), None),
+    /// Allows `cfg(target(abi = "..."))`.
+    (active, cfg_target_compact, "1.63.0", Some(96901), None),
     /// Allows `cfg(target_has_atomic_load_store = "...")`.
     (active, cfg_target_has_atomic, "1.60.0", Some(94039), None),
     /// Allows `cfg(target_has_atomic_equal_alignment = "...")`.
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 1e83434b9d062..63103061c9c29 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -536,9 +536,11 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
 
     fn encode_crate_root(&mut self) -> LazyValue<CrateRoot> {
         let tcx = self.tcx;
-        let mut i = self.position();
+        let mut i = 0;
+        let preamble_bytes = self.position() - i;
 
         // Encode the crate deps
+        i = self.position();
         let crate_deps = self.encode_crate_deps();
         let dylib_dependency_formats = self.encode_dylib_dependency_formats();
         let dep_bytes = self.position() - i;
@@ -564,7 +566,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
         let native_libraries = self.encode_native_libraries();
         let native_lib_bytes = self.position() - i;
 
+        i = self.position();
         let foreign_modules = self.encode_foreign_modules();
+        let foreign_modules_bytes = self.position() - i;
 
         // Encode DefPathTable
         i = self.position();
@@ -584,6 +588,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
         i = self.position();
         let incoherent_impls = self.encode_incoherent_impls();
         let incoherent_impls_bytes = self.position() - i;
+
         // Encode MIR.
         i = self.position();
         self.encode_mir();
@@ -596,6 +601,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
         let item_bytes = self.position() - i;
 
         // Encode the allocation index
+        i = self.position();
         let interpret_alloc_index = {
             let mut interpret_alloc_index = Vec::new();
             let mut n = 0;
@@ -618,6 +624,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             }
             self.lazy_array(interpret_alloc_index)
         };
+        let interpret_alloc_index_bytes = self.position() - i;
 
         // Encode the proc macro data. This affects 'tables',
         // so we need to do this before we encode the tables
@@ -662,9 +669,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
         let source_map = self.encode_source_map();
         let source_map_bytes = self.position() - i;
 
+        i = self.position();
         let attrs = tcx.hir().krate_attrs();
         let has_default_lib_allocator = tcx.sess.contains_name(&attrs, sym::default_lib_allocator);
-
         let root = self.lazy(CrateRoot {
             name: tcx.crate_name(LOCAL_CRATE),
             extra_filename: tcx.sess.opts.cg.extra_filename.clone(),
@@ -707,9 +714,34 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             expn_hashes,
             def_path_hash_map,
         });
+        let final_bytes = self.position() - i;
 
         let total_bytes = self.position();
 
+        let computed_total_bytes = preamble_bytes
+            + dep_bytes
+            + lib_feature_bytes
+            + lang_item_bytes
+            + diagnostic_item_bytes
+            + native_lib_bytes
+            + foreign_modules_bytes
+            + def_path_table_bytes
+            + traits_bytes
+            + impls_bytes
+            + incoherent_impls_bytes
+            + mir_bytes
+            + item_bytes
+            + interpret_alloc_index_bytes
+            + proc_macro_data_bytes
+            + tables_bytes
+            + debugger_visualizers_bytes
+            + exported_symbols_bytes
+            + hygiene_bytes
+            + def_path_hash_map_bytes
+            + source_map_bytes
+            + final_bytes;
+        assert_eq!(total_bytes, computed_total_bytes);
+
         if tcx.sess.meta_stats() {
             let mut zero_bytes = 0;
             for e in self.opaque.data.iter() {
@@ -718,27 +750,41 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                 }
             }
 
-            eprintln!("metadata stats:");
-            eprintln!("                  dep bytes: {}", dep_bytes);
-            eprintln!("          lib feature bytes: {}", lib_feature_bytes);
-            eprintln!("            lang item bytes: {}", lang_item_bytes);
-            eprintln!("      diagnostic item bytes: {}", diagnostic_item_bytes);
-            eprintln!("               native bytes: {}", native_lib_bytes);
-            eprintln!(" debugger visualizers bytes: {}", debugger_visualizers_bytes);
-            eprintln!("           source_map bytes: {}", source_map_bytes);
-            eprintln!("               traits bytes: {}", traits_bytes);
-            eprintln!("                impls bytes: {}", impls_bytes);
-            eprintln!("     incoherent_impls bytes: {}", incoherent_impls_bytes);
-            eprintln!("         exp. symbols bytes: {}", exported_symbols_bytes);
-            eprintln!("       def-path table bytes: {}", def_path_table_bytes);
-            eprintln!("      def-path hashes bytes: {}", def_path_hash_map_bytes);
-            eprintln!("      proc-macro-data-bytes: {}", proc_macro_data_bytes);
-            eprintln!("                  mir bytes: {}", mir_bytes);
-            eprintln!("                 item bytes: {}", item_bytes);
-            eprintln!("                table bytes: {}", tables_bytes);
-            eprintln!("              hygiene bytes: {}", hygiene_bytes);
-            eprintln!("                 zero bytes: {}", zero_bytes);
-            eprintln!("                total bytes: {}", total_bytes);
+            let perc = |bytes| (bytes * 100) as f64 / total_bytes as f64;
+            let p = |label, bytes| {
+                eprintln!("{:>21}: {:>8} bytes ({:4.1}%)", label, bytes, perc(bytes));
+            };
+
+            eprintln!("");
+            eprintln!(
+                "{} metadata bytes, of which {} bytes ({:.1}%) are zero",
+                total_bytes,
+                zero_bytes,
+                perc(zero_bytes)
+            );
+            p("preamble", preamble_bytes);
+            p("dep", dep_bytes);
+            p("lib feature", lib_feature_bytes);
+            p("lang item", lang_item_bytes);
+            p("diagnostic item", diagnostic_item_bytes);
+            p("native lib", native_lib_bytes);
+            p("foreign modules", foreign_modules_bytes);
+            p("def-path table", def_path_table_bytes);
+            p("traits", traits_bytes);
+            p("impls", impls_bytes);
+            p("incoherent_impls", incoherent_impls_bytes);
+            p("mir", mir_bytes);
+            p("item", item_bytes);
+            p("interpret_alloc_index", interpret_alloc_index_bytes);
+            p("proc-macro-data", proc_macro_data_bytes);
+            p("tables", tables_bytes);
+            p("debugger visualizers", debugger_visualizers_bytes);
+            p("exported symbols", exported_symbols_bytes);
+            p("hygiene", hygiene_bytes);
+            p("def-path hashes", def_path_hash_map_bytes);
+            p("source_map", source_map_bytes);
+            p("final", final_bytes);
+            eprintln!("");
         }
 
         root
diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
index fb0537c543dc5..0a0c7659b086d 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
@@ -52,11 +52,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 })
             }
             ExprKind::Repeat { value, count } => {
-                let value_operand = unpack!(
-                    block =
-                        this.as_operand(block, scope, &this.thir[value], None, NeedsTemporary::No)
-                );
-                block.and(Rvalue::Repeat(value_operand, count))
+                if Some(0) == count.try_eval_usize(this.tcx, this.param_env) {
+                    this.build_zero_repeat(block, value, scope, source_info)
+                } else {
+                    let value_operand = unpack!(
+                        block = this.as_operand(
+                            block,
+                            scope,
+                            &this.thir[value],
+                            None,
+                            NeedsTemporary::No
+                        )
+                    );
+                    block.and(Rvalue::Repeat(value_operand, count))
+                }
             }
             ExprKind::Binary { op, lhs, rhs } => {
                 let lhs = unpack!(
@@ -516,6 +525,37 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
     }
 
+    fn build_zero_repeat(
+        &mut self,
+        mut block: BasicBlock,
+        value: ExprId,
+        scope: Option<region::Scope>,
+        outer_source_info: SourceInfo,
+    ) -> BlockAnd<Rvalue<'tcx>> {
+        let this = self;
+        let value = &this.thir[value];
+        let elem_ty = value.ty;
+        if let Some(Category::Constant) = Category::of(&value.kind) {
+            // Repeating a const does nothing
+        } else {
+            // For a non-const, we may need to generate an appropriate `Drop`
+            let value_operand =
+                unpack!(block = this.as_operand(block, scope, value, None, NeedsTemporary::No));
+            if let Operand::Move(to_drop) = value_operand {
+                let success = this.cfg.start_new_block();
+                this.cfg.terminate(
+                    block,
+                    outer_source_info,
+                    TerminatorKind::Drop { place: to_drop, target: success, unwind: None },
+                );
+                this.diverge_from(block);
+                block = success;
+            }
+            this.record_operands_moved(&[value_operand]);
+        }
+        block.and(Rvalue::Aggregate(Box::new(AggregateKind::Array(elem_ty)), Vec::new()))
+    }
+
     fn limit_capture_mutability(
         &mut self,
         upvar_span: Span,
diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs
index 53f9706f021ee..a5f8a5847c270 100644
--- a/compiler/rustc_mir_build/src/build/scope.rs
+++ b/compiler/rustc_mir_build/src/build/scope.rs
@@ -1033,6 +1033,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 self.cfg.block_data(start).terminator().kind,
                 TerminatorKind::Assert { .. }
                     | TerminatorKind::Call { .. }
+                    | TerminatorKind::Drop { .. }
                     | TerminatorKind::DropAndReplace { .. }
                     | TerminatorKind::FalseUnwind { .. }
                     | TerminatorKind::InlineAsm { .. }
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 37e3465694131..bb6d892138a38 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -2291,16 +2291,9 @@ impl<'a> Parser<'a> {
                         .span_label(else_span, "expected an `if` or a block after this `else`")
                         .span_suggestion(
                             cond.span.shrink_to_lo(),
-                            "add an `if` if this is the condition to an chained `if` statement after the `else`",
+                            "add an `if` if this is the condition of a chained `else if` statement",
                             "if ".to_string(),
                             Applicability::MaybeIncorrect,
-                        ).multipart_suggestion(
-                            "... otherwise, place this expression inside of a block if it is not an `if` condition",
-                            vec![
-                                (cond.span.shrink_to_lo(), "{ ".to_string()),
-                                (cond.span.shrink_to_hi(), " }".to_string()),
-                            ],
-                            Applicability::MaybeIncorrect,
                         )
                         .emit();
                     self.parse_if_after_cond(AttrVec::new(), cond.span.shrink_to_lo(), cond)?
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 5c9c16350e469..406e9a4113ef3 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -427,6 +427,7 @@ symbols! {
         cfg_panic,
         cfg_sanitize,
         cfg_target_abi,
+        cfg_target_compact,
         cfg_target_feature,
         cfg_target_has_atomic,
         cfg_target_has_atomic_equal_alignment,
@@ -1375,6 +1376,7 @@ symbols! {
         sym,
         sync,
         t32,
+        target,
         target_abi,
         target_arch,
         target_endian,
diff --git a/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs
index 7d41819819536..ed7d16f7a5419 100644
--- a/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs
+++ b/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs
@@ -89,8 +89,8 @@ impl<'tcx> OnUnimplementedDirective {
                         None,
                     )
                 })?;
-            attr::eval_condition(cond, &tcx.sess.parse_sess, Some(tcx.features()), &mut |item| {
-                if let Some(symbol) = item.value_str() && let Err(guar) = parse_value(symbol) {
+            attr::eval_condition(cond, &tcx.sess.parse_sess, Some(tcx.features()), &mut |cfg| {
+                if let Some(value) = cfg.value && let Err(guar) = parse_value(value) {
                     errored = Some(guar);
                 }
                 true
@@ -226,14 +226,12 @@ impl<'tcx> OnUnimplementedDirective {
                 condition,
                 &tcx.sess.parse_sess,
                 Some(tcx.features()),
-                &mut |c| {
-                    c.ident().map_or(false, |ident| {
-                        let value = c.value_str().map(|s| {
-                            OnUnimplementedFormatString(s).format(tcx, trait_ref, &options_map)
-                        });
+                &mut |cfg| {
+                    let value = cfg.value.map(|v| {
+                        OnUnimplementedFormatString(v).format(tcx, trait_ref, &options_map)
+                    });
 
-                        options.contains(&(ident.name, value))
-                    })
+                    options.contains(&(cfg.name, value))
                 },
             ) {
                 debug!("evaluate: skipping {:?} due to condition", command);
diff --git a/library/core/src/asserting.rs b/library/core/src/asserting.rs
new file mode 100644
index 0000000000000..212b637d34365
--- /dev/null
+++ b/library/core/src/asserting.rs
@@ -0,0 +1,109 @@
+// Contains the machinery necessary to print useful `assert!` messages. Not intended for public
+// usage, not even nightly use-cases.
+//
+// Based on https://github.com/dtolnay/case-studies/tree/master/autoref-specialization. When
+// 'specialization' is robust enough (5 years? 10 years? Never?), `Capture` can be specialized
+// to [Printable].
+
+#![allow(missing_debug_implementations)]
+#![doc(hidden)]
+#![unstable(feature = "generic_assert_internals", issue = "44838")]
+
+use crate::{
+    fmt::{Debug, Formatter},
+    marker::PhantomData,
+};
+
+// ***** TryCapture - Generic *****
+
+/// Marker used by [Capture]
+#[unstable(feature = "generic_assert_internals", issue = "44838")]
+pub struct TryCaptureWithoutDebug;
+
+/// Catches an arbitrary `E` and modifies `to` accordingly
+#[unstable(feature = "generic_assert_internals", issue = "44838")]
+pub trait TryCaptureGeneric<E, M> {
+    /// Similar to [TryCapturePrintable] but generic to any `E`.
+    fn try_capture(&self, to: &mut Capture<E, M>);
+}
+
+impl<E> TryCaptureGeneric<E, TryCaptureWithoutDebug> for &Wrapper<&E> {
+    #[inline]
+    fn try_capture(&self, _: &mut Capture<E, TryCaptureWithoutDebug>) {}
+}
+
+impl<E> Debug for Capture<E, TryCaptureWithoutDebug> {
+    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), core::fmt::Error> {
+        f.write_str("N/A")
+    }
+}
+
+// ***** TryCapture - Printable *****
+
+/// Marker used by [Capture]
+#[unstable(feature = "generic_assert_internals", issue = "44838")]
+pub struct TryCaptureWithDebug;
+
+/// Catches an arbitrary `E: Printable` and modifies `to` accordingly
+#[unstable(feature = "generic_assert_internals", issue = "44838")]
+pub trait TryCapturePrintable<E, M> {
+    /// Similar as [TryCaptureGeneric] but specialized to any `E: Printable`.
+    fn try_capture(&self, to: &mut Capture<E, M>);
+}
+
+impl<E> TryCapturePrintable<E, TryCaptureWithDebug> for Wrapper<&E>
+where
+    E: Printable,
+{
+    #[inline]
+    fn try_capture(&self, to: &mut Capture<E, TryCaptureWithDebug>) {
+        to.elem = Some(*self.0);
+    }
+}
+
+impl<E> Debug for Capture<E, TryCaptureWithDebug>
+where
+    E: Printable,
+{
+    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), core::fmt::Error> {
+        match self.elem {
+            None => f.write_str("N/A"),
+            Some(ref value) => Debug::fmt(value, f),
+        }
+    }
+}
+
+// ***** Others *****
+
+/// All possible captured `assert!` elements
+///
+/// # Types
+///
+/// * `E`: **E**lement that is going to be displayed.
+/// * `M`: **M**arker used to differentiate [Capture]s in regards to [Debug].
+#[unstable(feature = "generic_assert_internals", issue = "44838")]
+pub struct Capture<E, M> {
+    // If None, then `E` does not implements [Printable] or `E` wasn't evaluated (`assert!( ... )`
+    // short-circuited).
+    //
+    // If Some, then `E` implements [Printable] and was evaluated.
+    pub elem: Option<E>,
+    phantom: PhantomData<M>,
+}
+
+impl<M, T> Capture<M, T> {
+    #[inline]
+    pub const fn new() -> Self {
+        Self { elem: None, phantom: PhantomData }
+    }
+}
+
+/// Necessary for the implementations of `TryCapture*`
+#[unstable(feature = "generic_assert_internals", issue = "44838")]
+pub struct Wrapper<T>(pub T);
+
+/// Tells which elements can be copied and displayed
+#[unstable(feature = "generic_assert_internals", issue = "44838")]
+pub trait Printable: Copy + Debug {}
+
+impl<T> Printable for T where T: Copy + Debug {}
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 7b04e4423b782..cfcc3ffb9c092 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -310,6 +310,7 @@ pub mod ops;
 pub mod any;
 pub mod array;
 pub mod ascii;
+pub mod asserting;
 #[unstable(feature = "async_iterator", issue = "79024")]
 pub mod async_iter;
 pub mod cell;
diff --git a/library/core/tests/asserting.rs b/library/core/tests/asserting.rs
new file mode 100644
index 0000000000000..4b626ba6f2d5d
--- /dev/null
+++ b/library/core/tests/asserting.rs
@@ -0,0 +1,37 @@
+use core::asserting::{Capture, TryCaptureGeneric, TryCapturePrintable, Wrapper};
+
+macro_rules! test {
+    ($test_name:ident, $elem:expr, $captured_elem:expr, $output:literal) => {
+        #[test]
+        fn $test_name() {
+            let elem = $elem;
+            let mut capture = Capture::new();
+            assert!(capture.elem == None);
+            (&Wrapper(&elem)).try_capture(&mut capture);
+            assert!(capture.elem == $captured_elem);
+            assert_eq!(format!("{:?}", capture), $output);
+        }
+    };
+}
+
+#[derive(Debug, PartialEq)]
+struct NoCopy;
+
+#[derive(PartialEq)]
+struct NoCopyNoDebug;
+
+#[derive(Clone, Copy, PartialEq)]
+struct NoDebug;
+
+test!(
+    capture_with_non_copyable_and_non_debugabble_elem_has_correct_params,
+    NoCopyNoDebug,
+    None,
+    "N/A"
+);
+
+test!(capture_with_non_copyable_elem_has_correct_params, NoCopy, None, "N/A");
+
+test!(capture_with_non_debugabble_elem_has_correct_params, NoDebug, None, "N/A");
+
+test!(capture_with_copyable_and_debugabble_elem_has_correct_params, 1i32, Some(1i32), "1");
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index 004589bbc31cf..9ea374e1045a5 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -35,6 +35,7 @@
 #![feature(float_minimum_maximum)]
 #![feature(future_join)]
 #![feature(future_poll_fn)]
+#![feature(generic_assert_internals)]
 #![feature(array_try_from_fn)]
 #![feature(hasher_prefixfree_extras)]
 #![feature(hashmap_internals)]
@@ -104,6 +105,7 @@ mod alloc;
 mod any;
 mod array;
 mod ascii;
+mod asserting;
 mod atomic;
 mod bool;
 mod cell;
diff --git a/src/test/ui/cfg/cfg-target-compact-errors.rs b/src/test/ui/cfg/cfg-target-compact-errors.rs
new file mode 100644
index 0000000000000..bca2275b1a957
--- /dev/null
+++ b/src/test/ui/cfg/cfg-target-compact-errors.rs
@@ -0,0 +1,17 @@
+// check-fail
+
+#![feature(cfg_target_compact)]
+
+#[cfg(target(o::o))]
+//~^ ERROR `cfg` predicate key must be an identifier
+fn one() {}
+
+#[cfg(target(os = 8))]
+//~^ ERROR literal in `cfg` predicate value must be a string
+fn two() {}
+
+#[cfg(target(os = "linux", pointer(width = "64")))]
+//~^ ERROR invalid predicate `target_pointer`
+fn three() {}
+
+fn main() {}
diff --git a/src/test/ui/cfg/cfg-target-compact-errors.stderr b/src/test/ui/cfg/cfg-target-compact-errors.stderr
new file mode 100644
index 0000000000000..bb858301eb581
--- /dev/null
+++ b/src/test/ui/cfg/cfg-target-compact-errors.stderr
@@ -0,0 +1,22 @@
+error: `cfg` predicate key must be an identifier
+  --> $DIR/cfg-target-compact-errors.rs:5:14
+   |
+LL | #[cfg(target(o::o))]
+   |              ^^^^
+
+error[E0565]: literal in `cfg` predicate value must be a string
+  --> $DIR/cfg-target-compact-errors.rs:9:19
+   |
+LL | #[cfg(target(os = 8))]
+   |                   ^
+
+error[E0537]: invalid predicate `target_pointer`
+  --> $DIR/cfg-target-compact-errors.rs:13:28
+   |
+LL | #[cfg(target(os = "linux", pointer(width = "64")))]
+   |                            ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0537, E0565.
+For more information about an error, try `rustc --explain E0537`.
diff --git a/src/test/ui/cfg/cfg-target-compact.rs b/src/test/ui/cfg/cfg-target-compact.rs
new file mode 100644
index 0000000000000..dc95a80915c43
--- /dev/null
+++ b/src/test/ui/cfg/cfg-target-compact.rs
@@ -0,0 +1,10 @@
+// run-pass
+#![feature(cfg_target_compact)]
+
+#[cfg(target(os = "linux", pointer_width = "64"))]
+pub fn main() {
+}
+
+#[cfg(not(target(os = "linux", pointer_width = "64")))]
+pub fn main() {
+}
diff --git a/src/test/ui/check-cfg/compact-names.rs b/src/test/ui/check-cfg/compact-names.rs
new file mode 100644
index 0000000000000..bff8074003965
--- /dev/null
+++ b/src/test/ui/check-cfg/compact-names.rs
@@ -0,0 +1,15 @@
+// This test check that we correctly emit an warning for compact cfg
+//
+// check-pass
+// compile-flags:--check-cfg=names() -Z unstable-options
+
+#![feature(cfg_target_compact)]
+
+#[cfg(target(os = "linux", arch = "arm"))]
+pub fn expected() {}
+
+#[cfg(target(os = "linux", architecture = "arm"))]
+//~^ WARNING unexpected `cfg` condition name
+pub fn unexpected() {}
+
+fn main() {}
diff --git a/src/test/ui/check-cfg/compact-names.stderr b/src/test/ui/check-cfg/compact-names.stderr
new file mode 100644
index 0000000000000..f1fc4285a71b7
--- /dev/null
+++ b/src/test/ui/check-cfg/compact-names.stderr
@@ -0,0 +1,10 @@
+warning: unexpected `cfg` condition name
+  --> $DIR/compact-names.rs:11:28
+   |
+LL | #[cfg(target(os = "linux", architecture = "arm"))]
+   |                            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(unexpected_cfgs)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/check-cfg/compact-values.rs b/src/test/ui/check-cfg/compact-values.rs
new file mode 100644
index 0000000000000..1f17057840cca
--- /dev/null
+++ b/src/test/ui/check-cfg/compact-values.rs
@@ -0,0 +1,15 @@
+// This test check that we correctly emit an warning for compact cfg
+//
+// check-pass
+// compile-flags:--check-cfg=values() -Z unstable-options
+
+#![feature(cfg_target_compact)]
+
+#[cfg(target(os = "linux", arch = "arm"))]
+pub fn expected() {}
+
+#[cfg(target(os = "linux", arch = "X"))]
+//~^ WARNING unexpected `cfg` condition value
+pub fn unexpected() {}
+
+fn main() {}
diff --git a/src/test/ui/check-cfg/compact-values.stderr b/src/test/ui/check-cfg/compact-values.stderr
new file mode 100644
index 0000000000000..a196e1537df57
--- /dev/null
+++ b/src/test/ui/check-cfg/compact-values.stderr
@@ -0,0 +1,11 @@
+warning: unexpected `cfg` condition value
+  --> $DIR/compact-values.rs:11:28
+   |
+LL | #[cfg(target(os = "linux", arch = "X"))]
+   |                            ^^^^^^^^^^
+   |
+   = note: `#[warn(unexpected_cfgs)]` on by default
+   = note: expected values for `target_arch` are: aarch64, arm, avr, bpf, hexagon, m68k, mips, mips64, msp430, nvptx64, powerpc, powerpc64, riscv32, riscv64, s390x, sparc, sparc64, wasm32, wasm64, x86, x86_64
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/drop/repeat-drop-2.rs b/src/test/ui/drop/repeat-drop-2.rs
new file mode 100644
index 0000000000000..2e7855328ecbf
--- /dev/null
+++ b/src/test/ui/drop/repeat-drop-2.rs
@@ -0,0 +1,15 @@
+fn borrowck_catch() {
+    let foo = String::new();
+    let _bar = foo;
+    let _baz = [foo; 0]; //~ ERROR use of moved value: `foo` [E0382]
+}
+
+const _: [String; 0] = [String::new(); 0];
+//~^ ERROR destructors cannot be evaluated at compile-time [E0493]
+
+fn must_be_init() {
+    let x: u8;
+    let _ = [x; 0]; //~ ERROR: use of possibly-uninitialized variable: `x`
+}
+
+fn main() {}
diff --git a/src/test/ui/drop/repeat-drop-2.stderr b/src/test/ui/drop/repeat-drop-2.stderr
new file mode 100644
index 0000000000000..cdc58180c37b4
--- /dev/null
+++ b/src/test/ui/drop/repeat-drop-2.stderr
@@ -0,0 +1,29 @@
+error[E0382]: use of moved value: `foo`
+  --> $DIR/repeat-drop-2.rs:4:17
+   |
+LL |     let foo = String::new();
+   |         --- move occurs because `foo` has type `String`, which does not implement the `Copy` trait
+LL |     let _bar = foo;
+   |                --- value moved here
+LL |     let _baz = [foo; 0];
+   |                 ^^^ value used here after move
+
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/repeat-drop-2.rs:7:25
+   |
+LL | const _: [String; 0] = [String::new(); 0];
+   |                        -^^^^^^^^^^^^^----
+   |                        ||
+   |                        |constants cannot evaluate destructors
+   |                        value is dropped here
+
+error[E0381]: use of possibly-uninitialized variable: `x`
+  --> $DIR/repeat-drop-2.rs:12:14
+   |
+LL |     let _ = [x; 0];
+   |              ^ use of possibly-uninitialized `x`
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0381, E0382, E0493.
+For more information about an error, try `rustc --explain E0381`.
diff --git a/src/test/ui/drop/repeat-drop.rs b/src/test/ui/drop/repeat-drop.rs
new file mode 100644
index 0000000000000..03e832adb3b3b
--- /dev/null
+++ b/src/test/ui/drop/repeat-drop.rs
@@ -0,0 +1,120 @@
+// run-pass
+// ignore-wasm32-bare no unwinding panic
+// ignore-avr no unwinding panic
+// ignore-nvptx64 no unwinding panic
+
+static mut CHECK: usize = 0;
+
+struct DropChecker(usize);
+
+impl Drop for DropChecker {
+    fn drop(&mut self) {
+        unsafe {
+            if CHECK != self.0 - 1 {
+                panic!("Found {}, should have found {}", CHECK, self.0 - 1);
+            }
+            CHECK = self.0;
+        }
+    }
+}
+
+macro_rules! check_drops {
+    ($l:literal) => {
+        unsafe { assert_eq!(CHECK, $l) }
+    };
+}
+
+struct DropPanic;
+
+impl Drop for DropPanic {
+    fn drop(&mut self) {
+        panic!()
+    }
+}
+
+fn value_zero() {
+    unsafe { CHECK = 0 };
+    let foo = DropChecker(1);
+    let v: [DropChecker; 0] = [foo; 0];
+    check_drops!(1);
+    std::mem::drop(v);
+    check_drops!(1);
+}
+
+fn value_one() {
+    unsafe { CHECK = 0 };
+    let foo = DropChecker(1);
+    let v: [DropChecker; 1] = [foo; 1];
+    check_drops!(0);
+    std::mem::drop(v);
+    check_drops!(1);
+}
+
+const DROP_CHECKER: DropChecker = DropChecker(1);
+
+fn const_zero() {
+    unsafe { CHECK = 0 };
+    let v: [DropChecker; 0] = [DROP_CHECKER; 0];
+    check_drops!(0);
+    std::mem::drop(v);
+    check_drops!(0);
+}
+
+fn const_one() {
+    unsafe { CHECK = 0 };
+    let v: [DropChecker; 1] = [DROP_CHECKER; 1];
+    check_drops!(0);
+    std::mem::drop(v);
+    check_drops!(1);
+}
+
+fn const_generic_zero<const N: usize>() {
+    unsafe { CHECK = 0 };
+    let v: [DropChecker; N] = [DROP_CHECKER; N];
+    check_drops!(0);
+    std::mem::drop(v);
+    check_drops!(0);
+}
+
+fn const_generic_one<const N: usize>() {
+    unsafe { CHECK = 0 };
+    let v: [DropChecker; N] = [DROP_CHECKER; N];
+    check_drops!(0);
+    std::mem::drop(v);
+    check_drops!(1);
+}
+
+// Make sure that things are allowed to promote as expected
+
+fn allow_promote() {
+    unsafe { CHECK = 0 };
+    let foo = DropChecker(1);
+    let v: &'static [DropChecker; 0] = &[foo; 0];
+    check_drops!(1);
+    std::mem::drop(v);
+    check_drops!(1);
+}
+
+// Verify that unwinding in the drop causes the right things to drop in the right order
+fn on_unwind() {
+    unsafe { CHECK = 0 };
+    std::panic::catch_unwind(|| {
+        let panic = DropPanic;
+        let _local = DropChecker(2);
+        let _v = (DropChecker(1), [panic; 0]);
+        std::process::abort();
+    })
+    .unwrap_err();
+    check_drops!(2);
+}
+
+fn main() {
+    value_zero();
+    value_one();
+    const_zero();
+    const_one();
+    const_generic_zero::<0>();
+    const_generic_one::<1>();
+    allow_promote();
+    on_unwind();
+}
diff --git a/src/test/ui/feature-gates/feature-gate-cfg-target-compact.rs b/src/test/ui/feature-gates/feature-gate-cfg-target-compact.rs
new file mode 100644
index 0000000000000..df81b7d2297ea
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-cfg-target-compact.rs
@@ -0,0 +1,13 @@
+#[cfg(target(os = "x"))] //~ ERROR compact `cfg(target(..))` is experimental
+struct Foo(u64, u64);
+
+#[cfg_attr(target(os = "x"), x)] //~ ERROR compact `cfg(target(..))` is experimental
+struct Bar(u64, u64);
+
+#[cfg(not(any(all(target(os = "x")))))] //~ ERROR compact `cfg(target(..))` is experimental
+fn foo() {}
+
+fn main() {
+    cfg!(target(os = "x"));
+    //~^ ERROR compact `cfg(target(..))` is experimental and subject to change
+}
diff --git a/src/test/ui/feature-gates/feature-gate-cfg-target-compact.stderr b/src/test/ui/feature-gates/feature-gate-cfg-target-compact.stderr
new file mode 100644
index 0000000000000..be6fe23ded171
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-cfg-target-compact.stderr
@@ -0,0 +1,39 @@
+error[E0658]: compact `cfg(target(..))` is experimental and subject to change
+  --> $DIR/feature-gate-cfg-target-compact.rs:1:7
+   |
+LL | #[cfg(target(os = "x"))]
+   |       ^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #96901 <https://github.com/rust-lang/rust/issues/96901> for more information
+   = help: add `#![feature(cfg_target_compact)]` to the crate attributes to enable
+
+error[E0658]: compact `cfg(target(..))` is experimental and subject to change
+  --> $DIR/feature-gate-cfg-target-compact.rs:4:12
+   |
+LL | #[cfg_attr(target(os = "x"), x)]
+   |            ^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #96901 <https://github.com/rust-lang/rust/issues/96901> for more information
+   = help: add `#![feature(cfg_target_compact)]` to the crate attributes to enable
+
+error[E0658]: compact `cfg(target(..))` is experimental and subject to change
+  --> $DIR/feature-gate-cfg-target-compact.rs:7:19
+   |
+LL | #[cfg(not(any(all(target(os = "x")))))]
+   |                   ^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #96901 <https://github.com/rust-lang/rust/issues/96901> for more information
+   = help: add `#![feature(cfg_target_compact)]` to the crate attributes to enable
+
+error[E0658]: compact `cfg(target(..))` is experimental and subject to change
+  --> $DIR/feature-gate-cfg-target-compact.rs:11:10
+   |
+LL |     cfg!(target(os = "x"));
+   |          ^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #96901 <https://github.com/rust-lang/rust/issues/96901> for more information
+   = help: add `#![feature(cfg_target_compact)]` to the crate attributes to enable
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/parser/else-no-if.stderr b/src/test/ui/parser/else-no-if.stderr
index 27abbadd7ad24..b9c1a75276c1f 100644
--- a/src/test/ui/parser/else-no-if.stderr
+++ b/src/test/ui/parser/else-no-if.stderr
@@ -6,14 +6,10 @@ LL |     } else false {
    |       |
    |       expected an `if` or a block after this `else`
    |
-help: add an `if` if this is the condition to an chained `if` statement after the `else`
+help: add an `if` if this is the condition of a chained `else if` statement
    |
 LL |     } else if false {
    |            ++
-help: ... otherwise, place this expression inside of a block if it is not an `if` condition
-   |
-LL |     } else { false } {
-   |            +       +
 
 error: expected `{`, found `falsy`
   --> $DIR/else-no-if.rs:10:12
@@ -23,14 +19,10 @@ LL |     } else falsy() {
    |       |
    |       expected an `if` or a block after this `else`
    |
-help: add an `if` if this is the condition to an chained `if` statement after the `else`
+help: add an `if` if this is the condition of a chained `else if` statement
    |
 LL |     } else if falsy() {
    |            ++
-help: ... otherwise, place this expression inside of a block if it is not an `if` condition
-   |
-LL |     } else { falsy() } {
-   |            +         +
 
 error: expected `{`, found `falsy`
   --> $DIR/else-no-if.rs:17:12