about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-09-17 10:56:42 +0000
committerbors <bors@rust-lang.org>2022-09-17 10:56:42 +0000
commit672831a5c890f51d3222511ab2575ca7a86c8e20 (patch)
treefa6f0d0797bb75d188725c2a027d8f0d6475f2c2
parentb195f5349a5f7b01369e7bba2f9fff250e62d36d (diff)
parent80cceb8f7705b9809c726cd6d8dda93451d32cc6 (diff)
downloadrust-672831a5c890f51d3222511ab2575ca7a86c8e20.tar.gz
rust-672831a5c890f51d3222511ab2575ca7a86c8e20.zip
Auto merge of #101938 - Dylan-DPC:rollup-6vlohhs, r=Dylan-DPC
Rollup of 6 pull requests

Successful merges:

 - #93628 (Stabilize `let else`)
 - #98441 (Implement simd_as for pointers)
 - #101790 (Do not suggest a placeholder to const and static without a type)
 - #101807 (Disallow defaults on type GATs)
 - #101915 (doc: fix redirected link in `/index.html`)
 - #101931 (doc: Fix a typo in `Rc::make_mut` docstring)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_ast/src/lib.rs2
-rw-r--r--compiler/rustc_ast_lowering/src/block.rs11
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs2
-rw-r--r--compiler/rustc_ast_passes/src/lib.rs2
-rw-r--r--compiler/rustc_attr/src/lib.rs2
-rw-r--r--compiler/rustc_borrowck/src/lib.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/lib.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/intrinsic.rs91
-rw-r--r--compiler/rustc_codegen_llvm/src/lib.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/lib.rs2
-rw-r--r--compiler/rustc_const_eval/src/lib.rs2
-rw-r--r--compiler/rustc_data_structures/src/lib.rs2
-rw-r--r--compiler/rustc_driver/src/lib.rs2
-rw-r--r--compiler/rustc_errors/src/lib.rs6
-rw-r--r--compiler/rustc_expand/src/lib.rs2
-rw-r--r--compiler/rustc_feature/src/accepted.rs2
-rw-r--r--compiler/rustc_feature/src/active.rs2
-rw-r--r--compiler/rustc_hir/src/lib.rs2
-rw-r--r--compiler/rustc_incremental/src/lib.rs2
-rw-r--r--compiler/rustc_index/src/lib.rs2
-rw-r--r--compiler/rustc_infer/src/lib.rs2
-rw-r--r--compiler/rustc_interface/src/lib.rs2
-rw-r--r--compiler/rustc_lint/src/lib.rs2
-rw-r--r--compiler/rustc_macros/src/lib.rs2
-rw-r--r--compiler/rustc_metadata/src/lib.rs2
-rw-r--r--compiler/rustc_middle/src/lib.rs2
-rw-r--r--compiler/rustc_mir_build/src/lib.rs2
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/check_match.rs4
-rw-r--r--compiler/rustc_mir_dataflow/src/lib.rs2
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs2
-rw-r--r--compiler/rustc_monomorphize/src/lib.rs2
-rw-r--r--compiler/rustc_parse/src/lib.rs2
-rw-r--r--compiler/rustc_passes/src/lib.rs2
-rw-r--r--compiler/rustc_privacy/src/lib.rs2
-rw-r--r--compiler/rustc_query_system/src/lib.rs2
-rw-r--r--compiler/rustc_resolve/src/lib.rs2
-rw-r--r--compiler/rustc_save_analysis/src/lib.rs2
-rw-r--r--compiler/rustc_serialize/src/lib.rs2
-rw-r--r--compiler/rustc_session/src/lib.rs2
-rw-r--r--compiler/rustc_span/src/lib.rs2
-rw-r--r--compiler/rustc_span/src/symbol.rs3
-rw-r--r--compiler/rustc_target/src/lib.rs2
-rw-r--r--compiler/rustc_trait_selection/src/lib.rs2
-rw-r--r--compiler/rustc_traits/src/lib.rs2
-rw-r--r--compiler/rustc_ty_utils/src/lib.rs2
-rw-r--r--compiler/rustc_typeck/src/check/intrinsic.rs6
-rw-r--r--compiler/rustc_typeck/src/collect.rs69
-rw-r--r--compiler/rustc_typeck/src/lib.rs2
-rw-r--r--library/alloc/src/lib.rs2
-rw-r--r--library/alloc/src/rc.rs2
-rw-r--r--library/std/src/lib.rs2
-rw-r--r--src/doc/index.md2
-rw-r--r--src/librustdoc/lib.rs2
-rw-r--r--src/test/ui/async-await/async-await-let-else.rs2
-rw-r--r--src/test/ui/empty/empty-never-array.stderr2
-rw-r--r--src/test/ui/error-codes/E0005.stderr2
-rw-r--r--src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr2
-rw-r--r--src/test/ui/feature-gates/feature-gate-let_else.rs5
-rw-r--r--src/test/ui/feature-gates/feature-gate-let_else.stderr14
-rw-r--r--src/test/ui/generic-associated-types/type-param-defaults.rs34
-rw-r--r--src/test/ui/generic-associated-types/type-param-defaults.stderr20
-rw-r--r--src/test/ui/let-else/issue-100103.rs2
-rw-r--r--src/test/ui/let-else/issue-94176.rs2
-rw-r--r--src/test/ui/let-else/issue-99975.rs2
-rw-r--r--src/test/ui/let-else/let-else-allow-in-expr.rs2
-rw-r--r--src/test/ui/let-else/let-else-allow-in-expr.stderr6
-rw-r--r--src/test/ui/let-else/let-else-allow-unused.rs2
-rw-r--r--src/test/ui/let-else/let-else-binding-explicit-mut-annotated.rs2
-rw-r--r--src/test/ui/let-else/let-else-binding-explicit-mut-borrow.rs4
-rw-r--r--src/test/ui/let-else/let-else-binding-explicit-mut-pass.rs2
-rw-r--r--src/test/ui/let-else/let-else-binding-explicit-mut.rs2
-rw-r--r--src/test/ui/let-else/let-else-binding-immutable.rs2
-rw-r--r--src/test/ui/let-else/let-else-bindings.rs2
-rw-r--r--src/test/ui/let-else/let-else-bool-binop-init.fixed2
-rw-r--r--src/test/ui/let-else/let-else-bool-binop-init.rs2
-rw-r--r--src/test/ui/let-else/let-else-brace-before-else.fixed2
-rw-r--r--src/test/ui/let-else/let-else-brace-before-else.rs2
-rw-r--r--src/test/ui/let-else/let-else-check.rs2
-rw-r--r--src/test/ui/let-else/let-else-check.stderr6
-rw-r--r--src/test/ui/let-else/let-else-deref-coercion-annotated.rs2
-rw-r--r--src/test/ui/let-else/let-else-deref-coercion.rs2
-rw-r--r--src/test/ui/let-else/let-else-destructuring.rs1
-rw-r--r--src/test/ui/let-else/let-else-destructuring.stderr4
-rw-r--r--src/test/ui/let-else/let-else-drop-order.rs2
-rw-r--r--src/test/ui/let-else/let-else-if.rs2
-rw-r--r--src/test/ui/let-else/let-else-if.stderr2
-rw-r--r--src/test/ui/let-else/let-else-irrefutable.rs2
-rw-r--r--src/test/ui/let-else/let-else-missing-semicolon.rs2
-rw-r--r--src/test/ui/let-else/let-else-missing-semicolon.stderr4
-rw-r--r--src/test/ui/let-else/let-else-no-double-error.rs2
-rw-r--r--src/test/ui/let-else/let-else-non-copy.rs2
-rw-r--r--src/test/ui/let-else/let-else-non-diverging.rs2
-rw-r--r--src/test/ui/let-else/let-else-non-diverging.stderr6
-rw-r--r--src/test/ui/let-else/let-else-ref-bindings-pass.rs2
-rw-r--r--src/test/ui/let-else/let-else-ref-bindings.rs2
-rw-r--r--src/test/ui/let-else/let-else-run-pass.rs2
-rw-r--r--src/test/ui/let-else/let-else-scope.rs2
-rw-r--r--src/test/ui/let-else/let-else-scope.stderr2
-rw-r--r--src/test/ui/let-else/let-else-slicing-error.rs2
-rw-r--r--src/test/ui/let-else/let-else-source-expr-nomove-pass.rs2
-rw-r--r--src/test/ui/let-else/let-else-temp-borrowck.rs2
-rw-r--r--src/test/ui/let-else/let-else-temporary-lifetime.rs1
-rw-r--r--src/test/ui/let-else/let-else-then-diverge.rs2
-rw-r--r--src/test/ui/let-else/let-else.rs8
-rw-r--r--src/test/ui/pattern/usefulness/issue-31561.stderr2
-rw-r--r--src/test/ui/pattern/usefulness/non-exhaustive-defined-here.stderr2
-rw-r--r--src/test/ui/pattern/usefulness/top-level-alternation.rs2
-rw-r--r--src/test/ui/pattern/usefulness/top-level-alternation.stderr24
-rw-r--r--src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr2
-rw-r--r--src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.rs2
-rw-r--r--src/test/ui/simd/intrinsic/ptr-cast.rs33
-rw-r--r--src/test/ui/typeck/do-not-suggest-placeholder-to-const-static-without-type.rs8
-rw-r--r--src/test/ui/typeck/do-not-suggest-placeholder-to-const-static-without-type.stderr20
-rw-r--r--src/test/ui/uninhabited/uninhabited-irrefutable.stderr2
-rw-r--r--src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr2
-rw-r--r--src/test/ui/unpretty/pretty-let-else.rs2
-rw-r--r--src/test/ui/unpretty/pretty-let-else.stdout8
-rw-r--r--src/tools/clippy/clippy_dev/src/lib.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs2
-rw-r--r--src/tools/clippy/tests/ui/needless_return.fixed1
-rw-r--r--src/tools/clippy/tests/ui/needless_return.rs1
-rw-r--r--src/tools/clippy/tests/ui/needless_return.stderr74
-rw-r--r--src/tools/clippy/tests/ui/semicolon_if_nothing_returned.rs1
-rw-r--r--src/tools/clippy/tests/ui/semicolon_if_nothing_returned.stderr10
125 files changed, 437 insertions, 236 deletions
diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs
index 4d3620ee8b0..bd7a85b07a0 100644
--- a/compiler/rustc_ast/src/lib.rs
+++ b/compiler/rustc_ast/src/lib.rs
@@ -15,7 +15,7 @@
 #![feature(if_let_guard)]
 #![cfg_attr(bootstrap, feature(label_break_value))]
 #![feature(let_chains)]
-#![feature(let_else)]
+#![cfg_attr(bootstrap, feature(let_else))]
 #![feature(min_specialization)]
 #![feature(negative_impls)]
 #![feature(slice_internals)]
diff --git a/compiler/rustc_ast_lowering/src/block.rs b/compiler/rustc_ast_lowering/src/block.rs
index e0869bb1063..12a0cc0d255 100644
--- a/compiler/rustc_ast_lowering/src/block.rs
+++ b/compiler/rustc_ast_lowering/src/block.rs
@@ -1,8 +1,6 @@
 use crate::{ImplTraitContext, ImplTraitPosition, LoweringContext};
 use rustc_ast::{Block, BlockCheckMode, Local, LocalKind, Stmt, StmtKind};
 use rustc_hir as hir;
-use rustc_session::parse::feature_err;
-use rustc_span::sym;
 
 use smallvec::SmallVec;
 
