about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2025-01-10 11:40:56 +0000
committerbors <bors@rust-lang.org>2025-01-10 11:40:56 +0000
commit252b07bba419a075acfa1fa85d66683e9623c281 (patch)
treec178b717b7aa795e0ce5ac771c1a29852b39f2a6
parentb44e14f762fd4062faeba97f8f2bc470298ec1ac (diff)
parentb557f1baa711a9ff6368843ecd4d368452aa0261 (diff)
Auto merge of #135327 - jhpratt:rollup-5uyir52, r=jhpratt
Rollup of 7 pull requests

Successful merges:

 - #132607 (Used pthread name functions returning result for FreeBSD and DragonFly)
 - #134693 (proc_macro: Use `ToTokens` trait in `quote` macro)
 - #134732 (Unify conditional-const error reporting with non-const error reporting)
 - #135083 (Do not ICE when encountering predicates from other items in method error reporting)
 - #135251 (Only treat plain literal patterns as short)
 - #135320 (Fix typo in `#[coroutine]` gating error)
 - #135321 (remove more redundant into() conversions)

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_const_eval/messages.ftl59
-rw-r--r--compiler/rustc_const_eval/src/check_consts/check.rs14
-rw-r--r--compiler/rustc_const_eval/src/check_consts/ops.rs423
-rw-r--r--compiler/rustc_const_eval/src/errors.rs39
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs10
-rw-r--r--compiler/rustc_mir_transform/src/coverage/mappings.rs5
-rw-r--r--compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs2
-rw-r--r--library/proc_macro/src/lib.rs2
-rw-r--r--library/proc_macro/src/quote.rs149
-rw-r--r--library/std/src/sys/pal/unix/thread.rs24
-rw-r--r--src/tools/rustfmt/src/patterns.rs37
-rw-r--r--src/tools/rustfmt/tests/source/pattern.rs10
-rw-r--r--src/tools/rustfmt/tests/target/pattern.rs8
-rw-r--r--tests/ui/coroutine/gen_block.e2024.stderr4
-rw-r--r--tests/ui/coroutine/gen_block.none.stderr4
-rw-r--r--tests/ui/coroutine/gen_block.rs4
-rw-r--r--tests/ui/issues/issue-25901.rs2
-rw-r--r--tests/ui/issues/issue-25901.stderr9
-rw-r--r--tests/ui/methods/bad-wf-when-selecting-method.rs18
-rw-r--r--tests/ui/methods/bad-wf-when-selecting-method.stderr54
-rw-r--r--tests/ui/proc-macro/quote-debug.stdout49
-rw-r--r--tests/ui/proc-macro/quote/auxiliary/basic.rs361
-rw-r--r--tests/ui/proc-macro/quote/basic.rs8
-rw-r--r--tests/ui/proc-macro/quote/debug.rs (renamed from tests/ui/proc-macro/quote-debug.rs)1
-rw-r--r--tests/ui/proc-macro/quote/debug.stdout72
-rw-r--r--tests/ui/proc-macro/quote/does-not-have-iter-interpolated-dup.rs17
-rw-r--r--tests/ui/proc-macro/quote/does-not-have-iter-interpolated-dup.stderr10
-rw-r--r--tests/ui/proc-macro/quote/does-not-have-iter-interpolated.rs17
-rw-r--r--tests/ui/proc-macro/quote/does-not-have-iter-interpolated.stderr10
-rw-r--r--tests/ui/proc-macro/quote/does-not-have-iter-separated.rs13
-rw-r--r--tests/ui/proc-macro/quote/does-not-have-iter-separated.stderr10
-rw-r--r--tests/ui/proc-macro/quote/does-not-have-iter.rs13
-rw-r--r--tests/ui/proc-macro/quote/does-not-have-iter.stderr10
-rw-r--r--tests/ui/proc-macro/quote/not-quotable.rs12
-rw-r--r--tests/ui/proc-macro/quote/not-quotable.stderr24
-rw-r--r--tests/ui/proc-macro/quote/not-repeatable.rs16
-rw-r--r--tests/ui/proc-macro/quote/not-repeatable.stderr10
-rw-r--r--tests/ui/self/arbitrary-self-from-method-substs-ice.stderr1
-rw-r--r--tests/ui/traits/const-traits/cross-crate.stock.stderr5
-rw-r--r--tests/ui/traits/const-traits/cross-crate.stocknc.stderr10
-rw-r--r--tests/ui/traits/const-traits/staged-api-user-crate.stderr1
-rw-r--r--tests/ui/traits/const-traits/super-traits-fail-3.nyn.stderr5
-rw-r--r--tests/ui/traits/const-traits/super-traits-fail-3.nyy.stderr5
45 files changed, 1162 insertions, 399 deletions
diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl
index 0c2242b810b..4861b7a4430 100644
--- a/compiler/rustc_const_eval/messages.ftl
+++ b/compiler/rustc_const_eval/messages.ftl
@@ -12,8 +12,6 @@ const_eval_already_reported =
 const_eval_assume_false =
     `assume` called with `false`
 
-const_eval_await_non_const =
-    cannot convert `{$ty}` into a future in {const_eval_const_context}s
 const_eval_bounds_check_failed =
     indexing out of bounds: the len is {$len} but the index is {$index}
 const_eval_call_nonzero_intrinsic =
@@ -23,11 +21,6 @@ const_eval_closure_call =
     closures need an RFC before allowed to be called in {const_eval_const_context}s
 const_eval_closure_fndef_not_const =
     function defined here, but it is not `const`
-const_eval_closure_non_const =
-    cannot call non-const closure in {const_eval_const_context}s
-
-const_eval_conditionally_const_call =
-    cannot call conditionally-const {$def_descr} `{$def_path_str}` in {const_eval_const_context}s
 
 const_eval_consider_dereferencing =
     consider dereferencing here
@@ -62,10 +55,6 @@ const_eval_dealloc_incorrect_layout =
 const_eval_dealloc_kind_mismatch =
     deallocating {$alloc}, which is {$alloc_kind} memory, using {$kind} deallocation operation
 
-const_eval_deref_coercion_non_const =
-    cannot perform deref coercion on `{$ty}` in {const_eval_const_context}s
-    .note = attempting to deref into `{$target_ty}`
-    .target_note = deref defined here
 const_eval_deref_function_pointer =
     accessing {$allocation} which contains a function
 const_eval_deref_vtable_pointer =
@@ -109,9 +98,6 @@ const_eval_extern_type_field = `extern type` field does not have a known offset
 
 const_eval_fn_ptr_call =
     function pointers need an RFC before allowed to be called in {const_eval_const_context}s
-const_eval_for_loop_into_iter_non_const =
-    cannot use `for` loop on `{$ty}` in {const_eval_const_context}s
-
 const_eval_frame_note = {$times ->
     [0] {const_eval_frame_note_inner}
     *[other] [... {$times} additional calls {const_eval_frame_note_inner} ...]
@@ -216,9 +202,6 @@ const_eval_long_running =
     .label = the const evaluator is currently interpreting this expression
     .help = the constant being evaluated
 
-const_eval_match_eq_non_const = cannot match on `{$ty}` in {const_eval_const_context}s
-    .note = `{$ty}` cannot be compared in compile-time, and therefore cannot be used in `match`es
-
 const_eval_max_num_nodes_in_const = maximum number of nodes exceeded in constant {$global_const_id}
 
 const_eval_memory_access_test = memory access failed
@@ -249,11 +232,26 @@ const_eval_mutable_ref_escaping =
         If you really want global mutable state, try using an interior mutable `static` or a `static mut`.
 
 const_eval_nested_static_in_thread_local = #[thread_local] does not support implicit nested statics, please create explicit static items and refer to them instead
+
+const_eval_non_const_await =
+    cannot convert `{$ty}` into a future in {const_eval_const_context}s
+
+const_eval_non_const_closure =
+    cannot call {$non_or_conditionally}-const closure in {const_eval_const_context}s
+
+const_eval_non_const_deref_coercion =
+    cannot perform {$non_or_conditionally}-const deref coercion on `{$ty}` in {const_eval_const_context}s
+    .note = attempting to deref into `{$target_ty}`
+    .target_note = deref defined here
+
 const_eval_non_const_fmt_macro_call =
-    cannot call non-const formatting macro in {const_eval_const_context}s
+    cannot call {$non_or_conditionally}-const formatting macro in {const_eval_const_context}s
 
 const_eval_non_const_fn_call =
-    cannot call non-const {$def_descr} `{$def_path_str}` in {const_eval_const_context}s
+    cannot call {$non_or_conditionally}-const {$def_descr} `{$def_path_str}` in {const_eval_const_context}s
+
+const_eval_non_const_for_loop_into_iter =
+    cannot use `for` loop on `{$ty}` in {const_eval_const_context}s
 
 const_eval_non_const_impl =
     impl defined here, but it is not `const`
@@ -261,6 +259,20 @@ const_eval_non_const_impl =
 const_eval_non_const_intrinsic =
     cannot call non-const intrinsic `{$name}` in {const_eval_const_context}s
 
+const_eval_non_const_match_eq = cannot match on `{$ty}` in {const_eval_const_context}s
+    .note = `{$ty}` cannot be compared in compile-time, and therefore cannot be used in `match`es
+
+const_eval_non_const_operator =
+    cannot call {$non_or_conditionally}-const operator in {const_eval_const_context}s
+
+const_eval_non_const_question_branch =
+    `?` is not allowed on `{$ty}` in {const_eval_const_context}s
+const_eval_non_const_question_from_residual =
+    `?` is not allowed on `{$ty}` in {const_eval_const_context}s
+
+const_eval_non_const_try_block_from_output =
+    `try` block cannot convert `{$ty}` to the result in {const_eval_const_context}s
+
 const_eval_not_enough_caller_args =
     calling a function with fewer arguments than it requires
 
@@ -281,8 +293,6 @@ const_eval_offset_from_unsigned_overflow =
         *[false] offset
     } than second: {$a_offset} < {$b_offset}
 
-const_eval_operator_non_const =
-    cannot call non-const operator in {const_eval_const_context}s
 const_eval_overflow_arith =
     arithmetic overflow in `{$intrinsic}`
 const_eval_overflow_shift =
@@ -325,11 +335,6 @@ const_eval_ptr_as_bytes_1 =
 const_eval_ptr_as_bytes_2 =
     the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
-const_eval_question_branch_non_const =
-    `?` is not allowed on `{$ty}` in {const_eval_const_context}s
-const_eval_question_from_residual_non_const =
-    `?` is not allowed on `{$ty}` in {const_eval_const_context}s
-
 const_eval_range = in the range {$lo}..={$hi}
 const_eval_range_lower = greater or equal to {$lo}
 const_eval_range_singular = equal to {$lo}
@@ -379,8 +384,6 @@ const_eval_too_generic =
 const_eval_too_many_caller_args =
     calling a function with more arguments than it expected
 
-const_eval_try_block_from_output_non_const =
-    `try` block cannot convert `{$ty}` to the result in {const_eval_const_context}s
 const_eval_unallowed_fn_pointer_call = function pointer calls are not allowed in {const_eval_const_context}s
 
 const_eval_unallowed_heap_allocations =
diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs
index e895c44199b..015e1671682 100644
--- a/compiler/rustc_const_eval/src/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/check_consts/check.rs
@@ -708,7 +708,12 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
 
                     if trait_is_const {
                         // Trait calls are always conditionally-const.
-                        self.check_op(ops::ConditionallyConstCall { callee, args: fn_args });
+                        self.check_op(ops::ConditionallyConstCall {
+                            callee,
+                            args: fn_args,
+                            span: *fn_span,
+                            call_source,
+                        });
                         // FIXME(const_trait_impl): do a more fine-grained check whether this
                         // particular trait can be const-stably called.
                     } else {
@@ -726,7 +731,12 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
 
                 // Even if we know the callee, ensure we can use conditionally-const calls.
                 if has_const_conditions {
-                    self.check_op(ops::ConditionallyConstCall { callee, args: fn_args });
+                    self.check_op(ops::ConditionallyConstCall {
+                        callee,
+                        args: fn_args,
+                        span: *fn_span,
+                        call_source,
+                    });
                 }
 
                 // At this point, we are calling a function, `callee`, whose `DefId` is known...
diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs
index ebd680ac28a..6707ebe7d1c 100644
--- a/compiler/rustc_const_eval/src/check_consts/ops.rs
+++ b/compiler/rustc_const_eval/src/check_consts/ops.rs
@@ -15,6 +15,7 @@ use rustc_middle::ty::{
     suggest_constraining_type_param,
 };
 use rustc_middle::util::{CallDesugaringKind, CallKind, call_kind};
+use rustc_session::parse::add_feature_diagnostics;
 use rustc_span::{BytePos, Pos, Span, Symbol, sym};
 use rustc_trait_selection::traits::SelectionContext;
 use tracing::debug;
@@ -77,6 +78,8 @@ impl<'tcx> NonConstOp<'tcx> for FnCallIndirect {
 pub(crate) struct ConditionallyConstCall<'tcx> {
     pub callee: DefId,
     pub args: GenericArgsRef<'tcx>,
+    pub span: Span,
+    pub call_source: CallSource,
 }
 
 impl<'tcx> NonConstOp<'tcx> for ConditionallyConstCall<'tcx> {
@@ -91,16 +94,22 @@ impl<'tcx> NonConstOp<'tcx> for ConditionallyConstCall<'tcx> {
         }
     }
 
-    fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
-        ccx.tcx.sess.create_feature_err(
-            errors::ConditionallyConstCall {
-                span,
-                def_path_str: ccx.tcx.def_path_str_with_args(self.callee, self.args),
-                def_descr: ccx.tcx.def_descr(self.callee),
-                kind: ccx.const_kind(),
-            },
-            sym::const_trait_impl,
-        )
+    fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, _: Span) -> Diag<'tcx> {
+        let mut diag = build_error_for_const_call(
+            ccx,
+            self.callee,
+            self.args,
+            self.span,
+            self.call_source,
+            "conditionally",
+            |_, _, _| {},
+        );
+
+        // Override code and mention feature.
+        diag.code(E0658);
+        add_feature_diagnostics(&mut diag, ccx.tcx.sess, sym::const_trait_impl);
+
+        diag
     }
 }
 
@@ -118,210 +127,250 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
     #[allow(rustc::diagnostic_outside_of_impl)]
     #[allow(rustc::untranslatable_diagnostic)]
     fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, _: Span) -> Diag<'tcx> {
-        let FnCallNonConst { callee, args, span, call_source } = *self;
-        let ConstCx { tcx, typing_env, .. } = *ccx;
+        let tcx = ccx.tcx;
         let caller = ccx.def_id();
 
