From 85d2b6e3f3c39489784b2f7ca54b33458a7b4da8 Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Sat, 23 Dec 2023 04:10:27 +0000
Subject: [PATCH 01/27] Remove unnecessary arm in check_expr_yield

---
 compiler/rustc_hir/src/hir.rs         |  6 ------
 compiler/rustc_hir_typeck/src/expr.rs | 11 +----------
 2 files changed, 1 insertion(+), 16 deletions(-)

diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 26430dcf965fe..f5389d15832c1 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -2071,12 +2071,6 @@ pub enum YieldSource {
     Yield,
 }
 
-impl YieldSource {
-    pub fn is_await(&self) -> bool {
-        matches!(self, YieldSource::Await { .. })
-    }
-}
-
 impl fmt::Display for YieldSource {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.write_str(match self {
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 5d5b5f39ccfc8..f99abfaf5db6d 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -349,7 +349,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             ExprKind::Index(base, idx, brackets_span) => {
                 self.check_expr_index(base, idx, expr, brackets_span)
             }
-            ExprKind::Yield(value, ref src) => self.check_expr_yield(value, expr, src),
+            ExprKind::Yield(value, _) => self.check_expr_yield(value, expr),
             hir::ExprKind::Err(guar) => Ty::new_error(tcx, guar),
         }
     }
@@ -3155,7 +3155,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         value: &'tcx hir::Expr<'tcx>,
         expr: &'tcx hir::Expr<'tcx>,
-        src: &'tcx hir::YieldSource,
     ) -> Ty<'tcx> {
         match self.resume_yield_tys {
             Some((resume_ty, yield_ty)) => {
@@ -3163,14 +3162,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
                 resume_ty
             }
-            // Given that this `yield` expression was generated as a result of lowering a `.await`,
-            // we know that the yield type must be `()`; however, the context won't contain this
-            // information. Hence, we check the source of the yield expression here and check its
-            // value's type against `()` (this check should always hold).
-            None if src.is_await() => {
-                self.check_expr_coercible_to_type(value, Ty::new_unit(self.tcx), None);
-                Ty::new_unit(self.tcx)
-            }
             _ => {
                 self.tcx.sess.emit_err(YieldExprOutsideOfCoroutine { span: expr.span });
                 // Avoid expressions without types during writeback (#78653).

From f521b4c5c18a5a38d4c653a062bc297db1873522 Mon Sep 17 00:00:00 2001
From: onur-ozkan <work@onurozkan.dev>
Date: Wed, 27 Dec 2023 10:21:07 +0300
Subject: [PATCH 02/27] suppress change-tracker warnings in containers

Signed-off-by: onur-ozkan <work@onurozkan.dev>
---
 src/ci/run.sh | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/src/ci/run.sh b/src/ci/run.sh
index 5700172fd3ec4..9b28c7ed50c67 100755
--- a/src/ci/run.sh
+++ b/src/ci/run.sh
@@ -47,6 +47,11 @@ source "$ci_dir/shared.sh"
 
 export CARGO_REGISTRIES_CRATES_IO_PROTOCOL=sparse
 
+# suppress change-tracker warnings on CI
+if [ "$CI" != "" ]; then
+    RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set change-id=99999999"
+fi
+
 if ! isCI || isCiBranch auto || isCiBranch beta || isCiBranch try || isCiBranch try-perf || \
   isCiBranch automation/bors/try; then
     RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.print-step-timings --enable-verbose-tests"
@@ -241,7 +246,7 @@ fi
 
 if [ "$RUN_CHECK_WITH_PARALLEL_QUERIES" != "" ]; then
   rm -f config.toml
-  $SRC/configure --set rust.parallel-compiler
+  $SRC/configure --set change-id=99999999 --set rust.parallel-compiler
 
   # Save the build metrics before we wipe the directory
   if [ "$HAS_METRICS" = 1 ]; then

From 8dd6faca463bfd35a7c47353de69c40d6e054855 Mon Sep 17 00:00:00 2001
From: onur-ozkan <work@onurozkan.dev>
Date: Tue, 26 Dec 2023 15:46:39 +0300
Subject: [PATCH 03/27] don't return suggestion message if no changes detected

Signed-off-by: onur-ozkan <work@onurozkan.dev>
---
 src/bootstrap/src/bin/main.rs | 32 +++++++++++++++++---------------
 1 file changed, 17 insertions(+), 15 deletions(-)

diff --git a/src/bootstrap/src/bin/main.rs b/src/bootstrap/src/bin/main.rs
index b1ab8dae535db..a44e7c75a1403 100644
--- a/src/bootstrap/src/bin/main.rs
+++ b/src/bootstrap/src/bin/main.rs
@@ -158,25 +158,27 @@ fn check_version(config: &Config) -> Option<String> {
 
         let changes = find_recent_config_change_ids(id);
 
-        if !changes.is_empty() {
-            msg.push_str("There have been changes to x.py since you last updated:\n");
-
-            for change in changes {
-                msg.push_str(&format!("  [{}] {}\n", change.severity.to_string(), change.summary));
-                msg.push_str(&format!(
-                    "    - PR Link https://github.com/rust-lang/rust/pull/{}\n",
-                    change.change_id
-                ));
-            }
+        if changes.is_empty() {
+            return None;
+        }
+
+        msg.push_str("There have been changes to x.py since you last updated:\n");
 
-            msg.push_str("NOTE: to silence this warning, ");
+        for change in changes {
+            msg.push_str(&format!("  [{}] {}\n", change.severity.to_string(), change.summary));
             msg.push_str(&format!(
-                "update `config.toml` to use `change-id = {latest_change_id}` instead"
+                "    - PR Link https://github.com/rust-lang/rust/pull/{}\n",
+                change.change_id
             ));
+        }
 
-            if io::stdout().is_terminal() && !config.dry_run() {
-                t!(fs::write(warned_id_path, latest_change_id.to_string()));
-            }
+        msg.push_str("NOTE: to silence this warning, ");
+        msg.push_str(&format!(
+            "update `config.toml` to use `change-id = {latest_change_id}` instead"
+        ));
+
+        if io::stdout().is_terminal() && !config.dry_run() {
+            t!(fs::write(warned_id_path, latest_change_id.to_string()));
         }
     } else {
         msg.push_str("WARNING: The `change-id` is missing in the `config.toml`. This means that you will not be able to track the major changes made to the bootstrap configurations.\n");

From 2c23c06c32b0cc43545ddf5b361e2a0edd69d595 Mon Sep 17 00:00:00 2001
From: Taiki Endo <te316e89@gmail.com>
Date: Sat, 30 Dec 2023 16:27:51 +0900
Subject: [PATCH 04/27] rc: Take *const T in is_dangling

It is not important which one is used since `is_dangling` does not access
memory, but `*const` removes the needs of `*const T` -> `*mut T` casts
in `from_raw_in`.
---
 library/alloc/src/rc.rs   | 4 ++--
 library/alloc/src/sync.rs | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs
index 59f3a50ddb722..263b1449de156 100644
--- a/library/alloc/src/rc.rs
+++ b/library/alloc/src/rc.rs
@@ -2778,7 +2778,7 @@ impl<T, A: Allocator> Weak<T, A> {
     }
 }
 
-pub(crate) fn is_dangling<T: ?Sized>(ptr: *mut T) -> bool {
+pub(crate) fn is_dangling<T: ?Sized>(ptr: *const T) -> bool {
     (ptr.cast::<()>()).addr() == usize::MAX
 }
 
@@ -3003,7 +3003,7 @@ impl<T: ?Sized, A: Allocator> Weak<T, A> {
     pub unsafe fn from_raw_in(ptr: *const T, alloc: A) -> Self {
         // See Weak::as_ptr for context on how the input pointer is derived.
 
-        let ptr = if is_dangling(ptr as *mut T) {
+        let ptr = if is_dangling(ptr) {
             // This is a dangling Weak.
             ptr as *mut RcBox<T>
         } else {
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index 85df491636ab7..edf2f66a30d3c 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -2722,7 +2722,7 @@ impl<T: ?Sized, A: Allocator> Weak<T, A> {
     pub unsafe fn from_raw_in(ptr: *const T, alloc: A) -> Self {
         // See Weak::as_ptr for context on how the input pointer is derived.
 
-        let ptr = if is_dangling(ptr as *mut T) {
+        let ptr = if is_dangling(ptr) {
             // This is a dangling Weak.
             ptr as *mut ArcInner<T>
         } else {

From 07adee70729a2c88080c97045c7357c498815401 Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Sat, 30 Dec 2023 15:19:54 +0000
Subject: [PATCH 05/27] is_coroutine -> is_coroutine_or_closure

---
 .../rustc_borrowck/src/diagnostics/conflict_errors.rs    | 4 ++--
 compiler/rustc_borrowck/src/type_check/input_output.rs   | 2 +-
 compiler/rustc_codegen_llvm/src/attributes.rs            | 2 +-
 compiler/rustc_codegen_ssa/src/codegen_attrs.rs          | 6 +++---
 .../rustc_const_eval/src/transform/check_consts/mod.rs   | 2 +-
 compiler/rustc_hir_typeck/src/check.rs                   | 3 ++-
 compiler/rustc_hir_typeck/src/gather_locals.rs           | 2 +-
 compiler/rustc_middle/src/mir/pretty.rs                  | 2 +-
 compiler/rustc_middle/src/ty/closure.rs                  | 4 ++--
 compiler/rustc_middle/src/ty/instance.rs                 | 9 ++++++---
 compiler/rustc_middle/src/ty/util.rs                     | 2 +-
 compiler/rustc_mir_transform/src/coverage/mod.rs         | 2 +-
 .../rustc_mir_transform/src/coverage/spans/from_mir.rs   | 4 ++--
 compiler/rustc_monomorphize/src/collector.rs             | 5 ++++-
 compiler/rustc_passes/src/upvars.rs                      | 2 +-
 15 files changed, 29 insertions(+), 22 deletions(-)

diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 3ec07572d1d60..d824260f47c18 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -3067,7 +3067,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     ) -> Option<AnnotatedBorrowFnSignature<'tcx>> {
         // Define a fallback for when we can't match a closure.
         let fallback = || {
-            let is_closure = self.infcx.tcx.is_closure(self.mir_def_id().to_def_id());
+            let is_closure = self.infcx.tcx.is_closure_or_coroutine(self.mir_def_id().to_def_id());
             if is_closure {
                 None
             } else {
@@ -3277,7 +3277,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         sig: ty::PolyFnSig<'tcx>,
     ) -> Option<AnnotatedBorrowFnSignature<'tcx>> {
         debug!("annotate_fn_sig: did={:?} sig={:?}", did, sig);
-        let is_closure = self.infcx.tcx.is_closure(did.to_def_id());
+        let is_closure = self.infcx.tcx.is_closure_or_coroutine(did.to_def_id());
         let fn_hir_id = self.infcx.tcx.local_def_id_to_hir_id(did);
         let fn_decl = self.infcx.tcx.hir().fn_decl_by_hir_id(fn_hir_id)?;
 
diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs
index f717d91c35c60..5bd7cc9514ca2 100644
--- a/compiler/rustc_borrowck/src/type_check/input_output.rs
+++ b/compiler/rustc_borrowck/src/type_check/input_output.rs
@@ -22,7 +22,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
     #[instrument(skip(self, body), level = "debug")]
     pub(super) fn check_signature_annotation(&mut self, body: &Body<'tcx>) {
         let mir_def_id = body.source.def_id().expect_local();
-        if !self.tcx().is_closure(mir_def_id.to_def_id()) {
+        if !self.tcx().is_closure_or_coroutine(mir_def_id.to_def_id()) {
             return;
         }
         let user_provided_poly_sig = self.tcx().closure_user_provided_sig(mir_def_id);
diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs
index 3cc33b8343403..b3fa7b7cd445c 100644
--- a/compiler/rustc_codegen_llvm/src/attributes.rs
+++ b/compiler/rustc_codegen_llvm/src/attributes.rs
@@ -481,7 +481,7 @@ pub fn from_fn_attrs<'ll, 'tcx>(
         // `+multivalue` feature because the purpose of the wasm abi is to match
         // the WebAssembly specification, which has this feature. This won't be
         // needed when LLVM enables this `multivalue` feature by default.
-        if !cx.tcx.is_closure(instance.def_id()) {
+        if !cx.tcx.is_closure_or_coroutine(instance.def_id()) {
             let abi = cx.tcx.fn_sig(instance.def_id()).skip_binder().abi();
             if abi == Abi::Wasm {
                 function_features.push("+multivalue".to_string());
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
index f5f2416abb6dc..63fd7b42f7ba1 100644
--- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -232,7 +232,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
             }
             sym::thread_local => codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL,
             sym::track_caller => {
-                let is_closure = tcx.is_closure(did.to_def_id());
+                let is_closure = tcx.is_closure_or_coroutine(did.to_def_id());
 
                 if !is_closure
                     && let Some(fn_sig) = fn_sig()
@@ -277,7 +277,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
                 }
             }
             sym::target_feature => {
-                if !tcx.is_closure(did.to_def_id())
+                if !tcx.is_closure_or_coroutine(did.to_def_id())
                     && let Some(fn_sig) = fn_sig()
                     && fn_sig.skip_binder().unsafety() == hir::Unsafety::Normal
                 {
@@ -531,7 +531,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
     // would result in this closure being compiled without the inherited target features, but this
     // is probably a poor usage of `#[inline(always)]` and easily avoided by not using the attribute.
     if tcx.features().target_feature_11
-        && tcx.is_closure(did.to_def_id())
+        && tcx.is_closure_or_coroutine(did.to_def_id())
         && codegen_fn_attrs.inline != InlineAttr::Always
     {
         let owner_id = tcx.parent(did.to_def_id());
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs
index fbc95072802f9..98276ff2e68d6 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs
@@ -72,7 +72,7 @@ impl<'mir, 'tcx> ConstCx<'mir, 'tcx> {
 
     pub fn fn_sig(&self) -> PolyFnSig<'tcx> {
         let did = self.def_id().to_def_id();
-        if self.tcx.is_closure(did) {
+        if self.tcx.is_closure_or_coroutine(did) {
             let ty = self.tcx.type_of(did).instantiate_identity();
             let ty::Closure(_, args) = ty.kind() else { bug!("type_of closure not ty::Closure") };
             args.as_closure().sig()
diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs
index 0ca0f7d2daf92..2a408ac255c44 100644
--- a/compiler/rustc_hir_typeck/src/check.rs
+++ b/compiler/rustc_hir_typeck/src/check.rs
@@ -125,7 +125,8 @@ pub(super) fn check_fn<'a, 'tcx>(
                 // ty_span == binding_span iff this is a closure parameter with no type ascription,
                 // or if it's an implicit `self` parameter
                 traits::SizedArgumentType(
-                    if ty_span == Some(param.span) && tcx.is_closure(fn_def_id.into()) {
+                    if ty_span == Some(param.span) && tcx.is_closure_or_coroutine(fn_def_id.into())
+                    {
                         None
                     } else {
                         ty_span
diff --git a/compiler/rustc_hir_typeck/src/gather_locals.rs b/compiler/rustc_hir_typeck/src/gather_locals.rs
index 0cca779b1560e..e169b45d725f4 100644
--- a/compiler/rustc_hir_typeck/src/gather_locals.rs
+++ b/compiler/rustc_hir_typeck/src/gather_locals.rs
@@ -150,7 +150,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
                         // ascription, or if it's an implicit `self` parameter
                         traits::SizedArgumentType(
                             if ty_span == ident.span
-                                && self.fcx.tcx.is_closure(self.fcx.body_id.into())
+                                && self.fcx.tcx.is_closure_or_coroutine(self.fcx.body_id.into())
                             {
                                 None
                             } else {
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index 8e7aaee065fd3..0b487eae36dbd 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -520,7 +520,7 @@ fn write_mir_sig(tcx: TyCtxt<'_>, body: &Body<'_>, w: &mut dyn io::Write) -> io:
     let kind = tcx.def_kind(def_id);
     let is_function = match kind {
         DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(..) => true,
-        _ => tcx.is_closure(def_id),
+        _ => tcx.is_closure_or_coroutine(def_id),
     };
     match (kind, body.source.promoted) {
         (_, Some(i)) => write!(w, "{i:?} in ")?,
diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs
index 8c29bc5a42865..8ff5b135acae8 100644
--- a/compiler/rustc_middle/src/ty/closure.rs
+++ b/compiler/rustc_middle/src/ty/closure.rs
@@ -197,7 +197,7 @@ pub struct ClosureTypeInfo<'tcx> {
 }
 
 fn closure_typeinfo<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ClosureTypeInfo<'tcx> {
-    debug_assert!(tcx.is_closure(def.to_def_id()));
+    debug_assert!(tcx.is_closure_or_coroutine(def.to_def_id()));
     let typeck_results = tcx.typeck(def);
     let user_provided_sig = typeck_results.user_provided_sigs[&def];
     let captures = typeck_results.closure_min_captures_flattened(def);
@@ -217,7 +217,7 @@ impl<'tcx> TyCtxt<'tcx> {
     }
 
     pub fn closure_captures(self, def_id: LocalDefId) -> &'tcx [&'tcx ty::CapturedPlace<'tcx>] {
-        if !self.is_closure(def_id.to_def_id()) {
+        if !self.is_closure_or_coroutine(def_id.to_def_id()) {
             return &[];
         };
         self.closure_typeinfo(def_id).captures
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index 1b6d59ab25777..4b222d33b1057 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -426,7 +426,10 @@ impl<'tcx> Instance<'tcx> {
     ) -> Option<Instance<'tcx>> {
         debug!("resolve(def_id={:?}, args={:?})", def_id, args);
         // Use either `resolve_closure` or `resolve_for_vtable`
-        assert!(!tcx.is_closure(def_id), "Called `resolve_for_fn_ptr` on closure: {def_id:?}");
+        assert!(
+            !tcx.is_closure_or_coroutine(def_id),
+            "Called `resolve_for_fn_ptr` on closure: {def_id:?}"
+        );
         Instance::resolve(tcx, param_env, def_id, args).ok().flatten().map(|mut resolved| {
             match resolved.def {
                 InstanceDef::Item(def) if resolved.def.requires_caller_location(tcx) => {
@@ -488,7 +491,7 @@ impl<'tcx> Instance<'tcx> {
                                 })
                             )
                         {
-                            if tcx.is_closure(def) {
+                            if tcx.is_closure_or_coroutine(def) {
                                 debug!(" => vtable fn pointer created for closure with #[track_caller]: {:?} for method {:?} {:?}",
                                        def, def_id, args);
 
@@ -658,7 +661,7 @@ fn polymorphize<'tcx>(
     // the unpolymorphized upvar closure would result in a polymorphized closure producing
     // multiple mono items (and eventually symbol clashes).
     let def_id = instance.def_id();
-    let upvars_ty = if tcx.is_closure(def_id) {
+    let upvars_ty = if tcx.is_closure_or_coroutine(def_id) {
         Some(args.as_closure().tupled_upvars_ty())
     } else if tcx.type_of(def_id).skip_binder().is_coroutine() {
         Some(args.as_coroutine().tupled_upvars_ty())
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 5e24b47fbd2f0..ad2442a7963f0 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -547,7 +547,7 @@ impl<'tcx> TyCtxt<'tcx> {
     /// closure appears (and, sadly, a corresponding `NodeId`, since
     /// those are not yet phased out). The parent of the closure's
     /// `DefId` will also be the context where it appears.
-    pub fn is_closure(self, def_id: DefId) -> bool {
+    pub fn is_closure_or_coroutine(self, def_id: DefId) -> bool {
         matches!(self.def_kind(def_id), DefKind::Closure)
     }
 
diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs
index 078612aa59ca0..4c1e3f9bed3b3 100644
--- a/compiler/rustc_mir_transform/src/coverage/mod.rs
+++ b/compiler/rustc_mir_transform/src/coverage/mod.rs
@@ -345,7 +345,7 @@ fn get_body_span<'tcx>(
 ) -> Span {
     let mut body_span = hir_body.value.span;
 
-    if tcx.is_closure(def_id.to_def_id()) {
+    if tcx.is_closure_or_coroutine(def_id.to_def_id()) {
         // If the current function is a closure, and its "body" span was created
         // by macro expansion or compiler desugaring, try to walk backwards to
         // the pre-expansion call site or body.
diff --git a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs
index ff6545e9d2586..8f6592afe85cb 100644
--- a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs
+++ b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs
@@ -74,7 +74,7 @@ fn bcb_to_initial_coverage_spans<'a, 'tcx>(
             let expn_span = filtered_statement_span(statement)?;
             let span = unexpand_into_body_span(expn_span, body_span)?;
 
-            Some(CoverageSpan::new(span, expn_span, bcb, is_closure(statement)))
+            Some(CoverageSpan::new(span, expn_span, bcb, is_closure_or_coroutine(statement)))
         });
 
         let terminator_span = Some(data.terminator()).into_iter().filter_map(move |terminator| {
@@ -88,7 +88,7 @@ fn bcb_to_initial_coverage_spans<'a, 'tcx>(
     })
 }
 
-fn is_closure(statement: &Statement<'_>) -> bool {
+fn is_closure_or_coroutine(statement: &Statement<'_>) -> bool {
     match statement.kind {
         StatementKind::Assign(box (_, Rvalue::Aggregate(box ref agg_kind, _))) => match agg_kind {
             AggregateKind::Closure(_, _) | AggregateKind::Coroutine(_, _) => true,
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 54464600d99a8..44beafa08736e 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -1119,7 +1119,10 @@ fn create_fn_mono_item<'tcx>(
     source: Span,
 ) -> Spanned<MonoItem<'tcx>> {
     let def_id = instance.def_id();
-    if tcx.sess.opts.unstable_opts.profile_closures && def_id.is_local() && tcx.is_closure(def_id) {
+    if tcx.sess.opts.unstable_opts.profile_closures
+        && def_id.is_local()
+        && tcx.is_closure_or_coroutine(def_id)
+    {
         crate::util::dump_closure_profile(tcx, instance);
     }
 
diff --git a/compiler/rustc_passes/src/upvars.rs b/compiler/rustc_passes/src/upvars.rs
index d87df706cc84e..ded20c38543d4 100644
--- a/compiler/rustc_passes/src/upvars.rs
+++ b/compiler/rustc_passes/src/upvars.rs
@@ -11,7 +11,7 @@ use rustc_span::Span;
 
 pub fn provide(providers: &mut Providers) {
     providers.upvars_mentioned = |tcx, def_id| {
-        if !tcx.is_closure(def_id) {
+        if !tcx.is_closure_or_coroutine(def_id) {
             return None;
         }
 

From 847cd6c9deee0bfc87c293c4a94bbf1df851f6bb Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Sat, 30 Dec 2023 16:32:44 +0000
Subject: [PATCH 06/27] Use the right type for upvars

---
 compiler/rustc_middle/src/ty/instance.rs | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index 4b222d33b1057..2ac3cddfa15ad 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -661,12 +661,10 @@ fn polymorphize<'tcx>(
     // the unpolymorphized upvar closure would result in a polymorphized closure producing
     // multiple mono items (and eventually symbol clashes).
     let def_id = instance.def_id();
-    let upvars_ty = if tcx.is_closure_or_coroutine(def_id) {
-        Some(args.as_closure().tupled_upvars_ty())
-    } else if tcx.type_of(def_id).skip_binder().is_coroutine() {
-        Some(args.as_coroutine().tupled_upvars_ty())
-    } else {
-        None
+    let upvars_ty = match tcx.type_of(def_id).skip_binder().kind() {
+        ty::Closure(..) => Some(args.as_closure().tupled_upvars_ty()),
+        ty::Coroutine(..) => Some(args.as_coroutine().tupled_upvars_ty()),
+        _ => None,
     };
     let has_upvars = upvars_ty.is_some_and(|ty| !ty.tuple_fields().is_empty());
     debug!("polymorphize: upvars_ty={:?} has_upvars={:?}", upvars_ty, has_upvars);

From 86bd81fe833c338c1fb82428ea3414f54fd9d567 Mon Sep 17 00:00:00 2001
From: Gary Guo <gary@garyguo.net>
Date: Sun, 31 Dec 2023 16:25:15 +0000
Subject: [PATCH 07/27] Update tracking issue of naked_functions

The original tracking issue was superseded by a new one
(constrainted naked functions) and therefore is closed.
---
 compiler/rustc_feature/src/unstable.rs                     | 2 +-
 tests/ui/feature-gates/feature-gate-naked_functions.stderr | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 763bd4fc3916b..e6faad7438457 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -525,7 +525,7 @@ declare_features! (
     /// Allows the `#[must_not_suspend]` attribute.
     (unstable, must_not_suspend, "1.57.0", Some(83310)),
     /// Allows using `#[naked]` on functions.
-    (unstable, naked_functions, "1.9.0", Some(32408)),
+    (unstable, naked_functions, "1.9.0", Some(90957)),
     /// Allows specifying the as-needed link modifier
     (unstable, native_link_modifiers_as_needed, "1.53.0", Some(81490)),
     /// Allow negative trait implementations.
diff --git a/tests/ui/feature-gates/feature-gate-naked_functions.stderr b/tests/ui/feature-gates/feature-gate-naked_functions.stderr
index 4378fb36367ad..dc6c9138c5d2d 100644
--- a/tests/ui/feature-gates/feature-gate-naked_functions.stderr
+++ b/tests/ui/feature-gates/feature-gate-naked_functions.stderr
@@ -4,7 +4,7 @@ error[E0658]: the `#[naked]` attribute is an experimental feature
 LL | #[naked]
    | ^^^^^^^^
    |
-   = note: see issue #32408 <https://github.com/rust-lang/rust/issues/32408> for more information
+   = note: see issue #90957 <https://github.com/rust-lang/rust/issues/90957> for more information
    = help: add `#![feature(naked_functions)]` to the crate attributes to enable
 
 error[E0658]: the `#[naked]` attribute is an experimental feature
@@ -13,7 +13,7 @@ error[E0658]: the `#[naked]` attribute is an experimental feature
 LL | #[naked]
    | ^^^^^^^^
    |
-   = note: see issue #32408 <https://github.com/rust-lang/rust/issues/32408> for more information
+   = note: see issue #90957 <https://github.com/rust-lang/rust/issues/90957> for more information
    = help: add `#![feature(naked_functions)]` to the crate attributes to enable
 
 error: aborting due to 2 previous errors

From d796ad4209b2c45d66a8e8b2fa8beac462c80671 Mon Sep 17 00:00:00 2001
From: Lukas Markeffsky <@>
Date: Sun, 31 Dec 2023 20:31:06 +0100
Subject: [PATCH 08/27] rustdoc ui: adjust tooltip z-index to be above sidebar

---
 src/librustdoc/html/static/css/rustdoc.css  |  2 +-
 tests/rustdoc-gui/tooltip-over-sidebar.goml | 12 ++++++++++++
 2 files changed, 13 insertions(+), 1 deletion(-)
 create mode 100644 tests/rustdoc-gui/tooltip-over-sidebar.goml

diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index 995fd5d054d53..3686bbbda7a24 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -1046,7 +1046,7 @@ so that we can apply CSS-filters to change the arrow color in themes */
 	position: absolute;
 	top: 100%;
 	right: 0;
-	z-index: 2;
+	z-index: 101;
 	margin-top: 7px;
 	border-radius: 3px;
 	border: 1px solid var(--border-color);
diff --git a/tests/rustdoc-gui/tooltip-over-sidebar.goml b/tests/rustdoc-gui/tooltip-over-sidebar.goml
new file mode 100644
index 0000000000000..71bf69787317b
--- /dev/null
+++ b/tests/rustdoc-gui/tooltip-over-sidebar.goml
@@ -0,0 +1,12 @@
+// Check that the doctest info tooltips are above the sidebar.
+go-to: "file://" + |DOC_PATH| + "/test_docs/fn.foo.html"
+move-cursor-to: ".example-wrap.ignore .tooltip"
+wait-for: ".tooltip.popover"
+
+// Move cursor to top left corner of the tooltip and check that it doesn't fade.
+move-cursor-to: ".tooltip.popover"
+wait-for: 100
+assert: ".tooltip.popover:not(.fade-out)"
+
+move-cursor-to: (0, 0)
+wait-for: ".tooltip.popover.fade-out"

From f118c76235c383ed01eded4619f7d275bdb51acb Mon Sep 17 00:00:00 2001
From: bjorn3 <17426603+bjorn3@users.noreply.github.com>
Date: Sun, 31 Dec 2023 18:45:29 +0000
Subject: [PATCH 09/27] Remove two unused feature gates from rustc_query_impl

---
 compiler/rustc_query_impl/src/lib.rs | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs
index 59812efc32465..d5883f5281998 100644
--- a/compiler/rustc_query_impl/src/lib.rs
+++ b/compiler/rustc_query_impl/src/lib.rs
@@ -3,9 +3,6 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![doc(rust_logo)]
 #![feature(rustdoc_internals)]
-// this shouldn't be necessary, but the check for `&mut _` is too naive and denies returning a function pointer that takes a mut ref
-#![feature(const_mut_refs)]
-#![feature(const_refs_to_cell)]
 #![feature(min_specialization)]
 #![feature(never_type)]
 #![feature(rustc_attrs)]

From 5cbe41ae9e1058eb143adecccc2e12c622b67342 Mon Sep 17 00:00:00 2001
From: Carter Hunt Fogelman <chfogelman@gmail.com>
Date: Tue, 26 Dec 2023 02:09:48 -0800
Subject: [PATCH 10/27] Document that File does not buffer reads/writes, refer
 to BufReader/BufWriter

---
 library/std/src/fs.rs | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index 4310e10830380..0478aacf5288a 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -31,6 +31,10 @@ use crate::time::SystemTime;
 /// on closing are ignored by the implementation of `Drop`.  Use the method
 /// [`sync_all`] if these errors must be manually handled.
 ///
+/// `File` does not buffer reads and writes. For efficiency, consider wrapping the
+/// file in a [`BufReader`] or [`BufWriter`] when performing many small [`read`]
+/// or [`write`] calls, unless unbuffered reads and writes are required.
+///
 /// # Examples
 ///
 /// Creates a new file and write bytes to it (you can also use [`write()`]):
@@ -61,8 +65,7 @@ use crate::time::SystemTime;
 /// }
 /// ```
 ///
-/// It can be more efficient to read the contents of a file with a buffered
-/// [`Read`]er. This can be accomplished with [`BufReader<R>`]:
+/// Using a buffered [`Read`]er:
 ///
 /// ```no_run
 /// use std::fs::File;
@@ -93,8 +96,11 @@ use crate::time::SystemTime;
 /// perform synchronous I/O operations. Therefore the underlying file must not
 /// have been opened for asynchronous I/O (e.g. by using `FILE_FLAG_OVERLAPPED`).
 ///
-/// [`BufReader<R>`]: io::BufReader
+/// [`BufReader`]: io::BufReader
+/// [`BufWriter`]: io::BufReader
 /// [`sync_all`]: File::sync_all
+/// [`write`]: File::write
+/// [`read`]: File::read
 #[stable(feature = "rust1", since = "1.0.0")]
 #[cfg_attr(not(test), rustc_diagnostic_item = "File")]
 pub struct File {

From 884cb41d73da06527a25024153db236c22ba36b6 Mon Sep 17 00:00:00 2001
From: Gurinder Singh <frederick.the.fool@gmail.com>
Date: Mon, 1 Jan 2024 13:21:49 +0530
Subject: [PATCH 11/27] Minor improvements in comment for

---
 compiler/rustc_infer/src/infer/freshen.rs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs
index 11ab86277c1b1..c7cab048db1ba 100644
--- a/compiler/rustc_infer/src/infer/freshen.rs
+++ b/compiler/rustc_infer/src/infer/freshen.rs
@@ -5,7 +5,7 @@
 //! Freshening is used primarily to get a good type for inserting into a cache. The result
 //! summarizes what the type inferencer knows "so far". The primary place it is used right now is
 //! in the trait matching algorithm, which needs to be able to cache whether an `impl` self type
-//! matches some other type X -- *without* affecting `X`. That means if that if the type `X` is in
+//! matches some other type X -- *without* affecting `X`. That means that if the type `X` is in
 //! fact an unbound type variable, we want the match to be regarded as ambiguous, because depending
 //! on what type that type variable is ultimately assigned, the match may or may not succeed.
 //!
@@ -21,7 +21,7 @@
 //! Because of the manipulation required to handle closures, doing arbitrary operations on
 //! freshened types is not recommended. However, in addition to doing equality/hash
 //! comparisons (for caching), it is possible to do a `ty::_match` operation between
-//! 2 freshened types - this works even with the closure encoding.
+//! two freshened types - this works even with the closure encoding.
 //!
 //! __An important detail concerning regions.__ The freshener also replaces *all* free regions with
 //! 'erased. The reason behind this is that, in general, we do not take region relationships into

From 01ac44a664f575f209d2f507b38b6497162bc6e2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= <me@fmease.dev>
Date: Sun, 31 Dec 2023 18:23:23 +0100
Subject: [PATCH 12/27] Pretty-print always-const trait predicates correctly

---
 compiler/rustc_middle/src/ty/print/pretty.rs  | 33 +++++++++++------
 .../call-generic-method-nonconst.rs           |  2 +-
 .../call-generic-method-nonconst.stderr       |  4 +-
 .../unsatisfied-const-trait-bound.rs          | 33 +++++++++++++++++
 .../unsatisfied-const-trait-bound.stderr      | 37 +++++++++++++++++++
 5 files changed, 94 insertions(+), 15 deletions(-)
 create mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/unsatisfied-const-trait-bound.rs
 create mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/unsatisfied-const-trait-bound.stderr

diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 99384e34222d9..ebbd02e01bf33 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -1697,6 +1697,25 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
         })
     }
 
+    fn pretty_print_bound_constness(
+        &mut self,
+        trait_ref: ty::TraitRef<'tcx>,
+    ) -> Result<(), PrintError> {
+        define_scoped_cx!(self);
+
+        let Some(idx) = self.tcx().generics_of(trait_ref.def_id).host_effect_index else {
+            return Ok(());
+        };
+        let arg = trait_ref.args.const_at(idx);
+
+        if arg == self.tcx().consts.false_ {
+            p!("const ");
+        } else if arg != self.tcx().consts.true_ && !arg.has_infer() {
+            p!("~const ");
+        }
+        Ok(())
+    }
+
     fn should_print_verbose(&self) -> bool {
         self.tcx().sess.verbose_internals()
     }
@@ -2866,13 +2885,7 @@ define_print_and_forward_display! {
     }
 
     TraitPredPrintModifiersAndPath<'tcx> {
-        if let Some(idx) = cx.tcx().generics_of(self.0.trait_ref.def_id).host_effect_index
-        {
-            let arg = self.0.trait_ref.args.const_at(idx);
-            if arg != cx.tcx().consts.true_ && !arg.has_infer() {
-                p!("~const ");
-            }
-        }
+        p!(pretty_print_bound_constness(self.0.trait_ref));
         if let ty::ImplPolarity::Negative = self.0.polarity {
             p!("!")
         }
@@ -2905,11 +2918,7 @@ define_print_and_forward_display! {
 
     ty::TraitPredicate<'tcx> {
         p!(print(self.trait_ref.self_ty()), ": ");
-        if let Some(idx) = cx.tcx().generics_of(self.trait_ref.def_id).host_effect_index {
-            if self.trait_ref.args.const_at(idx) != cx.tcx().consts.true_ {
-                p!("~const ");
-            }
-        }
+        p!(pretty_print_bound_constness(self.trait_ref));
         if let ty::ImplPolarity::Negative = self.polarity {
             p!("!");
         }
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs
index 76bc738123d39..8d6176a5bace4 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs
@@ -21,6 +21,6 @@ const fn equals_self<T: ~const Foo>(t: &T) -> bool {
 // it not using the impl.
 
 pub const EQ: bool = equals_self(&S);
-//~^ ERROR: the trait bound `S: ~const Foo` is not satisfied
+//~^ ERROR: the trait bound `S: const Foo` is not satisfied
 
 fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr
index aea9a39b26107..3581b1fcd7dfb 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr
@@ -1,8 +1,8 @@
-error[E0277]: the trait bound `S: ~const Foo` is not satisfied
+error[E0277]: the trait bound `S: const Foo` is not satisfied
   --> $DIR/call-generic-method-nonconst.rs:23:34
    |
 LL | pub const EQ: bool = equals_self(&S);
-   |                      ----------- ^^ the trait `~const Foo` is not implemented for `S`
+   |                      ----------- ^^ the trait `const Foo` is not implemented for `S`
    |                      |
    |                      required by a bound introduced by this call
    |
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/unsatisfied-const-trait-bound.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/unsatisfied-const-trait-bound.rs
new file mode 100644
index 0000000000000..62a7b31237842
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/unsatisfied-const-trait-bound.rs
@@ -0,0 +1,33 @@
+// Ensure that we print unsatisfied always-const trait bounds as `const Trait` in diagnostics.
+
+#![feature(const_trait_impl, effects, generic_const_exprs)]
+#![allow(incomplete_features)]
+
+fn require<T: const Trait>() {}
+
+#[const_trait]
+trait Trait {
+    fn make() -> u32;
+}
+
+struct Ty;
+
+impl Trait for Ty {
+    fn make() -> u32 { 0 }
+}
+
+fn main() {
+    require::<Ty>(); //~ ERROR the trait bound `Ty: const Trait` is not satisfied
+}
+
+struct Container<const N: u32>;
+
+// FIXME(effects): Somehow emit `the trait bound `T: const Trait` is not satisfied` here instead
+//                 and suggest changing `Trait` to `const Trait`.
+fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
+//~^ ERROR mismatched types
+
+// FIXME(effects): Instead of suggesting `+ const Trait`, suggest
+//                 changing `~const Trait` to `const Trait`.
+const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {}
+//~^ ERROR the trait bound `T: const Trait` is not satisfied
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/unsatisfied-const-trait-bound.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/unsatisfied-const-trait-bound.stderr
new file mode 100644
index 0000000000000..2fb4fc1aa2b8e
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/unsatisfied-const-trait-bound.stderr
@@ -0,0 +1,37 @@
+error[E0308]: mismatched types
+  --> $DIR/unsatisfied-const-trait-bound.rs:27:37
+   |
+LL | fn accept0<T: Trait>(_: Container<{ T::make() }>) {}
+   |                                     ^^^^^^^^^ expected `false`, found `true`
+   |
+   = note: expected constant `false`
+              found constant `true`
+
+error[E0277]: the trait bound `T: const Trait` is not satisfied
+  --> $DIR/unsatisfied-const-trait-bound.rs:32:50
+   |
+LL | const fn accept1<T: ~const Trait>(_: Container<{ T::make() }>) {}
+   |                                                  ^ the trait `const Trait` is not implemented for `T`
+   |
+help: consider further restricting this bound
+   |
+LL | const fn accept1<T: ~const Trait + const Trait>(_: Container<{ T::make() }>) {}
+   |                                  +++++++++++++
+
+error[E0277]: the trait bound `Ty: const Trait` is not satisfied
+  --> $DIR/unsatisfied-const-trait-bound.rs:20:15
+   |
+LL |     require::<Ty>();
+   |               ^^ the trait `const Trait` is not implemented for `Ty`
+   |
+   = help: the trait `Trait` is implemented for `Ty`
+note: required by a bound in `require`
+  --> $DIR/unsatisfied-const-trait-bound.rs:6:15
+   |
+LL | fn require<T: const Trait>() {}
+   |               ^^^^^^^^^^^ required by this bound in `require`
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0277, E0308.
+For more information about an error, try `rustc --explain E0277`.

From b1853eb3bd579d9126fa392ced94b05d45efc67e Mon Sep 17 00:00:00 2001
From: Lukas Markeffsky <@>
Date: Sun, 31 Dec 2023 22:25:46 +0100
Subject: [PATCH 13/27] use css variable for z-index of the sidebar

and calculate the z-indices of things that go over the sidebar
---
 src/librustdoc/html/static/css/rustdoc.css | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index 3686bbbda7a24..cd53fcb8b7c16 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -14,6 +14,7 @@
 	   and on the RUSTDOC_MOBILE_BREAKPOINT */
 	--desktop-sidebar-width: 200px;
 	--src-sidebar-width: 300px;
+	--desktop-sidebar-z-index: 100;
 }
 
 /* See FiraSans-LICENSE.txt for the Fira Sans license. */
@@ -386,7 +387,7 @@ img {
 	height: 100vh;
 	top: 0;
 	left: 0;
-	z-index: 100;
+	z-index: var(--desktop-sidebar-z-index);
 }
 
 .rustdoc.src .sidebar {
@@ -407,7 +408,7 @@ img {
 	touch-action: none;
 	width: 9px;
 	cursor: col-resize;
-	z-index: 200;
+	z-index: calc(var(--desktop-sidebar-z-index) + 1);
 	position: fixed;
 	height: 100%;
 	/* make sure there's a 1px gap between the scrollbar and resize handle */
@@ -439,7 +440,6 @@ img {
 
 .sidebar-resizing .sidebar {
 	position: fixed;
-	z-index: 100;
 }
 .sidebar-resizing > body {
 	padding-left: var(--resizing-sidebar-width);
@@ -1046,7 +1046,7 @@ so that we can apply CSS-filters to change the arrow color in themes */
 	position: absolute;
 	top: 100%;
 	right: 0;
-	z-index: 101;
+	z-index: calc(var(--desktop-sidebar-z-index) + 1);
 	margin-top: 7px;
 	border-radius: 3px;
 	border: 1px solid var(--border-color);
@@ -1561,7 +1561,7 @@ a.tooltip:hover::after {
 }
 .src #sidebar-button {
 	left: 8px;
-	z-index: 101;
+	z-index: calc(var(--desktop-sidebar-z-index) + 1);
 }
 .hide-sidebar .src #sidebar-button {
 	position: static;

From 440ba5fae2b411855774783acd9e7937c55eb68b Mon Sep 17 00:00:00 2001
From: rustbot <47979223+rustbot@users.noreply.github.com>
Date: Mon, 1 Jan 2024 12:01:11 -0500
Subject: [PATCH 14/27] Update books

---
 src/doc/reference       | 2 +-
 src/doc/rust-by-example | 2 +-
 src/doc/rustc-dev-guide | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/doc/reference b/src/doc/reference
index f9f5b5babd955..3565c7978cfc9 160000
--- a/src/doc/reference
+++ b/src/doc/reference
@@ -1 +1 @@
-Subproject commit f9f5b5babd95515e7028c32d6ca4d9790f64c146
+Subproject commit 3565c7978cfc9662f5963b135690ff9cbbfa0318
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
index 4c2b24ff9d9cf..c0be6299e52e4 160000
--- a/src/doc/rust-by-example
+++ b/src/doc/rust-by-example
@@ -1 +1 @@
-Subproject commit 4c2b24ff9d9cf19f2fcff799a3a49b9a2c50ae8e
+Subproject commit c0be6299e52e4164c30ba6f41bd0ad0aaee64972
diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide
index 0610665a8687b..d13e85152a977 160000
--- a/src/doc/rustc-dev-guide
+++ b/src/doc/rustc-dev-guide
@@ -1 +1 @@
-Subproject commit 0610665a8687b1b0aa037917a1598b9f2a21e3ef
+Subproject commit d13e85152a977cd0bcaf583cf5f49e86225697de

From 82a57452376ef61515fadda0db2931e4099073e8 Mon Sep 17 00:00:00 2001
From: Lieselotte <52315535+she3py@users.noreply.github.com>
Date: Mon, 1 Jan 2024 20:06:23 +0100
Subject: [PATCH 15/27] Update deadlinks of `strict_provenance` lints

---
 compiler/rustc_lint_defs/src/builtin.rs | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 399e6968fae32..e35d1ee0461e3 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -2817,8 +2817,8 @@ declare_lint! {
     /// [`ptr::from_exposed_addr`].
     ///
     /// [issue #95228]: https://github.com/rust-lang/rust/issues/95228
-    /// [`ptr::with_addr`]: https://doc.rust-lang.org/core/ptr/fn.with_addr
-    /// [`ptr::from_exposed_addr`]: https://doc.rust-lang.org/core/ptr/fn.from_exposed_addr
+    /// [`ptr::with_addr`]: https://doc.rust-lang.org/core/primitive.pointer.html#method.with_addr
+    /// [`ptr::from_exposed_addr`]: https://doc.rust-lang.org/core/ptr/fn.from_exposed_addr.html
     pub FUZZY_PROVENANCE_CASTS,
     Allow,
     "a fuzzy integer to pointer cast is used",
@@ -2863,8 +2863,8 @@ declare_lint! {
     /// about the semantics.
     ///
     /// [issue #95228]: https://github.com/rust-lang/rust/issues/95228
-    /// [`ptr::addr`]: https://doc.rust-lang.org/core/ptr/fn.addr
-    /// [`ptr::expose_addr`]: https://doc.rust-lang.org/core/ptr/fn.expose_addr
+    /// [`ptr::addr`]: https://doc.rust-lang.org/core/primitive.pointer.html#method.addr
+    /// [`ptr::expose_addr`]: https://doc.rust-lang.org/core/primitive.pointer.html#method.expose_addr
     pub LOSSY_PROVENANCE_CASTS,
     Allow,
     "a lossy pointer to integer cast is used",

From 3d0297a1e1b74ab50b97f78cf4fd056cb0ed51a7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= <me@fmease.dev>
Date: Mon, 1 Jan 2024 19:29:27 +0100
Subject: [PATCH 16/27] Deny defaults for higher-ranked generic parameters

---
 compiler/rustc_ast_lowering/messages.ftl      |  5 +-
 compiler/rustc_ast_lowering/src/errors.rs     |  4 +-
 compiler/rustc_ast_lowering/src/lib.rs        | 70 +++++++++++--------
 tests/ui/closures/issue-112547.rs             | 15 ----
 .../parser/generic-param-default-in-binder.rs | 10 +++
 tests/ui/parser/issue-119042.rs               |  7 --
 .../binder-defaults-112547.rs                 | 16 +++++
 .../binder-defaults-112547.stderr}            | 15 +++-
 ...ue-118697.rs => binder-defaults-118697.rs} |  2 +-
 ...7.stderr => binder-defaults-118697.stderr} | 12 ++--
 .../binder-defaults-119489.rs                 | 12 ++++
 .../binder-defaults-119489.stderr             | 31 ++++++++
 12 files changed, 133 insertions(+), 66 deletions(-)
 delete mode 100644 tests/ui/closures/issue-112547.rs
 create mode 100644 tests/ui/parser/generic-param-default-in-binder.rs
 delete mode 100644 tests/ui/parser/issue-119042.rs
 create mode 100644 tests/ui/traits/non_lifetime_binders/binder-defaults-112547.rs
 rename tests/ui/{closures/issue-112547.stderr => traits/non_lifetime_binders/binder-defaults-112547.stderr} (62%)
 rename tests/ui/traits/non_lifetime_binders/{issue-118697.rs => binder-defaults-118697.rs} (74%)
 rename tests/ui/traits/non_lifetime_binders/{issue-118697.stderr => binder-defaults-118697.stderr} (61%)
 create mode 100644 tests/ui/traits/non_lifetime_binders/binder-defaults-119489.rs
 create mode 100644 tests/ui/traits/non_lifetime_binders/binder-defaults-119489.stderr

diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl
index 5a1b1c799eb98..fd94e7e9341d4 100644
--- a/compiler/rustc_ast_lowering/messages.ftl
+++ b/compiler/rustc_ast_lowering/messages.ftl
@@ -45,8 +45,6 @@ ast_lowering_closure_cannot_be_static = closures cannot be static
 ast_lowering_coroutine_too_many_parameters =
     too many parameters for a coroutine (expected 0 or 1 parameters)
 
-ast_lowering_default_parameter_in_binder = default parameter is not allowed in this binder
-
 ast_lowering_does_not_support_modifiers =
     the `{$class_name}` register class does not support template modifiers
 
@@ -58,6 +56,9 @@ ast_lowering_functional_record_update_destructuring_assignment =
     functional record updates are not allowed in destructuring assignments
     .suggestion = consider removing the trailing pattern
 
+ast_lowering_generic_param_default_in_binder =
+    defaults for generic parameters are not allowed in `for<...>` binders
+
 ast_lowering_generic_type_with_parentheses =
     parenthesized type parameters may only be used with a `Fn` trait
     .label = only `Fn` traits may use parentheses
diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs
index 718a5b03cf27b..710690d0d86a4 100644
--- a/compiler/rustc_ast_lowering/src/errors.rs
+++ b/compiler/rustc_ast_lowering/src/errors.rs
@@ -397,8 +397,8 @@ pub enum BadReturnTypeNotation {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_lowering_default_parameter_in_binder)]
-pub(crate) struct UnexpectedDefaultParameterInBinder {
+#[diag(ast_lowering_generic_param_default_in_binder)]
+pub(crate) struct GenericParamDefaultInBinder {
     #[primary_span]
     pub span: Span,
 }
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 92fd29c47aff3..c7c77bf56b7b0 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -66,7 +66,6 @@ use rustc_session::parse::{add_feature_diagnostics, feature_err};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{DesugaringKind, Span, DUMMY_SP};
 use smallvec::SmallVec;
-use std::borrow::Cow;
 use std::collections::hash_map::Entry;
 use thin_vec::ThinVec;
 
@@ -884,27 +883,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         binder: NodeId,
         generic_params: &[GenericParam],
     ) -> &'hir [hir::GenericParam<'hir>] {
-        let mut generic_params: Vec<_> = generic_params
-            .iter()
-            .map(|param| {
-                let param = match param.kind {
-                    GenericParamKind::Type { ref default } if let Some(ty) = default => {
-                        // Default type is not permitted in non-lifetime binders.
-                        // So we emit an error and default to `None` to prevent
-                        // potential ice.
-                        self.dcx().emit_err(errors::UnexpectedDefaultParameterInBinder {
-                            span: ty.span(),
-                        });
-                        let param = GenericParam {
-                            kind: GenericParamKind::Type { default: None },
-                            ..param.clone()
-                        };
-                        Cow::Owned(param)
-                    }
-                    _ => Cow::Borrowed(param),
-                };
-                self.lower_generic_param(param.as_ref(), hir::GenericParamSource::Binder)
-            })
+        let mut generic_params: Vec<_> = self
+            .lower_generic_params_mut(generic_params, hir::GenericParamSource::Binder)
             .collect();
         let extra_lifetimes = self.resolver.take_extra_lifetime_params(binder);
         debug!(?extra_lifetimes);
@@ -2136,7 +2116,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         param: &GenericParam,
         source: hir::GenericParamSource,
     ) -> hir::GenericParam<'hir> {
-        let (name, kind) = self.lower_generic_param_kind(param);
+        let (name, kind) = self.lower_generic_param_kind(param, source);
 
         let hir_id = self.lower_node_id(param.id);
         self.lower_attrs(hir_id, &param.attrs);
@@ -2155,6 +2135,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     fn lower_generic_param_kind(
         &mut self,
         param: &GenericParam,
+        source: hir::GenericParamSource,
     ) -> (hir::ParamName, hir::GenericParamKind<'hir>) {
         match &param.kind {
             GenericParamKind::Lifetime => {
@@ -2173,22 +2154,51 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 (param_name, kind)
             }
             GenericParamKind::Type { default, .. } => {
-                let kind = hir::GenericParamKind::Type {
-                    default: default.as_ref().map(|x| {
+                // Not only do we deny type param defaults in binders but we also map them to `None`
+                // since later compiler stages cannot handle them (and shouldn't need to be able to).
+                let default = default
+                    .as_ref()
+                    .filter(|_| match source {
+                        hir::GenericParamSource::Generics => true,
+                        hir::GenericParamSource::Binder => {
+                            self.dcx().emit_err(errors::GenericParamDefaultInBinder {
+                                span: param.span(),
+                            });
+
+                            false
+                        }
+                    })
+                    .map(|def| {
                         self.lower_ty(
-                            x,
+                            def,
                             &ImplTraitContext::Disallowed(ImplTraitPosition::GenericDefault),
                         )
-                    }),
-                    synthetic: false,
-                };
+                    });
+
+                let kind = hir::GenericParamKind::Type { default, synthetic: false };
 
                 (hir::ParamName::Plain(self.lower_ident(param.ident)), kind)
             }
             GenericParamKind::Const { ty, kw_span: _, default } => {
                 let ty = self
                     .lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::GenericDefault));
-                let default = default.as_ref().map(|def| self.lower_anon_const(def));
+
+                // Not only do we deny const param defaults in binders but we also map them to `None`
+                // since later compiler stages cannot handle them (and shouldn't need to be able to).
+                let default = default
+                    .as_ref()
+                    .filter(|_| match source {
+                        hir::GenericParamSource::Generics => true,
+                        hir::GenericParamSource::Binder => {
+                            self.dcx().emit_err(errors::GenericParamDefaultInBinder {
+                                span: param.span(),
+                            });
+
+                            false
+                        }
+                    })
+                    .map(|def| self.lower_anon_const(def));
+
                 (
                     hir::ParamName::Plain(self.lower_ident(param.ident)),
                     hir::GenericParamKind::Const { ty, default, is_host_effect: false },
diff --git a/tests/ui/closures/issue-112547.rs b/tests/ui/closures/issue-112547.rs
deleted file mode 100644
index 8ecb2abccd4f9..0000000000000
--- a/tests/ui/closures/issue-112547.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-#![feature(non_lifetime_binders)]
-        //~^ WARNING the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-
-pub fn bar()
-where
-    for<const N: usize = {
-    (||1usize)()
-}> V: IntoIterator
-//~^ ERROR cannot find type `V` in this scope [E0412]
-{
-}
-
-fn main() {
-    bar();
-}
diff --git a/tests/ui/parser/generic-param-default-in-binder.rs b/tests/ui/parser/generic-param-default-in-binder.rs
new file mode 100644
index 0000000000000..78dc4186b3a53
--- /dev/null
+++ b/tests/ui/parser/generic-param-default-in-binder.rs
@@ -0,0 +1,10 @@
+// Check that defaults for generic parameters in `for<...>` binders are
+// syntactically valid. See also PR #119042.
+
+// check-pass
+
+macro_rules! a { ($ty:ty) => {} }
+
+a! { for<T = &i32> fn() }
+
+fn main() {}
diff --git a/tests/ui/parser/issue-119042.rs b/tests/ui/parser/issue-119042.rs
deleted file mode 100644
index a4fee169d1cbc..0000000000000
--- a/tests/ui/parser/issue-119042.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-// check-pass
-
-macro_rules! a { ($ty:ty) => {} }
-
-a! { for<T = &i32> fn() }
-
-fn main() {}
diff --git a/tests/ui/traits/non_lifetime_binders/binder-defaults-112547.rs b/tests/ui/traits/non_lifetime_binders/binder-defaults-112547.rs
new file mode 100644
index 0000000000000..c6bf0dc1f720f
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/binder-defaults-112547.rs
@@ -0,0 +1,16 @@
+#![feature(non_lifetime_binders)]
+//~^ WARN the feature `non_lifetime_binders` is incomplete
+
+pub fn bar()
+where
+    for<const N: usize = {
+    (||1usize)()
+}> V: IntoIterator
+//~^^^ ERROR defaults for generic parameters are not allowed in `for<...>` binders
+//~^^ ERROR cannot find type `V` in this scope
+{
+}
+
+fn main() {
+    bar();
+}
diff --git a/tests/ui/closures/issue-112547.stderr b/tests/ui/traits/non_lifetime_binders/binder-defaults-112547.stderr
similarity index 62%
rename from tests/ui/closures/issue-112547.stderr
rename to tests/ui/traits/non_lifetime_binders/binder-defaults-112547.stderr
index f47ea60729763..edc55a3c8e68f 100644
--- a/tests/ui/closures/issue-112547.stderr
+++ b/tests/ui/traits/non_lifetime_binders/binder-defaults-112547.stderr
@@ -1,5 +1,5 @@
 error[E0412]: cannot find type `V` in this scope
-  --> $DIR/issue-112547.rs:8:4
+  --> $DIR/binder-defaults-112547.rs:8:4
    |
 LL | }> V: IntoIterator
    |    ^ not found in this scope
@@ -10,7 +10,7 @@ LL | pub fn bar<V>()
    |           +++
 
 warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-112547.rs:1:12
+  --> $DIR/binder-defaults-112547.rs:1:12
    |
 LL | #![feature(non_lifetime_binders)]
    |            ^^^^^^^^^^^^^^^^^^^^
@@ -18,6 +18,15 @@ LL | #![feature(non_lifetime_binders)]
    = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
    = note: `#[warn(incomplete_features)]` on by default
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: defaults for generic parameters are not allowed in `for<...>` binders
+  --> $DIR/binder-defaults-112547.rs:6:9
+   |
+LL |       for<const N: usize = {
+   |  _________^
+LL | |     (||1usize)()
+LL | | }> V: IntoIterator
+   | |_^
+
+error: aborting due to 2 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0412`.
diff --git a/tests/ui/traits/non_lifetime_binders/issue-118697.rs b/tests/ui/traits/non_lifetime_binders/binder-defaults-118697.rs
similarity index 74%
rename from tests/ui/traits/non_lifetime_binders/issue-118697.rs
rename to tests/ui/traits/non_lifetime_binders/binder-defaults-118697.rs
index a282d0c5a40d9..2dc9fb98b153d 100644
--- a/tests/ui/traits/non_lifetime_binders/issue-118697.rs
+++ b/tests/ui/traits/non_lifetime_binders/binder-defaults-118697.rs
@@ -2,7 +2,7 @@
 #![feature(non_lifetime_binders)]
 
 type T = dyn for<V = A(&())> Fn(());
-//~^ ERROR default parameter is not allowed in this binder
+//~^ ERROR defaults for generic parameters are not allowed in `for<...>` binders
 //~| ERROR cannot find type `A` in this scope
 //~| ERROR late-bound type parameter not allowed on trait object types
 
diff --git a/tests/ui/traits/non_lifetime_binders/issue-118697.stderr b/tests/ui/traits/non_lifetime_binders/binder-defaults-118697.stderr
similarity index 61%
rename from tests/ui/traits/non_lifetime_binders/issue-118697.stderr
rename to tests/ui/traits/non_lifetime_binders/binder-defaults-118697.stderr
index 52ce568d69ddc..6b93f52dbfcaa 100644
--- a/tests/ui/traits/non_lifetime_binders/issue-118697.stderr
+++ b/tests/ui/traits/non_lifetime_binders/binder-defaults-118697.stderr
@@ -1,20 +1,20 @@
 error[E0412]: cannot find type `A` in this scope
-  --> $DIR/issue-118697.rs:4:22
+  --> $DIR/binder-defaults-118697.rs:4:22
    |
 LL | type T = dyn for<V = A(&())> Fn(());
    |                      ^ not found in this scope
 
-error: default parameter is not allowed in this binder
-  --> $DIR/issue-118697.rs:4:22
+error: defaults for generic parameters are not allowed in `for<...>` binders
+  --> $DIR/binder-defaults-118697.rs:4:18
    |
 LL | type T = dyn for<V = A(&())> Fn(());
-   |                      ^^^^^^
+   |                  ^^^^^^^^^^
 
 error: late-bound type parameter not allowed on trait object types
-  --> $DIR/issue-118697.rs:4:18
+  --> $DIR/binder-defaults-118697.rs:4:18
    |
 LL | type T = dyn for<V = A(&())> Fn(());
-   |                  ^
+   |                  ^^^^^^^^^^
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/traits/non_lifetime_binders/binder-defaults-119489.rs b/tests/ui/traits/non_lifetime_binders/binder-defaults-119489.rs
new file mode 100644
index 0000000000000..f33da416ad8ae
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/binder-defaults-119489.rs
@@ -0,0 +1,12 @@
+#![feature(non_lifetime_binders, generic_const_exprs)]
+//~^ WARN the feature `non_lifetime_binders` is incomplete
+//~| WARN the feature `generic_const_exprs` is incomplete
+
+fn fun()
+where
+    for<T = (), const N: usize = 1> ():,
+//~^ ERROR defaults for generic parameters are not allowed in `for<...>` binders
+//~| ERROR defaults for generic parameters are not allowed in `for<...>` binders
+{}
+
+fn main() {}
diff --git a/tests/ui/traits/non_lifetime_binders/binder-defaults-119489.stderr b/tests/ui/traits/non_lifetime_binders/binder-defaults-119489.stderr
new file mode 100644
index 0000000000000..7fe82f1f097c4
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/binder-defaults-119489.stderr
@@ -0,0 +1,31 @@
+warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/binder-defaults-119489.rs:1:12
+   |
+LL | #![feature(non_lifetime_binders, generic_const_exprs)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/binder-defaults-119489.rs:1:34
+   |
+LL | #![feature(non_lifetime_binders, generic_const_exprs)]
+   |                                  ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
+
+error: defaults for generic parameters are not allowed in `for<...>` binders
+  --> $DIR/binder-defaults-119489.rs:7:9
+   |
+LL |     for<T = (), const N: usize = 1> ():,
+   |         ^^^^^^
+
+error: defaults for generic parameters are not allowed in `for<...>` binders
+  --> $DIR/binder-defaults-119489.rs:7:17
+   |
+LL |     for<T = (), const N: usize = 1> ():,
+   |                 ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors; 2 warnings emitted
+

From 23924fe3a1dfa372c17db15686a7cd53eb1ee18d Mon Sep 17 00:00:00 2001
From: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date: Tue, 2 Jan 2024 10:19:03 +0000
Subject: [PATCH 17/27] Mark myself as back from leave

---
 triagebot.toml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/triagebot.toml b/triagebot.toml
index 27b174454b4e0..5406500cec302 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -639,7 +639,7 @@ cc = ["@nnethercote"]
 [assign]
 warn_non_default_branch = true
 contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html"
-users_on_vacation = ["jyn514", "oli-obk", "spastorino"]
+users_on_vacation = ["jyn514", "spastorino"]
 
 [assign.adhoc_groups]
 compiler-team = [

From 5e7c1b93ac7f5fb1bd5297980e8b6b3657a10c32 Mon Sep 17 00:00:00 2001
From: Zalathar <Zalathar@users.noreply.github.com>
Date: Tue, 2 Jan 2024 22:57:04 +1100
Subject: [PATCH 18/27] coverage: Avoid a query stability hazard in
 `function_coverage_map`

When #118865 started enforcing the `rustc::potential_query_instability` lint in
`rustc_codegen_llvm`, it added an exemption for this site, arguing that the
entries are only used to create a list of filenames that is later sorted.

However, the list of entries also gets traversed when creating the function
coverage records in LLVM IR, which may be sensitive to hash-based ordering.

This patch therefore changes `function_coverage_map` to use `FxIndexMap`, which
should avoid hash-based instability by iterating in insertion order.
---
 compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs | 5 -----
 compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs    | 8 ++++----
 2 files changed, 4 insertions(+), 9 deletions(-)

diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
index 33bfde03a31c3..51df14df644e0 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
@@ -58,11 +58,6 @@ pub fn finalize(cx: &CodegenCx<'_, '_>) {
         return;
     }
 
-    // The entries of the map are only used to get a list of all files with
-    // coverage info. In the end the list of files is passed into
-    // `GlobalFileTable::new()` which internally do `.sort_unstable_by()`, so
-    // the iteration order here does not matter.
-    #[allow(rustc::potential_query_instability)]
     let function_coverage_entries = function_coverage_map
         .into_iter()
         .map(|(instance, function_coverage)| (instance, function_coverage.into_finished()))
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
index 0befbb5a39be3..733a77d24c2a4 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
@@ -10,7 +10,7 @@ use rustc_codegen_ssa::traits::{
     BaseTypeMethods, BuilderMethods, ConstMethods, CoverageInfoBuilderMethods, MiscMethods,
     StaticMethods,
 };
-use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
 use rustc_llvm::RustString;
 use rustc_middle::bug;
 use rustc_middle::mir::coverage::CoverageKind;
@@ -30,7 +30,7 @@ const VAR_ALIGN_BYTES: usize = 8;
 pub struct CrateCoverageContext<'ll, 'tcx> {
     /// Coverage data for each instrumented function identified by DefId.
     pub(crate) function_coverage_map:
-        RefCell<FxHashMap<Instance<'tcx>, FunctionCoverageCollector<'tcx>>>,
+        RefCell<FxIndexMap<Instance<'tcx>, FunctionCoverageCollector<'tcx>>>,
     pub(crate) pgo_func_name_var_map: RefCell<FxHashMap<Instance<'tcx>, &'ll llvm::Value>>,
 }
 
@@ -44,8 +44,8 @@ impl<'ll, 'tcx> CrateCoverageContext<'ll, 'tcx> {
 
     pub fn take_function_coverage_map(
         &self,
-    ) -> FxHashMap<Instance<'tcx>, FunctionCoverageCollector<'tcx>> {
-        self.function_coverage_map.replace(FxHashMap::default())
+    ) -> FxIndexMap<Instance<'tcx>, FunctionCoverageCollector<'tcx>> {
+        self.function_coverage_map.replace(FxIndexMap::default())
     }
 }
 

From 94c43ccd876f87a556aacd8f87228b41632573b4 Mon Sep 17 00:00:00 2001
From: Ben Kimock <kimockb@gmail.com>
Date: Mon, 1 Jan 2024 22:34:07 -0500
Subject: [PATCH 19/27] Report I/O errors with emit_fatal not emit_err

---
 .../rustc_incremental/src/persist/file_format.rs   | 14 +++-----------
 compiler/rustc_interface/src/queries.rs            |  2 +-
 compiler/rustc_metadata/src/rmeta/encoder.rs       |  4 ++--
 3 files changed, 6 insertions(+), 14 deletions(-)

diff --git a/compiler/rustc_incremental/src/persist/file_format.rs b/compiler/rustc_incremental/src/persist/file_format.rs
index e68195acee097..b459f82f23e32 100644
--- a/compiler/rustc_incremental/src/persist/file_format.rs
+++ b/compiler/rustc_incremental/src/persist/file_format.rs
@@ -55,18 +55,12 @@ where
             debug!("save: remove old file");
         }
         Err(err) if err.kind() == io::ErrorKind::NotFound => (),
-        Err(err) => {
-            sess.dcx().emit_err(errors::DeleteOld { name, path: path_buf, err });
-            return;
-        }
+        Err(err) => sess.dcx().emit_fatal(errors::DeleteOld { name, path: path_buf, err }),
     }
 
     let mut encoder = match FileEncoder::new(&path_buf) {
         Ok(encoder) => encoder,
-        Err(err) => {
-            sess.dcx().emit_err(errors::CreateNew { name, path: path_buf, err });
-            return;
-        }
+        Err(err) => sess.dcx().emit_fatal(errors::CreateNew { name, path: path_buf, err }),
     };
 
     write_file_header(&mut encoder, sess);
@@ -80,9 +74,7 @@ where
             );
             debug!("save: data written to disk successfully");
         }
-        Err((path, err)) => {
-            sess.dcx().emit_err(errors::WriteNew { name, path, err });
-        }
+        Err((path, err)) => sess.dcx().emit_fatal(errors::WriteNew { name, path, err }),
     }
 }
 
diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs
index 1ea3db26e212b..07bbe78dc2d45 100644
--- a/compiler/rustc_interface/src/queries.rs
+++ b/compiler/rustc_interface/src/queries.rs
@@ -332,7 +332,7 @@ impl Compiler {
         // the global context.
         _timer = Some(self.sess.timer("free_global_ctxt"));
         if let Err((path, error)) = queries.finish() {
-            self.sess.dcx().emit_err(errors::FailedWritingFile { path: &path, error });
+            self.sess.dcx().emit_fatal(errors::FailedWritingFile { path: &path, error });
         }
 
         ret
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 3e7297a74f983..9e1f6585db97b 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -2241,12 +2241,12 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) {
     // If we forget this, compilation can succeed with an incomplete rmeta file,
     // causing an ICE when the rmeta file is read by another compilation.
     if let Err((path, err)) = ecx.opaque.finish() {
-        tcx.dcx().emit_err(FailWriteFile { path: &path, err });
+        tcx.dcx().emit_fatal(FailWriteFile { path: &path, err });
     }
 
     let file = ecx.opaque.file();
     if let Err(err) = encode_root_position(file, root.position.get()) {
-        tcx.dcx().emit_err(FailWriteFile { path: ecx.opaque.path(), err });
+        tcx.dcx().emit_fatal(FailWriteFile { path: ecx.opaque.path(), err });
     }
 
     // Record metadata size for self-profiling

From ba860344e1656eb577b0e1484cd68b16b7735a59 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= <me@fmease.dev>
Date: Mon, 1 Jan 2024 23:23:11 +0100
Subject: [PATCH 20/27] Don't synthesize host effect params for trait assoc fns
 marked const

---
 compiler/rustc_ast_lowering/src/item.rs           | 10 ++++++----
 .../effects/trait-fn-const.rs                     | 13 +++++++++++++
 .../effects/trait-fn-const.stderr                 | 15 +++++++++++++++
 3 files changed, 34 insertions(+), 4 deletions(-)
 create mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/effects/trait-fn-const.rs
 create mode 100644 tests/ui/rfcs/rfc-2632-const-trait-impl/effects/trait-fn-const.stderr

diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index 3848f3b778298..3e58570767d70 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -1254,11 +1254,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
         coroutine_kind: Option<CoroutineKind>,
     ) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) {
         let header = self.lower_fn_header(sig.header);
+        // Don't pass along the user-provided constness of trait associated functions; we don't want to
+        // synthesize a host effect param for them. We reject `const` on them during AST validation.
+        let constness = if kind == FnDeclKind::Inherent { sig.header.constness } else { Const::No };
         let itctx = ImplTraitContext::Universal;
-        let (generics, decl) =
-            self.lower_generics(generics, sig.header.constness, id, &itctx, |this| {
-                this.lower_fn_decl(&sig.decl, id, sig.span, kind, coroutine_kind)
-            });
+        let (generics, decl) = self.lower_generics(generics, constness, id, &itctx, |this| {
+            this.lower_fn_decl(&sig.decl, id, sig.span, kind, coroutine_kind)
+        });
         (generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) })
     }
 
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/trait-fn-const.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/trait-fn-const.rs
new file mode 100644
index 0000000000000..40e8bfdcc172f
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/trait-fn-const.rs
@@ -0,0 +1,13 @@
+// Regression test for issue #113378.
+#![feature(const_trait_impl, effects)]
+
+#[const_trait]
+trait Trait {
+    const fn fun(); //~ ERROR functions in traits cannot be declared const
+}
+
+impl const Trait for () {
+    const fn fun() {}  //~ ERROR functions in traits cannot be declared const
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/trait-fn-const.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/trait-fn-const.stderr
new file mode 100644
index 0000000000000..09fe580ae5c42
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/trait-fn-const.stderr
@@ -0,0 +1,15 @@
+error[E0379]: functions in traits cannot be declared const
+  --> $DIR/trait-fn-const.rs:6:5
+   |
+LL |     const fn fun();
+   |     ^^^^^ functions in traits cannot be const
+
+error[E0379]: functions in traits cannot be declared const
+  --> $DIR/trait-fn-const.rs:10:5
+   |
+LL |     const fn fun() {}
+   |     ^^^^^ functions in traits cannot be const
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0379`.

From 8f546aa495dee00326d40fe277ed5fef1f68175e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= <me@fmease.dev>
Date: Tue, 2 Jan 2024 01:11:21 +0100
Subject: [PATCH 21/27] Turn a bug!() into a span_delay_bug()

No reason why this needs to be a `bug!()`.
---
 compiler/rustc_hir_analysis/src/collect/generics_of.rs | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
index 5abc752309ad5..b44b2eefabbc6 100644
--- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
@@ -315,7 +315,10 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
 
             if is_host_effect {
                 if let Some(idx) = host_effect_index {
-                    bug!("parent also has host effect param? index: {idx}, def: {def_id:?}");
+                    tcx.dcx().span_delayed_bug(
+                        param.span,
+                        format!("parent also has host effect param? index: {idx}, def: {def_id:?}"),
+                    );
                 }
 
                 host_effect_index = Some(index as usize);

From ae8e401c9f8b51dc8ff3ac5914e0203ea95e26d2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= <me@fmease.dev>
Date: Tue, 2 Jan 2024 00:26:50 +0100
Subject: [PATCH 22/27] E0379: Make diagnostic more precise

---
 compiler/rustc_ast_passes/messages.ftl                 | 10 ++++++++--
 compiler/rustc_ast_passes/src/ast_validation.rs        |  2 +-
 compiler/rustc_ast_passes/src/errors.rs                |  1 +
 compiler/rustc_error_codes/src/error_codes/E0379.md    |  4 ++++
 tests/ui/consts/const-fn-mismatch.rs                   |  2 +-
 tests/ui/consts/const-fn-mismatch.stderr               |  4 ++--
 tests/ui/feature-gates/feature-gate-min_const_fn.rs    |  2 +-
 .../ui/feature-gates/feature-gate-min_const_fn.stderr  |  4 ++--
 tests/ui/mismatched_types/const-fn-in-trait.stderr     |  4 ++--
 tests/ui/parser/fn-header-semantic-fail.rs             |  4 ++--
 tests/ui/parser/fn-header-semantic-fail.stderr         |  8 ++++----
 .../effects/trait-fn-const.rs                          |  2 +-
 .../effects/trait-fn-const.stderr                      |  4 ++--
 13 files changed, 31 insertions(+), 20 deletions(-)

diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl
index b5612c1820d0c..b7274db029f6e 100644
--- a/compiler/rustc_ast_passes/messages.ftl
+++ b/compiler/rustc_ast_passes/messages.ftl
@@ -233,8 +233,14 @@ ast_passes_tilde_const_disallowed = `~const` is not allowed here
     .item = this item cannot have `~const` trait bounds
 
 ast_passes_trait_fn_const =
-    functions in traits cannot be declared const
-    .label = functions in traits cannot be const
+    functions in {$in_impl ->
+        [true] trait impls
+        *[false] traits
+    } cannot be declared const
+    .label = functions in {$in_impl ->
+        [true] trait impls
+        *[false] traits
+    } cannot be const
 
 ast_passes_trait_object_single_bound = only a single explicit lifetime bound is permitted
 
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index bc5cf463f1204..39ea684087e51 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -293,7 +293,7 @@ impl<'a> AstValidator<'a> {
 
     fn check_trait_fn_not_const(&self, constness: Const) {
         if let Const::Yes(span) = constness {
-            self.dcx().emit_err(errors::TraitFnConst { span });
+            self.dcx().emit_err(errors::TraitFnConst { span, in_impl: self.in_trait_impl });
         }
     }
 
diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs
index 0cec4374be2ee..ebaa7ccecc916 100644
--- a/compiler/rustc_ast_passes/src/errors.rs
+++ b/compiler/rustc_ast_passes/src/errors.rs
@@ -49,6 +49,7 @@ pub struct TraitFnConst {
     #[primary_span]
     #[label]
     pub span: Span,
+    pub in_impl: bool,
 }
 
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_error_codes/src/error_codes/E0379.md b/compiler/rustc_error_codes/src/error_codes/E0379.md
index ab438e4144712..35f546cfdb737 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0379.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0379.md
@@ -6,6 +6,10 @@ Erroneous code example:
 trait Foo {
     const fn bar() -> u32; // error!
 }
+
+impl Foo for () {
+    const fn bar() -> u32 { 0 } // error!
+}
 ```
 
 Trait methods cannot be declared `const` by design. For more information, see
diff --git a/tests/ui/consts/const-fn-mismatch.rs b/tests/ui/consts/const-fn-mismatch.rs
index 3107b8128e602..b17e4cedd3ff6 100644
--- a/tests/ui/consts/const-fn-mismatch.rs
+++ b/tests/ui/consts/const-fn-mismatch.rs
@@ -9,7 +9,7 @@ trait Foo {
 
 impl Foo for u32 {
     const fn f() -> u32 {
-        //~^ ERROR functions in traits cannot be declared const
+        //~^ ERROR functions in trait impls cannot be declared const
         22
     }
 }
diff --git a/tests/ui/consts/const-fn-mismatch.stderr b/tests/ui/consts/const-fn-mismatch.stderr
index beaf52c0cfb36..7d681c212b960 100644
--- a/tests/ui/consts/const-fn-mismatch.stderr
+++ b/tests/ui/consts/const-fn-mismatch.stderr
@@ -1,8 +1,8 @@
-error[E0379]: functions in traits cannot be declared const
+error[E0379]: functions in trait impls cannot be declared const
   --> $DIR/const-fn-mismatch.rs:11:5
    |
 LL |     const fn f() -> u32 {
-   |     ^^^^^ functions in traits cannot be const
+   |     ^^^^^ functions in trait impls cannot be const
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/feature-gates/feature-gate-min_const_fn.rs b/tests/ui/feature-gates/feature-gate-min_const_fn.rs
index 8f9b433009d3c..3d61a9eb93777 100644
--- a/tests/ui/feature-gates/feature-gate-min_const_fn.rs
+++ b/tests/ui/feature-gates/feature-gate-min_const_fn.rs
@@ -8,7 +8,7 @@ trait Foo {
 }
 
 impl Foo for u32 {
-    const fn foo() -> u32 { 0 } //~ ERROR functions in traits cannot be declared const
+    const fn foo() -> u32 { 0 } //~ ERROR functions in trait impls cannot be declared const
 }
 
 trait Bar {}
diff --git a/tests/ui/feature-gates/feature-gate-min_const_fn.stderr b/tests/ui/feature-gates/feature-gate-min_const_fn.stderr
index d7a58591364ed..abc9ddabd51ea 100644
--- a/tests/ui/feature-gates/feature-gate-min_const_fn.stderr
+++ b/tests/ui/feature-gates/feature-gate-min_const_fn.stderr
@@ -10,11 +10,11 @@ error[E0379]: functions in traits cannot be declared const
 LL |     const fn bar() -> u32 { 0 }
    |     ^^^^^ functions in traits cannot be const
 
-error[E0379]: functions in traits cannot be declared const
+error[E0379]: functions in trait impls cannot be declared const
   --> $DIR/feature-gate-min_const_fn.rs:11:5
    |
 LL |     const fn foo() -> u32 { 0 }
-   |     ^^^^^ functions in traits cannot be const
+   |     ^^^^^ functions in trait impls cannot be const
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/mismatched_types/const-fn-in-trait.stderr b/tests/ui/mismatched_types/const-fn-in-trait.stderr
index 7d1fbe45c5302..75122237bf596 100644
--- a/tests/ui/mismatched_types/const-fn-in-trait.stderr
+++ b/tests/ui/mismatched_types/const-fn-in-trait.stderr
@@ -4,11 +4,11 @@ error[E0379]: functions in traits cannot be declared const
 LL |     const fn g();
    |     ^^^^^ functions in traits cannot be const
 
-error[E0379]: functions in traits cannot be declared const
+error[E0379]: functions in trait impls cannot be declared const
   --> $DIR/const-fn-in-trait.rs:7:5
    |
 LL |     const fn f() -> u32 { 22 }
-   |     ^^^^^ functions in traits cannot be const
+   |     ^^^^^ functions in trait impls cannot be const
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/parser/fn-header-semantic-fail.rs b/tests/ui/parser/fn-header-semantic-fail.rs
index f8b58cad7c144..f01e1c2277c6f 100644
--- a/tests/ui/parser/fn-header-semantic-fail.rs
+++ b/tests/ui/parser/fn-header-semantic-fail.rs
@@ -26,10 +26,10 @@ fn main() {
     impl X for Y {
         async fn ft1() {} // OK.
         unsafe fn ft2() {} // OK.
-        const fn ft3() {} //~ ERROR functions in traits cannot be declared const
+        const fn ft3() {} //~ ERROR functions in trait impls cannot be declared const
         extern "C" fn ft4() {}
         const async unsafe extern "C" fn ft5() {}
-        //~^ ERROR functions in traits cannot be declared const
+        //~^ ERROR functions in trait impls cannot be declared const
         //~| ERROR functions cannot be both `const` and `async`
     }
 
diff --git a/tests/ui/parser/fn-header-semantic-fail.stderr b/tests/ui/parser/fn-header-semantic-fail.stderr
index cdf01e0c5df64..1f280424cf381 100644
--- a/tests/ui/parser/fn-header-semantic-fail.stderr
+++ b/tests/ui/parser/fn-header-semantic-fail.stderr
@@ -28,17 +28,17 @@ LL |         const async unsafe extern "C" fn ft5();
    |         |     `async` because of this
    |         `const` because of this
 
-error[E0379]: functions in traits cannot be declared const
+error[E0379]: functions in trait impls cannot be declared const
   --> $DIR/fn-header-semantic-fail.rs:29:9
    |
 LL |         const fn ft3() {}
-   |         ^^^^^ functions in traits cannot be const
+   |         ^^^^^ functions in trait impls cannot be const
 
-error[E0379]: functions in traits cannot be declared const
+error[E0379]: functions in trait impls cannot be declared const
   --> $DIR/fn-header-semantic-fail.rs:31:9
    |
 LL |         const async unsafe extern "C" fn ft5() {}
-   |         ^^^^^ functions in traits cannot be const
+   |         ^^^^^ functions in trait impls cannot be const
 
 error: functions cannot be both `const` and `async`
   --> $DIR/fn-header-semantic-fail.rs:31:9
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/trait-fn-const.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/trait-fn-const.rs
index 40e8bfdcc172f..0d1c926fef5d2 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/trait-fn-const.rs
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/trait-fn-const.rs
@@ -7,7 +7,7 @@ trait Trait {
 }
 
 impl const Trait for () {
-    const fn fun() {}  //~ ERROR functions in traits cannot be declared const
+    const fn fun() {}  //~ ERROR functions in trait impls cannot be declared const
 }
 
 fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/trait-fn-const.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/trait-fn-const.stderr
index 09fe580ae5c42..cf8a2772d891f 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/trait-fn-const.stderr
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/trait-fn-const.stderr
@@ -4,11 +4,11 @@ error[E0379]: functions in traits cannot be declared const
 LL |     const fn fun();
    |     ^^^^^ functions in traits cannot be const
 
-error[E0379]: functions in traits cannot be declared const
+error[E0379]: functions in trait impls cannot be declared const
   --> $DIR/trait-fn-const.rs:10:5
    |
 LL |     const fn fun() {}
-   |     ^^^^^ functions in traits cannot be const
+   |     ^^^^^ functions in trait impls cannot be const
 
 error: aborting due to 2 previous errors
 

From aa799049d731f2922c237b27211d4e19b4db918b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= <me@fmease.dev>
Date: Tue, 2 Jan 2024 00:57:30 +0100
Subject: [PATCH 23/27] E0379: Provide suggestions

---
 compiler/rustc_ast_passes/messages.ftl        |   7 +
 .../rustc_ast_passes/src/ast_validation.rs    | 130 +++++++++++++-----
 compiler/rustc_ast_passes/src/errors.rs       |  19 ++-
 tests/ui/consts/const-fn-mismatch.stderr      |   5 +-
 tests/ui/consts/const-fn-not-in-trait.stderr  |  10 +-
 tests/ui/consts/issue-54954.stderr            |   5 +-
 .../feature-gate-min_const_fn.stderr          |  15 +-
 .../mismatched_types/const-fn-in-trait.stderr |  10 +-
 .../ui/parser/fn-header-semantic-fail.stderr  |  20 ++-
 .../effects/trait-fn-const.rs                 |  10 +-
 .../effects/trait-fn-const.stderr             |  48 ++++++-
 11 files changed, 228 insertions(+), 51 deletions(-)

diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl
index b7274db029f6e..feea02c679ce1 100644
--- a/compiler/rustc_ast_passes/messages.ftl
+++ b/compiler/rustc_ast_passes/messages.ftl
@@ -241,6 +241,13 @@ ast_passes_trait_fn_const =
         [true] trait impls
         *[false] traits
     } cannot be const
+    .const_context_label = this declares all associated functions implicitly const
+    .remove_const_sugg = remove the `const`{$requires_multiple_changes ->
+        [true] {" ..."}
+        *[false] {""}
+    }
+    .make_impl_const_sugg = ... and declare the impl to be const instead
+    .make_trait_const_sugg = ... and declare the trait to be a `#[const_trait]` instead
 
 ast_passes_trait_object_single_bound = only a single explicit lifetime bound is permitted
 
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 39ea684087e51..b69d4cccaf04f 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -46,6 +46,21 @@ enum DisallowTildeConstContext<'a> {
     Item,
 }
 
+enum TraitOrTraitImpl<'a> {
+    Trait { span: Span, constness: Option<Span> },
+    TraitImpl { constness: Const, polarity: ImplPolarity, trait_ref: &'a TraitRef },
+}
+
+impl<'a> TraitOrTraitImpl<'a> {
+    fn constness(&self) -> Option<Span> {
+        match self {
+            Self::Trait { constness: Some(span), .. }
+            | Self::TraitImpl { constness: Const::Yes(span), .. } => Some(*span),
+            _ => None,
+        }
+    }
+}
+
 struct AstValidator<'a> {
     session: &'a Session,
     features: &'a Features,
@@ -53,11 +68,7 @@ struct AstValidator<'a> {
     /// The span of the `extern` in an `extern { ... }` block, if any.
     extern_mod: Option<&'a Item>,
 
-    /// Are we inside a trait impl?
-    in_trait_impl: bool,
-
-    /// Are we inside a const trait defn or impl?
-    in_const_trait_or_impl: bool,
+    outer_trait_or_trait_impl: Option<TraitOrTraitImpl<'a>>,
 
     has_proc_macro_decls: bool,
 
@@ -78,24 +89,28 @@ struct AstValidator<'a> {
 impl<'a> AstValidator<'a> {
     fn with_in_trait_impl(
         &mut self,
-        is_in: bool,
-        constness: Option<Const>,
+        trait_: Option<(Const, ImplPolarity, &'a TraitRef)>,
         f: impl FnOnce(&mut Self),
     ) {
-        let old = mem::replace(&mut self.in_trait_impl, is_in);
-        let old_const = mem::replace(
-            &mut self.in_const_trait_or_impl,
-            matches!(constness, Some(Const::Yes(_))),
+        let old = mem::replace(
+            &mut self.outer_trait_or_trait_impl,
+            trait_.map(|(constness, polarity, trait_ref)| TraitOrTraitImpl::TraitImpl {
+                constness,
+                polarity,
+                trait_ref,
+            }),
         );
         f(self);
-        self.in_trait_impl = old;
-        self.in_const_trait_or_impl = old_const;
+        self.outer_trait_or_trait_impl = old;
     }
 
-    fn with_in_trait(&mut self, is_const: bool, f: impl FnOnce(&mut Self)) {
-        let old = mem::replace(&mut self.in_const_trait_or_impl, is_const);
+    fn with_in_trait(&mut self, span: Span, constness: Option<Span>, f: impl FnOnce(&mut Self)) {
+        let old = mem::replace(
+            &mut self.outer_trait_or_trait_impl,
+            Some(TraitOrTraitImpl::Trait { span, constness }),
+        );
         f(self);
-        self.in_const_trait_or_impl = old;
+        self.outer_trait_or_trait_impl = old;
     }
 
     fn with_banned_impl_trait(&mut self, f: impl FnOnce(&mut Self)) {
@@ -291,10 +306,48 @@ impl<'a> AstValidator<'a> {
         }
     }
 
-    fn check_trait_fn_not_const(&self, constness: Const) {
-        if let Const::Yes(span) = constness {
-            self.dcx().emit_err(errors::TraitFnConst { span, in_impl: self.in_trait_impl });
-        }
+    fn check_trait_fn_not_const(&self, constness: Const, parent: &TraitOrTraitImpl<'a>) {
+        let Const::Yes(span) = constness else {
+            return;
+        };
+
+        let make_impl_const_sugg = if self.features.const_trait_impl
+            && let TraitOrTraitImpl::TraitImpl {
+                constness: Const::No,
+                polarity: ImplPolarity::Positive,
+                trait_ref,
+            } = parent
+        {
+            Some(trait_ref.path.span.shrink_to_lo())
+        } else {
+            None
+        };
+
+        let make_trait_const_sugg = if self.features.const_trait_impl
+            && let TraitOrTraitImpl::Trait { span, constness: None } = parent
+        {
+            Some(span.shrink_to_lo())
+        } else {
+            None
+        };
+
+        let parent_constness = parent.constness();
+        self.dcx().emit_err(errors::TraitFnConst {
+            span,
+            in_impl: matches!(parent, TraitOrTraitImpl::TraitImpl { .. }),
+            const_context_label: parent_constness,
+            remove_const_sugg: (
+                self.session.source_map().span_extend_while(span, |c| c == ' ').unwrap_or(span),
+                match parent_constness {
+                    Some(_) => rustc_errors::Applicability::MachineApplicable,
+                    None => rustc_errors::Applicability::MaybeIncorrect,
+                },
+            ),
+            requires_multiple_changes: make_impl_const_sugg.is_some()
+                || make_trait_const_sugg.is_some(),
+            make_impl_const_sugg,
+            make_trait_const_sugg,
+        });
     }
 
     fn check_fn_decl(&self, fn_decl: &FnDecl, self_semantic: SelfSemantic) {
@@ -817,7 +870,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 self_ty,
                 items,
             }) => {
-                self.with_in_trait_impl(true, Some(*constness), |this| {
+                self.with_in_trait_impl(Some((*constness, *polarity, t)), |this| {
                     this.visibility_not_permitted(
                         &item.vis,
                         errors::VisibilityNotPermittedNote::TraitImpl,
@@ -963,8 +1016,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 }
             }
             ItemKind::Trait(box Trait { is_auto, generics, bounds, items, .. }) => {
-                let is_const_trait = attr::contains_name(&item.attrs, sym::const_trait);
-                self.with_in_trait(is_const_trait, |this| {
+                let is_const_trait =
+                    attr::find_by_name(&item.attrs, sym::const_trait).map(|attr| attr.span);
+                self.with_in_trait(item.span, is_const_trait, |this| {
                     if *is_auto == IsAuto::Yes {
                         // Auto traits cannot have generics, super traits nor contain items.
                         this.deny_generic_params(generics, item.ident.span);
@@ -977,8 +1031,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                     // context for the supertraits.
                     this.visit_vis(&item.vis);
                     this.visit_ident(item.ident);
-                    let disallowed =
-                        (!is_const_trait).then(|| DisallowTildeConstContext::Trait(item.span));
+                    let disallowed = is_const_trait
+                        .is_none()
+                        .then(|| DisallowTildeConstContext::Trait(item.span));
                     this.with_tilde_const(disallowed, |this| {
                         this.visit_generics(generics);
                         walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits)
@@ -1342,7 +1397,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
 
         let tilde_const_allowed =
             matches!(fk.header(), Some(FnHeader { constness: ast::Const::Yes(_), .. }))
-                || matches!(fk.ctxt(), Some(FnCtxt::Assoc(_)) if self.in_const_trait_or_impl);
+                || matches!(fk.ctxt(), Some(FnCtxt::Assoc(_)))
+                    && self
+                        .outer_trait_or_trait_impl
+                        .as_ref()
+                        .and_then(TraitOrTraitImpl::constness)
+                        .is_some();
 
         let disallowed = (!tilde_const_allowed).then(|| DisallowTildeConstContext::Fn(fk));
         self.with_tilde_const(disallowed, |this| visit::walk_fn(this, fk));
@@ -1353,7 +1413,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
             self.check_nomangle_item_asciionly(item.ident, item.span);
         }
 
-        if ctxt == AssocCtxt::Trait || !self.in_trait_impl {
+        if ctxt == AssocCtxt::Trait || self.outer_trait_or_trait_impl.is_none() {
             self.check_defaultness(item.span, item.kind.defaultness());
         }
 
@@ -1401,10 +1461,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
             );
         }
 
-        if ctxt == AssocCtxt::Trait || self.in_trait_impl {
+        if let Some(parent) = &self.outer_trait_or_trait_impl {
             self.visibility_not_permitted(&item.vis, errors::VisibilityNotPermittedNote::TraitImpl);
             if let AssocItemKind::Fn(box Fn { sig, .. }) = &item.kind {
-                self.check_trait_fn_not_const(sig.header.constness);
+                self.check_trait_fn_not_const(sig.header.constness, parent);
             }
         }
 
@@ -1414,7 +1474,11 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
 
         match &item.kind {
             AssocItemKind::Fn(box Fn { sig, generics, body, .. })
-                if self.in_const_trait_or_impl
+                if self
+                    .outer_trait_or_trait_impl
+                    .as_ref()
+                    .and_then(TraitOrTraitImpl::constness)
+                    .is_some()
                     || ctxt == AssocCtxt::Trait
                     || matches!(sig.header.constness, Const::Yes(_)) =>
             {
@@ -1430,8 +1494,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 );
                 self.visit_fn(kind, item.span, item.id);
             }
-            _ => self
-                .with_in_trait_impl(false, None, |this| visit::walk_assoc_item(this, item, ctxt)),
+            _ => self.with_in_trait_impl(None, |this| visit::walk_assoc_item(this, item, ctxt)),
         }
     }
 }
@@ -1547,8 +1610,7 @@ pub fn check_crate(
         session,
         features,
         extern_mod: None,
-        in_trait_impl: false,
-        in_const_trait_or_impl: false,
+        outer_trait_or_trait_impl: None,
         has_proc_macro_decls: false,
         outer_impl_trait: None,
         disallow_tilde_const: Some(DisallowTildeConstContext::Item),
diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs
index ebaa7ccecc916..42ada39f51589 100644
--- a/compiler/rustc_ast_passes/src/errors.rs
+++ b/compiler/rustc_ast_passes/src/errors.rs
@@ -1,7 +1,7 @@
 //! Errors emitted by ast_passes.
 
 use rustc_ast::ParamKindOrd;
-use rustc_errors::AddToDiagnostic;
+use rustc_errors::{AddToDiagnostic, Applicability};
 use rustc_macros::{Diagnostic, Subdiagnostic};
 use rustc_span::{symbol::Ident, Span, Symbol};
 
@@ -50,6 +50,23 @@ pub struct TraitFnConst {
     #[label]
     pub span: Span,
     pub in_impl: bool,
+    #[label(ast_passes_const_context_label)]
+    pub const_context_label: Option<Span>,
+    #[suggestion(ast_passes_remove_const_sugg, code = "")]
+    pub remove_const_sugg: (Span, Applicability),
+    pub requires_multiple_changes: bool,
+    #[suggestion(
+        ast_passes_make_impl_const_sugg,
+        code = "const ",
+        applicability = "maybe-incorrect"
+    )]
+    pub make_impl_const_sugg: Option<Span>,
+    #[suggestion(
+        ast_passes_make_trait_const_sugg,
+        code = "#[const_trait]\n",
+        applicability = "maybe-incorrect"
+    )]
+    pub make_trait_const_sugg: Option<Span>,
 }
 
 #[derive(Diagnostic)]
diff --git a/tests/ui/consts/const-fn-mismatch.stderr b/tests/ui/consts/const-fn-mismatch.stderr
index 7d681c212b960..9e7d93b0c97bb 100644
--- a/tests/ui/consts/const-fn-mismatch.stderr
+++ b/tests/ui/consts/const-fn-mismatch.stderr
@@ -2,7 +2,10 @@ error[E0379]: functions in trait impls cannot be declared const
   --> $DIR/const-fn-mismatch.rs:11:5
    |
 LL |     const fn f() -> u32 {
-   |     ^^^^^ functions in trait impls cannot be const
+   |     ^^^^^-
+   |     |
+   |     functions in trait impls cannot be const
+   |     help: remove the `const`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/consts/const-fn-not-in-trait.stderr b/tests/ui/consts/const-fn-not-in-trait.stderr
index 5d364eb882dba..04430610ad00c 100644
--- a/tests/ui/consts/const-fn-not-in-trait.stderr
+++ b/tests/ui/consts/const-fn-not-in-trait.stderr
@@ -2,13 +2,19 @@ error[E0379]: functions in traits cannot be declared const
   --> $DIR/const-fn-not-in-trait.rs:5:5
    |
 LL |     const fn f() -> u32;
-   |     ^^^^^ functions in traits cannot be const
+   |     ^^^^^-
+   |     |
+   |     functions in traits cannot be const
+   |     help: remove the `const`
 
 error[E0379]: functions in traits cannot be declared const
   --> $DIR/const-fn-not-in-trait.rs:7:5
    |
 LL |     const fn g() -> u32 {
-   |     ^^^^^ functions in traits cannot be const
+   |     ^^^^^-
+   |     |
+   |     functions in traits cannot be const
+   |     help: remove the `const`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/consts/issue-54954.stderr b/tests/ui/consts/issue-54954.stderr
index b0701bab793c5..03c47030c0e3f 100644
--- a/tests/ui/consts/issue-54954.stderr
+++ b/tests/ui/consts/issue-54954.stderr
@@ -2,7 +2,10 @@ error[E0379]: functions in traits cannot be declared const
   --> $DIR/issue-54954.rs:5:5
    |
 LL |     const fn const_val<T: Sized>() -> usize {
-   |     ^^^^^ functions in traits cannot be const
+   |     ^^^^^-
+   |     |
+   |     functions in traits cannot be const
+   |     help: remove the `const`
 
 error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
   --> $DIR/issue-54954.rs:1:24
diff --git a/tests/ui/feature-gates/feature-gate-min_const_fn.stderr b/tests/ui/feature-gates/feature-gate-min_const_fn.stderr
index abc9ddabd51ea..0b16f9abb7071 100644
--- a/tests/ui/feature-gates/feature-gate-min_const_fn.stderr
+++ b/tests/ui/feature-gates/feature-gate-min_const_fn.stderr
@@ -2,19 +2,28 @@ error[E0379]: functions in traits cannot be declared const
   --> $DIR/feature-gate-min_const_fn.rs:6:5
    |
 LL |     const fn foo() -> u32;
-   |     ^^^^^ functions in traits cannot be const
+   |     ^^^^^-
+   |     |
+   |     functions in traits cannot be const
+   |     help: remove the `const`
 
 error[E0379]: functions in traits cannot be declared const
   --> $DIR/feature-gate-min_const_fn.rs:7:5
    |
 LL |     const fn bar() -> u32 { 0 }
-   |     ^^^^^ functions in traits cannot be const
+   |     ^^^^^-
+   |     |
+   |     functions in traits cannot be const
+   |     help: remove the `const`
 
 error[E0379]: functions in trait impls cannot be declared const
   --> $DIR/feature-gate-min_const_fn.rs:11:5
    |
 LL |     const fn foo() -> u32 { 0 }
-   |     ^^^^^ functions in trait impls cannot be const
+   |     ^^^^^-
+   |     |
+   |     functions in trait impls cannot be const
+   |     help: remove the `const`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/mismatched_types/const-fn-in-trait.stderr b/tests/ui/mismatched_types/const-fn-in-trait.stderr
index 75122237bf596..06976933b2f94 100644
--- a/tests/ui/mismatched_types/const-fn-in-trait.stderr
+++ b/tests/ui/mismatched_types/const-fn-in-trait.stderr
@@ -2,13 +2,19 @@ error[E0379]: functions in traits cannot be declared const
   --> $DIR/const-fn-in-trait.rs:3:5
    |
 LL |     const fn g();
-   |     ^^^^^ functions in traits cannot be const
+   |     ^^^^^-
+   |     |
+   |     functions in traits cannot be const
+   |     help: remove the `const`
 
 error[E0379]: functions in trait impls cannot be declared const
   --> $DIR/const-fn-in-trait.rs:7:5
    |
 LL |     const fn f() -> u32 { 22 }
-   |     ^^^^^ functions in trait impls cannot be const
+   |     ^^^^^-
+   |     |
+   |     functions in trait impls cannot be const
+   |     help: remove the `const`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/parser/fn-header-semantic-fail.stderr b/tests/ui/parser/fn-header-semantic-fail.stderr
index 1f280424cf381..696d8e01b6387 100644
--- a/tests/ui/parser/fn-header-semantic-fail.stderr
+++ b/tests/ui/parser/fn-header-semantic-fail.stderr
@@ -11,13 +11,19 @@ error[E0379]: functions in traits cannot be declared const
   --> $DIR/fn-header-semantic-fail.rs:18:9
    |
 LL |         const fn ft3();
-   |         ^^^^^ functions in traits cannot be const
+   |         ^^^^^-
+   |         |
+   |         functions in traits cannot be const
+   |         help: remove the `const`
 
 error[E0379]: functions in traits cannot be declared const
   --> $DIR/fn-header-semantic-fail.rs:20:9
    |
 LL |         const async unsafe extern "C" fn ft5();
-   |         ^^^^^ functions in traits cannot be const
+   |         ^^^^^-
+   |         |
+   |         functions in traits cannot be const
+   |         help: remove the `const`
 
 error: functions cannot be both `const` and `async`
   --> $DIR/fn-header-semantic-fail.rs:20:9
@@ -32,13 +38,19 @@ error[E0379]: functions in trait impls cannot be declared const
   --> $DIR/fn-header-semantic-fail.rs:29:9
    |
 LL |         const fn ft3() {}
-   |         ^^^^^ functions in trait impls cannot be const
+   |         ^^^^^-
+   |         |
+   |         functions in trait impls cannot be const
+   |         help: remove the `const`
 
 error[E0379]: functions in trait impls cannot be declared const
   --> $DIR/fn-header-semantic-fail.rs:31:9
    |
 LL |         const async unsafe extern "C" fn ft5() {}
-   |         ^^^^^ functions in trait impls cannot be const
+   |         ^^^^^-
+   |         |
+   |         functions in trait impls cannot be const
+   |         help: remove the `const`
 
 error: functions cannot be both `const` and `async`
   --> $DIR/fn-header-semantic-fail.rs:31:9
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/trait-fn-const.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/trait-fn-const.rs
index 0d1c926fef5d2..891e87d3b97d4 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/trait-fn-const.rs
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/trait-fn-const.rs
@@ -7,7 +7,15 @@ trait Trait {
 }
 
 impl const Trait for () {
-    const fn fun() {}  //~ ERROR functions in trait impls cannot be declared const
+    const fn fun() {} //~ ERROR functions in trait impls cannot be declared const
+}
+
+impl Trait for u32 {
+    const fn fun() {} //~ ERROR functions in trait impls cannot be declared const
+}
+
+trait NonConst {
+    const fn fun(); //~ ERROR functions in traits cannot be declared const
 }
 
 fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/trait-fn-const.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/trait-fn-const.stderr
index cf8a2772d891f..4d0b03046d27d 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/trait-fn-const.stderr
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/trait-fn-const.stderr
@@ -1,15 +1,59 @@
 error[E0379]: functions in traits cannot be declared const
   --> $DIR/trait-fn-const.rs:6:5
    |
+LL | #[const_trait]
+   | -------------- this declares all associated functions implicitly const
+LL | trait Trait {
 LL |     const fn fun();
-   |     ^^^^^ functions in traits cannot be const
+   |     ^^^^^-
+   |     |
+   |     functions in traits cannot be const
+   |     help: remove the `const`
 
 error[E0379]: functions in trait impls cannot be declared const
   --> $DIR/trait-fn-const.rs:10:5
    |
+LL | impl const Trait for () {
+   |      ----- this declares all associated functions implicitly const
+LL |     const fn fun() {}
+   |     ^^^^^-
+   |     |
+   |     functions in trait impls cannot be const
+   |     help: remove the `const`
+
+error[E0379]: functions in trait impls cannot be declared const
+  --> $DIR/trait-fn-const.rs:14:5
+   |
 LL |     const fn fun() {}
    |     ^^^^^ functions in trait impls cannot be const
+   |
+help: remove the `const` ...
+   |
+LL -     const fn fun() {}
+LL +     fn fun() {}
+   |
+help: ... and declare the impl to be const instead
+   |
+LL | impl const Trait for u32 {
+   |      +++++
+
+error[E0379]: functions in traits cannot be declared const
+  --> $DIR/trait-fn-const.rs:18:5
+   |
+LL |     const fn fun();
+   |     ^^^^^ functions in traits cannot be const
+   |
+help: remove the `const` ...
+   |
+LL -     const fn fun();
+LL +     fn fun();
+   |
+help: ... and declare the trait to be a `#[const_trait]` instead
+   |
+LL + #[const_trait]
+LL | trait NonConst {
+   |
 
-error: aborting due to 2 previous errors
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0379`.

From ee86b1f84cf47f9ffea1bfc9b4ab4357e9611c05 Mon Sep 17 00:00:00 2001
From: Matthew Maurer <mmaurer@google.com>
Date: Tue, 2 Jan 2024 17:46:57 +0000
Subject: [PATCH 24/27] llvm: Allow `noundef` in codegen tests

LLVM 18 will automatically infer `noundef` in some situations.
Adjust codegen tests to accept this.

See llvm/llvm-project#76553 for why `noundef` is being generated now.
---
 tests/codegen/abi-main-signature-32bit-c-int.rs | 2 +-
 tests/codegen/sparc-struct-abi.rs               | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/tests/codegen/abi-main-signature-32bit-c-int.rs b/tests/codegen/abi-main-signature-32bit-c-int.rs
index 34571823f1360..771ca66daf8ea 100644
--- a/tests/codegen/abi-main-signature-32bit-c-int.rs
+++ b/tests/codegen/abi-main-signature-32bit-c-int.rs
@@ -8,4 +8,4 @@
 fn main() {
 }
 
-// CHECK: define{{( hidden)?}} i32 @main(i32{{( %0)?}}, ptr{{( %1)?}})
+// CHECK: define{{( hidden| noundef)*}} i32 @main(i32{{( %0)?}}, ptr{{( %1)?}})
diff --git a/tests/codegen/sparc-struct-abi.rs b/tests/codegen/sparc-struct-abi.rs
index e8816e4f303d4..b94ef79aec7f8 100644
--- a/tests/codegen/sparc-struct-abi.rs
+++ b/tests/codegen/sparc-struct-abi.rs
@@ -18,7 +18,7 @@ pub struct Bool {
     b: bool,
 }
 
-// CHECK: define i64 @structbool()
+// CHECK: define{{.*}} i64 @structbool()
 // CHECK-NEXT: start:
 // CHECK-NEXT: ret i64 72057594037927936
 #[no_mangle]

From 6f49080fa8f5921e7e2062bb358fd1ad79b8d4ba Mon Sep 17 00:00:00 2001
From: Trevor Gross <tmgross@umich.edu>
Date: Tue, 2 Jan 2024 17:24:59 -0600
Subject: [PATCH 25/27] Update `thread_local` examples to use
 `local_key_cell_methods`

`local_key_cell_methods` has been stable for a while and provides a much less
clunky way to interface with thread-local variables.

Additionaly add context to the documentation about why types with interior
mutability are needed.
---
 library/std/src/thread/local.rs | 50 +++++++++++++++++++++------------
 1 file changed, 32 insertions(+), 18 deletions(-)

diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs
index def94acd45727..9cf37b0e6347c 100644
--- a/library/std/src/thread/local.rs
+++ b/library/std/src/thread/local.rs
@@ -16,7 +16,8 @@ use crate::fmt;
 ///
 /// This key uses the fastest possible implementation available to it for the
 /// target platform. It is instantiated with the [`thread_local!`] macro and the
-/// primary method is the [`with`] method.
+/// primary method is the [`with`] method, though there are helpers to make
+/// working with [`Cell`] types easier.
 ///
 /// The [`with`] method yields a reference to the contained value which cannot
 /// outlive the current thread or escape the given closure.
@@ -25,14 +26,30 @@ use crate::fmt;
 ///
 /// # Initialization and Destruction
 ///
-/// Initialization is dynamically performed on the first call to [`with`]
-/// within a thread, and values that implement [`Drop`] get destructed when a
-/// thread exits. Some caveats apply, which are explained below.
+/// Initialization is dynamically performed on the first call to a setter (e.g.
+/// [`with`]) within a thread, and values that implement [`Drop`] get
+/// destructed when a thread exits. Some caveats apply, which are explained below.
 ///
 /// A `LocalKey`'s initializer cannot recursively depend on itself. Using a
 /// `LocalKey` in this way may cause panics, aborts or infinite recursion on
 /// the first call to `with`.
 ///
+/// # Single-thread Synchronization
+///
+/// Though there is no potential race with other threads, it is still possible to
+/// obtain multiple references to the thread-local data in different places on
+/// the call stack. For this reason, only shared (`&T`) references may be obtained.
+///
+/// To allow obtaining an exclusive mutable reference (`&mut T`), typically a
+/// [`Cell`] or [`RefCell`] is used (see the [`std::cell`] for more information
+/// on how exactly this works). To make this easier there are specialized
+/// implementations for [`LocalKey<Cell<T>>`] and [`LocalKey<RefCell<T>>`].
+///
+/// [`std::cell`]: `crate::cell`
+/// [`LocalKey<Cell<T>>`]: struct.LocalKey.html#impl-LocalKey<Cell<T>>
+/// [`LocalKey<RefCell<T>>`]: struct.LocalKey.html#impl-LocalKey<RefCell<T>>
+///
+///
 /// # Examples
 ///
 /// ```
@@ -41,26 +58,20 @@ use crate::fmt;
 ///
 /// thread_local!(static FOO: RefCell<u32> = RefCell::new(1));
 ///
-/// FOO.with(|f| {
-///     assert_eq!(*f.borrow(), 1);
-///     *f.borrow_mut() = 2;
-/// });
+/// FOO.with_borrow(|v| assert_eq!(*v, 1));
+/// FOO.with_borrow_mut(|v| *v = 2);
 ///
 /// // each thread starts out with the initial value of 1
 /// let t = thread::spawn(move|| {
-///     FOO.with(|f| {
-///         assert_eq!(*f.borrow(), 1);
-///         *f.borrow_mut() = 3;
-///     });
+///     FOO.with_borrow(|v| assert_eq!(*v, 1));
+///     FOO.with_borrow_mut(|v| *v = 3);
 /// });
 ///
 /// // wait for the thread to complete and bail out on panic
 /// t.join().unwrap();
 ///
 /// // we retain our original value of 2 despite the child thread
-/// FOO.with(|f| {
-///     assert_eq!(*f.borrow(), 2);
-/// });
+/// FOO.with_borrow(|v| assert_eq!(*v, 2));
 /// ```
 ///
 /// # Platform-specific behavior
@@ -137,10 +148,13 @@ impl<T: 'static> fmt::Debug for LocalKey<T> {
 ///     static BAR: RefCell<f32> = RefCell::new(1.0);
 /// }
 ///
-/// FOO.with(|foo| assert_eq!(*foo.borrow(), 1));
-/// BAR.with(|bar| assert_eq!(*bar.borrow(), 1.0));
+/// FOO.with_borrow(|v| assert_eq!(*v, 1));
+/// BAR.with_borrow(|v| assert_eq!(*v, 1.0));
 /// ```
 ///
+/// Note that only shared references (`&T`) to the inner data may be obtained, so a
+/// type such as [`Cell`] or [`RefCell`] is typically used to allow mutating access.
+///
 /// This macro supports a special `const {}` syntax that can be used
 /// when the initialization expression can be evaluated as a constant.
 /// This can enable a more efficient thread local implementation that
@@ -155,7 +169,7 @@ impl<T: 'static> fmt::Debug for LocalKey<T> {
 ///     pub static FOO: Cell<u32> = const { Cell::new(1) };
 /// }
 ///
-/// FOO.with(|foo| assert_eq!(foo.get(), 1));
+/// assert_eq!(FOO.get(), 1);
 /// ```
 ///
 /// See [`LocalKey` documentation][`std::thread::LocalKey`] for more

From d9d23fa68d9b6349c01ff1f06e34f9ca384cdc97 Mon Sep 17 00:00:00 2001
From: roblabla <unfiltered@roblab.la>
Date: Wed, 3 Jan 2024 14:01:35 +0100
Subject: [PATCH 26/27] Fix: Properly set vendor in i686-win7-windows-msvc
 target

---
 compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs | 1 +
 1 file changed, 1 insertion(+)

diff --git a/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs
index ba80c23196e1d..5b91682e168ab 100644
--- a/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs
@@ -4,6 +4,7 @@ pub fn target() -> Target {
     let mut base = base::windows_msvc::opts();
     base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
+    base.vendor = "win7".into();
 
     base.add_pre_link_args(
         LinkerFlavor::Msvc(Lld::No),

From 0d421c5acec8719875d8261838cb6d047fe9b23b Mon Sep 17 00:00:00 2001
From: Ross Smyth <rsmyth@electrocraft.com>
Date: Mon, 18 Dec 2023 10:48:21 -0500
Subject: [PATCH 27/27] Add useful panic messages if queries fail to start

---
 .../rustc_query_system/src/query/plumbing.rs  | 32 ++++++++++++-------
 1 file changed, 21 insertions(+), 11 deletions(-)

diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs
index 41638b38c742d..fb11820407bd4 100644
--- a/compiler/rustc_query_system/src/query/plumbing.rs
+++ b/compiler/rustc_query_system/src/query/plumbing.rs
@@ -44,6 +44,18 @@ enum QueryResult {
     Poisoned,
 }
 
+impl QueryResult {
+    /// Unwraps the query job expecting that it has started.
+    fn expect_job(self) -> QueryJob {
+        match self {
+            Self::Started(job) => job,
+            Self::Poisoned => {
+                panic!("job for query failed to start and was poisoned")
+            }
+        }
+    }
+}
+
 impl<K> QueryState<K>
 where
     K: Eq + Hash + Copy + Debug,
@@ -169,10 +181,7 @@ where
 
         let job = {
             let mut lock = state.active.lock_shard_by_value(&key);
-            match lock.remove(&key).unwrap() {
-                QueryResult::Started(job) => job,
-                QueryResult::Poisoned => panic!(),
-            }
+            lock.remove(&key).unwrap().expect_job()
         };
 
         job.signal_complete();
@@ -190,10 +199,8 @@ where
         let state = self.state;
         let job = {
             let mut shard = state.active.lock_shard_by_value(&self.key);
-            let job = match shard.remove(&self.key).unwrap() {
-                QueryResult::Started(job) => job,
-                QueryResult::Poisoned => panic!(),
-            };
+            let job = shard.remove(&self.key).unwrap().expect_job();
+
             shard.insert(self.key, QueryResult::Poisoned);
             job
         };
@@ -277,11 +284,14 @@ where
                     // We didn't find the query result in the query cache. Check if it was
                     // poisoned due to a panic instead.
                     let lock = query.query_state(qcx).active.get_shard_by_value(&key).lock();
+
                     match lock.get(&key) {
-                        // The query we waited on panicked. Continue unwinding here.
-                        Some(QueryResult::Poisoned) => FatalError.raise(),
+                        Some(QueryResult::Poisoned) => {
+                            panic!("query '{}' not cached due to poisoning", query.name())
+                        }
                         _ => panic!(
-                            "query result must in the cache or the query must be poisoned after a wait"
+                            "query '{}' result must be in the cache or the query must be poisoned after a wait",
+                            query.name()
                         ),
                     }
                 })