@@ -92,15 +90,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         let hir_id = self.lower_node_id(l.id);
         let pat = self.lower_pat(&l.pat);
         let els = if let LocalKind::InitElse(_, els) = &l.kind {
-            if !self.tcx.features().let_else {
-                feature_err(
-                    &self.tcx.sess.parse_sess,
-                    sym::let_else,
-                    l.span,
-                    "`let...else` statements are unstable",
-                )
-                .emit();
-            }
             Some(self.lower_block(els, false))
         } else {
             None
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index cb6bf0863b3..d2ce6bdb08e 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -32,7 +32,7 @@
 
 #![feature(box_patterns)]
 #![feature(let_chains)]
-#![feature(let_else)]
+#![cfg_attr(bootstrap, feature(let_else))]
 #![feature(never_type)]
 #![recursion_limit = "256"]
 #![allow(rustc::potential_query_instability)]
diff --git a/compiler/rustc_ast_passes/src/lib.rs b/compiler/rustc_ast_passes/src/lib.rs
index af25982e288..8aa9d57f046 100644
--- a/compiler/rustc_ast_passes/src/lib.rs
+++ b/compiler/rustc_ast_passes/src/lib.rs
@@ -9,7 +9,7 @@
 #![feature(if_let_guard)]
 #![feature(iter_is_partitioned)]
 #![feature(let_chains)]
-#![feature(let_else)]
+#![cfg_attr(bootstrap, feature(let_else))]
 #![recursion_limit = "256"]
 
 #[macro_use]
diff --git a/compiler/rustc_attr/src/lib.rs b/compiler/rustc_attr/src/lib.rs
index 053f848aacb..52e65a9c774 100644
--- a/compiler/rustc_attr/src/lib.rs
+++ b/compiler/rustc_attr/src/lib.rs
@@ -5,7 +5,7 @@
 //! to this crate.
 
 #![feature(let_chains)]
-#![feature(let_else)]
+#![cfg_attr(bootstrap, feature(let_else))]
 #![deny(rustc::untranslatable_diagnostic)]
 #![deny(rustc::diagnostic_outside_of_impl)]
 
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index ec652f85217..86da87d0603 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -3,7 +3,7 @@
 #![allow(rustc::potential_query_instability)]
 #![feature(box_patterns)]
 #![feature(let_chains)]
-#![feature(let_else)]
+#![cfg_attr(bootstrap, feature(let_else))]
 #![feature(min_specialization)]
 #![feature(never_type)]
 #![feature(rustc_attrs)]
diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs
index 280fa704511..8aeb3b82a9c 100644
--- a/compiler/rustc_builtin_macros/src/lib.rs
+++ b/compiler/rustc_builtin_macros/src/lib.rs
@@ -9,7 +9,7 @@
 #![feature(if_let_guard)]
 #![feature(is_sorted)]
 #![feature(let_chains)]
-#![feature(let_else)]
+#![cfg_attr(bootstrap, feature(let_else))]
 #![feature(proc_macro_internals)]
 #![feature(proc_macro_quote)]
 #![recursion_limit = "256"]
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index 3d789904707..a640de42a6a 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -1705,6 +1705,97 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
     bitwise_red!(simd_reduce_all: vector_reduce_and, true);
     bitwise_red!(simd_reduce_any: vector_reduce_or, true);
 
+    if name == sym::simd_cast_ptr {
+        require_simd!(ret_ty, "return");
+        let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx());
+        require!(
+            in_len == out_len,
+            "expected return type with length {} (same as input type `{}`), \
+                  found `{}` with length {}",
+            in_len,
+            in_ty,
+            ret_ty,
+            out_len
+        );
+
+        match in_elem.kind() {
+            ty::RawPtr(p) => {
+                let (metadata, check_sized) = p.ty.ptr_metadata_ty(bx.tcx, |ty| {
+                    bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty)
+                });
+                assert!(!check_sized); // we are in codegen, so we shouldn't see these types
+                require!(metadata.is_unit(), "cannot cast fat pointer `{}`", in_elem)
+            }
+            _ => return_error!("expected pointer, got `{}`", in_elem),
+        }
+        match out_elem.kind() {
+            ty::RawPtr(p) => {
+                let (metadata, check_sized) = p.ty.ptr_metadata_ty(bx.tcx, |ty| {
+                    bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty)
+                });
+                assert!(!check_sized); // we are in codegen, so we shouldn't see these types
+                require!(metadata.is_unit(), "cannot cast to fat pointer `{}`", out_elem)
+            }
+            _ => return_error!("expected pointer, got `{}`", out_elem),
+        }
+
+        if in_elem == out_elem {
+            return Ok(args[0].immediate());
+        } else {
+            return Ok(bx.pointercast(args[0].immediate(), llret_ty));
+        }
+    }
+
+    if name == sym::simd_expose_addr {
+        require_simd!(ret_ty, "return");
+        let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx());
+        require!(
+            in_len == out_len,
+            "expected return type with length {} (same as input type `{}`), \
+                  found `{}` with length {}",
+            in_len,
+            in_ty,
+            ret_ty,
+            out_len
+        );
+
+        match in_elem.kind() {
+            ty::RawPtr(_) => {}
+            _ => return_error!("expected pointer, got `{}`", in_elem),
+        }
+        match out_elem.kind() {
+            ty::Uint(ty::UintTy::Usize) => {}
+            _ => return_error!("expected `usize`, got `{}`", out_elem),
+        }
+
+        return Ok(bx.ptrtoint(args[0].immediate(), llret_ty));
+    }
+
+    if name == sym::simd_from_exposed_addr {
+        require_simd!(ret_ty, "return");
+        let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx());
+        require!(
+            in_len == out_len,
+            "expected return type with length {} (same as input type `{}`), \
+                  found `{}` with length {}",
+            in_len,
+            in_ty,
+            ret_ty,
+            out_len
+        );
+
+        match in_elem.kind() {
+            ty::Uint(ty::UintTy::Usize) => {}
+            _ => return_error!("expected `usize`, got `{}`", in_elem),
+        }
+        match out_elem.kind() {
+            ty::RawPtr(_) => {}
+            _ => return_error!("expected pointer, got `{}`", out_elem),
+        }
+
+        return Ok(bx.inttoptr(args[0].immediate(), llret_ty));
+    }
+
     if name == sym::simd_cast || name == sym::simd_as {
         require_simd!(ret_ty, "return");
         let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx());
diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs
index 334425ae55b..42c65e04e3b 100644
--- a/compiler/rustc_codegen_llvm/src/lib.rs
+++ b/compiler/rustc_codegen_llvm/src/lib.rs
@@ -7,7 +7,7 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![feature(hash_raw_entry)]
 #![feature(let_chains)]
-#![feature(let_else)]
+#![cfg_attr(bootstrap, feature(let_else))]
 #![feature(extern_types)]
 #![feature(once_cell)]
 #![feature(iter_intersperse)]
diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs
index 4ea75dba471..e736b2aba9c 100644
--- a/compiler/rustc_codegen_ssa/src/lib.rs
+++ b/compiler/rustc_codegen_ssa/src/lib.rs
@@ -1,7 +1,7 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![feature(box_patterns)]
 #![feature(try_blocks)]
-#![feature(let_else)]
+#![cfg_attr(bootstrap, feature(let_else))]
 #![feature(once_cell)]
 #![feature(associated_type_bounds)]
 #![feature(strict_provenance)]
diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs
index 72ac6af685d..9f47d302a0c 100644
--- a/compiler/rustc_const_eval/src/lib.rs
+++ b/compiler/rustc_const_eval/src/lib.rs
@@ -10,7 +10,7 @@ Rust MIR: a lowered representation of Rust.
 #![feature(decl_macro)]
 #![feature(exact_size_is_empty)]
 #![feature(let_chains)]
-#![feature(let_else)]
+#![cfg_attr(bootstrap, feature(let_else))]
 #![feature(map_try_insert)]
 #![feature(min_specialization)]
 #![feature(slice_ptr_get)]
diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs
index a7429ed008f..56f7823efe0 100644
--- a/compiler/rustc_data_structures/src/lib.rs
+++ b/compiler/rustc_data_structures/src/lib.rs
@@ -13,7 +13,7 @@
 #![feature(cell_leak)]
 #![feature(control_flow_enum)]
 #![feature(extend_one)]
-#![feature(let_else)]
+#![cfg_attr(bootstrap, feature(let_else))]
 #![feature(hash_raw_entry)]
 #![feature(hasher_prefixfree_extras)]
 #![feature(maybe_uninit_uninit_array)]
diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs
index d6f51d7eee1..8fb9508194b 100644
--- a/compiler/rustc_driver/src/lib.rs
+++ b/compiler/rustc_driver/src/lib.rs
@@ -5,7 +5,7 @@
 //! This API is completely unstable and subject to change.
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
-#![feature(let_else)]
+#![cfg_attr(bootstrap, feature(let_else))]
 #![feature(once_cell)]
 #![recursion_limit = "256"]
 #![allow(rustc::potential_query_instability)]
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 1b24f07e689..6f969bfcc53 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -7,7 +7,7 @@
 #![feature(if_let_guard)]
 #![feature(adt_const_params)]
 #![feature(let_chains)]
-#![feature(let_else)]
+#![cfg_attr(bootstrap, feature(let_else))]
 #![feature(never_type)]
 #![feature(result_option_inspect)]
 #![feature(rustc_attrs)]
@@ -635,6 +635,10 @@ impl Handler {
         inner.steal((span, key)).map(|diag| DiagnosticBuilder::new_diagnostic(self, diag))
     }
 