-        let diag_trait = |err, self_ty: Ty<'_>, trait_id| {
-            let trait_ref = TraitRef::from_method(tcx, trait_id, args);
-
-            match self_ty.kind() {
-                Param(param_ty) => {
-                    debug!(?param_ty);
-                    if let Some(generics) = tcx.hir_node_by_def_id(caller).generics() {
-                        let constraint = with_no_trimmed_paths!(format!(
-                            "~const {}",
-                            trait_ref.print_trait_sugared(),
-                        ));
-                        suggest_constraining_type_param(
-                            tcx,
-                            generics,
-                            err,
-                            param_ty.name.as_str(),
-                            &constraint,
-                            Some(trait_ref.def_id),
-                            None,
-                        );
+        let mut err = build_error_for_const_call(
+            ccx,
+            self.callee,
+            self.args,
+            self.span,
+            self.call_source,
+            "non",
+            |err, self_ty, trait_id| {
+                // FIXME(const_trait_impl): Do we need any of this on the non-const codepath?
+
+                let trait_ref = TraitRef::from_method(tcx, trait_id, self.args);
+
+                match self_ty.kind() {
+                    Param(param_ty) => {
+                        debug!(?param_ty);
+                        if let Some(generics) = tcx.hir_node_by_def_id(caller).generics() {
+                            let constraint = with_no_trimmed_paths!(format!(
+                                "~const {}",
+                                trait_ref.print_trait_sugared(),
+                            ));
+                            suggest_constraining_type_param(
+                                tcx,
+                                generics,
+                                err,
+                                param_ty.name.as_str(),
+                                &constraint,
+                                Some(trait_ref.def_id),
+                                None,
+                            );
+                        }
                     }
-                }
-                ty::Adt(..) => {
-                    let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env);
-                    let obligation =
-                        Obligation::new(tcx, ObligationCause::dummy(), param_env, trait_ref);
-                    let mut selcx = SelectionContext::new(&infcx);
-                    let implsrc = selcx.select(&obligation);
-                    if let Ok(Some(ImplSource::UserDefined(data))) = implsrc {
-                        // FIXME(const_trait_impl) revisit this
-                        if !tcx.is_const_trait_impl(data.impl_def_id) {
-                            let span = tcx.def_span(data.impl_def_id);
-                            err.subdiagnostic(errors::NonConstImplNote { span });
+                    ty::Adt(..) => {
+                        let (infcx, param_env) =
+                            tcx.infer_ctxt().build_with_typing_env(ccx.typing_env);
+                        let obligation =
+                            Obligation::new(tcx, ObligationCause::dummy(), param_env, trait_ref);
+                        let mut selcx = SelectionContext::new(&infcx);
+                        let implsrc = selcx.select(&obligation);
+                        if let Ok(Some(ImplSource::UserDefined(data))) = implsrc {
+                            // FIXME(const_trait_impl) revisit this
+                            if !tcx.is_const_trait_impl(data.impl_def_id) {
+                                let span = tcx.def_span(data.impl_def_id);
+                                err.subdiagnostic(errors::NonConstImplNote { span });
+                            }
                         }
                     }
+                    _ => {}
                 }
-                _ => {}
+            },
+        );
+
+        if let ConstContext::Static(_) = ccx.const_kind() {
+            err.note(fluent_generated::const_eval_lazy_lock);
+        }
+
+        err
+    }
+}
+
+/// Build an error message reporting that a function call is not const (or only
+/// conditionally const). In case that this call is desugared (like an operator
+/// or sugar from something like a `for` loop), try to build a better error message
+/// that doesn't call it a method.
+fn build_error_for_const_call<'tcx>(
+    ccx: &ConstCx<'_, 'tcx>,
+    callee: DefId,
+    args: ty::GenericArgsRef<'tcx>,
+    span: Span,
+    call_source: CallSource,
+    non_or_conditionally: &'static str,
+    note_trait_if_possible: impl FnOnce(&mut Diag<'tcx>, Ty<'tcx>, DefId),
+) -> Diag<'tcx> {
+    let tcx = ccx.tcx;
+
+    let call_kind =
+        call_kind(tcx, ccx.typing_env, callee, args, span, call_source.from_hir_call(), None);
+
+    debug!(?call_kind);
+
+    let mut err = match call_kind {
+        CallKind::Normal { desugaring: Some((kind, self_ty)), .. } => {
+            macro_rules! error {
+                ($err:ident) => {
+                    tcx.dcx().create_err(errors::$err {
+                        span,
+                        ty: self_ty,
+                        kind: ccx.const_kind(),
+                        non_or_conditionally,
+                    })
+                };
             }
-        };
-
-        let call_kind =
-            call_kind(tcx, ccx.typing_env, callee, args, span, call_source.from_hir_call(), None);
-
-        debug!(?call_kind);
-
-        let mut err = match call_kind {
-            CallKind::Normal { desugaring: Some((kind, self_ty)), .. } => {
-                macro_rules! error {
-                    ($err:ident) => {
-                        tcx.dcx().create_err(errors::$err {
-                            span,
-                            ty: self_ty,
-                            kind: ccx.const_kind(),
-                        })
-                    };
-                }
 
-                // Don't point at the trait if this is a desugaring...
-                // FIXME(const_trait_impl): we could perhaps do this for `Iterator`.
-                match kind {
-                    CallDesugaringKind::ForLoopIntoIter | CallDesugaringKind::ForLoopNext => {
-                        error!(NonConstForLoopIntoIter)
-                    }
-                    CallDesugaringKind::QuestionBranch => {
-                        error!(NonConstQuestionBranch)
-                    }
-                    CallDesugaringKind::QuestionFromResidual => {
-                        error!(NonConstQuestionFromResidual)
-                    }
-                    CallDesugaringKind::TryBlockFromOutput => {
-                        error!(NonConstTryBlockFromOutput)
-                    }
-                    CallDesugaringKind::Await => {
-                        error!(NonConstAwait)
-                    }
+            // Don't point at the trait if this is a desugaring...
+            // FIXME(const_trait_impl): we could perhaps do this for `Iterator`.
+            match kind {
+                CallDesugaringKind::ForLoopIntoIter | CallDesugaringKind::ForLoopNext => {
+                    error!(NonConstForLoopIntoIter)
+                }
+                CallDesugaringKind::QuestionBranch => {
+                    error!(NonConstQuestionBranch)
+                }
+                CallDesugaringKind::QuestionFromResidual => {
+                    error!(NonConstQuestionFromResidual)
+                }
+                CallDesugaringKind::TryBlockFromOutput => {
+                    error!(NonConstTryBlockFromOutput)
+                }
+                CallDesugaringKind::Await => {
+                    error!(NonConstAwait)
                 }
             }
-            CallKind::FnCall { fn_trait_id, self_ty } => {
-                let note = match self_ty.kind() {
-                    FnDef(def_id, ..) => {
-                        let span = tcx.def_span(*def_id);
-                        if ccx.tcx.is_const_fn(*def_id) {
-                            span_bug!(span, "calling const FnDef errored when it shouldn't");
-                        }
-
-                        Some(errors::NonConstClosureNote::FnDef { span })
+        }
+        CallKind::FnCall { fn_trait_id, self_ty } => {
+            let note = match self_ty.kind() {
+                FnDef(def_id, ..) => {
+                    let span = tcx.def_span(*def_id);
+                    if ccx.tcx.is_const_fn(*def_id) {
+                        span_bug!(span, "calling const FnDef errored when it shouldn't");
                     }
-                    FnPtr(..) => Some(errors::NonConstClosureNote::FnPtr),
-                    Closure(..) => Some(errors::NonConstClosureNote::Closure),
-                    _ => None,
-                };
 
-                let mut err = tcx.dcx().create_err(errors::NonConstClosure {
+                    Some(errors::NonConstClosureNote::FnDef { span })
+                }
+                FnPtr(..) => Some(errors::NonConstClosureNote::FnPtr),
+                Closure(..) => Some(errors::NonConstClosureNote::Closure),
+                _ => None,
+            };
+
+            let mut err = tcx.dcx().create_err(errors::NonConstClosure {
+                span,
+                kind: ccx.const_kind(),
+                note,
+                non_or_conditionally,
+            });
+
+            note_trait_if_possible(&mut err, self_ty, fn_trait_id);
+            err
+        }
+        CallKind::Operator { trait_id, self_ty, .. } => {
+            let mut err = if let CallSource::MatchCmp = call_source {
+                tcx.dcx().create_err(errors::NonConstMatchEq {
                     span,
                     kind: ccx.const_kind(),
-                    note,
-                });
-
-                diag_trait(&mut err, self_ty, fn_trait_id);
-                err
-            }
-            CallKind::Operator { trait_id, self_ty, .. } => {
-                let mut err = if let CallSource::MatchCmp = call_source {
-                    tcx.dcx().create_err(errors::NonConstMatchEq {
-                        span,
-                        kind: ccx.const_kind(),
-                        ty: self_ty,
-                    })
-                } else {
-                    let mut sugg = None;
-
-                    if ccx.tcx.is_lang_item(trait_id, LangItem::PartialEq) {
-                        match (args[0].unpack(), args[1].unpack()) {
-                            (GenericArgKind::Type(self_ty), GenericArgKind::Type(rhs_ty))
-                                if self_ty == rhs_ty
-                                    && self_ty.is_ref()
-                                    && self_ty.peel_refs().is_primitive() =>
-                            {
-                                let mut num_refs = 0;
-                                let mut tmp_ty = self_ty;
-                                while let rustc_middle::ty::Ref(_, inner_ty, _) = tmp_ty.kind() {
-                                    num_refs += 1;
-                                    tmp_ty = *inner_ty;
-                                }
-                                let deref = "*".repeat(num_refs);
-
-                                if let Ok(call_str) =
-                                    ccx.tcx.sess.source_map().span_to_snippet(span)
-                                {
-                                    if let Some(eq_idx) = call_str.find("==") {
-                                        if let Some(rhs_idx) = call_str[(eq_idx + 2)..]
-                                            .find(|c: char| !c.is_whitespace())
-                                        {
-                                            let rhs_pos = span.lo()
-                                                + BytePos::from_usize(eq_idx + 2 + rhs_idx);
-                                            let rhs_span = span.with_lo(rhs_pos).with_hi(rhs_pos);
-                                            sugg = Some(errors::ConsiderDereferencing {
-                                                deref,
-                                                span: span.shrink_to_lo(),
-                                                rhs_span,
-                                            });
-                                        }
+                    ty: self_ty,
+                    non_or_conditionally,
+                })
+            } else {
+                let mut sugg = None;
+
+                if ccx.tcx.is_lang_item(trait_id, LangItem::PartialEq) {
+                    match (args[0].unpack(), args[1].unpack()) {
+                        (GenericArgKind::Type(self_ty), GenericArgKind::Type(rhs_ty))
+                            if self_ty == rhs_ty
+                                && self_ty.is_ref()
+                                && self_ty.peel_refs().is_primitive() =>
+                        {
+                            let mut num_refs = 0;
+                            let mut tmp_ty = self_ty;
+                            while let rustc_middle::ty::Ref(_, inner_ty, _) = tmp_ty.kind() {
+                                num_refs += 1;
+                                tmp_ty = *inner_ty;
+                            }
+                            let deref = "*".repeat(num_refs);
+
+                            if let Ok(call_str) = ccx.tcx.sess.source_map().span_to_snippet(span) {
+                                if let Some(eq_idx) = call_str.find("==") {
+                                    if let Some(rhs_idx) =
+                                        call_str[(eq_idx + 2)..].find(|c: char| !c.is_whitespace())
+                                    {
+                                        let rhs_pos =
+                                            span.lo() + BytePos::from_usize(eq_idx + 2 + rhs_idx);
+                                        let rhs_span = span.with_lo(rhs_pos).with_hi(rhs_pos);
+                                        sugg = Some(errors::ConsiderDereferencing {
+                                            deref,
+                                            span: span.shrink_to_lo(),
+                                            rhs_span,
+                                        });
                                     }
                                 }
                             }
-                            _ => {}
                         }
+                        _ => {}
                     }
-                    tcx.dcx().create_err(errors::NonConstOperator {
-                        span,
-                        kind: ccx.const_kind(),
-                        sugg,
-                    })
-                };
-
-                diag_trait(&mut err, self_ty, trait_id);
-                err
-            }
-            CallKind::DerefCoercion { deref_target, deref_target_ty, self_ty } => {
-                // Check first whether the source is accessible (issue #87060)
-                let target = if tcx.sess.source_map().is_span_accessible(deref_target) {
-                    Some(deref_target)
-                } else {
-                    None
-                };
-
-                let mut err = tcx.dcx().create_err(errors::NonConstDerefCoercion {
+                }
+                tcx.dcx().create_err(errors::NonConstOperator {
                     span,
-                    ty: self_ty,
                     kind: ccx.const_kind(),
-                    target_ty: deref_target_ty,
-                    deref_target: target,
-                });
+                    sugg,
+                    non_or_conditionally,
+                })
+            };
 
-                diag_trait(&mut err, self_ty, tcx.require_lang_item(LangItem::Deref, Some(span)));
-                err
-            }
-            _ if tcx.opt_parent(callee) == tcx.get_diagnostic_item(sym::ArgumentMethods) => {
-                ccx.dcx().create_err(errors::NonConstFmtMacroCall { span, kind: ccx.const_kind() })
-            }
-            _ => ccx.dcx().create_err(errors::NonConstFnCall {
+            note_trait_if_possible(&mut err, self_ty, trait_id);
+            err
+        }
+        CallKind::DerefCoercion { deref_target, deref_target_ty, self_ty } => {
+            // Check first whether the source is accessible (issue #87060)
+            let target = if tcx.sess.source_map().is_span_accessible(deref_target) {
+                Some(deref_target)
+            } else {
+                None
+            };
+
+            let mut err = tcx.dcx().create_err(errors::NonConstDerefCoercion {
                 span,
-                def_descr: ccx.tcx.def_descr(callee),
-                def_path_str: ccx.tcx.def_path_str_with_args(callee, args),
+                ty: self_ty,
                 kind: ccx.const_kind(),
-            }),
-        };
+                target_ty: deref_target_ty,
+                deref_target: target,
+                non_or_conditionally,
+            });
+
+            note_trait_if_possible(
+                &mut err,
+                self_ty,
+                tcx.require_lang_item(LangItem::Deref, Some(span)),
+            );
+            err
+        }
+        _ if tcx.opt_parent(callee) == tcx.get_diagnostic_item(sym::ArgumentMethods) => {
+            ccx.dcx().create_err(errors::NonConstFmtMacroCall {
+                span,
+                kind: ccx.const_kind(),
+                non_or_conditionally,
+            })
+        }
+        _ => ccx.dcx().create_err(errors::NonConstFnCall {
+            span,
+            def_descr: ccx.tcx.def_descr(callee),
+            def_path_str: ccx.tcx.def_path_str_with_args(callee, args),
+            kind: ccx.const_kind(),
+            non_or_conditionally,
+        }),
+    };
 
-        err.note(format!(
-            "calls in {}s are limited to constant functions, \
+    err.note(format!(
+        "calls in {}s are limited to constant functions, \
              tuple structs and tuple variants",
-            ccx.const_kind(),
-        ));
-
-        if let ConstContext::Static(_) = ccx.const_kind() {
-            err.note(fluent_generated::const_eval_lazy_lock);
-        }
+        ccx.const_kind(),
+    ));
 
-        err
-    }
+    err
 }
 
 /// A call to an `#[unstable]` const fn or `#[rustc_const_unstable]` function.
diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs
index 57534540019..3fe78171cd9 100644
--- a/compiler/rustc_const_eval/src/errors.rs
+++ b/compiler/rustc_const_eval/src/errors.rs
@@ -174,16 +174,7 @@ pub(crate) struct NonConstFmtMacroCall {
     #[primary_span]
     pub span: Span,
     pub kind: ConstContext,
-}
-
-#[derive(Diagnostic)]
-#[diag(const_eval_conditionally_const_call)]
-pub(crate) struct ConditionallyConstCall {
-    #[primary_span]
-    pub span: Span,
-    pub def_path_str: String,
-    pub def_descr: &'static str,
-    pub kind: ConstContext,
+    pub non_or_conditionally: &'static str,
 }
 
 #[derive(Diagnostic)]
@@ -194,6 +185,7 @@ pub(crate) struct NonConstFnCall {
     pub def_path_str: String,
     pub def_descr: &'static str,
     pub kind: ConstContext,
+    pub non_or_conditionally: &'static str,
 }
 
 #[derive(Diagnostic)]
@@ -293,68 +285,75 @@ pub struct RawBytesNote {
 // FIXME(fee1-dead) do not use stringly typed `ConstContext`
 
 #[derive(Diagnostic)]
-#[diag(const_eval_match_eq_non_const, code = E0015)]
+#[diag(const_eval_non_const_match_eq, code = E0015)]
 #[note]
 pub struct NonConstMatchEq<'tcx> {
     #[primary_span]
     pub span: Span,
     pub ty: Ty<'tcx>,
     pub kind: ConstContext,
+    pub non_or_conditionally: &'static str,
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_for_loop_into_iter_non_const, code = E0015)]
+#[diag(const_eval_non_const_for_loop_into_iter, code = E0015)]
 pub struct NonConstForLoopIntoIter<'tcx> {
     #[primary_span]
     pub span: Span,
     pub ty: Ty<'tcx>,
     pub kind: ConstContext,
+    pub non_or_conditionally: &'static str,
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_question_branch_non_const, code = E0015)]
+#[diag(const_eval_non_const_question_branch, code = E0015)]
 pub struct NonConstQuestionBranch<'tcx> {
     #[primary_span]
     pub span: Span,
     pub ty: Ty<'tcx>,
     pub kind: ConstContext,
+    pub non_or_conditionally: &'static str,
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_question_from_residual_non_const, code = E0015)]
+#[diag(const_eval_non_const_question_from_residual, code = E0015)]
 pub struct NonConstQuestionFromResidual<'tcx> {
     #[primary_span]
     pub span: Span,
     pub ty: Ty<'tcx>,
     pub kind: ConstContext,
+    pub non_or_conditionally: &'static str,
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_try_block_from_output_non_const, code = E0015)]
+#[diag(const_eval_non_const_try_block_from_output, code = E0015)]
 pub struct NonConstTryBlockFromOutput<'tcx> {
     #[primary_span]
     pub span: Span,
     pub ty: Ty<'tcx>,
     pub kind: ConstContext,
+    pub non_or_conditionally: &'static str,
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_await_non_const, code = E0015)]
+#[diag(const_eval_non_const_await, code = E0015)]
 pub struct NonConstAwait<'tcx> {
     #[primary_span]
     pub span: Span,
     pub ty: Ty<'tcx>,
     pub kind: ConstContext,
+    pub non_or_conditionally: &'static str,
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_closure_non_const, code = E0015)]
+#[diag(const_eval_non_const_closure, code = E0015)]
 pub struct NonConstClosure {
     #[primary_span]
     pub span: Span,
     pub kind: ConstContext,
     #[subdiagnostic]
     pub note: Option<NonConstClosureNote>,
+    pub non_or_conditionally: &'static str,
 }
 
 #[derive(Subdiagnostic)]
@@ -381,17 +380,18 @@ pub struct ConsiderDereferencing {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_operator_non_const, code = E0015)]
+#[diag(const_eval_non_const_operator, code = E0015)]
 pub struct NonConstOperator {
     #[primary_span]
     pub span: Span,
     pub kind: ConstContext,
     #[subdiagnostic]
     pub sugg: Option<ConsiderDereferencing>,
+    pub non_or_conditionally: &'static str,
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_deref_coercion_non_const, code = E0015)]
+#[diag(const_eval_non_const_deref_coercion, code = E0015)]
 #[note]
 pub struct NonConstDerefCoercion<'tcx> {
     #[primary_span]
@@ -401,6 +401,7 @@ pub struct NonConstDerefCoercion<'tcx> {
     pub target_ty: Ty<'tcx>,
     #[note(const_eval_target_note)]
     pub deref_target: Option<Span>,
+    pub non_or_conditionally: &'static str,
 }
 
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 5421517046d..3c3bbc8c31d 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -572,7 +572,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     // `#[coroutine]` attribute to be applied to closures to make them coroutines instead
     gated!(
         coroutine, Normal, template!(Word), ErrorFollowing,
-        EncodeCrossCrate::No, coroutines, experimental!(coroutines)
+        EncodeCrossCrate::No, coroutines, experimental!(coroutine)
     ),
 
     // RFC 3543
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index 0c19e2e4c51..1569c0963c8 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -1036,7 +1036,7 @@ pub(super) fn const_conditions<'tcx>(
 
         icx.lowerer().lower_bounds(
             tcx.types.self_param,
-            supertraits.into_iter(),
+            supertraits,
             &mut bounds,
             ty::List::empty(),
             PredicateFilter::ConstIfConst,
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 72a1e4af9bf..b3d87ef4ad2 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -1096,7 +1096,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     )
                 ) {
                     continue;
-                };
+                }
 
                 match self.tcx.hir().get_if_local(item_def_id) {
                     // Unmet obligation comes from a `derive` macro, point at it once to
@@ -1210,8 +1210,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         entry.1.insert((cause_span, "unsatisfied trait bound introduced here"));
                         entry.2.push(p);
                     }