+    pub fn has_stashed_diagnostic(&self, span: Span, key: StashKey) -> bool {
+        self.inner.borrow().stashed_diagnostics.get(&(span, key)).is_some()
+    }
+
     /// Emit all stashed diagnostics.
     pub fn emit_stashed_diagnostics(&self) -> Option<ErrorGuaranteed> {
         self.inner.borrow_mut().emit_stashed_diagnostics()
diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs
index ac0e200b1b7..ffc9abe64d2 100644
--- a/compiler/rustc_expand/src/lib.rs
+++ b/compiler/rustc_expand/src/lib.rs
@@ -3,7 +3,7 @@
 #![feature(associated_type_defaults)]
 #![feature(if_let_guard)]
 #![feature(let_chains)]
-#![feature(let_else)]
+#![cfg_attr(bootstrap, feature(let_else))]
 #![feature(macro_metavar_expr)]
 #![feature(proc_macro_diagnostic)]
 #![feature(proc_macro_internals)]
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
index 100000f4cd6..5f7de94e726 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -190,6 +190,8 @@ declare_features! (
     (accepted, item_like_imports, "1.15.0", Some(35120), None),
     /// Allows `'a: { break 'a; }`.
     (accepted, label_break_value, "CURRENT_RUSTC_VERSION", Some(48594), None),
+    /// Allows `let...else` statements.
+    (accepted, let_else, "CURRENT_RUSTC_VERSION", Some(87335), None),
     /// Allows `break {expr}` with a value inside `loop`s.
     (accepted, loop_break_value, "1.19.0", Some(37339), None),
     /// Allows use of `?` as the Kleene "at most one" operator in macros.
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index c28fa654a6c..ad28595ca82 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -430,8 +430,6 @@ declare_features! (
     (active, large_assignments, "1.52.0", Some(83518), None),
     /// Allows `if/while p && let q = r && ...` chains.
     (active, let_chains, "1.37.0", Some(53667), None),
-    /// Allows `let...else` statements.
-    (active, let_else, "1.56.0", Some(87335), None),
     /// Allows `#[link(..., cfg(..))]`.
     (active, link_cfg, "1.14.0", Some(37406), None),
     /// Allows using `reason` in lint attributes and the `#[expect(lint)]` lint check.
diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs
index 1b33cb9c2da..946da9265ba 100644
--- a/compiler/rustc_hir/src/lib.rs
+++ b/compiler/rustc_hir/src/lib.rs
@@ -5,7 +5,7 @@
 #![feature(associated_type_defaults)]
 #![feature(closure_track_caller)]
 #![feature(const_btree_new)]
-#![feature(let_else)]
+#![cfg_attr(bootstrap, feature(let_else))]
 #![feature(once_cell)]
 #![feature(min_specialization)]
 #![feature(never_type)]
diff --git a/compiler/rustc_incremental/src/lib.rs b/compiler/rustc_incremental/src/lib.rs
index 1e88e8091c3..2c9e21f769f 100644
--- a/compiler/rustc_incremental/src/lib.rs
+++ b/compiler/rustc_incremental/src/lib.rs
@@ -2,7 +2,7 @@
 
 #![deny(missing_docs)]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
-#![feature(let_else)]
+#![cfg_attr(bootstrap, feature(let_else))]
 #![recursion_limit = "256"]
 #![allow(rustc::potential_query_instability)]
 
diff --git a/compiler/rustc_index/src/lib.rs b/compiler/rustc_index/src/lib.rs
index aa34673de81..a00d7bd6801 100644
--- a/compiler/rustc_index/src/lib.rs
+++ b/compiler/rustc_index/src/lib.rs
@@ -3,7 +3,7 @@
 #![feature(allow_internal_unstable)]
 #![feature(bench_black_box)]
 #![feature(extend_one)]
-#![feature(let_else)]
+#![cfg_attr(bootstrap, feature(let_else))]
 #![feature(min_specialization)]
 #![feature(new_uninit)]
 #![feature(step_trait)]
diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs
index 931ebca7d01..ef60d2c9188 100644
--- a/compiler/rustc_infer/src/lib.rs
+++ b/compiler/rustc_infer/src/lib.rs
@@ -19,7 +19,7 @@
 #![feature(extend_one)]
 #![cfg_attr(bootstrap, feature(label_break_value))]
 #![feature(let_chains)]
-#![feature(let_else)]
+#![cfg_attr(bootstrap, feature(let_else))]
 #![feature(min_specialization)]
 #![feature(never_type)]
 #![feature(try_blocks)]
diff --git a/compiler/rustc_interface/src/lib.rs b/compiler/rustc_interface/src/lib.rs
index 1a8d619fafb..41cd7b0e9b1 100644
--- a/compiler/rustc_interface/src/lib.rs
+++ b/compiler/rustc_interface/src/lib.rs
@@ -1,5 +1,5 @@
 #![feature(box_patterns)]
-#![feature(let_else)]
+#![cfg_attr(bootstrap, feature(let_else))]
 #![feature(internal_output_capture)]
 #![feature(thread_spawn_unchecked)]
 #![feature(once_cell)]
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index 2a22a6e5be1..c760e435699 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -34,7 +34,7 @@
 #![feature(iter_intersperse)]
 #![feature(iter_order_by)]
 #![feature(let_chains)]
-#![feature(let_else)]
+#![cfg_attr(bootstrap, feature(let_else))]
 #![feature(min_specialization)]
 #![feature(never_type)]
 #![recursion_limit = "256"]
diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs
index 20ee5dfc727..2c027d754da 100644
--- a/compiler/rustc_macros/src/lib.rs
+++ b/compiler/rustc_macros/src/lib.rs
@@ -1,5 +1,5 @@
 #![feature(allow_internal_unstable)]
-#![feature(let_else)]
+#![cfg_attr(bootstrap, feature(let_else))]
 #![feature(never_type)]
 #![feature(proc_macro_diagnostic)]
 #![feature(proc_macro_span)]
diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs
index ba6f1e4a3a5..6f5604b7e11 100644
--- a/compiler/rustc_metadata/src/lib.rs
+++ b/compiler/rustc_metadata/src/lib.rs
@@ -5,7 +5,7 @@
 #![cfg_attr(bootstrap, feature(generic_associated_types))]
 #![feature(iter_from_generator)]
 #![feature(let_chains)]
-#![feature(let_else)]
+#![cfg_attr(bootstrap, feature(let_else))]
 #![feature(once_cell)]
 #![feature(proc_macro_internals)]
 #![feature(macro_metavar_expr)]
diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index ea08879cb53..01b9277b983 100644
--- a/compiler/rustc_middle/src/lib.rs
+++ b/compiler/rustc_middle/src/lib.rs
@@ -40,7 +40,7 @@
 #![feature(new_uninit)]
 #![feature(once_cell)]
 #![feature(let_chains)]
-#![feature(let_else)]
+#![cfg_attr(bootstrap, feature(let_else))]
 #![feature(min_specialization)]
 #![feature(trusted_len)]
 #![feature(type_alias_impl_trait)]
diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs
index 11cd2a9aa4d..0c0a2fe9c9e 100644
--- a/compiler/rustc_mir_build/src/lib.rs
+++ b/compiler/rustc_mir_build/src/lib.rs
@@ -6,7 +6,7 @@
 #![feature(control_flow_enum)]
 #![feature(if_let_guard)]
 #![feature(let_chains)]
-#![feature(let_else)]
+#![cfg_attr(bootstrap, feature(let_else))]
 #![feature(min_specialization)]
 #![feature(once_cell)]
 #![recursion_limit = "256"]
diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
index 69a8c98b27a..d45b886903b 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -491,8 +491,8 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
                     err.span_suggestion_verbose(
                         semi_span.shrink_to_lo(),
                         &format!(
-                            "alternatively, on nightly, you might want to use \
-                             `#![feature(let_else)]` to handle the variant{} that {} matched",
+                            "alternatively, you might want to use \
+                             let else to handle the variant{} that {} matched",
                             pluralize!(witnesses.len()),
                             match witnesses.len() {
                                 1 => "isn't",
diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs
index 62b712f7b8d..b45c32ee986 100644
--- a/compiler/rustc_mir_dataflow/src/lib.rs
+++ b/compiler/rustc_mir_dataflow/src/lib.rs
@@ -1,7 +1,7 @@
 #![feature(associated_type_defaults)]
 #![feature(box_patterns)]
 #![feature(exact_size_is_empty)]
-#![feature(let_else)]
+#![cfg_attr(bootstrap, feature(let_else))]
 #![feature(min_specialization)]
 #![feature(once_cell)]
 #![feature(stmt_expr_attributes)]
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index 162f7d969b1..e6fc8559571 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -1,7 +1,7 @@
 #![allow(rustc::potential_query_instability)]
 #![feature(box_patterns)]
 #![feature(let_chains)]
-#![feature(let_else)]
+#![cfg_attr(bootstrap, feature(let_else))]
 #![feature(map_try_insert)]
 #![feature(min_specialization)]
 #![feature(never_type)]
diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs
index 3afff7bcabf..ba6ce9fd40f 100644
--- a/compiler/rustc_monomorphize/src/lib.rs
+++ b/compiler/rustc_monomorphize/src/lib.rs
@@ -1,6 +1,6 @@
 #![feature(array_windows)]
 #![feature(control_flow_enum)]
-#![feature(let_else)]
+#![cfg_attr(bootstrap, feature(let_else))]
 #![recursion_limit = "256"]
 #![allow(rustc::potential_query_instability)]
 #![deny(rustc::untranslatable_diagnostic)]
diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs
index 3c88e1ef377..a37327f4294 100644
--- a/compiler/rustc_parse/src/lib.rs
+++ b/compiler/rustc_parse/src/lib.rs
@@ -4,7 +4,7 @@
 #![feature(box_patterns)]
 #![feature(if_let_guard)]
 #![feature(let_chains)]
-#![feature(let_else)]
+#![cfg_attr(bootstrap, feature(let_else))]
 #![feature(never_type)]
 #![feature(rustc_attrs)]
 #![recursion_limit = "256"]
diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs
index 7b2f83958af..39ebb8db21c 100644
--- a/compiler/rustc_passes/src/lib.rs
+++ b/compiler/rustc_passes/src/lib.rs
@@ -8,7 +8,7 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![feature(iter_intersperse)]
 #![feature(let_chains)]
-#![feature(let_else)]
+#![cfg_attr(bootstrap, feature(let_else))]
 #![feature(map_try_insert)]
 #![feature(min_specialization)]
 #![feature(try_blocks)]
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 92ef61fe64c..48ab31ab92d 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -1,7 +1,7 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![feature(associated_type_defaults)]
 #![feature(control_flow_enum)]
-#![feature(let_else)]
+#![cfg_attr(bootstrap, feature(let_else))]
 #![feature(rustc_private)]
 #![feature(try_blocks)]
 #![recursion_limit = "256"]
diff --git a/compiler/rustc_query_system/src/lib.rs b/compiler/rustc_query_system/src/lib.rs
index 8a88b5c3340..f92c3831f26 100644
--- a/compiler/rustc_query_system/src/lib.rs
+++ b/compiler/rustc_query_system/src/lib.rs
@@ -1,7 +1,7 @@
 #![feature(assert_matches)]
 #![feature(core_intrinsics)]
 #![feature(hash_raw_entry)]
-#![feature(let_else)]
+#![cfg_attr(bootstrap, feature(let_else))]
 #![feature(min_specialization)]
 #![feature(extern_types)]
 #![allow(rustc::potential_query_instability)]
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 749a78a7552..54a7f416ce6 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -12,7 +12,7 @@
 #![feature(if_let_guard)]
 #![feature(iter_intersperse)]
 #![feature(let_chains)]
-#![feature(let_else)]
+#![cfg_attr(bootstrap, feature(let_else))]
 #![feature(never_type)]
 #![recursion_limit = "256"]
 #![allow(rustdoc::private_intra_doc_links)]
diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs
index ebe44a56449..ce03c2a8ad0 100644
--- a/compiler/rustc_save_analysis/src/lib.rs
+++ b/compiler/rustc_save_analysis/src/lib.rs
@@ -1,6 +1,6 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![feature(if_let_guard)]
-#![feature(let_else)]
+#![cfg_attr(bootstrap, feature(let_else))]
 #![recursion_limit = "256"]
 #![allow(rustc::potential_query_instability)]
 #![feature(never_type)]
diff --git a/compiler/rustc_serialize/src/lib.rs b/compiler/rustc_serialize/src/lib.rs
index 91f4cfaf5ac..fa9c7bd54c3 100644
--- a/compiler/rustc_serialize/src/lib.rs
+++ b/compiler/rustc_serialize/src/lib.rs
@@ -14,7 +14,7 @@ Core encoding and decoding interfaces.
 #![feature(min_specialization)]
 #![feature(core_intrinsics)]
 #![feature(maybe_uninit_slice)]
-#![feature(let_else)]
+#![cfg_attr(bootstrap, feature(let_else))]
 #![feature(new_uninit)]
 #![feature(allocator_api)]
 #![cfg_attr(test, feature(test))]
diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs
index b9b243f6f08..f6bab775e76 100644
--- a/compiler/rustc_session/src/lib.rs
+++ b/compiler/rustc_session/src/lib.rs
@@ -1,6 +1,6 @@
 #![feature(if_let_guard)]
 #![feature(let_chains)]
-#![feature(let_else)]
+#![cfg_attr(bootstrap, feature(let_else))]
 #![feature(min_specialization)]
 #![feature(never_type)]
 #![feature(once_cell)]
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index 26b4ebeab1b..ada3bae6150 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -15,7 +15,7 @@
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![feature(array_windows)]
-#![feature(let_else)]
+#![cfg_attr(bootstrap, feature(let_else))]
 #![feature(if_let_guard)]
 #![feature(negative_impls)]
 #![feature(min_specialization)]
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index fcc22e22cc1..ae4d1a4635b 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1322,9 +1322,11 @@ symbols! {
         simd_as,
         simd_bitmask,
         simd_cast,
+        simd_cast_ptr,
         simd_ceil,
         simd_div,
         simd_eq,
+        simd_expose_addr,
         simd_extract,
         simd_fabs,
         simd_fcos,
@@ -1340,6 +1342,7 @@ symbols! {
         simd_fmin,
         simd_fpow,
         simd_fpowi,
+        simd_from_exposed_addr,
         simd_fsin,
         simd_fsqrt,
         simd_gather,
diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs
index 9c9e297849e..a7deab9d2ef 100644
--- a/compiler/rustc_target/src/lib.rs
+++ b/compiler/rustc_target/src/lib.rs
@@ -11,7 +11,7 @@
 #![feature(assert_matches)]
 #![feature(associated_type_bounds)]
 #![feature(exhaustive_patterns)]
-#![feature(let_else)]
+#![cfg_attr(bootstrap, feature(let_else))]
 #![feature(min_specialization)]
 #![feature(never_type)]
 #![feature(rustc_attrs)]
diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs
index f039b1fca18..d35f74974fd 100644
--- a/compiler/rustc_trait_selection/src/lib.rs
+++ b/compiler/rustc_trait_selection/src/lib.rs
@@ -18,7 +18,7 @@
 #![feature(hash_drain_filter)]
 #![cfg_attr(bootstrap, feature(label_break_value))]
 #![feature(let_chains)]
-#![feature(let_else)]
+#![cfg_attr(bootstrap, feature(let_else))]
 #![feature(if_let_guard)]
 #![feature(never_type)]
 #![feature(type_alias_impl_trait)]
diff --git a/compiler/rustc_traits/src/lib.rs b/compiler/rustc_traits/src/lib.rs
index 318e76c79f1..2d39e973ed9 100644
--- a/compiler/rustc_traits/src/lib.rs
+++ b/compiler/rustc_traits/src/lib.rs
@@ -3,7 +3,7 @@
 
 #![deny(rustc::untranslatable_diagnostic)]
 #![deny(rustc::diagnostic_outside_of_impl)]
-#![feature(let_else)]
+#![cfg_attr(bootstrap, feature(let_else))]
 #![recursion_limit = "256"]
 
 #[macro_use]
diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs
index 6931b15b1ba..8524e57cb58 100644
--- a/compiler/rustc_ty_utils/src/lib.rs
+++ b/compiler/rustc_ty_utils/src/lib.rs
@@ -6,7 +6,7 @@
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![feature(control_flow_enum)]
-#![feature(let_else)]
+#![cfg_attr(bootstrap, feature(let_else))]
 #![feature(never_type)]
 #![feature(box_patterns)]
 #![recursion_limit = "256"]
diff --git a/compiler/rustc_typeck/src/check/intrinsic.rs b/compiler/rustc_typeck/src/check/intrinsic.rs
index 4fa33da50c9..c7425ff7865 100644
--- a/compiler/rustc_typeck/src/check/intrinsic.rs
+++ b/compiler/rustc_typeck/src/check/intrinsic.rs
@@ -477,7 +477,11 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>)
         sym::simd_scatter => (3, vec![param(0), param(1), param(2)], tcx.mk_unit()),
         sym::simd_insert => (2, vec![param(0), tcx.types.u32, param(1)], param(0)),
         sym::simd_extract => (2, vec![param(0), tcx.types.u32], param(1)),
-        sym::simd_cast | sym::simd_as => (2, vec![param(0)], param(1)),
+        sym::simd_cast
+        | sym::simd_as
+        | sym::simd_cast_ptr
+        | sym::simd_expose_addr
+        | sym::simd_from_exposed_addr => (2, vec![param(0)], param(1)),
         sym::simd_bitmask => (2, vec![param(0)], param(1)),
         sym::simd_select | sym::simd_select_bitmask => {
             (2, vec![param(0), param(1), param(1)], param(1))
diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs
index f9660b4a7fa..45a5eca708a 100644
--- a/compiler/rustc_typeck/src/collect.rs
+++ b/compiler/rustc_typeck/src/collect.rs
@@ -25,7 +25,7 @@ use rustc_ast::{MetaItemKind, NestedMetaItem};
 use rustc_attr::{list_contains_name, InlineAttr, InstructionSetAttr, OptimizeAttr};
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
-use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed};
+use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, StashKey};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind};
 use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
@@ -852,12 +852,14 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
             tcx.ensure().type_of(trait_item_id.def_id);
         }
 
-        hir::TraitItemKind::Const(..) => {
+        hir::TraitItemKind::Const(hir_ty, _) => {
             tcx.ensure().type_of(trait_item_id.def_id);
             // Account for `const C: _;`.
             let mut visitor = HirPlaceholderCollector::default();
             visitor.visit_trait_item(trait_item);
-            placeholder_type_error(tcx, None, visitor.0, false, None, "constant");
+            if !tcx.sess.diagnostic().has_stashed_diagnostic(hir_ty.span, StashKey::ItemNoType) {
+                placeholder_type_error(tcx, None, visitor.0, false, None, "constant");
+            }
         }
 
         hir::TraitItemKind::Type(_, Some(_)) => {
@@ -1604,6 +1606,13 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
         _ => None,
     };
 
+    enum Defaults {
+        Allowed,
+        // See #36887
+        FutureCompatDisallowed,
+        Deny,
+    }
+
     let no_generics = hir::Generics::empty();
     let ast_generics = node.generics().unwrap_or(&no_generics);
     let (opt_self, allow_defaults) = match node {
@@ -1625,17 +1634,26 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
                         },
                     });
 
-                    (opt_self, true)
+                    (opt_self, Defaults::Allowed)
                 }
                 ItemKind::TyAlias(..)
                 | ItemKind::Enum(..)
                 | ItemKind::Struct(..)
                 | ItemKind::OpaqueTy(..)
-                | ItemKind::Union(..) => (None, true),
-                _ => (None, false),
+                | ItemKind::Union(..) => (None, Defaults::Allowed),
+                _ => (None, Defaults::FutureCompatDisallowed),
             }
         }
-        _ => (None, false),
+
+        // GATs
+        Node::TraitItem(item) if matches!(item.kind, TraitItemKind::Type(..)) => {
+            (None, Defaults::Deny)
+        }
+        Node::ImplItem(item) if matches!(item.kind, ImplItemKind::TyAlias(..)) => {
+            (None, Defaults::Deny)
+        }
+
+        _ => (None, Defaults::FutureCompatDisallowed),
     };
 
     let has_self = opt_self.is_some();
@@ -1668,23 +1686,30 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
     let type_start = own_start - has_self as u32 + params.len() as u32;
     let mut i = 0;
 
+    const TYPE_DEFAULT_NOT_ALLOWED: &'static str = "defaults for type parameters are only allowed in \
+    `struct`, `enum`, `type`, or `trait` definitions";
+
     params.extend(ast_generics.params.iter().filter_map(|param| match param.kind {
         GenericParamKind::Lifetime { .. } => None,
         GenericParamKind::Type { ref default, synthetic, .. } => {
-            if !allow_defaults && default.is_some() {
-                if !tcx.features().default_type_parameter_fallback {
-                    tcx.struct_span_lint_hir(
-                        lint::builtin::INVALID_TYPE_PARAM_DEFAULT,
-                        param.hir_id,
-                        param.span,
-                        |lint| {
-                            lint.build(
-                                "defaults for type parameters are only allowed in \
-                                 `struct`, `enum`, `type`, or `trait` definitions",
-                            )
-                            .emit();
-                        },
-                    );
+            if default.is_some() {
+                match allow_defaults {
+                    Defaults::Allowed => {}
+                    Defaults::FutureCompatDisallowed
+                        if tcx.features().default_type_parameter_fallback => {}
+                    Defaults::FutureCompatDisallowed => {
+                        tcx.struct_span_lint_hir(
+                            lint::builtin::INVALID_TYPE_PARAM_DEFAULT,
+                            param.hir_id,
+                            param.span,
+                            |lint| {
+                                lint.build(TYPE_DEFAULT_NOT_ALLOWED).emit();
+                            },
+                        );
+                    }
+                    Defaults::Deny => {
+                        tcx.sess.span_err(param.span, TYPE_DEFAULT_NOT_ALLOWED);
+                    }
                 }
             }
 
@@ -1701,7 +1726,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
             Some(param_def)
         }
         GenericParamKind::Const { default, .. } => {
-            if !allow_defaults && default.is_some() {
+            if !matches!(allow_defaults, Defaults::Allowed) && default.is_some() {
                 tcx.sess.span_err(
                     param.span,
                     "defaults for const parameters are only allowed in \
diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs
index ac66819d283..b1ce972e1d6 100644
--- a/compiler/rustc_typeck/src/lib.rs
+++ b/compiler/rustc_typeck/src/lib.rs
@@ -66,7 +66,7 @@ This API is completely unstable and subject to change.
 #![feature(iter_intersperse)]
 #![cfg_attr(bootstrap, feature(label_break_value))]
 #![feature(let_chains)]
-#![feature(let_else)]
+#![cfg_attr(bootstrap, feature(let_else))]
 #![feature(min_specialization)]
 #![feature(never_type)]
 #![feature(once_cell)]
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index e5cf9033c86..8619467c2d9 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -169,7 +169,7 @@
 #![cfg_attr(not(test), feature(generator_trait))]
 #![feature(hashmap_internals)]
 #![feature(lang_items)]
-#![feature(let_else)]
+#![cfg_attr(bootstrap, feature(let_else))]
 #![feature(min_specialization)]
 #![feature(negative_impls)]
 #![feature(never_type)]
diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs
index b89b03683ba..6d247681c66 100644
--- a/library/alloc/src/rc.rs
+++ b/library/alloc/src/rc.rs
@@ -1142,7 +1142,7 @@ impl<T: Clone> Rc<T> {
     /// be cloned.
     ///
     /// See also [`get_mut`], which will fail rather than cloning the inner value
-    /// or diassociating [`Weak`] pointers.
+    /// or disassociating [`Weak`] pointers.
     ///
     /// [`clone`]: Clone::clone
     /// [`get_mut`]: Rc::get_mut
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index f13500de014..bc4f1b27c2a 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -255,7 +255,7 @@
 #![cfg_attr(bootstrap, feature(label_break_value))]
 #![feature(lang_items)]
 #![feature(let_chains)]
-#![feature(let_else)]
+#![cfg_attr(bootstrap, feature(let_else))]
 #![feature(linkage)]
 #![feature(link_cfg)]
 #![feature(min_specialization)]
diff --git a/src/doc/index.md b/src/doc/index.md
index b77790e33b7..744c7f709a6 100644
--- a/src/doc/index.md
+++ b/src/doc/index.md
@@ -101,7 +101,7 @@ accomplishing various tasks.
 
 Many of Rust's errors come with error codes, and you can request extended
 diagnostics from the compiler on those errors. You can also [read them
-here](error-index.html), if you prefer to read them that way.
+here](error_codes/index.html), if you prefer to read them that way.
 
 # Master Rust
 
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index f6c648140b8..14d695582b0 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -9,7 +9,7 @@
 #![feature(control_flow_enum)]
 #![feature(drain_filter)]
 #![feature(let_chains)]
-#![feature(let_else)]
+#![cfg_attr(bootstrap, feature(let_else))]
 #![feature(test)]
 #![feature(never_type)]
 #![feature(once_cell)]
diff --git a/src/test/ui/async-await/async-await-let-else.rs b/src/test/ui/async-await/async-await-let-else.rs
index 4b287159d13..3fb2142b9e5 100644
--- a/src/test/ui/async-await/async-await-let-else.rs
+++ b/src/test/ui/async-await/async-await-let-else.rs
@@ -2,7 +2,7 @@
 // revisions: drop-tracking no-drop-tracking
 // [drop-tracking] compile-flags: -Zdrop-tracking=yes
 // [no-drop-tracking] compile-flags: -Zdrop-tracking=no
-#![feature(let_else)]
+
 use std::rc::Rc;
 
 async fn foo(x: Option<bool>) {
diff --git a/src/test/ui/empty/empty-never-array.stderr b/src/test/ui/empty/empty-never-array.stderr
index 8c80b05ee3a..adf78274368 100644
--- a/src/test/ui/empty/empty-never-array.stderr
+++ b/src/test/ui/empty/empty-never-array.stderr
@@ -18,7 +18,7 @@ help: you might want to use `if let` to ignore the variant that isn't matched
    |
 LL |     let u = if let Helper::U(u) = Helper::T(t, []) { u } else { todo!() };
    |     ++++++++++                                     ++++++++++++++++++++++
-help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variant that isn't matched
+help: alternatively, you might want to use let else to handle the variant that isn't matched
    |
 LL |     let Helper::U(u) = Helper::T(t, []) else { todo!() };
    |                                         ++++++++++++++++
diff --git a/src/test/ui/error-codes/E0005.stderr b/src/test/ui/error-codes/E0005.stderr
index f01a77bd374..de8e6bac486 100644
--- a/src/test/ui/error-codes/E0005.stderr
+++ b/src/test/ui/error-codes/E0005.stderr
@@ -19,7 +19,7 @@ help: you might want to use `if let` to ignore the variant that isn't matched
    |
 LL |     let y = if let Some(y) = x { y } else { todo!() };
    |     ++++++++++                 ++++++++++++++++++++++
-help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variant that isn't matched
+help: alternatively, you might want to use let else to handle the variant that isn't matched
    |
 LL |     let Some(y) = x else { todo!() };
    |                     ++++++++++++++++
diff --git a/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr b/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr
index f8349391a0f..5ced344f13f 100644
--- a/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr
+++ b/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr
@@ -19,7 +19,7 @@ help: you might want to use `if let` to ignore the variant that isn't matched
    |
 LL |     let _x = if let Ok(_x) = foo() { _x } else { todo!() };
    |     +++++++++++                    +++++++++++++++++++++++
-help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variant that isn't matched
+help: alternatively, you might want to use let else to handle the variant that isn't matched
    |
 LL |     let Ok(_x) = foo() else { todo!() };
    |                        ++++++++++++++++
diff --git a/src/test/ui/feature-gates/feature-gate-let_else.rs b/src/test/ui/feature-gates/feature-gate-let_else.rs
deleted file mode 100644
index 3f04a9dabfd..00000000000
--- a/src/test/ui/feature-gates/feature-gate-let_else.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-fn main() {
-    let Some(x) = Some(1) else { //~ ERROR `let...else` statements are unstable
-        return;
-    };
-}
diff --git a/src/test/ui/feature-gates/feature-gate-let_else.stderr b/src/test/ui/feature-gates/feature-gate-let_else.stderr
deleted file mode 100644
index 86252604154..00000000000
--- a/src/test/ui/feature-gates/feature-gate-let_else.stderr
+++ /dev/null
@@ -1,14 +0,0 @@
-error[E0658]: `let...else` statements are unstable
-  --> $DIR/feature-gate-let_else.rs:2:5
-   |
-LL | /     let Some(x) = Some(1) else {
-LL | |         return;
-LL | |     };
-   | |______^
-   |
-   = note: see issue #87335 <https://github.com/rust-lang/rust/issues/87335> for more information
-   = help: add `#![feature(let_else)]` to the crate attributes to enable
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/generic-associated-types/type-param-defaults.rs b/src/test/ui/generic-associated-types/type-param-defaults.rs
new file mode 100644
index 00000000000..f034076b010
--- /dev/null
+++ b/src/test/ui/generic-associated-types/type-param-defaults.rs
@@ -0,0 +1,34 @@
+// Check that we disallow GAT param defaults, even with `invalid_type_param_default` allowed
+
+#![allow(invalid_type_param_default)]
+
+trait Trait {
+    type Assoc<T = u32>;
+    //~^ defaults for type parameters are only allowed
+}
+
+impl Trait for () {
+    type Assoc<T = u32> = u64;
+    //~^ defaults for type parameters are only allowed
+}
+
+impl Trait for u32 {
+    type Assoc<T = u32> = T;
+    //~^ defaults for type parameters are only allowed
+}
+
+trait Other {}
+impl Other for u32 {}
+
+fn foo<T>()
+where
+    T: Trait<Assoc = u32>,
+    T::Assoc: Other {
+    }
+
+fn main() {
+    // errors
+    foo::<()>();
+    // works
+    foo::<u32>();
+}
diff --git a/src/test/ui/generic-associated-types/type-param-defaults.stderr b/src/test/ui/generic-associated-types/type-param-defaults.stderr
new file mode 100644
index 00000000000..85ccaba0e69
--- /dev/null
+++ b/src/test/ui/generic-associated-types/type-param-defaults.stderr
@@ -0,0 +1,20 @@
+error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
+  --> $DIR/type-param-defaults.rs:6:16
+   |
+LL |     type Assoc<T = u32>;
+   |                ^^^^^^^
+
+error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
+  --> $DIR/type-param-defaults.rs:11:16
+   |
+LL |     type Assoc<T = u32> = u64;
+   |                ^^^^^^^
+
+error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
+  --> $DIR/type-param-defaults.rs:16:16
+   |
+LL |     type Assoc<T = u32> = T;
+   |                ^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/let-else/issue-100103.rs b/src/test/ui/let-else/issue-100103.rs
index e393deab764..f5f9b2f5f06 100644
--- a/src/test/ui/let-else/issue-100103.rs
+++ b/src/test/ui/let-else/issue-100103.rs
@@ -2,7 +2,7 @@
 // check-pass
 
 #![feature(try_blocks)]
-#![feature(let_else)]
+
 
 fn main() {
     let _: Result<i32, i32> = try {
diff --git a/src/test/ui/let-else/issue-94176.rs b/src/test/ui/let-else/issue-94176.rs
index e35bbd88830..f76dfc15bc1 100644
--- a/src/test/ui/let-else/issue-94176.rs
+++ b/src/test/ui/let-else/issue-94176.rs
@@ -1,6 +1,6 @@
 // Issue #94176: wrong span for the error message of a mismatched type error,
 // if the function uses a `let else` construct.
-#![feature(let_else)]
+
 
 pub fn test(a: Option<u32>) -> Option<u32> { //~ ERROR mismatched types
     let Some(_) = a else { return None; };
diff --git a/src/test/ui/let-else/issue-99975.rs b/src/test/ui/let-else/issue-99975.rs
index 80f63556194..5b164f347e7 100644
--- a/src/test/ui/let-else/issue-99975.rs
+++ b/src/test/ui/let-else/issue-99975.rs
@@ -1,7 +1,7 @@
 // run-pass
 // compile-flags: -C opt-level=3 -Zvalidate-mir
 
-#![feature(let_else)]
+
 
 fn return_result() -> Option<String> {
     Some("ok".to_string())
diff --git a/src/test/ui/let-else/let-else-allow-in-expr.rs b/src/test/ui/let-else/let-else-allow-in-expr.rs
index 39f4c9060fe..33acb6c6a29 100644
--- a/src/test/ui/let-else/let-else-allow-in-expr.rs
+++ b/src/test/ui/let-else/let-else-allow-in-expr.rs
@@ -1,5 +1,3 @@
-#![feature(let_else)]
-
 #![deny(unused_variables)]
 
 fn main() {
diff --git a/src/test/ui/let-else/let-else-allow-in-expr.stderr b/src/test/ui/let-else/let-else-allow-in-expr.stderr
index e86bcbc8500..3b2b9066c90 100644
--- a/src/test/ui/let-else/let-else-allow-in-expr.stderr
+++ b/src/test/ui/let-else/let-else-allow-in-expr.stderr
@@ -1,17 +1,17 @@
 error: unused variable: `x`
-  --> $DIR/let-else-allow-in-expr.rs:7:13
+  --> $DIR/let-else-allow-in-expr.rs:5:13
    |
 LL |         let x = 1;
    |             ^ help: if this is intentional, prefix it with an underscore: `_x`
    |
 note: the lint level is defined here
-  --> $DIR/let-else-allow-in-expr.rs:3:9
+  --> $DIR/let-else-allow-in-expr.rs:1:9
    |
 LL | #![deny(unused_variables)]
    |         ^^^^^^^^^^^^^^^^
 
 error: unused variable: `x`
-  --> $DIR/let-else-allow-in-expr.rs:29:9
+  --> $DIR/let-else-allow-in-expr.rs:27:9
    |
 LL |     let x = 1;
    |         ^ help: if this is intentional, prefix it with an underscore: `_x`
diff --git a/src/test/ui/let-else/let-else-allow-unused.rs b/src/test/ui/let-else/let-else-allow-unused.rs
index 86ebacfa7b7..bbb1c7beaf8 100644
--- a/src/test/ui/let-else/let-else-allow-unused.rs
+++ b/src/test/ui/let-else/let-else-allow-unused.rs
@@ -1,6 +1,6 @@
 // issue #89807
 
-#![feature(let_else)]
+
 
 #[deny(unused_variables)]
 
diff --git a/src/test/ui/let-else/let-else-binding-explicit-mut-annotated.rs b/src/test/ui/let-else/let-else-binding-explicit-mut-annotated.rs
index b65fa13c1de..955f33ee134 100644
--- a/src/test/ui/let-else/let-else-binding-explicit-mut-annotated.rs
+++ b/src/test/ui/let-else/let-else-binding-explicit-mut-annotated.rs
@@ -1,6 +1,6 @@
 // from rfc2005 test suite
 
-#![feature(let_else)]
+
 
 // Verify the binding mode shifts - only when no `&` are auto-dereferenced is the
 // final default binding mode mutable.
diff --git a/src/test/ui/let-else/let-else-binding-explicit-mut-borrow.rs b/src/test/ui/let-else/let-else-binding-explicit-mut-borrow.rs
index 63b35df76aa..1524d010233 100644
--- a/src/test/ui/let-else/let-else-binding-explicit-mut-borrow.rs
+++ b/src/test/ui/let-else/let-else-binding-explicit-mut-borrow.rs
@@ -1,8 +1,8 @@
-#![feature(let_else)]
-
 // Slightly different from explicit-mut-annotated -- this won't show an error until borrowck.
 // Should it show a type error instead?
 
+
+
 fn main() {
     let Some(n): &mut Option<i32> = &mut &Some(5i32) else {
         //~^ ERROR cannot borrow data in a `&` reference as mutable
diff --git a/src/test/ui/let-else/let-else-binding-explicit-mut-pass.rs b/src/test/ui/let-else/let-else-binding-explicit-mut-pass.rs
index 305be922192..b0a6264a10d 100644
--- a/src/test/ui/let-else/let-else-binding-explicit-mut-pass.rs
+++ b/src/test/ui/let-else/let-else-binding-explicit-mut-pass.rs
@@ -1,6 +1,6 @@
 // check-pass
 
-#![feature(let_else)]
+
 
 fn main() {
     let Some(n) = &mut &mut Some(5i32) else { return; };
diff --git a/src/test/ui/let-else/let-else-binding-explicit-mut.rs b/src/test/ui/let-else/let-else-binding-explicit-mut.rs
index dbe4715b1a9..a153b3af0de 100644
--- a/src/test/ui/let-else/let-else-binding-explicit-mut.rs
+++ b/src/test/ui/let-else/let-else-binding-explicit-mut.rs
@@ -1,6 +1,6 @@
 // from rfc2005 test suite
 
-#![feature(let_else)]
+
 
 // Verify the binding mode shifts - only when no `&` are auto-dereferenced is the
 // final default binding mode mutable.
diff --git a/src/test/ui/let-else/let-else-binding-immutable.rs b/src/test/ui/let-else/let-else-binding-immutable.rs
index 96de0ffe26e..ff2d9f240a0 100644
--- a/src/test/ui/let-else/let-else-binding-immutable.rs
+++ b/src/test/ui/let-else/let-else-binding-immutable.rs
@@ -1,6 +1,6 @@
 // from rfc2005 test suite
 
-#![feature(let_else)]
+
 
 pub fn main() {
     let Some(x) = &Some(3) else {
diff --git a/src/test/ui/let-else/let-else-bindings.rs b/src/test/ui/let-else/let-else-bindings.rs
index d5121e744da..7d2cad978fc 100644
--- a/src/test/ui/let-else/let-else-bindings.rs
+++ b/src/test/ui/let-else/let-else-bindings.rs
@@ -1,6 +1,6 @@
 // run-pass
 // adapted from src/test/ui/binding/if-let.rs
-#![feature(let_else)]
+
 #![allow(dead_code)]
 
 fn none() -> bool {
diff --git a/src/test/ui/let-else/let-else-bool-binop-init.fixed b/src/test/ui/let-else/let-else-bool-binop-init.fixed
index e47f7f23d7e..20e558ca909 100644
--- a/src/test/ui/let-else/let-else-bool-binop-init.fixed
+++ b/src/test/ui/let-else/let-else-bool-binop-init.fixed
@@ -1,6 +1,6 @@
 // run-rustfix
 
-#![feature(let_else)]
+
 
 fn main() {
     let true = (true && false) else { return }; //~ ERROR a `&&` expression cannot be directly assigned in `let...else`
diff --git a/src/test/ui/let-else/let-else-bool-binop-init.rs b/src/test/ui/let-else/let-else-bool-binop-init.rs
index e443fb0d6a3..f88179a940b 100644
--- a/src/test/ui/let-else/let-else-bool-binop-init.rs
+++ b/src/test/ui/let-else/let-else-bool-binop-init.rs
@@ -1,6 +1,6 @@
 // run-rustfix
 
-#![feature(let_else)]
+
 
 fn main() {
     let true = true && false else { return }; //~ ERROR a `&&` expression cannot be directly assigned in `let...else`
diff --git a/src/test/ui/let-else/let-else-brace-before-else.fixed b/src/test/ui/let-else/let-else-brace-before-else.fixed
index fb4fd77791e..a75c770ddf2 100644
--- a/src/test/ui/let-else/let-else-brace-before-else.fixed
+++ b/src/test/ui/let-else/let-else-brace-before-else.fixed
@@ -1,6 +1,6 @@
 // run-rustfix
 
-#![feature(let_else)]
+
 
 fn main() {
     let Some(1) = ({ Some(1) }) else {
diff --git a/src/test/ui/let-else/let-else-brace-before-else.rs b/src/test/ui/let-else/let-else-brace-before-else.rs
index c4c5a1ca28b..5603b946f38 100644
--- a/src/test/ui/let-else/let-else-brace-before-else.rs
+++ b/src/test/ui/let-else/let-else-brace-before-else.rs
@@ -1,6 +1,6 @@
 // run-rustfix
 
-#![feature(let_else)]
+
 
 fn main() {
     let Some(1) = { Some(1) } else {
diff --git a/src/test/ui/let-else/let-else-check.rs b/src/test/ui/let-else/let-else-check.rs
index 9e32cbef742..713fd986e97 100644
--- a/src/test/ui/let-else/let-else-check.rs
+++ b/src/test/ui/let-else/let-else-check.rs
@@ -1,5 +1,3 @@
-#![feature(let_else)]
-
 #![deny(unused_variables)]
 
 fn main() {
diff --git a/src/test/ui/let-else/let-else-check.stderr b/src/test/ui/let-else/let-else-check.stderr
index 3d647a4c05d..bdecbf708f9 100644
--- a/src/test/ui/let-else/let-else-check.stderr
+++ b/src/test/ui/let-else/let-else-check.stderr
@@ -1,17 +1,17 @@
 error: unused variable: `x`
-  --> $DIR/let-else-check.rs:14:13
+  --> $DIR/let-else-check.rs:12:13
    |
 LL |         let x = 1;
    |             ^ help: if this is intentional, prefix it with an underscore: `_x`
    |
 note: the lint level is defined here
-  --> $DIR/let-else-check.rs:3:9
+  --> $DIR/let-else-check.rs:1:9
    |
 LL | #![deny(unused_variables)]
    |         ^^^^^^^^^^^^^^^^
 
 error: unused variable: `x`
-  --> $DIR/let-else-check.rs:18:9
+  --> $DIR/let-else-check.rs:16:9
    |
 LL |     let x = 1;
    |         ^ help: if this is intentional, prefix it with an underscore: `_x`
diff --git a/src/test/ui/let-else/let-else-deref-coercion-annotated.rs b/src/test/ui/let-else/let-else-deref-coercion-annotated.rs
index 65d88a6d828..60fdf825a33 100644
--- a/src/test/ui/let-else/let-else-deref-coercion-annotated.rs
+++ b/src/test/ui/let-else/let-else-deref-coercion-annotated.rs
@@ -6,7 +6,7 @@
 // Deref/DerefMut to Bar. You can do this with an irrefutable binding, so it should work with
 // let-else too.
 
-#![feature(let_else)]
+
 use std::ops::{Deref, DerefMut};
 
 struct Foo(Bar);
diff --git a/src/test/ui/let-else/let-else-deref-coercion.rs b/src/test/ui/let-else/let-else-deref-coercion.rs
index 87489d84bbf..052a5a8c73c 100644
--- a/src/test/ui/let-else/let-else-deref-coercion.rs
+++ b/src/test/ui/let-else/let-else-deref-coercion.rs
@@ -3,7 +3,7 @@
 // We attempt to `let Bar::Present(_) = foo else { ... }` where foo is meant to Deref/DerefMut to
 // Bar. This fails, you must add a type annotation like `let _: &mut Bar = _ else { ... }`
 
-#![feature(let_else)]
+
 use std::ops::{Deref, DerefMut};
 
 struct Foo(Bar);
diff --git a/src/test/ui/let-else/let-else-destructuring.rs b/src/test/ui/let-else/let-else-destructuring.rs
index 9a09c414ac8..d1f1a69bfc2 100644
--- a/src/test/ui/let-else/let-else-destructuring.rs
+++ b/src/test/ui/let-else/let-else-destructuring.rs
@@ -1,4 +1,3 @@
-#![feature(let_else)]
 #[derive(Debug)]
 enum Foo {
     Done,
diff --git a/src/test/ui/let-else/let-else-destructuring.stderr b/src/test/ui/let-else/let-else-destructuring.stderr
index 95efb711682..7d6cb238644 100644
--- a/src/test/ui/let-else/let-else-destructuring.stderr
+++ b/src/test/ui/let-else/let-else-destructuring.stderr
@@ -1,11 +1,11 @@
 error: <assignment> ... else { ... } is not allowed
-  --> $DIR/let-else-destructuring.rs:11:9
+  --> $DIR/let-else-destructuring.rs:10:9
    |
 LL |         &Foo::Nested(Some(value)) = value else { break };
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0070]: invalid left-hand side of assignment
-  --> $DIR/let-else-destructuring.rs:11:35
+  --> $DIR/let-else-destructuring.rs:10:35
    |
 LL |         &Foo::Nested(Some(value)) = value else { break };
    |         ------------------------- ^
diff --git a/src/test/ui/let-else/let-else-drop-order.rs b/src/test/ui/let-else/let-else-drop-order.rs
index 0054f3d4182..e91e5de84e4 100644
--- a/src/test/ui/let-else/let-else-drop-order.rs
+++ b/src/test/ui/let-else/let-else-drop-order.rs
@@ -16,7 +16,7 @@
 // This is important as it's easy to update the stdout file
 // with a --bless and miss the impact of that change.
 
-#![feature(let_else)]
+
 #![allow(irrefutable_let_patterns)]
 
 use std::cell::RefCell;
diff --git a/src/test/ui/let-else/let-else-if.rs b/src/test/ui/let-else/let-else-if.rs
index c3a17330d6e..e8c54ca7ab2 100644
--- a/src/test/ui/let-else/let-else-if.rs
+++ b/src/test/ui/let-else/let-else-if.rs
@@ -1,5 +1,3 @@
-#![feature(let_else)]
-
 fn main() {
     let Some(_) = Some(()) else if true {
         //~^ ERROR conditional `else if` is not supported for `let...else`
diff --git a/src/test/ui/let-else/let-else-if.stderr b/src/test/ui/let-else/let-else-if.stderr
index 746738bbd93..c63fd61c5de 100644
--- a/src/test/ui/let-else/let-else-if.stderr
+++ b/src/test/ui/let-else/let-else-if.stderr
@@ -1,5 +1,5 @@
 error: conditional `else if` is not supported for `let...else`
-  --> $DIR/let-else-if.rs:4:33
+  --> $DIR/let-else-if.rs:2:33
    |
 LL |     let Some(_) = Some(()) else if true {
    |                                 ^^ expected `{`
diff --git a/src/test/ui/let-else/let-else-irrefutable.rs b/src/test/ui/let-else/let-else-irrefutable.rs
index b1e09a1248f..1cb68ecb8a6 100644
--- a/src/test/ui/let-else/let-else-irrefutable.rs
+++ b/src/test/ui/let-else/let-else-irrefutable.rs
@@ -1,6 +1,6 @@
 // check-pass
 
-#![feature(let_else)]
+
 
 fn main() {
     let x = 1 else { return }; //~ WARN irrefutable `let...else` pattern
diff --git a/src/test/ui/let-else/let-else-missing-semicolon.rs b/src/test/ui/let-else/let-else-missing-semicolon.rs
index ed9d79f1ebd..d87ac90c1a7 100644
--- a/src/test/ui/let-else/let-else-missing-semicolon.rs
+++ b/src/test/ui/let-else/let-else-missing-semicolon.rs
@@ -1,5 +1,3 @@
-#![feature(let_else)]
-
 fn main() {
     let Some(x) = Some(1) else {
         return;
diff --git a/src/test/ui/let-else/let-else-missing-semicolon.stderr b/src/test/ui/let-else/let-else-missing-semicolon.stderr
index 1818a0b1263..99029ff33fe 100644
--- a/src/test/ui/let-else/let-else-missing-semicolon.stderr
+++ b/src/test/ui/let-else/let-else-missing-semicolon.stderr
@@ -1,5 +1,5 @@
 error: expected `;`, found keyword `let`
-  --> $DIR/let-else-missing-semicolon.rs:6:6
+  --> $DIR/let-else-missing-semicolon.rs:4:6
    |
 LL |     }
    |      ^ help: add `;` here
@@ -7,7 +7,7 @@ LL |     let _ = "";
    |     --- unexpected token
 
 error: expected `;`, found `}`
-  --> $DIR/let-else-missing-semicolon.rs:10:6
+  --> $DIR/let-else-missing-semicolon.rs:8:6
    |
 LL |     }
    |      ^ help: add `;` here
diff --git a/src/test/ui/let-else/let-else-no-double-error.rs b/src/test/ui/let-else/let-else-no-double-error.rs
index 35dcdd3f6be..91fcc5d7e91 100644
--- a/src/test/ui/let-else/let-else-no-double-error.rs
+++ b/src/test/ui/let-else/let-else-no-double-error.rs
@@ -1,6 +1,6 @@
 // from rfc2005 test suite
 
-#![feature(let_else)]
+
 
 // Without caching type lookups in FnCtxt.resolve_ty_and_def_ufcs
 // the error below would be reported twice (once when checking
diff --git a/src/test/ui/let-else/let-else-non-copy.rs b/src/test/ui/let-else/let-else-non-copy.rs
index 79ed82dd124..08c07dd1a43 100644
--- a/src/test/ui/let-else/let-else-non-copy.rs
+++ b/src/test/ui/let-else/let-else-non-copy.rs
@@ -10,7 +10,7 @@
 //
 // The move was due to mir::Place being Copy, but mir::VarDebugInfoContents not being Copy.
 
-#![feature(let_else)]
+
 
 #[derive(Copy, Clone)]
 struct Copyable;
diff --git a/src/test/ui/let-else/let-else-non-diverging.rs b/src/test/ui/let-else/let-else-non-diverging.rs
index a1cee335aee..b5bd91ceb9e 100644
--- a/src/test/ui/let-else/let-else-non-diverging.rs
+++ b/src/test/ui/let-else/let-else-non-diverging.rs
@@ -1,5 +1,3 @@
-#![feature(let_else)]
-
 fn main() {
     let Some(x) = Some(1) else { //~ ERROR does not diverge
         Some(2)
diff --git a/src/test/ui/let-else/let-else-non-diverging.stderr b/src/test/ui/let-else/let-else-non-diverging.stderr
index 05e45f68989..c999a549525 100644
--- a/src/test/ui/let-else/let-else-non-diverging.stderr
+++ b/src/test/ui/let-else/let-else-non-diverging.stderr
@@ -1,5 +1,5 @@
 error[E0308]: `else` clause of `let...else` does not diverge
-  --> $DIR/let-else-non-diverging.rs:4:32
+  --> $DIR/let-else-non-diverging.rs:2:32
    |
 LL |       let Some(x) = Some(1) else {
    |  ________________________________^
@@ -13,7 +13,7 @@ LL | |     };
    = help: ...or use `match` instead of `let...else`
 
 error[E0308]: `else` clause of `let...else` does not diverge
-  --> $DIR/let-else-non-diverging.rs:7:32
+  --> $DIR/let-else-non-diverging.rs:5:32
    |
 LL |       let Some(x) = Some(1) else {
    |  ________________________________^
@@ -29,7 +29,7 @@ LL | |     };
    = help: ...or use `match` instead of `let...else`
 
 error[E0308]: `else` clause of `let...else` does not diverge
-  --> $DIR/let-else-non-diverging.rs:12:32
+  --> $DIR/let-else-non-diverging.rs:10:32
    |
 LL |     let Some(x) = Some(1) else { Some(2) };
    |                                ^^^^^^^^^^^ expected `!`, found enum `Option`
diff --git a/src/test/ui/let-else/let-else-ref-bindings-pass.rs b/src/test/ui/let-else/let-else-ref-bindings-pass.rs
index f4abd6cc2df..62fc65731cd 100644
--- a/src/test/ui/let-else/let-else-ref-bindings-pass.rs
+++ b/src/test/ui/let-else/let-else-ref-bindings-pass.rs
@@ -1,6 +1,6 @@
 // check-pass
 
-#![feature(let_else)]
+
 #![allow(unused_variables)]
 
 fn ref_() {
diff --git a/src/test/ui/let-else/let-else-ref-bindings.rs b/src/test/ui/let-else/let-else-ref-bindings.rs
index a4cd8e8c47d..687e235d47e 100644
--- a/src/test/ui/let-else/let-else-ref-bindings.rs
+++ b/src/test/ui/let-else/let-else-ref-bindings.rs
@@ -1,6 +1,6 @@
-#![feature(let_else)]
 #![allow(unused_variables)]
 
+
 fn ref_() {
     let bytes: Vec<u8> = b"Hello"[..].to_vec();
     let some = Some(bytes);
diff --git a/src/test/ui/let-else/let-else-run-pass.rs b/src/test/ui/let-else/let-else-run-pass.rs
index 5d96623236d..a0fb6c683f8 100644
--- a/src/test/ui/let-else/let-else-run-pass.rs
+++ b/src/test/ui/let-else/let-else-run-pass.rs
@@ -1,6 +1,6 @@
 // run-pass
 
-#![feature(let_else)]
+
 
 fn main() {
     #[allow(dead_code)]
diff --git a/src/test/ui/let-else/let-else-scope.rs b/src/test/ui/let-else/let-else-scope.rs
index f17682db4c3..78a67769ef2 100644
--- a/src/test/ui/let-else/let-else-scope.rs
+++ b/src/test/ui/let-else/let-else-scope.rs
@@ -1,5 +1,3 @@
-#![feature(let_else)]
-
 fn main() {
     let Some(x) = Some(2) else {
         panic!("{}", x); //~ ERROR cannot find value `x` in this scope
diff --git a/src/test/ui/let-else/let-else-scope.stderr b/src/test/ui/let-else/let-else-scope.stderr
index 4b3936eac4b..3b4f0982940 100644
--- a/src/test/ui/let-else/let-else-scope.stderr
+++ b/src/test/ui/let-else/let-else-scope.stderr
@@ -1,5 +1,5 @@
 error[E0425]: cannot find value `x` in this scope
-  --> $DIR/let-else-scope.rs:5:22
+  --> $DIR/let-else-scope.rs:3:22
    |
 LL |         panic!("{}", x);
    |                      ^ not found in this scope
diff --git a/src/test/ui/let-else/let-else-slicing-error.rs b/src/test/ui/let-else/let-else-slicing-error.rs
index 4022656a8f5..25770094bce 100644
--- a/src/test/ui/let-else/let-else-slicing-error.rs
+++ b/src/test/ui/let-else/let-else-slicing-error.rs
@@ -1,5 +1,5 @@
 // issue #92069
-#![feature(let_else)]
+
 
 fn main() {
     let nums = vec![5, 4, 3, 2, 1];
diff --git a/src/test/ui/let-else/let-else-source-expr-nomove-pass.rs b/src/test/ui/let-else/let-else-source-expr-nomove-pass.rs
index 2aa17ae8ceb..ee378abcf2b 100644
--- a/src/test/ui/let-else/let-else-source-expr-nomove-pass.rs
+++ b/src/test/ui/let-else/let-else-source-expr-nomove-pass.rs
@@ -1,7 +1,7 @@
 // run-pass
 // issue #89688
 
-#![feature(let_else)]
+
 
 fn example_let_else(value: Option<String>) {
     let Some(inner) = value else {
diff --git a/src/test/ui/let-else/let-else-temp-borrowck.rs b/src/test/ui/let-else/let-else-temp-borrowck.rs
index 3910d35e776..6b4642d2f98 100644
--- a/src/test/ui/let-else/let-else-temp-borrowck.rs
+++ b/src/test/ui/let-else/let-else-temp-borrowck.rs
@@ -3,7 +3,7 @@
 // from issue #93951, where borrowck complained the temporary that `foo(&x)` was stored in was to
 // be dropped sometime after `x` was. It then suggested adding a semicolon that was already there.
 
-#![feature(let_else)]
+
 use std::fmt::Debug;
 
 fn foo<'a>(x: &'a str) -> Result<impl Debug + 'a, ()> {
diff --git a/src/test/ui/let-else/let-else-temporary-lifetime.rs b/src/test/ui/let-else/let-else-temporary-lifetime.rs
index 8542c3496b0..c23eaa997fe 100644
--- a/src/test/ui/let-else/let-else-temporary-lifetime.rs
+++ b/src/test/ui/let-else/let-else-temporary-lifetime.rs
@@ -1,6 +1,5 @@
 // run-pass
 // compile-flags: -Zvalidate-mir
-#![feature(let_else)]
 
 use std::fmt::Display;
 use std::rc::Rc;
diff --git a/src/test/ui/let-else/let-else-then-diverge.rs b/src/test/ui/let-else/let-else-then-diverge.rs
index 49633d943be..1c8f7d758e8 100644
--- a/src/test/ui/let-else/let-else-then-diverge.rs
+++ b/src/test/ui/let-else/let-else-then-diverge.rs
@@ -2,7 +2,7 @@
 // popped up in in #94012, where an alternative desugaring was
 // causing unreachable code errors
 
-#![feature(let_else)]
+
 #![deny(unused_variables)]
 #![deny(unreachable_code)]
 
diff --git a/src/test/ui/let-else/let-else.rs b/src/test/ui/let-else/let-else.rs
new file mode 100644
index 00000000000..3505533e63f
--- /dev/null
+++ b/src/test/ui/let-else/let-else.rs
@@ -0,0 +1,8 @@
+// run-pass
+
+fn main() {
+    let Some(x) = Some(1) else {
+        return;
+    };
+    assert_eq!(x, 1);
+}
diff --git a/src/test/ui/pattern/usefulness/issue-31561.stderr b/src/test/ui/pattern/usefulness/issue-31561.stderr
index 46aebccc5ff..20f2f09500a 100644
--- a/src/test/ui/pattern/usefulness/issue-31561.stderr
+++ b/src/test/ui/pattern/usefulness/issue-31561.stderr
@@ -21,7 +21,7 @@ help: you might want to use `if let` to ignore the variants that aren't matched
    |
 LL |     let y = if let Thing::Foo(y) = Thing::Foo(1) { y } else { todo!() };
    |     ++++++++++                                   ++++++++++++++++++++++
-help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variants that aren't matched
+help: alternatively, you might want to use let else to handle the variants that aren't matched
    |
 LL |     let Thing::Foo(y) = Thing::Foo(1) else { todo!() };
    |                                       ++++++++++++++++
diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-defined-here.stderr b/src/test/ui/pattern/usefulness/non-exhaustive-defined-here.stderr
index ac2a9713e7d..678c9b2ab58 100644
--- a/src/test/ui/pattern/usefulness/non-exhaustive-defined-here.stderr
+++ b/src/test/ui/pattern/usefulness/non-exhaustive-defined-here.stderr
@@ -187,7 +187,7 @@ help: you might want to use `if let` to ignore the variant that isn't matched
    |
 LL |     let _x = if let Opt::Some(ref _x) = e { _x } else { todo!() };
    |     +++++++++++                           +++++++++++++++++++++++
-help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variant that isn't matched
+help: alternatively, you might want to use let else to handle the variant that isn't matched
    |
 LL |     let Opt::Some(ref _x) = e else { todo!() };
    |                               ++++++++++++++++
diff --git a/src/test/ui/pattern/usefulness/top-level-alternation.rs b/src/test/ui/pattern/usefulness/top-level-alternation.rs
index 076de846129..e8cd12ea4a2 100644
--- a/src/test/ui/pattern/usefulness/top-level-alternation.rs
+++ b/src/test/ui/pattern/usefulness/top-level-alternation.rs
@@ -1,5 +1,3 @@
-#![feature(let_else)]
-
 #![deny(unreachable_patterns)]
 
 fn main() {
diff --git a/src/test/ui/pattern/usefulness/top-level-alternation.stderr b/src/test/ui/pattern/usefulness/top-level-alternation.stderr
index dd5936fdcc4..17fa951c539 100644
--- a/src/test/ui/pattern/usefulness/top-level-alternation.stderr
+++ b/src/test/ui/pattern/usefulness/top-level-alternation.stderr
@@ -1,71 +1,71 @@
 error: unreachable pattern
-  --> $DIR/top-level-alternation.rs:6:23
+  --> $DIR/top-level-alternation.rs:4:23
    |
 LL |     while let 0..=2 | 1 = 0 {}
    |                       ^
    |
 note: the lint level is defined here
-  --> $DIR/top-level-alternation.rs:3:9
+  --> $DIR/top-level-alternation.rs:1:9
    |
 LL | #![deny(unreachable_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/top-level-alternation.rs:7:20
+  --> $DIR/top-level-alternation.rs:5:20
    |
 LL |     if let 0..=2 | 1 = 0 {}
    |                    ^
 
 error: unreachable pattern
-  --> $DIR/top-level-alternation.rs:11:15
+  --> $DIR/top-level-alternation.rs:9:15
    |
 LL |             | 0 => {}
    |               ^
 
 error: unreachable pattern
-  --> $DIR/top-level-alternation.rs:16:15
+  --> $DIR/top-level-alternation.rs:14:15
    |
 LL |             | Some(0) => {}
    |               ^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/top-level-alternation.rs:21:9
+  --> $DIR/top-level-alternation.rs:19:9
    |
 LL |         (0, 0) => {}
    |         ^^^^^^
 
 error: unreachable pattern
-  --> $DIR/top-level-alternation.rs:41:9
+  --> $DIR/top-level-alternation.rs:39:9
    |
 LL |         _ => {}
    |         ^
 
 error: unreachable pattern
-  --> $DIR/top-level-alternation.rs:45:9
+  --> $DIR/top-level-alternation.rs:43:9
    |
 LL |         Some(_) => {}
    |         ^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/top-level-alternation.rs:46:9
+  --> $DIR/top-level-alternation.rs:44:9
    |
 LL |         None => {}
    |         ^^^^
 
 error: unreachable pattern
-  --> $DIR/top-level-alternation.rs:51:9
+  --> $DIR/top-level-alternation.rs:49:9
    |
 LL |         None | Some(_) => {}
    |         ^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/top-level-alternation.rs:55:9
+  --> $DIR/top-level-alternation.rs:53:9
    |
 LL |         1..=2 => {},
    |         ^^^^^
 
 error: unreachable pattern
-  --> $DIR/top-level-alternation.rs:58:14
+  --> $DIR/top-level-alternation.rs:56:14
    |
 LL |     let (0 | 0) = 0 else { return };
    |              ^
diff --git a/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr b/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr
index acbd0d05984..321ee0a3694 100644
--- a/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr
+++ b/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr
@@ -19,7 +19,7 @@ help: you might want to use `if let` to ignore the variant that isn't matched
    |
 LL |     let x = if let Ok(x) = res { x } else { todo!() };
    |     ++++++++++                 ++++++++++++++++++++++
-help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variant that isn't matched
+help: alternatively, you might want to use let else to handle the variant that isn't matched
    |
 LL |     let Ok(x) = res else { todo!() };
    |                     ++++++++++++++++
diff --git a/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.rs b/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.rs
index 12befc637c7..2a6c144350a 100644
--- a/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.rs
+++ b/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.rs
@@ -1,4 +1,4 @@
-#![feature(let_chains, let_else)]
+#![feature(let_chains)]
 
 fn main() {
     let opt = Some(1i32);
diff --git a/src/test/ui/simd/intrinsic/ptr-cast.rs b/src/test/ui/simd/intrinsic/ptr-cast.rs
new file mode 100644
index 00000000000..1d13720bcd3
--- /dev/null
+++ b/src/test/ui/simd/intrinsic/ptr-cast.rs
@@ -0,0 +1,33 @@
+// run-pass
+
+#![feature(repr_simd, platform_intrinsics)]
+
+extern "platform-intrinsic" {
+    fn simd_cast_ptr<T, U>(x: T) -> U;
+    fn simd_expose_addr<T, U>(x: T) -> U;
+    fn simd_from_exposed_addr<T, U>(x: T) -> U;
+}
+
+#[derive(Copy, Clone)]
+#[repr(simd)]
+struct V<T>([T; 2]);
+
+fn main() {
+    unsafe {
+        let mut foo = 4i8;
+        let ptr = &mut foo as *mut i8;
+
+        let ptrs = V::<*mut i8>([ptr, core::ptr::null_mut()]);
+
+        // change constness and type
+        let const_ptrs: V<*const u8> = simd_cast_ptr(ptrs);
+
+        let exposed_addr: V<usize> = simd_expose_addr(const_ptrs);
+
+        let from_exposed_addr: V<*mut i8> = simd_from_exposed_addr(exposed_addr);
+
+        assert!(const_ptrs.0 == [ptr as *const u8, core::ptr::null()]);
+        assert!(exposed_addr.0 == [ptr as usize, 0]);
+        assert!(from_exposed_addr.0 == ptrs.0);
+    }
+}
diff --git a/src/test/ui/typeck/do-not-suggest-placeholder-to-const-static-without-type.rs b/src/test/ui/typeck/do-not-suggest-placeholder-to-const-static-without-type.rs
new file mode 100644
index 00000000000..97e0b213f2e
--- /dev/null
+++ b/src/test/ui/typeck/do-not-suggest-placeholder-to-const-static-without-type.rs
@@ -0,0 +1,8 @@
+trait Foo {
+    const A; //~ ERROR missing type for `const` item
+    static B;
+    //~^ ERROR associated `static` items are not allowed
+    //~| ERROR missing type for `static` item
+}
+
+fn main() {}
diff --git a/src/test/ui/typeck/do-not-suggest-placeholder-to-const-static-without-type.stderr b/src/test/ui/typeck/do-not-suggest-placeholder-to-const-static-without-type.stderr
new file mode 100644
index 00000000000..8982d628561
--- /dev/null
+++ b/src/test/ui/typeck/do-not-suggest-placeholder-to-const-static-without-type.stderr
@@ -0,0 +1,20 @@
+error: associated `static` items are not allowed
+  --> $DIR/do-not-suggest-placeholder-to-const-static-without-type.rs:3:5
+   |
+LL |     static B;
+   |     ^^^^^^^^^
+
+error: missing type for `const` item
+  --> $DIR/do-not-suggest-placeholder-to-const-static-without-type.rs:2:12
+   |
+LL |     const A;
+   |            ^ help: provide a type for the item: `: <type>`
+
+error: missing type for `static` item
+  --> $DIR/do-not-suggest-placeholder-to-const-static-without-type.rs:3:13
+   |
+LL |     static B;
+   |             ^ help: provide a type for the item: `: <type>`
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/uninhabited/uninhabited-irrefutable.stderr b/src/test/ui/uninhabited/uninhabited-irrefutable.stderr
index feeaa89e76f..32f287a1818 100644
--- a/src/test/ui/uninhabited/uninhabited-irrefutable.stderr
+++ b/src/test/ui/uninhabited/uninhabited-irrefutable.stderr
@@ -18,7 +18,7 @@ help: you might want to use `if let` to ignore the variant that isn't matched
    |
 LL |     let (_y, _z) = if let Foo::D(_y, _z) = x { (_y, _z) } else { todo!() };
    |     +++++++++++++++++                        +++++++++++++++++++++++++++++
-help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variant that isn't matched
+help: alternatively, you might want to use let else to handle the variant that isn't matched
    |
 LL |     let Foo::D(_y, _z) = x else { todo!() };
    |                            ++++++++++++++++
diff --git a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr
index 2c107b1f7a4..c7882963407 100644
--- a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr
+++ b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr
@@ -122,7 +122,7 @@ help: you might want to use `if let` to ignore the variant that isn't matched
    |
 LL |     let x = if let Ok(x) = x { x } else { todo!() };
    |     ++++++++++               ++++++++++++++++++++++
-help: alternatively, on nightly, you might want to use `#![feature(let_else)]` to handle the variant that isn't matched
+help: alternatively, you might want to use let else to handle the variant that isn't matched
    |
 LL |     let Ok(x) = x else { todo!() };
    |                   ++++++++++++++++
diff --git a/src/test/ui/unpretty/pretty-let-else.rs b/src/test/ui/unpretty/pretty-let-else.rs
index 5abfa2523b7..b5ae529699d 100644
--- a/src/test/ui/unpretty/pretty-let-else.rs
+++ b/src/test/ui/unpretty/pretty-let-else.rs
@@ -1,7 +1,7 @@
 // compile-flags: -Zunpretty=hir
 // check-pass
 
-#![feature(let_else)]
+
 
 fn foo(x: Option<u32>) {
     let Some(_) = x else { panic!() };
diff --git a/src/test/ui/unpretty/pretty-let-else.stdout b/src/test/ui/unpretty/pretty-let-else.stdout
index ffe1d1657aa..35ad1cd1b18 100644
--- a/src/test/ui/unpretty/pretty-let-else.stdout
+++ b/src/test/ui/unpretty/pretty-let-else.stdout
@@ -1,11 +1,11 @@
-// compile-flags: -Zunpretty=hir
-// check-pass
-
-#![feature(let_else)]
 #[prelude_import]
 use ::std::prelude::rust_2015::*;
 #[macro_use]
 extern crate std;
+// compile-flags: -Zunpretty=hir
+// check-pass
+
+
 
 fn foo(x:
         Option<u32>) {
diff --git a/src/tools/clippy/clippy_dev/src/lib.rs b/src/tools/clippy/clippy_dev/src/lib.rs
index 82574a8e64b..54c7456a2a3 100644
--- a/src/tools/clippy/clippy_dev/src/lib.rs
+++ b/src/tools/clippy/clippy_dev/src/lib.rs
@@ -1,5 +1,5 @@
 #![feature(let_chains)]
-#![feature(let_else)]
+#![cfg_attr(bootstrap, feature(let_else))]
 #![feature(once_cell)]
 #![feature(rustc_private)]
 #![cfg_attr(feature = "deny-warnings", deny(warnings))]
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index e984254bf29..ceaaf5c6d6e 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -5,7 +5,7 @@
 #![feature(drain_filter)]
 #![feature(iter_intersperse)]
 #![feature(let_chains)]
-#![feature(let_else)]
+#![cfg_attr(bootstrap, feature(let_else))]
 #![feature(lint_reasons)]
 #![feature(never_type)]
 #![feature(once_cell)]
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 23b51ec2d08..62da850a15e 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -1,9 +1,9 @@
 #![feature(array_chunks)]
 #![feature(box_patterns)]
 #![feature(control_flow_enum)]
-#![feature(let_else)]
 #![feature(let_chains)]
 #![feature(lint_reasons)]
+#![cfg_attr(bootstrap, feature(let_else))]
 #![feature(once_cell)]
 #![feature(rustc_private)]
 #![recursion_limit = "512"]
diff --git a/src/tools/clippy/tests/ui/needless_return.fixed b/src/tools/clippy/tests/ui/needless_return.fixed
index 87c8fc03b3c..695883e8dff 100644
--- a/src/tools/clippy/tests/ui/needless_return.fixed
+++ b/src/tools/clippy/tests/ui/needless_return.fixed
@@ -1,7 +1,6 @@
 // run-rustfix
 
 #![feature(lint_reasons)]
-#![feature(let_else)]
 #![allow(unused)]
 #![allow(
     clippy::if_same_then_else,
diff --git a/src/tools/clippy/tests/ui/needless_return.rs b/src/tools/clippy/tests/ui/needless_return.rs
index 5a86e656255..63d9fe9ecdf 100644
--- a/src/tools/clippy/tests/ui/needless_return.rs
+++ b/src/tools/clippy/tests/ui/needless_return.rs
@@ -1,7 +1,6 @@
 // run-rustfix
 
 #![feature(lint_reasons)]
-#![feature(let_else)]
 #![allow(unused)]
 #![allow(
     clippy::if_same_then_else,
diff --git a/src/tools/clippy/tests/ui/needless_return.stderr b/src/tools/clippy/tests/ui/needless_return.stderr
index 83ff0763869..cadee6e00df 100644
--- a/src/tools/clippy/tests/ui/needless_return.stderr
+++ b/src/tools/clippy/tests/ui/needless_return.stderr
@@ -1,5 +1,5 @@
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:27:5
+  --> $DIR/needless_return.rs:26:5
    |
 LL |     return true;
    |     ^^^^^^^^^^^^ help: remove `return`: `true`
@@ -7,217 +7,217 @@ LL |     return true;
    = note: `-D clippy::needless-return` implied by `-D warnings`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:31:5
+  --> $DIR/needless_return.rs:30:5
    |
 LL |     return true;
    |     ^^^^^^^^^^^^ help: remove `return`: `true`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:36:9
+  --> $DIR/needless_return.rs:35:9
    |
 LL |         return true;
    |         ^^^^^^^^^^^^ help: remove `return`: `true`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:38:9
+  --> $DIR/needless_return.rs:37:9
    |
 LL |         return false;
    |         ^^^^^^^^^^^^^ help: remove `return`: `false`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:44:17
+  --> $DIR/needless_return.rs:43:17
    |
 LL |         true => return false,
    |                 ^^^^^^^^^^^^ help: remove `return`: `false`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:46:13
+  --> $DIR/needless_return.rs:45:13
    |
 LL |             return true;
    |             ^^^^^^^^^^^^ help: remove `return`: `true`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:53:9
+  --> $DIR/needless_return.rs:52:9
    |
 LL |         return true;
    |         ^^^^^^^^^^^^ help: remove `return`: `true`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:55:16
+  --> $DIR/needless_return.rs:54:16
    |
 LL |     let _ = || return true;
    |                ^^^^^^^^^^^ help: remove `return`: `true`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:59:5
+  --> $DIR/needless_return.rs:58:5
    |
 LL |     return the_answer!();
    |     ^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `the_answer!()`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:63:5
+  --> $DIR/needless_return.rs:62:5
    |
 LL |     return;
    |     ^^^^^^^ help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:68:9
+  --> $DIR/needless_return.rs:67:9
    |
 LL |         return;
    |         ^^^^^^^ help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:70:9
+  --> $DIR/needless_return.rs:69:9
    |
 LL |         return;
    |         ^^^^^^^ help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:77:14
+  --> $DIR/needless_return.rs:76:14
    |
 LL |         _ => return,
    |              ^^^^^^ help: replace `return` with a unit value: `()`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:86:13
+  --> $DIR/needless_return.rs:85:13
    |
 LL |             return;
    |             ^^^^^^^ help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:88:14
+  --> $DIR/needless_return.rs:87:14
    |
 LL |         _ => return,
    |              ^^^^^^ help: replace `return` with a unit value: `()`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:101:9
+  --> $DIR/needless_return.rs:100:9
    |
 LL |         return String::from("test");
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `String::from("test")`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:103:9
+  --> $DIR/needless_return.rs:102:9
    |
 LL |         return String::new();
    |         ^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `String::new()`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:125:32
+  --> $DIR/needless_return.rs:124:32
    |
 LL |         bar.unwrap_or_else(|_| return)
    |                                ^^^^^^ help: replace `return` with an empty block: `{}`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:130:13
+  --> $DIR/needless_return.rs:129:13
    |
 LL |             return;
    |             ^^^^^^^ help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:132:20
+  --> $DIR/needless_return.rs:131:20
    |
 LL |         let _ = || return;
    |                    ^^^^^^ help: replace `return` with an empty block: `{}`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:138:32
+  --> $DIR/needless_return.rs:137:32
    |
 LL |         res.unwrap_or_else(|_| return Foo)
    |                                ^^^^^^^^^^ help: remove `return`: `Foo`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:147:5
+  --> $DIR/needless_return.rs:146:5
    |
 LL |     return true;
    |     ^^^^^^^^^^^^ help: remove `return`: `true`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:151:5
+  --> $DIR/needless_return.rs:150:5
    |
 LL |     return true;
    |     ^^^^^^^^^^^^ help: remove `return`: `true`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:156:9
+  --> $DIR/needless_return.rs:155:9
    |
 LL |         return true;
    |         ^^^^^^^^^^^^ help: remove `return`: `true`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:158:9
+  --> $DIR/needless_return.rs:157:9
    |
 LL |         return false;
    |         ^^^^^^^^^^^^^ help: remove `return`: `false`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:164:17
+  --> $DIR/needless_return.rs:163:17
    |
 LL |         true => return false,
    |                 ^^^^^^^^^^^^ help: remove `return`: `false`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:166:13
+  --> $DIR/needless_return.rs:165:13
    |
 LL |             return true;
    |             ^^^^^^^^^^^^ help: remove `return`: `true`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:173:9
+  --> $DIR/needless_return.rs:172:9
    |
 LL |         return true;
    |         ^^^^^^^^^^^^ help: remove `return`: `true`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:175:16
+  --> $DIR/needless_return.rs:174:16
    |
 LL |     let _ = || return true;
    |                ^^^^^^^^^^^ help: remove `return`: `true`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:179:5
+  --> $DIR/needless_return.rs:178:5
    |
 LL |     return the_answer!();
    |     ^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `the_answer!()`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:183:5
+  --> $DIR/needless_return.rs:182:5
    |
 LL |     return;
    |     ^^^^^^^ help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:188:9
+  --> $DIR/needless_return.rs:187:9
    |
 LL |         return;
    |         ^^^^^^^ help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:190:9
+  --> $DIR/needless_return.rs:189:9
    |
 LL |         return;
    |         ^^^^^^^ help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:197:14
+  --> $DIR/needless_return.rs:196:14
    |
 LL |         _ => return,
    |              ^^^^^^ help: replace `return` with a unit value: `()`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:210:9
+  --> $DIR/needless_return.rs:209:9
    |
 LL |         return String::from("test");
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `String::from("test")`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:212:9
+  --> $DIR/needless_return.rs:211:9
    |
 LL |         return String::new();
    |         ^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `String::new()`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:228:5
+  --> $DIR/needless_return.rs:227:5
    |
 LL |     return format!("Hello {}", "world!");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `format!("Hello {}", "world!")`
diff --git a/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.rs b/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.rs
index c3235f06779..c4dfbd9210e 100644
--- a/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.rs
+++ b/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.rs
@@ -1,6 +1,5 @@
 #![warn(clippy::semicolon_if_nothing_returned)]
 #![allow(clippy::redundant_closure)]
-#![feature(let_else)]
 
 fn get_unit() {}
 
diff --git a/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.stderr b/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.stderr
index 78813e7cc1c..8d9a67585cf 100644
--- a/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.stderr
+++ b/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.stderr
@@ -1,5 +1,5 @@
 error: consider adding a `;` to the last statement for consistent formatting
-  --> $DIR/semicolon_if_nothing_returned.rs:9:5
+  --> $DIR/semicolon_if_nothing_returned.rs:8:5
    |
 LL |     println!("Hello")
    |     ^^^^^^^^^^^^^^^^^ help: add a `;` here: `println!("Hello");`
@@ -7,25 +7,25 @@ LL |     println!("Hello")
    = note: `-D clippy::semicolon-if-nothing-returned` implied by `-D warnings`
 
 error: consider adding a `;` to the last statement for consistent formatting
-  --> $DIR/semicolon_if_nothing_returned.rs:13:5
+  --> $DIR/semicolon_if_nothing_returned.rs:12:5
    |
 LL |     get_unit()
    |     ^^^^^^^^^^ help: add a `;` here: `get_unit();`
 
 error: consider adding a `;` to the last statement for consistent formatting
-  --> $DIR/semicolon_if_nothing_returned.rs:18:5
+  --> $DIR/semicolon_if_nothing_returned.rs:17:5
    |
 LL |     y = x + 1
    |     ^^^^^^^^^ help: add a `;` here: `y = x + 1;`
 
 error: consider adding a `;` to the last statement for consistent formatting
-  --> $DIR/semicolon_if_nothing_returned.rs:24:9
+  --> $DIR/semicolon_if_nothing_returned.rs:23:9
    |
 LL |         hello()
    |         ^^^^^^^ help: add a `;` here: `hello();`
 
 error: consider adding a `;` to the last statement for consistent formatting
-  --> $DIR/semicolon_if_nothing_returned.rs:35:9
+  --> $DIR/semicolon_if_nothing_returned.rs:34:9
    |
 LL |         ptr::drop_in_place(s.as_mut_ptr())
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add a `;` here: `ptr::drop_in_place(s.as_mut_ptr());`