-                    Some(node) => unreachable!("encountered `{node:?}` due to `{cause:#?}`"),
-                    None => (),
+                    _ => {
+                        // It's possible to use well-formedness clauses to get obligations
+                        // which point arbitrary items like ADTs, so there's no use in ICEing
+                        // here if we find that the obligation originates from some other
+                        // node that we don't handle.
+                    }
                 }
             }
             let mut spanned_predicates: Vec<_> = spanned_predicates.into_iter().collect();
diff --git a/compiler/rustc_mir_transform/src/coverage/mappings.rs b/compiler/rustc_mir_transform/src/coverage/mappings.rs
index 4185b3f4d4d..5bd20e00eb6 100644
--- a/compiler/rustc_mir_transform/src/coverage/mappings.rs
+++ b/compiler/rustc_mir_transform/src/coverage/mappings.rs
@@ -367,9 +367,8 @@ fn calc_test_vectors_index(conditions: &mut Vec<MCDCBranch>) -> usize {
         })
         .collect::<FxIndexMap<_, _>>();
 
-    let mut queue = std::collections::VecDeque::from_iter(
-        next_conditions.swap_remove(&ConditionId::START).into_iter(),
-    );
+    let mut queue =
+        std::collections::VecDeque::from_iter(next_conditions.swap_remove(&ConditionId::START));
     num_paths_stats[ConditionId::START] = 1;
     let mut decision_end_nodes = Vec::new();
     while let Some(branch) = queue.pop_front() {
diff --git a/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs b/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs
index 6590702118c..50d10883d2c 100644
--- a/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs
+++ b/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs
@@ -691,7 +691,7 @@ impl Subdiagnostic for LocalLabel<'_> {
         for dtor in self.destructors {
             dtor.add_to_diag_with(diag, f);
         }
-        let msg = f(diag, crate::fluent_generated::mir_transform_label_local_epilogue.into());
+        let msg = f(diag, crate::fluent_generated::mir_transform_label_local_epilogue);
         diag.span_label(self.span, msg);
     }
 }
diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs
index 26a09f0daca..b19c9cee75a 100644
--- a/library/proc_macro/src/lib.rs
+++ b/library/proc_macro/src/lib.rs
@@ -419,7 +419,7 @@ pub mod token_stream {
 /// Unquoting is done with `$`, and works by taking the single next ident as the unquoted term.
 /// To quote `$` itself, use `$$`.
 #[unstable(feature = "proc_macro_quote", issue = "54722")]
-#[allow_internal_unstable(proc_macro_def_site, proc_macro_internals)]
+#[allow_internal_unstable(proc_macro_def_site, proc_macro_internals, proc_macro_totokens)]
 #[rustc_builtin_macro]
 pub macro quote($($t:tt)*) {
     /* compiler built-in */
diff --git a/library/proc_macro/src/quote.rs b/library/proc_macro/src/quote.rs
index 04fa696d5e6..bcb15912bb6 100644
--- a/library/proc_macro/src/quote.rs
+++ b/library/proc_macro/src/quote.rs
@@ -4,12 +4,14 @@
 //! This quasiquoter uses macros 2.0 hygiene to reliably access
 //! items from `proc_macro`, to build a `proc_macro::TokenStream`.
 
-use crate::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree};
+use crate::{
+    Delimiter, Group, Ident, Literal, Punct, Spacing, Span, ToTokens, TokenStream, TokenTree,
+};
 
-macro_rules! quote_tt {
-    (($($t:tt)*)) => { Group::new(Delimiter::Parenthesis, quote!($($t)*)) };
-    ([$($t:tt)*]) => { Group::new(Delimiter::Bracket, quote!($($t)*)) };
-    ({$($t:tt)*}) => { Group::new(Delimiter::Brace, quote!($($t)*)) };
+macro_rules! minimal_quote_tt {
+    (($($t:tt)*)) => { Group::new(Delimiter::Parenthesis, minimal_quote!($($t)*)) };
+    ([$($t:tt)*]) => { Group::new(Delimiter::Bracket, minimal_quote!($($t)*)) };
+    ({$($t:tt)*}) => { Group::new(Delimiter::Brace, minimal_quote!($($t)*)) };
     (,) => { Punct::new(',', Spacing::Alone) };
     (.) => { Punct::new('.', Spacing::Alone) };
     (;) => { Punct::new(';', Spacing::Alone) };
@@ -21,21 +23,20 @@ macro_rules! quote_tt {
     ($i:ident) => { Ident::new(stringify!($i), Span::def_site()) };
 }
 
-macro_rules! quote_ts {
+macro_rules! minimal_quote_ts {
     ((@ $($t:tt)*)) => { $($t)* };
     (::) => {
-        [
-            TokenTree::from(Punct::new(':', Spacing::Joint)),
-            TokenTree::from(Punct::new(':', Spacing::Alone)),
-        ].iter()
-            .cloned()
-            .map(|mut x| {
-                x.set_span(Span::def_site());
-                x
-            })
-            .collect::<TokenStream>()
+        {
+            let mut c = (
+                TokenTree::from(Punct::new(':', Spacing::Joint)),
+                TokenTree::from(Punct::new(':', Spacing::Alone))
+            );
+            c.0.set_span(Span::def_site());
+            c.1.set_span(Span::def_site());
+            [c.0, c.1].into_iter().collect::<TokenStream>()
+        }
     };
-    ($t:tt) => { TokenTree::from(quote_tt!($t)) };
+    ($t:tt) => { TokenTree::from(minimal_quote_tt!($t)) };
 }
 
 /// Simpler version of the real `quote!` macro, implemented solely
@@ -46,12 +47,14 @@ macro_rules! quote_ts {
 ///
 /// Note: supported tokens are a subset of the real `quote!`, but
 /// unquoting is different: instead of `$x`, this uses `(@ expr)`.
-macro_rules! quote {
-    () => { TokenStream::new() };
+macro_rules! minimal_quote {
     ($($t:tt)*) => {
-        [
-            $(TokenStream::from(quote_ts!($t)),)*
-        ].iter().cloned().collect::<TokenStream>()
+        {
+            #[allow(unused_mut)] // In case the expansion is empty
+            let mut ts = TokenStream::new();
+            $(ToTokens::to_tokens(&minimal_quote_ts!($t), &mut ts);)*
+            ts
+        }
     };
 }
 
@@ -62,52 +65,66 @@ macro_rules! quote {
 #[unstable(feature = "proc_macro_quote", issue = "54722")]
 pub fn quote(stream: TokenStream) -> TokenStream {
     if stream.is_empty() {
-        return quote!(crate::TokenStream::new());
+        return minimal_quote!(crate::TokenStream::new());
     }
-    let proc_macro_crate = quote!(crate);
+    let proc_macro_crate = minimal_quote!(crate);
     let mut after_dollar = false;
-    let tokens = stream
-        .into_iter()
-        .filter_map(|tree| {
-            if after_dollar {
-                after_dollar = false;
-                match tree {
-                    TokenTree::Ident(_) => {
-                        return Some(quote!(Into::<crate::TokenStream>::into(
-                        Clone::clone(&(@ tree))),));
-                    }
-                    TokenTree::Punct(ref tt) if tt.as_char() == '$' => {}
-                    _ => panic!("`$` must be followed by an ident or `$` in `quote!`"),
-                }
-            } else if let TokenTree::Punct(ref tt) = tree {
-                if tt.as_char() == '$' {
-                    after_dollar = true;
-                    return None;
+
+    let mut tokens = crate::TokenStream::new();
+    for tree in stream {
+        if after_dollar {
+            after_dollar = false;
+            match tree {
+                TokenTree::Ident(_) => {
+                    minimal_quote!(crate::ToTokens::to_tokens(&(@ tree), &mut ts);)
+                        .to_tokens(&mut tokens);
+                    continue;
                 }
+                TokenTree::Punct(ref tt) if tt.as_char() == '$' => {}
+                _ => panic!("`$` must be followed by an ident or `$` in `quote!`"),
             }
+        } else if let TokenTree::Punct(ref tt) = tree {
+            if tt.as_char() == '$' {
+                after_dollar = true;
+                continue;
+            }
+        }
 
-            Some(quote!(crate::TokenStream::from((@ match tree {
-                TokenTree::Punct(tt) => quote!(crate::TokenTree::Punct(crate::Punct::new(
+        match tree {
+            TokenTree::Punct(tt) => {
+                minimal_quote!(crate::ToTokens::to_tokens(&crate::TokenTree::Punct(crate::Punct::new(
                     (@ TokenTree::from(Literal::character(tt.as_char()))),
                     (@ match tt.spacing() {
-                        Spacing::Alone => quote!(crate::Spacing::Alone),
-                        Spacing::Joint => quote!(crate::Spacing::Joint),
+                        Spacing::Alone => minimal_quote!(crate::Spacing::Alone),
+                        Spacing::Joint => minimal_quote!(crate::Spacing::Joint),
                     }),
-                ))),
-                TokenTree::Group(tt) => quote!(crate::TokenTree::Group(crate::Group::new(
+                )), &mut ts);)
+            }
+            TokenTree::Group(tt) => {
+                minimal_quote!(crate::ToTokens::to_tokens(&crate::TokenTree::Group(crate::Group::new(
                     (@ match tt.delimiter() {
-                        Delimiter::Parenthesis => quote!(crate::Delimiter::Parenthesis),
-                        Delimiter::Brace => quote!(crate::Delimiter::Brace),
-                        Delimiter::Bracket => quote!(crate::Delimiter::Bracket),
-                        Delimiter::None => quote!(crate::Delimiter::None),
+                        Delimiter::Parenthesis => minimal_quote!(crate::Delimiter::Parenthesis),
+                        Delimiter::Brace => minimal_quote!(crate::Delimiter::Brace),
+                        Delimiter::Bracket => minimal_quote!(crate::Delimiter::Bracket),
+                        Delimiter::None => minimal_quote!(crate::Delimiter::None),
                     }),
                     (@ quote(tt.stream())),
-                ))),
-                TokenTree::Ident(tt) => quote!(crate::TokenTree::Ident(crate::Ident::new(
-                    (@ TokenTree::from(Literal::string(&tt.to_string()))),
+                )), &mut ts);)
+            }
+            TokenTree::Ident(tt) => {
+                let literal = tt.to_string();
+                let (literal, ctor) = if let Some(stripped) = literal.strip_prefix("r#") {
+                    (stripped, minimal_quote!(crate::Ident::new_raw))
+                } else {
+                    (literal.as_str(), minimal_quote!(crate::Ident::new))
+                };
+                minimal_quote!(crate::ToTokens::to_tokens(&crate::TokenTree::Ident((@ ctor)(
+                    (@ TokenTree::from(Literal::string(literal))),
                     (@ quote_span(proc_macro_crate.clone(), tt.span())),
-                ))),
-                TokenTree::Literal(tt) => quote!(crate::TokenTree::Literal({
+                )), &mut ts);)
+            }
+            TokenTree::Literal(tt) => {
+                minimal_quote!(crate::ToTokens::to_tokens(&crate::TokenTree::Literal({
                     let mut iter = (@ TokenTree::from(Literal::string(&tt.to_string())))
                         .parse::<crate::TokenStream>()
                         .unwrap()
@@ -120,16 +137,22 @@ pub fn quote(stream: TokenStream) -> TokenStream {
                     } else {
                         unreachable!()
                     }
-                }))
-            })),))
-        })
-        .collect::<TokenStream>();
-
+                }), &mut ts);)
+            }
+        }
+        .to_tokens(&mut tokens);
+    }
     if after_dollar {
         panic!("unexpected trailing `$` in `quote!`");
     }
 
-    quote!([(@ tokens)].iter().cloned().collect::<crate::TokenStream>())
+    minimal_quote! {
+        {
+            let mut ts = crate::TokenStream::new();
+            (@ tokens)
+            ts
+        }
+    }
 }
 
 /// Quote a `Span` into a `TokenStream`.
@@ -137,5 +160,5 @@ pub fn quote(stream: TokenStream) -> TokenStream {
 #[unstable(feature = "proc_macro_quote", issue = "54722")]
 pub fn quote_span(proc_macro_crate: TokenStream, span: Span) -> TokenStream {
     let id = span.save_span();
-    quote!((@ proc_macro_crate ) ::Span::recover_proc_macro_span((@ TokenTree::from(Literal::usize_unsuffixed(id)))))
+    minimal_quote!((@ proc_macro_crate ) ::Span::recover_proc_macro_span((@ TokenTree::from(Literal::usize_unsuffixed(id)))))
 }
diff --git a/library/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs
index e360ba0f6d7..f657f82e6e3 100644
--- a/library/std/src/sys/pal/unix/thread.rs
+++ b/library/std/src/sys/pal/unix/thread.rs
@@ -130,25 +130,27 @@ impl Thread {
         }
     }
 
-    #[cfg(target_os = "linux")]
+    #[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly"))]
     pub fn set_name(name: &CStr) {
-        const TASK_COMM_LEN: usize = 16;
-
         unsafe {
-            // Available since glibc 2.12, musl 1.1.16, and uClibc 1.0.20.
-            let name = truncate_cstr::<{ TASK_COMM_LEN }>(name);
+            cfg_if::cfg_if! {
+                if #[cfg(target_os = "linux")] {
+                    // Linux limits the allowed length of the name.
+                    const TASK_COMM_LEN: usize = 16;
+                    let name = truncate_cstr::<{ TASK_COMM_LEN }>(name);
+                } else {
+                    // FreeBSD and DragonFly BSD do not enforce length limits.
+                }
+            };
+            // Available since glibc 2.12, musl 1.1.16, and uClibc 1.0.20 for Linux,
+            // FreeBSD 12.2 and 13.0, and DragonFly BSD 6.0.
             let res = libc::pthread_setname_np(libc::pthread_self(), name.as_ptr());
             // We have no good way of propagating errors here, but in debug-builds let's check that this actually worked.
             debug_assert_eq!(res, 0);
         }
     }
 
-    #[cfg(any(
-        target_os = "freebsd",
-        target_os = "dragonfly",
-        target_os = "openbsd",
-        target_os = "nuttx"
-    ))]
+    #[cfg(any(target_os = "openbsd", target_os = "nuttx"))]
     pub fn set_name(name: &CStr) {
         unsafe {
             libc::pthread_set_name_np(libc::pthread_self(), name.as_ptr());
diff --git a/src/tools/rustfmt/src/patterns.rs b/src/tools/rustfmt/src/patterns.rs
index b55469f332a..1d88726d945 100644
--- a/src/tools/rustfmt/src/patterns.rs
+++ b/src/tools/rustfmt/src/patterns.rs
@@ -31,18 +31,31 @@ use crate::utils::{format_mutability, mk_sp, mk_sp_lo_plus_one, rewrite_ident};
 ///     - `[small, ntp]`
 ///     - unary tuple constructor `([small, ntp])`
 ///     - `&[small]`
-pub(crate) fn is_short_pattern(pat: &ast::Pat, pat_str: &str) -> bool {
+pub(crate) fn is_short_pattern(
+    context: &RewriteContext<'_>,
+    pat: &ast::Pat,
+    pat_str: &str,
+) -> bool {
     // We also require that the pattern is reasonably 'small' with its literal width.
-    pat_str.len() <= 20 && !pat_str.contains('\n') && is_short_pattern_inner(pat)
+    pat_str.len() <= 20 && !pat_str.contains('\n') && is_short_pattern_inner(context, pat)
 }
 
-fn is_short_pattern_inner(pat: &ast::Pat) -> bool {
-    match pat.kind {
-        ast::PatKind::Rest
-        | ast::PatKind::Never
-        | ast::PatKind::Wild
-        | ast::PatKind::Err(_)
-        | ast::PatKind::Expr(_) => true,
+fn is_short_pattern_inner(context: &RewriteContext<'_>, pat: &ast::Pat) -> bool {
+    match &pat.kind {
+        ast::PatKind::Rest | ast::PatKind::Never | ast::PatKind::Wild | ast::PatKind::Err(_) => {
+            true
+        }
+        ast::PatKind::Expr(expr) => match &expr.kind {
+            ast::ExprKind::Lit(_) => true,
+            ast::ExprKind::Unary(ast::UnOp::Neg, expr) => match &expr.kind {
+                ast::ExprKind::Lit(_) => true,
+                _ => unreachable!(),
+            },
+            ast::ExprKind::ConstBlock(_) | ast::ExprKind::Path(..) => {
+                context.config.style_edition() <= StyleEdition::Edition2024
+            }
+            _ => unreachable!(),
+        },
         ast::PatKind::Ident(_, _, ref pat) => pat.is_none(),
         ast::PatKind::Struct(..)
         | ast::PatKind::MacCall(..)
@@ -57,8 +70,8 @@ fn is_short_pattern_inner(pat: &ast::Pat) -> bool {
         ast::PatKind::Box(ref p)
         | PatKind::Deref(ref p)
         | ast::PatKind::Ref(ref p, _)
-        | ast::PatKind::Paren(ref p) => is_short_pattern_inner(&*p),
-        PatKind::Or(ref pats) => pats.iter().all(|p| is_short_pattern_inner(p)),
+        | ast::PatKind::Paren(ref p) => is_short_pattern_inner(context, &*p),
+        PatKind::Or(ref pats) => pats.iter().all(|p| is_short_pattern_inner(context, p)),
     }
 }
 
@@ -96,7 +109,7 @@ impl Rewrite for Pat {
                 let use_mixed_layout = pats
                     .iter()
                     .zip(pat_strs.iter())
-                    .all(|(pat, pat_str)| is_short_pattern(pat, pat_str));
+                    .all(|(pat, pat_str)| is_short_pattern(context, pat, pat_str));
                 let items: Vec<_> = pat_strs.into_iter().map(ListItem::from_str).collect();
                 let tactic = if use_mixed_layout {
                     DefinitiveListTactic::Mixed
diff --git a/src/tools/rustfmt/tests/source/pattern.rs b/src/tools/rustfmt/tests/source/pattern.rs
index f06d03cadf2..ed6ad690fa9 100644
--- a/src/tools/rustfmt/tests/source/pattern.rs
+++ b/src/tools/rustfmt/tests/source/pattern.rs
@@ -88,3 +88,13 @@ fn issue3728() {
         | c;
     foo((1,));
 }
+
+fn literals() {
+    match 42 {
+        const { 1 + 2 } | 4
+        | 6 => {}
+        10 | 11 | 12
+        | 13 | 14 => {}
+        _ => {}
+    }
+}
\ No newline at end of file
diff --git a/src/tools/rustfmt/tests/target/pattern.rs b/src/tools/rustfmt/tests/target/pattern.rs
index 576018ac623..e867f65929d 100644
--- a/src/tools/rustfmt/tests/target/pattern.rs
+++ b/src/tools/rustfmt/tests/target/pattern.rs
@@ -96,3 +96,11 @@ fn issue3728() {
     let foo = |(c,)| c;
     foo((1,));
 }
+
+fn literals() {
+    match 42 {
+        const { 1 + 2 } | 4 | 6 => {}
+        10 | 11 | 12 | 13 | 14 => {}
+        _ => {}
+    }
+}
diff --git a/tests/ui/coroutine/gen_block.e2024.stderr b/tests/ui/coroutine/gen_block.e2024.stderr
index 322259cf2f8..0491bdbc2e1 100644
--- a/tests/ui/coroutine/gen_block.e2024.stderr
+++ b/tests/ui/coroutine/gen_block.e2024.stderr
@@ -1,4 +1,4 @@
-error[E0658]: the `#[coroutines]` attribute is an experimental feature
+error[E0658]: the `#[coroutine]` attribute is an experimental feature
   --> $DIR/gen_block.rs:20:13
    |
 LL |     let _ = #[coroutine] || yield true;
@@ -8,7 +8,7 @@ LL |     let _ = #[coroutine] || yield true;
    = help: add `#![feature(coroutines)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: the `#[coroutines]` attribute is an experimental feature
+error[E0658]: the `#[coroutine]` attribute is an experimental feature
   --> $DIR/gen_block.rs:24:13
    |
 LL |     let _ = #[coroutine] || {};
diff --git a/tests/ui/coroutine/gen_block.none.stderr b/tests/ui/coroutine/gen_block.none.stderr
index 15123a49e48..43437793005 100644
--- a/tests/ui/coroutine/gen_block.none.stderr
+++ b/tests/ui/coroutine/gen_block.none.stderr
@@ -44,7 +44,7 @@ LL |     let _ = #[coroutine] || yield true;
    = help: add `#![feature(coroutines)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: the `#[coroutines]` attribute is an experimental feature
+error[E0658]: the `#[coroutine]` attribute is an experimental feature
   --> $DIR/gen_block.rs:20:13
    |
 LL |     let _ = #[coroutine] || yield true;
@@ -54,7 +54,7 @@ LL |     let _ = #[coroutine] || yield true;
    = help: add `#![feature(coroutines)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: the `#[coroutines]` attribute is an experimental feature
+error[E0658]: the `#[coroutine]` attribute is an experimental feature
   --> $DIR/gen_block.rs:24:13
    |
 LL |     let _ = #[coroutine] || {};
diff --git a/tests/ui/coroutine/gen_block.rs b/tests/ui/coroutine/gen_block.rs
index 6734de3b667..4494d654eeb 100644
--- a/tests/ui/coroutine/gen_block.rs
+++ b/tests/ui/coroutine/gen_block.rs
@@ -18,9 +18,9 @@ fn main() {
     //~^^ ERROR `yield` can only be used in
 
     let _ = #[coroutine] || yield true; //[none]~ ERROR yield syntax is experimental
-    //~^ ERROR `#[coroutines]` attribute is an experimental feature
+    //~^ ERROR `#[coroutine]` attribute is an experimental feature
     //~^^ ERROR yield syntax is experimental
 
     let _ = #[coroutine] || {};
-    //~^ ERROR `#[coroutines]` attribute is an experimental feature
+    //~^ ERROR `#[coroutine]` attribute is an experimental feature
 }
diff --git a/tests/ui/issues/issue-25901.rs b/tests/ui/issues/issue-25901.rs
index eae038c71a0..bfcee1ac503 100644
--- a/tests/ui/issues/issue-25901.rs
+++ b/tests/ui/issues/issue-25901.rs
@@ -2,7 +2,7 @@ struct A;
 struct B;
 
 static S: &'static B = &A;
-//~^ ERROR cannot call conditionally-const method
+//~^ ERROR cannot perform conditionally-const deref coercion
 
 use std::ops::Deref;
 
diff --git a/tests/ui/issues/issue-25901.stderr b/tests/ui/issues/issue-25901.stderr
index 655a8b78c6a..a954f38af83 100644
--- a/tests/ui/issues/issue-25901.stderr
+++ b/tests/ui/issues/issue-25901.stderr
@@ -1,9 +1,16 @@
-error[E0658]: cannot call conditionally-const method `<A as Deref>::deref` in statics
+error[E0658]: cannot perform conditionally-const deref coercion on `A` in statics
   --> $DIR/issue-25901.rs:4:24
    |
 LL | static S: &'static B = &A;
    |                        ^^
    |
+   = note: attempting to deref into `B`
+note: deref defined here
+  --> $DIR/issue-25901.rs:10:5
+   |
+LL |     type Target = B;
+   |     ^^^^^^^^^^^
+   = note: calls in statics are limited to constant functions, tuple structs and tuple variants
    = note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
    = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
diff --git a/tests/ui/methods/bad-wf-when-selecting-method.rs b/tests/ui/methods/bad-wf-when-selecting-method.rs
new file mode 100644
index 00000000000..638d1ffa982
--- /dev/null
+++ b/tests/ui/methods/bad-wf-when-selecting-method.rs
@@ -0,0 +1,18 @@
+trait Wf {
+    type Assoc;
+}
+
+struct Wrapper<T: Wf<Assoc = U>, U>(T);
+
+trait Trait {
+    fn needs_sized(self);
+}
+
+fn test<T>(t: T) {
+    Wrapper(t).needs_sized();
+    //~^ ERROR the trait bound `T: Wf` is not satisfied
+    //~| ERROR the trait bound `T: Wf` is not satisfied
+    //~| the method `needs_sized` exists for struct `Wrapper<T, _>`, but its trait bounds were not satisfied
+}
+
+fn main() {}
diff --git a/tests/ui/methods/bad-wf-when-selecting-method.stderr b/tests/ui/methods/bad-wf-when-selecting-method.stderr
new file mode 100644
index 00000000000..e6d50034967
--- /dev/null
+++ b/tests/ui/methods/bad-wf-when-selecting-method.stderr
@@ -0,0 +1,54 @@
+error[E0277]: the trait bound `T: Wf` is not satisfied
+  --> $DIR/bad-wf-when-selecting-method.rs:12:13
+   |
+LL |     Wrapper(t).needs_sized();
+   |     ------- ^ the trait `Wf` is not implemented for `T`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required by a bound in `Wrapper`
+  --> $DIR/bad-wf-when-selecting-method.rs:5:19
+   |
+LL | struct Wrapper<T: Wf<Assoc = U>, U>(T);
+   |                   ^^^^^^^^^^^^^ required by this bound in `Wrapper`
+help: consider restricting type parameter `T` with trait `Wf`
+   |
+LL | fn test<T: Wf>(t: T) {
+   |          ++++
+
+error[E0277]: the trait bound `T: Wf` is not satisfied
+  --> $DIR/bad-wf-when-selecting-method.rs:12:5
+   |
+LL |     Wrapper(t).needs_sized();
+   |     ^^^^^^^^^^ the trait `Wf` is not implemented for `T`
+   |
+note: required by a bound in `Wrapper`
+  --> $DIR/bad-wf-when-selecting-method.rs:5:19
+   |
+LL | struct Wrapper<T: Wf<Assoc = U>, U>(T);
+   |                   ^^^^^^^^^^^^^ required by this bound in `Wrapper`
+help: consider restricting type parameter `T` with trait `Wf`
+   |
+LL | fn test<T: Wf>(t: T) {
+   |          ++++
+
+error[E0599]: the method `needs_sized` exists for struct `Wrapper<T, _>`, but its trait bounds were not satisfied
+  --> $DIR/bad-wf-when-selecting-method.rs:12:16
+   |
+LL | struct Wrapper<T: Wf<Assoc = U>, U>(T);
+   | ----------------------------------- method `needs_sized` not found for this struct
+...
+LL |     Wrapper(t).needs_sized();
+   |                ^^^^^^^^^^^ method cannot be called on `Wrapper<T, _>` due to unsatisfied trait bounds
+   |
+   = note: the following trait bounds were not satisfied:
+           `T: Wf`
+help: consider restricting the type parameter to satisfy the trait bound
+   |
+LL | fn test<T>(t: T) where T: Wf {
+   |                  +++++++++++
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0277, E0599.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/proc-macro/quote-debug.stdout b/tests/ui/proc-macro/quote-debug.stdout
deleted file mode 100644
index d84b4e051e8..00000000000
--- a/tests/ui/proc-macro/quote-debug.stdout
+++ /dev/null
@@ -1,49 +0,0 @@
-#![feature(prelude_import)]
-#![no_std]
-//@ check-pass
-//@ force-host
-//@ no-prefer-dynamic
-//@ compile-flags: -Z unpretty=expanded
-//@ needs-unwind compiling proc macros with panic=abort causes a warning
-//
-// This file is not actually used as a proc-macro - instead,
-// it's just used to show the output of the `quote!` macro
-
-#![feature(proc_macro_quote)]
-#![crate_type = "proc-macro"]
-#[prelude_import]
-use ::std::prelude::rust_2015::*;
-#[macro_use]
-extern crate std;
-
-extern crate proc_macro;
-
-fn main() {
-    [crate::TokenStream::from(crate::TokenTree::Ident(crate::Ident::new("let",
-                                    crate::Span::recover_proc_macro_span(0)))),
-                        crate::TokenStream::from(crate::TokenTree::Ident(crate::Ident::new("hello",
-                                    crate::Span::recover_proc_macro_span(1)))),
-                        crate::TokenStream::from(crate::TokenTree::Punct(crate::Punct::new('=',
-                                    crate::Spacing::Alone))),
-                        crate::TokenStream::from(crate::TokenTree::Literal({
-                                    let mut iter =
-                                        "\"world\"".parse::<crate::TokenStream>().unwrap().into_iter();
-                                    if let (Some(crate::TokenTree::Literal(mut lit)), None) =
-                                                (iter.next(), iter.next()) {
-                                            lit.set_span(crate::Span::recover_proc_macro_span(2));
-                                            lit
-                                        } else {
-                                           ::core::panicking::panic("internal error: entered unreachable code")
-                                       }
-                                })),
-                        crate::TokenStream::from(crate::TokenTree::Punct(crate::Punct::new(';',
-                                    crate::Spacing::Alone)))].iter().cloned().collect::<crate::TokenStream>()
-}
-const _: () =
-    {
-        extern crate proc_macro;
-        #[rustc_proc_macro_decls]
-        #[used]
-        #[allow(deprecated)]
-        static _DECLS: &[proc_macro::bridge::client::ProcMacro] = &[];
-    };
diff --git a/tests/ui/proc-macro/quote/auxiliary/basic.rs b/tests/ui/proc-macro/quote/auxiliary/basic.rs
new file mode 100644
index 00000000000..ef726bbfbe3
--- /dev/null
+++ b/tests/ui/proc-macro/quote/auxiliary/basic.rs
@@ -0,0 +1,361 @@
+#![feature(proc_macro_quote)]
+#![feature(proc_macro_totokens)]
+
+extern crate proc_macro;
+
+use std::borrow::Cow;
+use std::ffi::{CStr, CString};
+
+use proc_macro::*;
+
+#[proc_macro]
+pub fn run_tests(_: TokenStream) -> TokenStream {
+    test_quote_impl();
+    test_substitution();
+    test_advanced();
+    test_integer();
+    test_floating();
+    test_char();
+    test_str();
+    test_string();
+    test_c_str();
+    test_c_string();
+    test_interpolated_literal();
+    test_ident();
+    test_underscore();
+    test_duplicate();
+    test_empty_quote();
+    test_box_str();
+    test_cow();
+    test_append_tokens();
+    test_outer_line_comment();
+    test_inner_line_comment();
+    test_outer_block_comment();
+    test_inner_block_comment();
+    test_outer_attr();
+    test_inner_attr();
+    test_quote_raw_id();
+
+    TokenStream::new()
+}
+
+// Based on https://github.com/dtolnay/quote/blob/0245506323a3616daa2ee41c6ad0b871e4d78ae4/tests/test.rs
+//
+// FIXME(quote):
+// The following tests are removed because they are not supported yet in `proc_macro::quote!`
+//
+// - quote_spanned:
+//   - fn test_quote_spanned_impl
+//   - fn test_type_inference_for_span
+//   - wrong-type-span.rs
+// - format_ident:
+//   - fn test_format_ident
+//   - fn test_format_ident_strip_raw
+// - repetition:
+//   - fn test_iter
+//   - fn test_array
+//   - fn test_fancy_repetition
+//   - fn test_nested_fancy_repetition
+//   - fn test_duplicate_name_repetition
+//   - fn test_duplicate_name_repetition_no_copy
+//   - fn test_btreeset_repetition
+//   - fn test_variable_name_conflict
+//   - fn test_nonrep_in_repetition
+//   - fn test_closure
+//   - fn test_star_after_repetition
+
+struct X;
+
+impl ToTokens for X {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        Ident::new("X", Span::call_site()).to_tokens(tokens)
+    }
+}
+
+fn test_quote_impl() {
+    let tokens = quote! {
+        impl<'a, T: ToTokens> ToTokens for &'a T {
+            fn to_tokens(&self, tokens: &mut TokenStream) {
+                (**self).to_tokens(tokens)
+            }
+        }
+    };
+
+    let expected = r#"impl < 'a, T : ToTokens > ToTokens for & 'a T
+{
+    fn to_tokens(& self, tokens : & mut TokenStream)
+    { (** self).to_tokens(tokens) }
+}"#;
+
+    assert_eq!(expected, tokens.to_string());
+}
+
+fn test_substitution() {
+    let x = X;
+    let tokens = quote!($x <$x> ($x) [$x] {$x});
+
+    let expected = "X <X > (X) [X] { X }";
+
+    assert_eq!(expected, tokens.to_string());
+}
+
+fn test_advanced() {
+    let generics = quote!( <'a, T> );
+
+    let where_clause = quote!( where T: Serialize );
+
+    let field_ty = quote!(String);
+
+    let item_ty = quote!(Cow<'a, str>);
+
+    let path = quote!(SomeTrait::serialize_with);
+
+    let value = quote!(self.x);
+
+    let tokens = quote! {
+        struct SerializeWith $generics $where_clause {
+            value: &'a $field_ty,
+            phantom: ::std::marker::PhantomData<$item_ty>,
+        }
+
+        impl $generics ::serde::Serialize for SerializeWith $generics $where_clause {
+            fn serialize<S>(&self, s: &mut S) -> Result<(), S::Error>
+                where S: ::serde::Serializer
+            {
+                $path(self.value, s)
+            }
+        }
+
+        SerializeWith {
+            value: $value,
+            phantom: ::std::marker::PhantomData::<$item_ty>,
+        }
+    };
+
+    let expected = r#"struct SerializeWith < 'a, T > where T : Serialize
+{
+    value : & 'a String, phantom : :: std :: marker :: PhantomData <Cow < 'a,
+    str > >,
+} impl < 'a, T > :: serde :: Serialize for SerializeWith < 'a, T > where T :
+Serialize
+{
+    fn serialize < S > (& self, s : & mut S) -> Result < (), S :: Error >
+    where S : :: serde :: Serializer
+    { SomeTrait :: serialize_with(self.value, s) }
+} SerializeWith
+{
+    value : self.x, phantom : :: std :: marker :: PhantomData ::<Cow < 'a, str
+    > >,
+}"#;
+
+    assert_eq!(expected, tokens.to_string());
+}
+
+fn test_integer() {
+    let ii8 = -1i8;
+    let ii16 = -1i16;
+    let ii32 = -1i32;
+    let ii64 = -1i64;
+    let ii128 = -1i128;
+    let iisize = -1isize;
+    let uu8 = 1u8;
+    let uu16 = 1u16;
+    let uu32 = 1u32;
+    let uu64 = 1u64;
+    let uu128 = 1u128;
+    let uusize = 1usize;
+
+    let tokens = quote! {
+        1 1i32 1u256
+        $ii8 $ii16 $ii32 $ii64 $ii128 $iisize
+        $uu8 $uu16 $uu32 $uu64 $uu128 $uusize
+    };
+    let expected = r#"1 1i32 1u256 -1i8 -1i16 -1i32 -1i64 -1i128 -1isize 1u8 1u16 1u32 1u64 1u128
+1usize"#;
+    assert_eq!(expected, tokens.to_string());
+}
+
+fn test_floating() {
+    let e32 = 2.345f32;
+
+    let e64 = 2.345f64;
+
+    let tokens = quote! {
+        $e32
+        $e64
+    };
+    let expected = concat!("2.345f32 2.345f64");
+    assert_eq!(expected, tokens.to_string());
+}
+
+fn test_char() {
+    let zero = '\u{1}';
+    let dollar = '$';
+    let pound = '#';
+    let quote = '"';
+    let apost = '\'';
+    let newline = '\n';
+    let heart = '\u{2764}';
+
+    let tokens = quote! {
+        $zero $dollar $pound $quote $apost $newline $heart
+    };
+    let expected = "'\\u{1}' '$' '#' '\"' '\\'' '\\n' '\u{2764}'";
+    assert_eq!(expected, tokens.to_string());
+}
+
+fn test_str() {
+    let s = "\u{1} a 'b \" c";
+    let tokens = quote!($s);
+    let expected = "\"\\u{1} a 'b \\\" c\"";
+    assert_eq!(expected, tokens.to_string());
+}
+
+fn test_string() {
+    let s = "\u{1} a 'b \" c".to_string();
+    let tokens = quote!($s);
+    let expected = "\"\\u{1} a 'b \\\" c\"";
+    assert_eq!(expected, tokens.to_string());
+}
+
+fn test_c_str() {
+    let s = CStr::from_bytes_with_nul(b"\x01 a 'b \" c\0").unwrap();
+    let tokens = quote!($s);
+    let expected = "c\"\\u{1} a 'b \\\" c\"";
+    assert_eq!(expected, tokens.to_string());
+}
+
+fn test_c_string() {
+    let s = CString::new(&b"\x01 a 'b \" c"[..]).unwrap();
+    let tokens = quote!($s);
+    let expected = "c\"\\u{1} a 'b \\\" c\"";
+    assert_eq!(expected, tokens.to_string());
+}
+
+fn test_interpolated_literal() {
+    macro_rules! m {
+        ($literal:literal) => {
+            quote!($literal)
+        };
+    }
+
+    let tokens = m!(1);
+    let expected = "1";
+    assert_eq!(expected, tokens.to_string());
+
+    let tokens = m!(-1);
+    let expected = "- 1";
+    assert_eq!(expected, tokens.to_string());
+
+    let tokens = m!(true);
+    let expected = "true";
+    assert_eq!(expected, tokens.to_string());
+
+    let tokens = m!(-true);
+    let expected = "- true";
+    assert_eq!(expected, tokens.to_string());
+}
+
+fn test_ident() {
+    let foo = Ident::new("Foo", Span::call_site());
+    let bar = Ident::new(&format!("Bar{}", 7), Span::call_site());
+    let tokens = quote!(struct $foo; enum $bar {});
+    let expected = "struct Foo; enum Bar7 {}";
+    assert_eq!(expected, tokens.to_string());
+}
+
+fn test_underscore() {
+    let tokens = quote!(let _;);
+    let expected = "let _;";
+    assert_eq!(expected, tokens.to_string());
+}
+
+fn test_duplicate() {
+    let ch = 'x';
+
+    let tokens = quote!($ch $ch);
+
+    let expected = "'x' 'x'";
+    assert_eq!(expected, tokens.to_string());
+}
+
+fn test_empty_quote() {
+    let tokens = quote!();
+    assert_eq!("", tokens.to_string());
+}
+
+fn test_box_str() {
+    let b = "str".to_owned().into_boxed_str();
+    let tokens = quote! { $b };
+    assert_eq!("\"str\"", tokens.to_string());
+}
+
+fn test_cow() {
+    let owned: Cow<Ident> = Cow::Owned(Ident::new("owned", Span::call_site()));
+
+    let ident = Ident::new("borrowed", Span::call_site());
+    let borrowed = Cow::Borrowed(&ident);
+
+    let tokens = quote! { $owned $borrowed };
+    assert_eq!("owned borrowed", tokens.to_string());
+}
+
+fn test_append_tokens() {
+    let mut a = quote!(a);
+    let b = quote!(b);
+    a.extend(b);
+    assert_eq!("a b", a.to_string());
+}
+
+fn test_outer_line_comment() {
+    let tokens = quote! {
+        /// doc
+    };
+    let expected = "#[doc = \" doc\"]";
+    assert_eq!(expected, tokens.to_string());
+}
+
+fn test_inner_line_comment() {
+    let tokens = quote! {
+        //! doc
+    };
+    let expected = "# ! [doc = \" doc\"]";
+    assert_eq!(expected, tokens.to_string());
+}
+
+fn test_outer_block_comment() {
+    let tokens = quote! {
+        /** doc */
+    };
+    let expected = "#[doc = \" doc \"]";
+    assert_eq!(expected, tokens.to_string());
+}
+
+fn test_inner_block_comment() {
+    let tokens = quote! {
+        /*! doc */
+    };
+    let expected = "# ! [doc = \" doc \"]";
+    assert_eq!(expected, tokens.to_string());
+}
+
+fn test_outer_attr() {
+    let tokens = quote! {
+        #[inline]
+    };
+    let expected = "#[inline]";
+    assert_eq!(expected, tokens.to_string());
+}
+
+fn test_inner_attr() {
+    let tokens = quote! {
+        #![no_std]
+    };
+    let expected = "#! [no_std]";
+    assert_eq!(expected, tokens.to_string());
+}
+
+fn test_quote_raw_id() {
+    let id = quote!(r#raw_id);
+    assert_eq!(id.to_string(), "r#raw_id");
+}
diff --git a/tests/ui/proc-macro/quote/basic.rs b/tests/ui/proc-macro/quote/basic.rs
new file mode 100644
index 00000000000..0336dbb7856
--- /dev/null
+++ b/tests/ui/proc-macro/quote/basic.rs
@@ -0,0 +1,8 @@
+//@ run-pass
+//@ proc-macro: basic.rs
+
+extern crate basic;
+
+fn main() {
+    basic::run_tests!();
+}
diff --git a/tests/ui/proc-macro/quote-debug.rs b/tests/ui/proc-macro/quote/debug.rs
index 11d144d609f..ce113079e56 100644
--- a/tests/ui/proc-macro/quote-debug.rs
+++ b/tests/ui/proc-macro/quote/debug.rs
@@ -15,5 +15,6 @@ extern crate proc_macro;
 fn main() {
     proc_macro::quote! {
         let hello = "world";
+        let r#raw_ident = r#"raw"literal"#;
     }
 }
diff --git a/tests/ui/proc-macro/quote/debug.stdout b/tests/ui/proc-macro/quote/debug.stdout
new file mode 100644
index 00000000000..3eaad9eb969
--- /dev/null
+++ b/tests/ui/proc-macro/quote/debug.stdout
@@ -0,0 +1,72 @@
+#![feature(prelude_import)]
+#![no_std]
+//@ check-pass
+//@ force-host
+//@ no-prefer-dynamic
+//@ compile-flags: -Z unpretty=expanded
+//@ needs-unwind compiling proc macros with panic=abort causes a warning
+//
+// This file is not actually used as a proc-macro - instead,
+// it's just used to show the output of the `quote!` macro
+
+#![feature(proc_macro_quote)]
+#![crate_type = "proc-macro"]
+#[prelude_import]
+use ::std::prelude::rust_2015::*;
+#[macro_use]
+extern crate std;
+
+extern crate proc_macro;
+
+fn main() {
+    {
+        let mut ts = crate::TokenStream::new();
+        crate::ToTokens::to_tokens(&crate::TokenTree::Ident(crate::Ident::new("let",
+                        crate::Span::recover_proc_macro_span(0))), &mut ts);
+        crate::ToTokens::to_tokens(&crate::TokenTree::Ident(crate::Ident::new("hello",
+                        crate::Span::recover_proc_macro_span(1))), &mut ts);
+        crate::ToTokens::to_tokens(&crate::TokenTree::Punct(crate::Punct::new('=',
+                        crate::Spacing::Alone)), &mut ts);
+        crate::ToTokens::to_tokens(&crate::TokenTree::Literal({
+                        let mut iter =
+                            "\"world\"".parse::<crate::TokenStream>().unwrap().into_iter();
+                        if let (Some(crate::TokenTree::Literal(mut lit)), None) =
+                                    (iter.next(), iter.next()) {
+                                lit.set_span(crate::Span::recover_proc_macro_span(2));
+                                lit
+                            } else {
+                               ::core::panicking::panic("internal error: entered unreachable code")
+                           }
+                    }), &mut ts);
+        crate::ToTokens::to_tokens(&crate::TokenTree::Punct(crate::Punct::new(';',
+                        crate::Spacing::Alone)), &mut ts);
+        crate::ToTokens::to_tokens(&crate::TokenTree::Ident(crate::Ident::new("let",
+                        crate::Span::recover_proc_macro_span(3))), &mut ts);
+        crate::ToTokens::to_tokens(&crate::TokenTree::Ident(crate::Ident::new_raw("raw_ident",
+                        crate::Span::recover_proc_macro_span(4))), &mut ts);
+        crate::ToTokens::to_tokens(&crate::TokenTree::Punct(crate::Punct::new('=',
+                        crate::Spacing::Alone)), &mut ts);
+        crate::ToTokens::to_tokens(&crate::TokenTree::Literal({
+                        let mut iter =
+                            "r#\"raw\"literal\"#".parse::<crate::TokenStream>().unwrap().into_iter();
+                        if let (Some(crate::TokenTree::Literal(mut lit)), None) =
+                                    (iter.next(), iter.next()) {
+                                lit.set_span(crate::Span::recover_proc_macro_span(5));
+                                lit
+                            } else {
+                               ::core::panicking::panic("internal error: entered unreachable code")
+                           }
+                    }), &mut ts);
+        crate::ToTokens::to_tokens(&crate::TokenTree::Punct(crate::Punct::new(';',
+                        crate::Spacing::Alone)), &mut ts);
+        ts
+    }
+}
+const _: () =
+    {
+        extern crate proc_macro;
+        #[rustc_proc_macro_decls]
+        #[used]
+        #[allow(deprecated)]
+        static _DECLS: &[proc_macro::bridge::client::ProcMacro] = &[];
+    };
diff --git a/tests/ui/proc-macro/quote/does-not-have-iter-interpolated-dup.rs b/tests/ui/proc-macro/quote/does-not-have-iter-interpolated-dup.rs
new file mode 100644
index 00000000000..2f67ae1bc6e
--- /dev/null
+++ b/tests/ui/proc-macro/quote/does-not-have-iter-interpolated-dup.rs
@@ -0,0 +1,17 @@
+// FIXME(quote): `proc_macro::quote!` doesn't support repetition at the moment, so the stderr is
+// expected to be incorrect.
+//@ known-bug: #54722
+
+#![feature(proc_macro_quote)]
+
+extern crate proc_macro;
+
+use proc_macro::quote;
+
+fn main() {
+    let nonrep = "";
+
+    // Without some protection against repetitions with no iterator somewhere
+    // inside, this would loop infinitely.
+    quote!($($nonrep $nonrep)*);
+}
diff --git a/tests/ui/proc-macro/quote/does-not-have-iter-interpolated-dup.stderr b/tests/ui/proc-macro/quote/does-not-have-iter-interpolated-dup.stderr
new file mode 100644
index 00000000000..5f28a46f318
--- /dev/null
+++ b/tests/ui/proc-macro/quote/does-not-have-iter-interpolated-dup.stderr
@@ -0,0 +1,10 @@
+error: proc macro panicked
+  --> $DIR/does-not-have-iter-interpolated-dup.rs:16:5
+   |
+LL |     quote!($($nonrep $nonrep)*);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: message: `$` must be followed by an ident or `$` in `quote!`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/proc-macro/quote/does-not-have-iter-interpolated.rs b/tests/ui/proc-macro/quote/does-not-have-iter-interpolated.rs
new file mode 100644
index 00000000000..1efb3eac642
--- /dev/null
+++ b/tests/ui/proc-macro/quote/does-not-have-iter-interpolated.rs
@@ -0,0 +1,17 @@
+// FIXME(quote): `proc_macro::quote!` doesn't support repetition at the moment, so the stderr is
+// expected to be incorrect.
+//@ known-bug: #54722
+
+#![feature(proc_macro_quote)]
+
+extern crate proc_macro;
+
+use proc_macro::quote;
+
+fn main() {
+    let nonrep = "";
+
+    // Without some protection against repetitions with no iterator somewhere
+    // inside, this would loop infinitely.
+    quote!($($nonrep)*);
+}
diff --git a/tests/ui/proc-macro/quote/does-not-have-iter-interpolated.stderr b/tests/ui/proc-macro/quote/does-not-have-iter-interpolated.stderr
new file mode 100644
index 00000000000..595aa858763
--- /dev/null
+++ b/tests/ui/proc-macro/quote/does-not-have-iter-interpolated.stderr
@@ -0,0 +1,10 @@
+error: proc macro panicked
+  --> $DIR/does-not-have-iter-interpolated.rs:16:5
+   |
+LL |     quote!($($nonrep)*);
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = help: message: `$` must be followed by an ident or `$` in `quote!`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/proc-macro/quote/does-not-have-iter-separated.rs b/tests/ui/proc-macro/quote/does-not-have-iter-separated.rs
new file mode 100644
index 00000000000..5f2ddabc390
--- /dev/null
+++ b/tests/ui/proc-macro/quote/does-not-have-iter-separated.rs
@@ -0,0 +1,13 @@
+// FIXME(quote): `proc_macro::quote!` doesn't support repetition at the moment, so the stderr is
+// expected to be incorrect.
+//@ known-bug: #54722
+
+#![feature(proc_macro_quote)]
+
+extern crate proc_macro;
+
+use proc_macro::quote;
+
+fn main() {
+    quote!($(a b),*);
+}
diff --git a/tests/ui/proc-macro/quote/does-not-have-iter-separated.stderr b/tests/ui/proc-macro/quote/does-not-have-iter-separated.stderr
new file mode 100644
index 00000000000..f6f5d7e007d
--- /dev/null
+++ b/tests/ui/proc-macro/quote/does-not-have-iter-separated.stderr
@@ -0,0 +1,10 @@
+error: proc macro panicked
+  --> $DIR/does-not-have-iter-separated.rs:12:5
+   |
+LL |     quote!($(a b),*);
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = help: message: `$` must be followed by an ident or `$` in `quote!`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/proc-macro/quote/does-not-have-iter.rs b/tests/ui/proc-macro/quote/does-not-have-iter.rs
new file mode 100644
index 00000000000..25ffd786cc6
--- /dev/null
+++ b/tests/ui/proc-macro/quote/does-not-have-iter.rs
@@ -0,0 +1,13 @@
+// FIXME(quote): `proc_macro::quote!` doesn't support repetition at the moment, so the stderr is
+// expected to be incorrect.
+//@ known-bug: #54722
+
+#![feature(proc_macro_quote)]
+
+extern crate proc_macro;
+
+use proc_macro::quote;
+
+fn main() {
+    quote!($(a b)*);
+}
diff --git a/tests/ui/proc-macro/quote/does-not-have-iter.stderr b/tests/ui/proc-macro/quote/does-not-have-iter.stderr
new file mode 100644
index 00000000000..0ed1daffc8c
--- /dev/null
+++ b/tests/ui/proc-macro/quote/does-not-have-iter.stderr
@@ -0,0 +1,10 @@
+error: proc macro panicked
+  --> $DIR/does-not-have-iter.rs:12:5
+   |
+LL |     quote!($(a b)*);
+   |     ^^^^^^^^^^^^^^^
+   |
+   = help: message: `$` must be followed by an ident or `$` in `quote!`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/proc-macro/quote/not-quotable.rs b/tests/ui/proc-macro/quote/not-quotable.rs
new file mode 100644
index 00000000000..7e38b441052
--- /dev/null
+++ b/tests/ui/proc-macro/quote/not-quotable.rs
@@ -0,0 +1,12 @@
+#![feature(proc_macro_quote)]
+
+extern crate proc_macro;
+
+use std::net::Ipv4Addr;
+
+use proc_macro::quote;
+
+fn main() {
+    let ip = Ipv4Addr::LOCALHOST;
+    let _ = quote! { $ip }; //~ ERROR the trait bound `Ipv4Addr: ToTokens` is not satisfied
+}
diff --git a/tests/ui/proc-macro/quote/not-quotable.stderr b/tests/ui/proc-macro/quote/not-quotable.stderr
new file mode 100644
index 00000000000..e349b2dce53
--- /dev/null
+++ b/tests/ui/proc-macro/quote/not-quotable.stderr
@@ -0,0 +1,24 @@
+error[E0277]: the trait bound `Ipv4Addr: ToTokens` is not satisfied
+  --> $DIR/not-quotable.rs:11:13
+   |
+LL |     let _ = quote! { $ip };
+   |             ^^^^^^^^^^^^^^
+   |             |
+   |             the trait `ToTokens` is not implemented for `Ipv4Addr`
+   |             required by a bound introduced by this call
+   |
+   = help: the following other types implement trait `ToTokens`:
+             &T
+             &mut T
+             Box<T>
+             CString
+             Cow<'_, T>
+             Option<T>
+             Rc<T>
+             bool
+           and 24 others
+   = note: this error originates in the macro `quote` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/proc-macro/quote/not-repeatable.rs b/tests/ui/proc-macro/quote/not-repeatable.rs
new file mode 100644
index 00000000000..d115da73181
--- /dev/null
+++ b/tests/ui/proc-macro/quote/not-repeatable.rs
@@ -0,0 +1,16 @@
+// FIXME(quote): `proc_macro::quote!` doesn't support repetition at the moment, so the stderr is
+// expected to be incorrect.
+//@ known-bug: #54722
+
+#![feature(proc_macro_quote)]
+
+extern crate proc_macro;
+
+use proc_macro::quote;
+
+struct Ipv4Addr;
+
+fn main() {
+    let ip = Ipv4Addr;
+    let _ = quote! { $($ip)* };
+}
diff --git a/tests/ui/proc-macro/quote/not-repeatable.stderr b/tests/ui/proc-macro/quote/not-repeatable.stderr
new file mode 100644
index 00000000000..18fbcd73798
--- /dev/null
+++ b/tests/ui/proc-macro/quote/not-repeatable.stderr
@@ -0,0 +1,10 @@
+error: proc macro panicked
+  --> $DIR/not-repeatable.rs:15:13
+   |
+LL |     let _ = quote! { $($ip)* };
+   |             ^^^^^^^^^^^^^^^^^^
+   |
+   = help: message: `$` must be followed by an ident or `$` in `quote!`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/self/arbitrary-self-from-method-substs-ice.stderr b/tests/ui/self/arbitrary-self-from-method-substs-ice.stderr
index cf4c219215e..90b63249eca 100644
--- a/tests/ui/self/arbitrary-self-from-method-substs-ice.stderr
+++ b/tests/ui/self/arbitrary-self-from-method-substs-ice.stderr
@@ -4,6 +4,7 @@ error[E0658]: cannot call conditionally-const method `<R as Deref>::deref` in co
 LL |         self.0
    |         ^^^^^^
    |
+   = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
    = note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
    = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
diff --git a/tests/ui/traits/const-traits/cross-crate.stock.stderr b/tests/ui/traits/const-traits/cross-crate.stock.stderr
index 09bf9c023c8..7cdde5a079f 100644
--- a/tests/ui/traits/const-traits/cross-crate.stock.stderr
+++ b/tests/ui/traits/const-traits/cross-crate.stock.stderr
@@ -1,9 +1,10 @@
 error[E0658]: cannot call conditionally-const method `<cross_crate::Const as cross_crate::MyTrait>::func` in constant functions
-  --> $DIR/cross-crate.rs:22:5
+  --> $DIR/cross-crate.rs:22:11
    |
 LL |     Const.func();
-   |     ^^^^^^^^^^^^
+   |           ^^^^^^
    |
+   = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
    = note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
    = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
diff --git a/tests/ui/traits/const-traits/cross-crate.stocknc.stderr b/tests/ui/traits/const-traits/cross-crate.stocknc.stderr
index e52e5609b01..2358731c901 100644
--- a/tests/ui/traits/const-traits/cross-crate.stocknc.stderr
+++ b/tests/ui/traits/const-traits/cross-crate.stocknc.stderr
@@ -1,19 +1,21 @@
 error[E0658]: cannot call conditionally-const method `<cross_crate::NonConst as cross_crate::MyTrait>::func` in constant functions
-  --> $DIR/cross-crate.rs:19:5
+  --> $DIR/cross-crate.rs:19:14
    |
 LL |     NonConst.func();
-   |     ^^^^^^^^^^^^^^^
+   |              ^^^^^^
    |
+   = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
    = note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
    = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: cannot call conditionally-const method `<cross_crate::Const as cross_crate::MyTrait>::func` in constant functions
-  --> $DIR/cross-crate.rs:22:5
+  --> $DIR/cross-crate.rs:22:11
    |
 LL |     Const.func();
-   |     ^^^^^^^^^^^^
+   |           ^^^^^^
    |
+   = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
    = note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
    = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
diff --git a/tests/ui/traits/const-traits/staged-api-user-crate.stderr b/tests/ui/traits/const-traits/staged-api-user-crate.stderr
index bf7466b8e16..400c76fcaf4 100644
--- a/tests/ui/traits/const-traits/staged-api-user-crate.stderr
+++ b/tests/ui/traits/const-traits/staged-api-user-crate.stderr
@@ -4,6 +4,7 @@ error[E0658]: cannot call conditionally-const associated function `<staged_api::
 LL |     Unstable::func();
    |     ^^^^^^^^^^^^^^^^
    |
+   = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
    = note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
    = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
diff --git a/tests/ui/traits/const-traits/super-traits-fail-3.nyn.stderr b/tests/ui/traits/const-traits/super-traits-fail-3.nyn.stderr
index 8abda1c8f8a..024db4b6d68 100644
--- a/tests/ui/traits/const-traits/super-traits-fail-3.nyn.stderr
+++ b/tests/ui/traits/const-traits/super-traits-fail-3.nyn.stderr
@@ -39,11 +39,12 @@ LL | #[cfg_attr(any(yyy, yny, nyy, nyn), const_trait)]
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: cannot call conditionally-const method `<T as Foo>::a` in constant functions
-  --> $DIR/super-traits-fail-3.rs:36:5
+  --> $DIR/super-traits-fail-3.rs:36:7
    |
 LL |     x.a();
-   |     ^^^^^
+   |       ^^^
    |
+   = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
    = note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
    = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
diff --git a/tests/ui/traits/const-traits/super-traits-fail-3.nyy.stderr b/tests/ui/traits/const-traits/super-traits-fail-3.nyy.stderr
index 8abda1c8f8a..024db4b6d68 100644
--- a/tests/ui/traits/const-traits/super-traits-fail-3.nyy.stderr
+++ b/tests/ui/traits/const-traits/super-traits-fail-3.nyy.stderr
@@ -39,11 +39,12 @@ LL | #[cfg_attr(any(yyy, yny, nyy, nyn), const_trait)]
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: cannot call conditionally-const method `<T as Foo>::a` in constant functions
-  --> $DIR/super-traits-fail-3.rs:36:5
+  --> $DIR/super-traits-fail-3.rs:36:7
    |
 LL |     x.a();
-   |     ^^^^^
+   |       ^^^
    |
+   = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
    = note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
    = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date