about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock2
-rw-r--r--compiler/rustc_builtin_macros/src/cfg_accessible.rs1
-rw-r--r--compiler/rustc_builtin_macros/src/derive.rs9
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/bounds.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/clone.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/debug.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/decodable.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/default.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/encodable.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/generic/mod.rs6
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/hash.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/mod.rs35
-rw-r--r--compiler/rustc_builtin_macros/src/lib.rs3
-rw-r--r--compiler/rustc_error_messages/locales/en-US/passes.ftl5
-rw-r--r--compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs1
-rw-r--r--compiler/rustc_errors/src/emitter.rs60
-rw-r--r--compiler/rustc_expand/src/base.rs4
-rw-r--r--compiler/rustc_expand/src/expand.rs13
-rw-r--r--compiler/rustc_expand/src/proc_macro.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_method.rs247
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs33
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs26
-rw-r--r--compiler/rustc_passes/src/check_attr.rs55
-rw-r--r--compiler/rustc_passes/src/errors.rs3
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs10
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs18
-rw-r--r--compiler/rustc_resolve/src/macros.rs2
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/specialize/mod.rs50
-rw-r--r--compiler/rustc_traits/src/dropck_outlives.rs207
-rw-r--r--library/core/src/macros/mod.rs13
-rw-r--r--library/core/src/prelude/v1.rs4
-rw-r--r--library/std/src/prelude/v1.rs4
-rw-r--r--src/librustdoc/html/static/css/settings.css57
-rw-r--r--src/librustdoc/html/static/css/themes/ayu.css10
-rw-r--r--src/librustdoc/html/static/css/themes/dark.css10
-rw-r--r--src/librustdoc/html/static/css/themes/light.css9
-rw-r--r--src/librustdoc/html/static/js/settings.js4
-rw-r--r--src/test/rustdoc-gui/docblock-code-block-line-number.goml4
-rw-r--r--src/test/rustdoc-gui/settings.goml92
-rw-r--r--src/test/ui/asm/naked-invalid-attr.stderr2
-rw-r--r--src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr6
-rw-r--r--src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs2
-rw-r--r--src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr8
-rw-r--r--src/test/ui/impl-trait/in-trait/method-signature-matches.rs51
-rw-r--r--src/test/ui/impl-trait/in-trait/method-signature-matches.stderr84
-rw-r--r--src/test/ui/issues/issue-32655.stderr14
-rw-r--r--src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr5
-rw-r--r--src/test/ui/iterators/collect-into-array.rs1
-rw-r--r--src/test/ui/iterators/collect-into-array.stderr2
-rw-r--r--src/test/ui/iterators/collect-into-slice.rs2
-rw-r--r--src/test/ui/iterators/collect-into-slice.stderr6
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-gate.rs4
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-gate.stderr11
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.rs13
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.stderr14
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-use.rs19
m---------src/tools/cargo0
-rw-r--r--triagebot.toml1
64 files changed, 795 insertions, 475 deletions
diff --git a/Cargo.lock b/Cargo.lock
index ddacf9cf024..c105d04c1f4 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -273,7 +273,7 @@ dependencies = [
 
 [[package]]
 name = "cargo"
-version = "0.67.0"
+version = "0.68.0"
 dependencies = [
  "anyhow",
  "atty",
diff --git a/compiler/rustc_builtin_macros/src/cfg_accessible.rs b/compiler/rustc_builtin_macros/src/cfg_accessible.rs
index cb5359dd1e2..86df3c44eb3 100644
--- a/compiler/rustc_builtin_macros/src/cfg_accessible.rs
+++ b/compiler/rustc_builtin_macros/src/cfg_accessible.rs
@@ -34,6 +34,7 @@ impl MultiItemModifier for Expander {
         span: Span,
         meta_item: &ast::MetaItem,
         item: Annotatable,
+        _is_derive_const: bool,
     ) -> ExpandResult<Vec<Annotatable>, Annotatable> {
         let template = AttributeTemplate { list: Some("path"), ..Default::default() };
         let attr = &ecx.attribute(meta_item.clone());
diff --git a/compiler/rustc_builtin_macros/src/derive.rs b/compiler/rustc_builtin_macros/src/derive.rs
index e0fb7affb34..01f237e6ab5 100644
--- a/compiler/rustc_builtin_macros/src/derive.rs
+++ b/compiler/rustc_builtin_macros/src/derive.rs
@@ -10,7 +10,7 @@ use rustc_session::Session;
 use rustc_span::symbol::{sym, Ident};
 use rustc_span::Span;
 
-pub(crate) struct Expander;
+pub(crate) struct Expander(pub bool);
 
 impl MultiItemModifier for Expander {
     fn expand(
@@ -19,6 +19,7 @@ impl MultiItemModifier for Expander {
         span: Span,
         meta_item: &ast::MetaItem,
         item: Annotatable,
+        _: bool,
     ) -> ExpandResult<Vec<Annotatable>, Annotatable> {
         let sess = ecx.sess;
         if report_bad_target(sess, &item, span) {
@@ -58,20 +59,20 @@ impl MultiItemModifier for Expander {
                         report_path_args(sess, &meta);
                         meta.path
                     })
-                    .map(|path| (path, dummy_annotatable(), None))
+                    .map(|path| (path, dummy_annotatable(), None, self.0))
                     .collect();
 
                 // Do not configure or clone items unless necessary.
                 match &mut resolutions[..] {
                     [] => {}
-                    [(_, first_item, _), others @ ..] => {
+                    [(_, first_item, ..), others @ ..] => {
                         *first_item = cfg_eval(
                             sess,
                             features,
                             item.clone(),
                             ecx.current_expansion.lint_node_id,
                         );
-                        for (_, item, _) in others {
+                        for (_, item, _, _) in others {
                             *item = first_item.clone();
                         }
                     }
diff --git a/compiler/rustc_builtin_macros/src/deriving/bounds.rs b/compiler/rustc_builtin_macros/src/deriving/bounds.rs
index 7bd344467d0..345db700298 100644
--- a/compiler/rustc_builtin_macros/src/deriving/bounds.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/bounds.rs
@@ -12,6 +12,7 @@ pub fn expand_deriving_copy(
     mitem: &MetaItem,
     item: &Annotatable,
     push: &mut dyn FnMut(Annotatable),
+    is_const: bool,
 ) {
     let trait_def = TraitDef {
         span,
@@ -22,6 +23,7 @@ pub fn expand_deriving_copy(
         supports_unions: true,
         methods: Vec::new(),
         associated_types: Vec::new(),
+        is_const,
     };
 
     trait_def.expand(cx, mitem, item, push);
diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs
index fa8685f5f4e..55cbb654723 100644
--- a/compiler/rustc_builtin_macros/src/deriving/clone.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs
@@ -14,6 +14,7 @@ pub fn expand_deriving_clone(
     mitem: &MetaItem,
     item: &Annotatable,
     push: &mut dyn FnMut(Annotatable),
+    is_const: bool,
 ) {
     // The simple form is `fn clone(&self) -> Self { *self }`, possibly with
     // some additional `AssertParamIsClone` assertions.
@@ -87,6 +88,7 @@ pub fn expand_deriving_clone(
             combine_substructure: substructure,
         }],
         associated_types: Vec::new(),
+        is_const,
     };
 
     trait_def.expand_ext(cx, mitem, item, push, is_simple)
diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs
index eab67b0d354..6190b7a8c77 100644
--- a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs
@@ -15,6 +15,7 @@ pub fn expand_deriving_eq(
     mitem: &MetaItem,
     item: &Annotatable,
     push: &mut dyn FnMut(Annotatable),
+    is_const: bool,
 ) {
     let span = cx.with_def_site_ctxt(span);
     let inline = cx.meta_word(span, sym::inline);
@@ -42,6 +43,7 @@ pub fn expand_deriving_eq(
             })),
         }],
         associated_types: Vec::new(),
+        is_const,
     };
 
     super::inject_impl_of_structural_trait(cx, span, item, path_std!(marker::StructuralEq), push);
diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs
index 7f117981a9a..d2412b20a09 100644
--- a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs
@@ -13,6 +13,7 @@ pub fn expand_deriving_ord(
     mitem: &MetaItem,
     item: &Annotatable,
     push: &mut dyn FnMut(Annotatable),
+    is_const: bool,
 ) {
     let inline = cx.meta_word(span, sym::inline);
     let attrs = thin_vec![cx.attribute(inline)];
@@ -34,6 +35,7 @@ pub fn expand_deriving_ord(
             combine_substructure: combine_substructure(Box::new(|a, b, c| cs_cmp(a, b, c))),
         }],
         associated_types: Vec::new(),
+        is_const,
     };
 
     trait_def.expand(cx, mitem, item, push)
diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs
index 236cbccaf9f..353f28fc45f 100644
--- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs
@@ -14,6 +14,7 @@ pub fn expand_deriving_partial_eq(
     mitem: &MetaItem,
     item: &Annotatable,
     push: &mut dyn FnMut(Annotatable),
+    is_const: bool,
 ) {
     fn cs_eq(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
         let base = true;
@@ -89,6 +90,7 @@ pub fn expand_deriving_partial_eq(
         supports_unions: false,
         methods,
         associated_types: Vec::new(),
+        is_const,
     };
     trait_def.expand(cx, mitem, item, push)
 }
diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs
index 4173403a1b8..e7458b23ef3 100644
--- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs
@@ -13,6 +13,7 @@ pub fn expand_deriving_partial_ord(
     mitem: &MetaItem,
     item: &Annotatable,
     push: &mut dyn FnMut(Annotatable),
+    is_const: bool,
 ) {
     let ordering_ty = Path(path_std!(cmp::Ordering));
     let ret_ty =
@@ -43,6 +44,7 @@ pub fn expand_deriving_partial_ord(
         supports_unions: false,
         methods: vec![partial_cmp_def],
         associated_types: Vec::new(),
+        is_const,
     };
     trait_def.expand(cx, mitem, item, push)
 }
diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs
index 2cf614ed947..e6d5759bb52 100644
--- a/compiler/rustc_builtin_macros/src/deriving/debug.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs
@@ -13,6 +13,7 @@ pub fn expand_deriving_debug(
     mitem: &MetaItem,
     item: &Annotatable,
     push: &mut dyn FnMut(Annotatable),
+    is_const: bool,
 ) {
     // &mut ::std::fmt::Formatter
     let fmtr = Ref(Box::new(Path(path_std!(fmt::Formatter))), ast::Mutability::Mut);
@@ -37,6 +38,7 @@ pub fn expand_deriving_debug(
             })),
         }],
         associated_types: Vec::new(),
+        is_const,
     };
     trait_def.expand(cx, mitem, item, push)
 }
diff --git a/compiler/rustc_builtin_macros/src/deriving/decodable.rs b/compiler/rustc_builtin_macros/src/deriving/decodable.rs
index d669f616802..37aa665e5c6 100644
--- a/compiler/rustc_builtin_macros/src/deriving/decodable.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/decodable.rs
@@ -16,6 +16,7 @@ pub fn expand_deriving_rustc_decodable(
     mitem: &MetaItem,
     item: &Annotatable,
     push: &mut dyn FnMut(Annotatable),
+    is_const: bool,
 ) {
     let krate = sym::rustc_serialize;
     let typaram = sym::__D;
@@ -55,6 +56,7 @@ pub fn expand_deriving_rustc_decodable(
             })),
         }],
         associated_types: Vec::new(),
+        is_const,
     };
 
     trait_def.expand(cx, mitem, item, push)
diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs
index 17df9fb279a..234957ab8a1 100644
--- a/compiler/rustc_builtin_macros/src/deriving/default.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/default.rs
@@ -16,6 +16,7 @@ pub fn expand_deriving_default(
     mitem: &ast::MetaItem,
     item: &Annotatable,
     push: &mut dyn FnMut(Annotatable),
+    is_const: bool,
 ) {
     item.visit_with(&mut DetectNonVariantDefaultAttr { cx });
 
@@ -47,6 +48,7 @@ pub fn expand_deriving_default(
             })),
         }],
         associated_types: Vec::new(),
+        is_const,
     };
     trait_def.expand(cx, mitem, item, push)
 }
diff --git a/compiler/rustc_builtin_macros/src/deriving/encodable.rs b/compiler/rustc_builtin_macros/src/deriving/encodable.rs
index f83f58b97d3..baacaa8b979 100644
--- a/compiler/rustc_builtin_macros/src/deriving/encodable.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/encodable.rs
@@ -100,6 +100,7 @@ pub fn expand_deriving_rustc_encodable(
     mitem: &MetaItem,
     item: &Annotatable,
     push: &mut dyn FnMut(Annotatable),
+    is_const: bool,
 ) {
     let krate = sym::rustc_serialize;
     let typaram = sym::__S;
@@ -139,6 +140,7 @@ pub fn expand_deriving_rustc_encodable(
             })),
         }],
         associated_types: Vec::new(),
+        is_const,
     };
 
     trait_def.expand(cx, mitem, item, push)
diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
index 16ee3aa89bb..3972c3b4934 100644
--- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
@@ -171,7 +171,7 @@ use rustc_ast::{GenericArg, GenericParamKind, VariantData};
 use rustc_attr as attr;
 use rustc_expand::base::{Annotatable, ExtCtxt};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
-use rustc_span::Span;
+use rustc_span::{Span, DUMMY_SP};
 use std::cell::RefCell;
 use std::iter;
 use std::ops::Not;
@@ -204,6 +204,8 @@ pub struct TraitDef<'a> {
     pub methods: Vec<MethodDef<'a>>,
 
     pub associated_types: Vec<(Ident, Ty)>,
+
+    pub is_const: bool,
 }
 
 pub struct MethodDef<'a> {
@@ -730,7 +732,7 @@ impl<'a> TraitDef<'a> {
                 unsafety: ast::Unsafe::No,
                 polarity: ast::ImplPolarity::Positive,
                 defaultness: ast::Defaultness::Final,
-                constness: ast::Const::No,
+                constness: if self.is_const { ast::Const::Yes(DUMMY_SP) } else { ast::Const::No },
                 generics: trait_generics,
                 of_trait: opt_trait_ref,
                 self_ty: self_type,
diff --git a/compiler/rustc_builtin_macros/src/deriving/hash.rs b/compiler/rustc_builtin_macros/src/deriving/hash.rs
index 6e9d5f08b94..8fb1a4ba262 100644
--- a/compiler/rustc_builtin_macros/src/deriving/hash.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/hash.rs
@@ -13,6 +13,7 @@ pub fn expand_deriving_hash(
     mitem: &MetaItem,
     item: &Annotatable,
     push: &mut dyn FnMut(Annotatable),
+    is_const: bool,
 ) {
     let path = Path::new_(pathvec_std!(hash::Hash), vec![], PathKind::Std);
 
@@ -39,6 +40,7 @@ pub fn expand_deriving_hash(
             })),
         }],
         associated_types: Vec::new(),
+        is_const,
     };
 
     hash_trait_def.expand(cx, mitem, item, push);
diff --git a/compiler/rustc_builtin_macros/src/deriving/mod.rs b/compiler/rustc_builtin_macros/src/deriving/mod.rs
index ee346047a0b..73a1df5d426 100644
--- a/compiler/rustc_builtin_macros/src/deriving/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/mod.rs
@@ -38,9 +38,10 @@ pub mod partial_ord;
 
 pub mod generic;
 
-pub(crate) struct BuiltinDerive(
-    pub(crate) fn(&mut ExtCtxt<'_>, Span, &MetaItem, &Annotatable, &mut dyn FnMut(Annotatable)),
-);
+pub(crate) type BuiltinDeriveFn =
+    fn(&mut ExtCtxt<'_>, Span, &MetaItem, &Annotatable, &mut dyn FnMut(Annotatable), bool);
+
+pub(crate) struct BuiltinDerive(pub(crate) BuiltinDeriveFn);
 
 impl MultiItemModifier for BuiltinDerive {
     fn expand(
@@ -49,6 +50,7 @@ impl MultiItemModifier for BuiltinDerive {
         span: Span,
         meta_item: &MetaItem,
         item: Annotatable,
+        is_derive_const: bool,
     ) -> ExpandResult<Vec<Annotatable>, Annotatable> {
         // FIXME: Built-in derives often forget to give spans contexts,
         // so we are doing it here in a centralized way.
@@ -57,21 +59,28 @@ impl MultiItemModifier for BuiltinDerive {
         match item {
             Annotatable::Stmt(stmt) => {
                 if let ast::StmtKind::Item(item) = stmt.into_inner().kind {
-                    (self.0)(ecx, span, meta_item, &Annotatable::Item(item), &mut |a| {
-                        // Cannot use 'ecx.stmt_item' here, because we need to pass 'ecx'
-                        // to the function
-                        items.push(Annotatable::Stmt(P(ast::Stmt {
-                            id: ast::DUMMY_NODE_ID,
-                            kind: ast::StmtKind::Item(a.expect_item()),
-                            span,
-                        })));
-                    });
+                    (self.0)(
+                        ecx,
+                        span,
+                        meta_item,
+                        &Annotatable::Item(item),
+                        &mut |a| {
+                            // Cannot use 'ecx.stmt_item' here, because we need to pass 'ecx'
+                            // to the function
+                            items.push(Annotatable::Stmt(P(ast::Stmt {
+                                id: ast::DUMMY_NODE_ID,
+                                kind: ast::StmtKind::Item(a.expect_item()),
+                                span,
+                            })));
+                        },
+                        is_derive_const,
+                    );
                 } else {
                     unreachable!("should have already errored on non-item statement")
                 }
             }
             _ => {
-                (self.0)(ecx, span, meta_item, &item, &mut |a| items.push(a));
+                (self.0)(ecx, span, meta_item, &item, &mut |a| items.push(a), is_derive_const);
             }
         }
         ExpandResult::Ready(items)
diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs
index bde0102186a..1cbbfb43264 100644
--- a/compiler/rustc_builtin_macros/src/lib.rs
+++ b/compiler/rustc_builtin_macros/src/lib.rs
@@ -99,7 +99,8 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
         bench: test::expand_bench,
         cfg_accessible: cfg_accessible::Expander,
         cfg_eval: cfg_eval::expand,
-        derive: derive::Expander,
+        derive: derive::Expander(false),
+        derive_const: derive::Expander(true),
         global_allocator: global_allocator::expand,
         test: test::expand_test,
         test_case: test::expand_test_case,
diff --git a/compiler/rustc_error_messages/locales/en-US/passes.ftl b/compiler/rustc_error_messages/locales/en-US/passes.ftl
index 5239ff9dc05..001e53d1d0e 100644
--- a/compiler/rustc_error_messages/locales/en-US/passes.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/passes.ftl
@@ -47,7 +47,10 @@ passes_no_coverage_not_coverable =
 
 passes_should_be_applied_to_fn =
     attribute should be applied to a function definition
-    .label = not a function definition
+    .label = {$on_crate ->
+        [true] cannot be applied to crates
+        *[false] not a function definition
+    }
 
 passes_naked_tracked_caller =
     cannot use `#[track_caller]` with `#[naked]`
diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
index f14b8ee3254..c450c276366 100644
--- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
+++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
@@ -52,7 +52,6 @@ impl Emitter for AnnotateSnippetEmitterWriter {
         let (mut primary_span, suggestions) = self.primary_span_formatted(&diag, &fluent_args);
 
         self.fix_multispans_in_extern_macros_and_render_macro_backtrace(
-            &self.source_map,
             &mut primary_span,
             &mut children,
             &diag.level,
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index b7b8fe3f25a..55c7997a513 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -314,7 +314,6 @@ pub trait Emitter: Translate {
 
     fn fix_multispans_in_extern_macros_and_render_macro_backtrace(
         &self,
-        source_map: &Option<Lrc<SourceMap>>,
         span: &mut MultiSpan,
         children: &mut Vec<SubDiagnostic>,
         level: &Level,
@@ -340,7 +339,7 @@ pub trait Emitter: Translate {
             .collect();
 
         if !backtrace {
-            self.fix_multispans_in_extern_macros(source_map, span, children);
+            self.fix_multispans_in_extern_macros(span, children);
         }
 
         self.render_multispans_macro_backtrace(span, children, backtrace);
@@ -480,15 +479,13 @@ pub trait Emitter: Translate {
     // this will change the span to point at the use site.
     fn fix_multispans_in_extern_macros(
         &self,
-        source_map: &Option<Lrc<SourceMap>>,
         span: &mut MultiSpan,
         children: &mut Vec<SubDiagnostic>,
     ) {
-        let Some(source_map) = source_map else { return };
         debug!("fix_multispans_in_extern_macros: before: span={:?} children={:?}", span, children);
-        self.fix_multispan_in_extern_macros(source_map, span);
+        self.fix_multispan_in_extern_macros(span);
         for child in children.iter_mut() {
-            self.fix_multispan_in_extern_macros(source_map, &mut child.span);
+            self.fix_multispan_in_extern_macros(&mut child.span);
         }
         debug!("fix_multispans_in_extern_macros: after: span={:?} children={:?}", span, children);
     }
@@ -496,7 +493,8 @@ pub trait Emitter: Translate {
     // This "fixes" MultiSpans that contain `Span`s pointing to locations inside of external macros.
     // Since these locations are often difficult to read,
     // we move these spans from the external macros to their corresponding use site.
-    fn fix_multispan_in_extern_macros(&self, source_map: &Lrc<SourceMap>, span: &mut MultiSpan) {
+    fn fix_multispan_in_extern_macros(&self, span: &mut MultiSpan) {
+        let Some(source_map) = self.source_map() else { return };
         // First, find all the spans in external macros and point instead at their use site.
         let replacements: Vec<(Span, Span)> = span
             .primary_spans()
@@ -544,7 +542,6 @@ impl Emitter for EmitterWriter {
         debug!("emit_diagnostic: suggestions={:?}", suggestions);
 
         self.fix_multispans_in_extern_macros_and_render_macro_backtrace(
-            &self.sm,
             &mut primary_span,
             &mut children,
             &diag.level,
@@ -2213,22 +2210,45 @@ impl FileWithAnnotatedLines {
 
         if let Some(ref sm) = emitter.source_map() {
             for span_label in msp.span_labels() {
+                let fixup_lo_hi = |span: Span| {
+                    let lo = sm.lookup_char_pos(span.lo());
+                    let mut hi = sm.lookup_char_pos(span.hi());
+
+                    // Watch out for "empty spans". If we get a span like 6..6, we
+                    // want to just display a `^` at 6, so convert that to
+                    // 6..7. This is degenerate input, but it's best to degrade
+                    // gracefully -- and the parser likes to supply a span like
+                    // that for EOF, in particular.
+
+                    if lo.col_display == hi.col_display && lo.line == hi.line {
+                        hi.col_display += 1;
+                    }
+                    (lo, hi)
+                };
+
                 if span_label.span.is_dummy() {
+                    if let Some(span) = msp.primary_span() {
+                        // if we don't know where to render the annotation, emit it as a note
+                        // on the primary span.
+
+                        let (lo, hi) = fixup_lo_hi(span);
+
+                        let ann = Annotation {
+                            start_col: lo.col_display,
+                            end_col: hi.col_display,
+                            is_primary: span_label.is_primary,
+                            label: span_label
+                                .label
+                                .as_ref()
+                                .map(|m| emitter.translate_message(m, args).to_string()),
+                            annotation_type: AnnotationType::Singleline,
+                        };
+                        add_annotation_to_file(&mut output, lo.file, lo.line, ann);
+                    }
                     continue;
                 }
 
-                let lo = sm.lookup_char_pos(span_label.span.lo());
-                let mut hi = sm.lookup_char_pos(span_label.span.hi());
-
-                // Watch out for "empty spans". If we get a span like 6..6, we
-                // want to just display a `^` at 6, so convert that to
-                // 6..7. This is degenerate input, but it's best to degrade
-                // gracefully -- and the parser likes to supply a span like
-                // that for EOF, in particular.
-
-                if lo.col_display == hi.col_display && lo.line == hi.line {
-                    hi.col_display += 1;
-                }
+                let (lo, hi) = fixup_lo_hi(span_label.span);
 
                 if lo.line != hi.line {
                     let ml = MultilineAnnotation {
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index c8de60ccb89..1294f1e17d4 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -250,6 +250,7 @@ pub trait MultiItemModifier {
         span: Span,
         meta_item: &ast::MetaItem,
         item: Annotatable,
+        is_derive_const: bool,
     ) -> ExpandResult<Vec<Annotatable>, Annotatable>;
 }
 
@@ -263,6 +264,7 @@ where
         span: Span,
         meta_item: &ast::MetaItem,
         item: Annotatable,
+        _is_derive_const: bool,
     ) -> ExpandResult<Vec<Annotatable>, Annotatable> {
         ExpandResult::Ready(self(ecx, span, meta_item, item))
     }
@@ -873,7 +875,7 @@ impl SyntaxExtension {
 /// Error type that denotes indeterminacy.
 pub struct Indeterminate;
 
-pub type DeriveResolutions = Vec<(ast::Path, Annotatable, Option<Lrc<SyntaxExtension>>)>;
+pub type DeriveResolutions = Vec<(ast::Path, Annotatable, Option<Lrc<SyntaxExtension>>, bool)>;
 
 pub trait ResolverExpand {
     fn next_node_id(&mut self) -> NodeId;
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index 57713fb3cd6..3d37e2c6568 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -337,6 +337,7 @@ pub enum InvocationKind {
     },
     Derive {
         path: ast::Path,
+        is_const: bool,
         item: Annotatable,
     },
 }
@@ -478,13 +479,13 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                             derive_invocations.reserve(derives.len());
                             derives
                                 .into_iter()
-                                .map(|(path, item, _exts)| {
+                                .map(|(path, item, _exts, is_const)| {
                                     // FIXME: Consider using the derive resolutions (`_exts`)
                                     // instead of enqueuing the derives to be resolved again later.
                                     let expn_id = LocalExpnId::fresh_empty();
                                     derive_invocations.push((
                                         Invocation {
-                                            kind: InvocationKind::Derive { path, item },
+                                            kind: InvocationKind::Derive { path, item, is_const },
                                             fragment_kind,
                                             expansion_data: ExpansionData {
                                                 id: expn_id,
@@ -717,7 +718,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                 SyntaxExtensionKind::LegacyAttr(expander) => {
                     match validate_attr::parse_meta(&self.cx.sess.parse_sess, &attr) {
                         Ok(meta) => {
-                            let items = match expander.expand(self.cx, span, &meta, item) {
+                            let items = match expander.expand(self.cx, span, &meta, item, false) {
                                 ExpandResult::Ready(items) => items,
                                 ExpandResult::Retry(item) => {
                                     // Reassemble the original invocation for retrying.
@@ -749,19 +750,19 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                 }
                 _ => unreachable!(),
             },
-            InvocationKind::Derive { path, item } => match ext {
+            InvocationKind::Derive { path, item, is_const } => match ext {
                 SyntaxExtensionKind::Derive(expander)
                 | SyntaxExtensionKind::LegacyDerive(expander) => {
                     if let SyntaxExtensionKind::Derive(..) = ext {
                         self.gate_proc_macro_input(&item);
                     }
                     let meta = ast::MetaItem { kind: MetaItemKind::Word, span, path };
-                    let items = match expander.expand(self.cx, span, &meta, item) {
+                    let items = match expander.expand(self.cx, span, &meta, item, is_const) {
                         ExpandResult::Ready(items) => items,
                         ExpandResult::Retry(item) => {
                             // Reassemble the original invocation for retrying.
                             return ExpandResult::Retry(Invocation {
-                                kind: InvocationKind::Derive { path: meta.path, item },
+                                kind: InvocationKind::Derive { path: meta.path, item, is_const },
                                 ..invoc
                             });
                         }
diff --git a/compiler/rustc_expand/src/proc_macro.rs b/compiler/rustc_expand/src/proc_macro.rs
index 1a2ab9d190e..e9a69192068 100644
--- a/compiler/rustc_expand/src/proc_macro.rs
+++ b/compiler/rustc_expand/src/proc_macro.rs
@@ -112,6 +112,7 @@ impl MultiItemModifier for DeriveProcMacro {
         span: Span,
         _meta_item: &ast::MetaItem,
         item: Annotatable,
+        _is_derive_const: bool,
     ) -> ExpandResult<Vec<Annotatable>, Annotatable> {
         // We need special handling for statement items
         // (e.g. `fn foo() { #[derive(Debug)] struct Bar; }`)
diff --git a/compiler/rustc_hir_analysis/src/check/compare_method.rs b/compiler/rustc_hir_analysis/src/check/compare_method.rs
index 04bf7c83b32..7c99896b457 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_method.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_method.rs
@@ -9,14 +9,15 @@ use rustc_hir::intravisit;
 use rustc_hir::{GenericParamKind, ImplItemKind, TraitItemKind};
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
-use rustc_infer::infer::{self, TyCtxtInferExt};
+use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
 use rustc_infer::traits::util;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::util::ExplicitSelf;
-use rustc_middle::ty::InternalSubsts;
 use rustc_middle::ty::{
-    self, AssocItem, DefIdTree, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable,
+    self, AssocItem, DefIdTree, TraitRef, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable,
+    TypeVisitable,
 };
+use rustc_middle::ty::{FnSig, InternalSubsts};
 use rustc_middle::ty::{GenericParamDefKind, ToPredicate, TyCtxt};
 use rustc_span::Span;
 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
@@ -303,102 +304,19 @@ fn compare_predicate_entailment<'tcx>(
     }
 
     if let Err(terr) = result {
-        debug!("sub_types failed: impl ty {:?}, trait ty {:?}", impl_fty, trait_fty);
+        debug!(?terr, "sub_types failed: impl ty {:?}, trait ty {:?}", impl_fty, trait_fty);
 
-        let (impl_err_span, trait_err_span) =
-            extract_spans_for_error_reporting(&infcx, terr, &cause, impl_m, trait_m);
-
-        cause.span = impl_err_span;
-
-        let mut diag = struct_span_err!(
-            tcx.sess,
-            cause.span(),
-            E0053,
-            "method `{}` has an incompatible type for trait",
-            trait_m.name
-        );
-        match &terr {
-            TypeError::ArgumentMutability(0) | TypeError::ArgumentSorts(_, 0)
-                if trait_m.fn_has_self_parameter =>
-            {
-                let ty = trait_sig.inputs()[0];
-                let sugg = match ExplicitSelf::determine(ty, |_| ty == impl_trait_ref.self_ty()) {
-                    ExplicitSelf::ByValue => "self".to_owned(),
-                    ExplicitSelf::ByReference(_, hir::Mutability::Not) => "&self".to_owned(),
-                    ExplicitSelf::ByReference(_, hir::Mutability::Mut) => "&mut self".to_owned(),
-                    _ => format!("self: {ty}"),
-                };
-
-                // When the `impl` receiver is an arbitrary self type, like `self: Box<Self>`, the
-                // span points only at the type `Box<Self`>, but we want to cover the whole
-                // argument pattern and type.
-                let span = match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind {
-                    ImplItemKind::Fn(ref sig, body) => tcx
-                        .hir()
-                        .body_param_names(body)
-                        .zip(sig.decl.inputs.iter())
-                        .map(|(param, ty)| param.span.to(ty.span))
-                        .next()
-                        .unwrap_or(impl_err_span),
-                    _ => bug!("{:?} is not a method", impl_m),
-                };
-
-                diag.span_suggestion(
-                    span,
-                    "change the self-receiver type to match the trait",
-                    sugg,
-                    Applicability::MachineApplicable,
-                );
-            }
-            TypeError::ArgumentMutability(i) | TypeError::ArgumentSorts(_, i) => {
-                if trait_sig.inputs().len() == *i {
-                    // Suggestion to change output type. We do not suggest in `async` functions
-                    // to avoid complex logic or incorrect output.
-                    match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind {
-                        ImplItemKind::Fn(ref sig, _)
-                            if sig.header.asyncness == hir::IsAsync::NotAsync =>
-                        {
-                            let msg = "change the output type to match the trait";
-                            let ap = Applicability::MachineApplicable;
-                            match sig.decl.output {
-                                hir::FnRetTy::DefaultReturn(sp) => {
-                                    let sugg = format!("-> {} ", trait_sig.output());
-                                    diag.span_suggestion_verbose(sp, msg, sugg, ap);
-                                }
-                                hir::FnRetTy::Return(hir_ty) => {
-                                    let sugg = trait_sig.output();
-                                    diag.span_suggestion(hir_ty.span, msg, sugg, ap);
-                                }
-                            };
-                        }
-                        _ => {}
-                    };
-                } else if let Some(trait_ty) = trait_sig.inputs().get(*i) {
-                    diag.span_suggestion(
-                        impl_err_span,
-                        "change the parameter type to match the trait",
-                        trait_ty,
-                        Applicability::MachineApplicable,
-                    );
-                }
-            }
-            _ => {}
-        }
-
-        infcx.err_ctxt().note_type_err(
-            &mut diag,
-            &cause,
-            trait_err_span.map(|sp| (sp, "type in trait".to_owned())),
-            Some(infer::ValuePairs::Terms(ExpectedFound {
-                expected: trait_fty.into(),
-                found: impl_fty.into(),
-            })),
+        let emitted = report_trait_method_mismatch(
+            tcx,
+            &mut cause,
+            &infcx,
             terr,
-            false,
-            false,
+            (trait_m, trait_fty),
+            (impl_m, impl_fty),
+            &trait_sig,
+            &impl_trait_ref,
         );
-
-        return Err(diag.emit());
+        return Err(emitted);
     }
 
     // Check that all obligations are satisfied by the implementation's
@@ -424,6 +342,7 @@ fn compare_predicate_entailment<'tcx>(
     Ok(())
 }
 
+#[instrument(skip(tcx), level = "debug", ret)]
 pub fn collect_trait_impl_trait_tys<'tcx>(
     tcx: TyCtxt<'tcx>,
     def_id: DefId,
@@ -437,7 +356,7 @@ pub fn collect_trait_impl_trait_tys<'tcx>(
 
     let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m.def_id.expect_local());
     let return_span = tcx.hir().fn_decl_by_hir_id(impl_m_hir_id).unwrap().output.span();
-    let cause = ObligationCause::new(
+    let mut cause = ObligationCause::new(
         return_span,
         impl_m_hir_id,
         ObligationCauseCode::CompareImplItemObligation {
@@ -514,23 +433,35 @@ pub fn collect_trait_impl_trait_tys<'tcx>(
         }
     }
 
+    debug!(?trait_sig, ?impl_sig, "equating function signatures");
+
+    let trait_fty = tcx.mk_fn_ptr(ty::Binder::dummy(trait_sig));
+    let impl_fty = tcx.mk_fn_ptr(ty::Binder::dummy(impl_sig));
+
     // Unify the whole function signature. We need to do this to fully infer
     // the lifetimes of the return type, but do this after unifying just the
     // return types, since we want to avoid duplicating errors from
     // `compare_predicate_entailment`.
-    match infcx
-        .at(&cause, param_env)
-        .eq(tcx.mk_fn_ptr(ty::Binder::dummy(trait_sig)), tcx.mk_fn_ptr(ty::Binder::dummy(impl_sig)))
-    {
+    match infcx.at(&cause, param_env).eq(trait_fty, impl_fty) {
         Ok(infer::InferOk { value: (), obligations }) => {
             ocx.register_obligations(obligations);
         }
         Err(terr) => {
-            let guar = tcx.sess.delay_span_bug(
-                return_span,
-                format!("could not unify `{trait_sig}` and `{impl_sig}`: {terr:?}"),
+            // This function gets called during `compare_predicate_entailment` when normalizing a
+            // signature that contains RPITIT. When the method signatures don't match, we have to
+            // emit an error now because `compare_predicate_entailment` will not report the error
+            // when normalization fails.
+            let emitted = report_trait_method_mismatch(
+                tcx,
+                &mut cause,
+                infcx,
+                terr,
+                (trait_m, trait_fty),
+                (impl_m, impl_fty),
+                &trait_sig,
+                &impl_trait_ref,
             );
-            return Err(guar);
+            return Err(emitted);
         }
     }
 
@@ -690,6 +621,112 @@ impl<'tcx> TypeFolder<'tcx> for ImplTraitInTraitCollector<'_, 'tcx> {
     }
 }
 
+fn report_trait_method_mismatch<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    cause: &mut ObligationCause<'tcx>,
+    infcx: &InferCtxt<'tcx>,
+    terr: TypeError<'tcx>,
+    (trait_m, trait_fty): (&AssocItem, Ty<'tcx>),
+    (impl_m, impl_fty): (&AssocItem, Ty<'tcx>),
+    trait_sig: &FnSig<'tcx>,
+    impl_trait_ref: &TraitRef<'tcx>,
+) -> ErrorGuaranteed {
+    let (impl_err_span, trait_err_span) =
+        extract_spans_for_error_reporting(&infcx, terr, &cause, impl_m, trait_m);
+
+    cause.span = impl_err_span;
+
+    let mut diag = struct_span_err!(
+        tcx.sess,
+        cause.span(),
+        E0053,
+        "method `{}` has an incompatible type for trait",
+        trait_m.name
+    );
+    match &terr {
+        TypeError::ArgumentMutability(0) | TypeError::ArgumentSorts(_, 0)
+            if trait_m.fn_has_self_parameter =>
+        {
+            let ty = trait_sig.inputs()[0];
+            let sugg = match ExplicitSelf::determine(ty, |_| ty == impl_trait_ref.self_ty()) {
+                ExplicitSelf::ByValue => "self".to_owned(),
+                ExplicitSelf::ByReference(_, hir::Mutability::Not) => "&self".to_owned(),
+                ExplicitSelf::ByReference(_, hir::Mutability::Mut) => "&mut self".to_owned(),
+                _ => format!("self: {ty}"),
+            };
+
+            // When the `impl` receiver is an arbitrary self type, like `self: Box<Self>`, the
+            // span points only at the type `Box<Self`>, but we want to cover the whole
+            // argument pattern and type.
+            let span = match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind {
+                ImplItemKind::Fn(ref sig, body) => tcx
+                    .hir()
+                    .body_param_names(body)
+                    .zip(sig.decl.inputs.iter())
+                    .map(|(param, ty)| param.span.to(ty.span))
+                    .next()
+                    .unwrap_or(impl_err_span),
+                _ => bug!("{:?} is not a method", impl_m),
+            };
+
+            diag.span_suggestion(
+                span,
+                "change the self-receiver type to match the trait",
+                sugg,
+                Applicability::MachineApplicable,
+            );
+        }
+        TypeError::ArgumentMutability(i) | TypeError::ArgumentSorts(_, i) => {
+            if trait_sig.inputs().len() == *i {
+                // Suggestion to change output type. We do not suggest in `async` functions
+                // to avoid complex logic or incorrect output.
+                match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind {
+                    ImplItemKind::Fn(ref sig, _)
+                        if sig.header.asyncness == hir::IsAsync::NotAsync =>
+                    {
+                        let msg = "change the output type to match the trait";
+                        let ap = Applicability::MachineApplicable;
+                        match sig.decl.output {
+                            hir::FnRetTy::DefaultReturn(sp) => {
+                                let sugg = format!("-> {} ", trait_sig.output());
+                                diag.span_suggestion_verbose(sp, msg, sugg, ap);
+                            }
+                            hir::FnRetTy::Return(hir_ty) => {
+                                let sugg = trait_sig.output();
+                                diag.span_suggestion(hir_ty.span, msg, sugg, ap);
+                            }
+                        };
+                    }
+                    _ => {}
+                };
+            } else if let Some(trait_ty) = trait_sig.inputs().get(*i) {
+                diag.span_suggestion(
+                    impl_err_span,
+                    "change the parameter type to match the trait",
+                    trait_ty,
+                    Applicability::MachineApplicable,
+                );
+            }
+        }
+        _ => {}
+    }
+
+    infcx.err_ctxt().note_type_err(
+        &mut diag,
+        &cause,
+        trait_err_span.map(|sp| (sp, "type in trait".to_owned())),
+        Some(infer::ValuePairs::Terms(ExpectedFound {
+            expected: trait_fty.into(),
+            found: impl_fty.into(),
+        })),
+        terr,
+        false,
+        false,
+    );
+
+    return diag.emit();
+}
+
 fn check_region_bounds_on_impl_item<'tcx>(
     tcx: TyCtxt<'tcx>,
     impl_m: &ty::AssocItem,
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 6ed7a93d463..c6bd771fad2 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -18,6 +18,7 @@ use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryRespons
 use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282;
 use rustc_infer::infer::{InferOk, InferResult};
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
+use rustc_middle::ty::error::TypeError;
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::visit::TypeVisitable;
 use rustc_middle::ty::{
@@ -32,9 +33,7 @@ use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::{Span, DUMMY_SP};
 use rustc_trait_selection::infer::InferCtxtExt as _;
 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
-use rustc_trait_selection::traits::{
-    self, ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt,
-};
+use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, ObligationCtxt};
 
 use std::collections::hash_map::Entry;
 use std::slice;
@@ -766,34 +765,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         let expect_args = self
             .fudge_inference_if_ok(|| {
+                let ocx = ObligationCtxt::new_in_snapshot(self);
+
                 // Attempt to apply a subtyping relationship between the formal
                 // return type (likely containing type variables if the function
                 // is polymorphic) and the expected return type.
                 // No argument expectations are produced if unification fails.
                 let origin = self.misc(call_span);
-                let ures = self.at(&origin, self.param_env).sup(ret_ty, formal_ret);
-
-                // FIXME(#27336) can't use ? here, Try::from_error doesn't default
-                // to identity so the resulting type is not constrained.
-                match ures {
-                    Ok(ok) => {
-                        // Process any obligations locally as much as
-                        // we can.  We don't care if some things turn
-                        // out unconstrained or ambiguous, as we're
-                        // just trying to get hints here.
-                        let errors = self.save_and_restore_in_snapshot_flag(|_| {
-                            let mut fulfill = <dyn TraitEngine<'_>>::new(self.tcx);
-                            for obligation in ok.obligations {
-                                fulfill.register_predicate_obligation(self, obligation);
-                            }
-                            fulfill.select_where_possible(self)
-                        });
-
-                        if !errors.is_empty() {
-                            return Err(());
-                        }
-                    }
-                    Err(_) => return Err(()),
+                ocx.sup(&origin, self.param_env, ret_ty, formal_ret)?;
+                if !ocx.select_where_possible().is_empty() {
+                    return Err(TypeError::Mismatch);
                 }
 
                 // Record all the argument types, with the substitutions
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index ccba197dc80..fd3b3e4d59f 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -778,32 +778,6 @@ impl<'tcx> InferCtxt<'tcx> {
         }
     }
 
-    /// Clear the "currently in a snapshot" flag, invoke the closure,
-    /// then restore the flag to its original value. This flag is a
-    /// debugging measure designed to detect cases where we start a
-    /// snapshot, create type variables, and register obligations
-    /// which may involve those type variables in the fulfillment cx,
-    /// potentially leaving "dangling type variables" behind.
-    /// In such cases, an assertion will fail when attempting to
-    /// register obligations, within a snapshot. Very useful, much
-    /// better than grovelling through megabytes of `RUSTC_LOG` output.
-    ///
-    /// HOWEVER, in some cases the flag is unhelpful. In particular, we
-    /// sometimes create a "mini-fulfilment-cx" in which we enroll
-    /// obligations. As long as this fulfillment cx is fully drained
-    /// before we return, this is not a problem, as there won't be any
-    /// escaping obligations in the main cx. In those cases, you can
-    /// use this function.
-    pub fn save_and_restore_in_snapshot_flag<F, R>(&self, func: F) -> R
-    where
-        F: FnOnce(&Self) -> R,
-    {
-        let flag = self.in_snapshot.replace(false);
-        let result = func(self);
-        self.in_snapshot.set(flag);
-        result
-    }
-
     fn start_snapshot(&self) -> CombinedSnapshot<'tcx> {
         debug!("start_snapshot()");
 
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index e0da0096c4e..2b6ff0a5cb9 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -119,13 +119,13 @@ impl CheckAttrVisitor<'_> {
                 }
                 sym::naked => self.check_naked(hir_id, attr, span, target),
                 sym::rustc_legacy_const_generics => {
-                    self.check_rustc_legacy_const_generics(&attr, span, target, item)
+                    self.check_rustc_legacy_const_generics(hir_id, &attr, span, target, item)
                 }
                 sym::rustc_lint_query_instability => {
-                    self.check_rustc_lint_query_instability(&attr, span, target)
+                    self.check_rustc_lint_query_instability(hir_id, &attr, span, target)
                 }
                 sym::rustc_lint_diagnostics => {
-                    self.check_rustc_lint_diagnostics(&attr, span, target)
+                    self.check_rustc_lint_diagnostics(hir_id, &attr, span, target)
                 }
                 sym::rustc_lint_opt_ty => self.check_rustc_lint_opt_ty(&attr, span, target),
                 sym::rustc_lint_opt_deny_field_access => {
@@ -135,7 +135,9 @@ impl CheckAttrVisitor<'_> {
                 | sym::rustc_dirty
                 | sym::rustc_if_this_changed
                 | sym::rustc_then_this_would_need => self.check_rustc_dirty_clean(&attr),
-                sym::cmse_nonsecure_entry => self.check_cmse_nonsecure_entry(attr, span, target),
+                sym::cmse_nonsecure_entry => {
+                    self.check_cmse_nonsecure_entry(hir_id, attr, span, target)
+                }
                 sym::collapse_debuginfo => self.check_collapse_debuginfo(attr, span, target),
                 sym::const_trait => self.check_const_trait(attr, span, target),
                 sym::must_not_suspend => self.check_must_not_suspend(&attr, span, target),
@@ -386,6 +388,7 @@ impl CheckAttrVisitor<'_> {
                 self.tcx.sess.emit_err(errors::AttrShouldBeAppliedToFn {
                     attr_span: attr.span,
                     defn_span: span,
+                    on_crate: hir_id == CRATE_HIR_ID,
                 });
                 false
             }
@@ -393,7 +396,13 @@ impl CheckAttrVisitor<'_> {
     }
 
     /// Checks if `#[cmse_nonsecure_entry]` is applied to a function definition.
-    fn check_cmse_nonsecure_entry(&self, attr: &Attribute, span: Span, target: Target) -> bool {
+    fn check_cmse_nonsecure_entry(
+        &self,
+        hir_id: HirId,
+        attr: &Attribute,
+        span: Span,
+        target: Target,
+    ) -> bool {
         match target {
             Target::Fn
             | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true,
@@ -401,6 +410,7 @@ impl CheckAttrVisitor<'_> {
                 self.tcx.sess.emit_err(errors::AttrShouldBeAppliedToFn {
                     attr_span: attr.span,
                     defn_span: span,
+                    on_crate: hir_id == CRATE_HIR_ID,
                 });
                 false
             }
@@ -465,9 +475,11 @@ impl CheckAttrVisitor<'_> {
                 true
             }
             _ => {
-                self.tcx
-                    .sess
-                    .emit_err(errors::TrackedCallerWrongLocation { attr_span, defn_span: span });
+                self.tcx.sess.emit_err(errors::TrackedCallerWrongLocation {
+                    attr_span,
+                    defn_span: span,
+                    on_crate: hir_id == CRATE_HIR_ID,
+                });
                 false
             }
         }
@@ -576,6 +588,7 @@ impl CheckAttrVisitor<'_> {
                 self.tcx.sess.emit_err(errors::AttrShouldBeAppliedToFn {
                     attr_span: attr.span,
                     defn_span: span,
+                    on_crate: hir_id == CRATE_HIR_ID,
                 });
                 false
             }
@@ -1230,7 +1243,7 @@ impl CheckAttrVisitor<'_> {
                     UNUSED_ATTRIBUTES,
                     hir_id,
                     attr.span,
-                    errors::Cold { span },
+                    errors::Cold { span, on_crate: hir_id == CRATE_HIR_ID },
                 );
             }
         }
@@ -1366,6 +1379,7 @@ impl CheckAttrVisitor<'_> {
     /// Checks if `#[rustc_legacy_const_generics]` is applied to a function and has a valid argument.
     fn check_rustc_legacy_const_generics(
         &self,
+        hir_id: HirId,
         attr: &Attribute,
         span: Span,
         target: Target,
@@ -1376,6 +1390,7 @@ impl CheckAttrVisitor<'_> {
             self.tcx.sess.emit_err(errors::AttrShouldBeAppliedToFn {
                 attr_span: attr.span,
                 defn_span: span,
+                on_crate: hir_id == CRATE_HIR_ID,
             });
             return false;
         }
@@ -1440,12 +1455,19 @@ impl CheckAttrVisitor<'_> {
 
     /// Helper function for checking that the provided attribute is only applied to a function or
     /// method.
-    fn check_applied_to_fn_or_method(&self, attr: &Attribute, span: Span, target: Target) -> bool {
+    fn check_applied_to_fn_or_method(
+        &self,
+        hir_id: HirId,
+        attr: &Attribute,
+        span: Span,
+        target: Target,
+    ) -> bool {
         let is_function = matches!(target, Target::Fn | Target::Method(..));
         if !is_function {
             self.tcx.sess.emit_err(errors::AttrShouldBeAppliedToFn {
                 attr_span: attr.span,
                 defn_span: span,
+                on_crate: hir_id == CRATE_HIR_ID,
             });
             false
         } else {
@@ -1457,17 +1479,24 @@ impl CheckAttrVisitor<'_> {
     /// or method.
     fn check_rustc_lint_query_instability(
         &self,
+        hir_id: HirId,
         attr: &Attribute,
         span: Span,
         target: Target,
     ) -> bool {
-        self.check_applied_to_fn_or_method(attr, span, target)
+        self.check_applied_to_fn_or_method(hir_id, attr, span, target)
     }
 
     /// Checks that the `#[rustc_lint_diagnostics]` attribute is only applied to a function or
     /// method.
-    fn check_rustc_lint_diagnostics(&self, attr: &Attribute, span: Span, target: Target) -> bool {
-        self.check_applied_to_fn_or_method(attr, span, target)
+    fn check_rustc_lint_diagnostics(
+        &self,
+        hir_id: HirId,
+        attr: &Attribute,
+        span: Span,
+        target: Target,
+    ) -> bool {
+        self.check_applied_to_fn_or_method(hir_id, attr, span, target)
     }
 
     /// Checks that the `#[rustc_lint_opt_ty]` attribute is only applied to a struct.
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 1dbf0d642e2..c6cd69add28 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -81,6 +81,7 @@ pub struct AttrShouldBeAppliedToFn {
     pub attr_span: Span,
     #[label]
     pub defn_span: Span,
+    pub on_crate: bool,
 }
 
 #[derive(Diagnostic)]
@@ -97,6 +98,7 @@ pub struct TrackedCallerWrongLocation {
     pub attr_span: Span,
     #[label]
     pub defn_span: Span,
+    pub on_crate: bool,
 }
 
 #[derive(Diagnostic)]
@@ -367,6 +369,7 @@ pub struct MustNotSuspend {
 pub struct Cold {
     #[label]
     pub span: Span,
+    pub on_crate: bool,
 }
 
 #[derive(LintDiagnostic)]
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 7961e3f1194..a12918b2979 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -241,10 +241,12 @@ impl<'a> Resolver<'a> {
         ));
 
         err.span_label(span, format!("`{}` re{} here", name, new_participle));
-        err.span_label(
-            self.session.source_map().guess_head_span(old_binding.span),
-            format!("previous {} of the {} `{}` here", old_noun, old_kind, name),
-        );
+        if !old_binding.span.is_dummy() && old_binding.span != span {
+            err.span_label(
+                self.session.source_map().guess_head_span(old_binding.span),
+                format!("previous {} of the {} `{}` here", old_noun, old_kind, name),
+            );
+        }
 
         // See https://github.com/rust-lang/rust/issues/32354
         use NameBindingKind::Import;
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index f2bfec5a2a3..95eff92ef5e 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -807,14 +807,16 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
         err.code(rustc_errors::error_code!(E0411));
         err.span_label(span, "`Self` is only available in impls, traits, and type definitions");
         if let Some(item_kind) = self.diagnostic_metadata.current_item {
-            err.span_label(
-                item_kind.ident.span,
-                format!(
-                    "`Self` not allowed in {} {}",
-                    item_kind.kind.article(),
-                    item_kind.kind.descr()
-                ),
-            );
+            if !item_kind.ident.span.is_dummy() {
+                err.span_label(
+                    item_kind.ident.span,
+                    format!(
+                        "`Self` not allowed in {} {}",
+                        item_kind.kind.article(),
+                        item_kind.kind.descr()
+                    ),
+                );
+            }
         }
         true
     }
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index 9526296f951..8c7972f8eeb 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -356,7 +356,7 @@ impl<'a> ResolverExpand for Resolver<'a> {
             has_derive_copy: false,
         });
         let parent_scope = self.invocation_parent_scopes[&expn_id];
-        for (i, (path, _, opt_ext)) in entry.resolutions.iter_mut().enumerate() {
+        for (i, (path, _, opt_ext, _)) in entry.resolutions.iter_mut().enumerate() {
             if opt_ext.is_none() {
                 *opt_ext = Some(
                     match self.resolve_macro_path(
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 54a61483a11..b48db73618b 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -620,6 +620,7 @@ symbols! {
         deref_mut,
         deref_target,
         derive,
+        derive_const,
         derive_default_enum,
         destruct,
         destructuring_assignment,
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 540b1fa2b0f..22e7d3ea5dd 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -2445,12 +2445,12 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                             (Ok(l), Ok(r)) => l.line == r.line,
                             _ => true,
                         };
-                    if !ident.span.overlaps(span) && !same_line {
+                    if !ident.span.is_dummy() && !ident.span.overlaps(span) && !same_line {
                         multispan.push_span_label(ident.span, "required by a bound in this");
                     }
                 }
                 let descr = format!("required by a bound in `{}`", item_name);
-                if span != DUMMY_SP {
+                if !span.is_dummy() {
                     let msg = format!("required by this bound in `{}`", item_name);
                     multispan.push_span_label(span, msg);
                     err.span_note(multispan, &descr);
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
index 43819b3f490..231a18f86ea 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
@@ -10,10 +10,12 @@
 //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/specialization.html
 
 pub mod specialization_graph;
+use rustc_infer::traits::{TraitEngine, TraitEngineExt as _};
 use specialization_graph::GraphExt;
 
 use crate::errors::NegativePositiveConflict;
 use crate::infer::{InferCtxt, InferOk, TyCtxtInferExt};
+use crate::traits::engine::TraitEngineExt as _;
 use crate::traits::select::IntercrateAmbiguityCause;
 use crate::traits::{self, coherence, FutureCompatOverlapErrorKind, ObligationCause};
 use rustc_data_structures::fx::FxIndexSet;
@@ -200,36 +202,32 @@ fn fulfill_implication<'tcx>(
         return Err(());
     };
 
+    // Needs to be `in_snapshot` because this function is used to rebase
+    // substitutions, which may happen inside of a select within a probe.
+    let mut engine = <dyn TraitEngine<'tcx>>::new_in_snapshot(infcx.tcx);
     // attempt to prove all of the predicates for impl2 given those for impl1
     // (which are packed up in penv)
+    engine.register_predicate_obligations(infcx, obligations.chain(more_obligations));
 
-    infcx.save_and_restore_in_snapshot_flag(|infcx| {
-        let errors = traits::fully_solve_obligations(&infcx, obligations.chain(more_obligations));
-        match &errors[..] {
-            [] => {
-                debug!(
-                    "fulfill_implication: an impl for {:?} specializes {:?}",
-                    source_trait, target_trait
-                );
+    let errors = engine.select_all_or_error(infcx);
+    if !errors.is_empty() {
+        // no dice!
+        debug!(
+            "fulfill_implication: for impls on {:?} and {:?}, \
+                 could not fulfill: {:?} given {:?}",
+            source_trait,
+            target_trait,
+            errors,
+            param_env.caller_bounds()
+        );
+        return Err(());
+    }
 
-                // Now resolve the *substitution* we built for the target earlier, replacing
-                // the inference variables inside with whatever we got from fulfillment.
-                Ok(infcx.resolve_vars_if_possible(target_substs))
-            }
-            errors => {
-                // no dice!
-                debug!(
-                    "fulfill_implication: for impls on {:?} and {:?}, \
-                     could not fulfill: {:?} given {:?}",
-                    source_trait,
-                    target_trait,
-                    errors,
-                    param_env.caller_bounds()
-                );
-                Err(())
-            }
-        }
-    })
+    debug!("fulfill_implication: an impl for {:?} specializes {:?}", source_trait, target_trait);
+
+    // Now resolve the *substitution* we built for the target earlier, replacing
+    // the inference variables inside with whatever we got from fulfillment.
+    Ok(infcx.resolve_vars_if_possible(target_substs))
 }
 
 // Query provider for `specialization_graph_of`.
diff --git a/compiler/rustc_traits/src/dropck_outlives.rs b/compiler/rustc_traits/src/dropck_outlives.rs
index d5a8ca5ea78..7b4ad9fea13 100644
--- a/compiler/rustc_traits/src/dropck_outlives.rs
+++ b/compiler/rustc_traits/src/dropck_outlives.rs
@@ -2,20 +2,18 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::canonical::{Canonical, QueryResponse};
 use rustc_infer::infer::TyCtxtInferExt;
-use rustc_infer::traits::TraitEngineExt as _;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::InternalSubsts;
 use rustc_middle::ty::{self, EarlyBinder, ParamEnvAnd, Ty, TyCtxt};
 use rustc_span::source_map::{Span, DUMMY_SP};
+use rustc_trait_selection::infer::InferCtxtBuilderExt;
 use rustc_trait_selection::traits::query::dropck_outlives::trivial_dropck_outlives;
 use rustc_trait_selection::traits::query::dropck_outlives::{
     DropckConstraint, DropckOutlivesResult,
 };
 use rustc_trait_selection::traits::query::normalize::AtExt;
 use rustc_trait_selection::traits::query::{CanonicalTyGoal, NoSolution};
-use rustc_trait_selection::traits::{
-    Normalized, ObligationCause, TraitEngine, TraitEngineExt as _,
-};
+use rustc_trait_selection::traits::{Normalized, ObligationCause};
 
 pub(crate) fn provide(p: &mut Providers) {
     *p = Providers { dropck_outlives, adt_dtorck_constraint, ..*p };
@@ -27,120 +25,109 @@ fn dropck_outlives<'tcx>(
 ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, DropckOutlivesResult<'tcx>>>, NoSolution> {
     debug!("dropck_outlives(goal={:#?})", canonical_goal);
 
-    let (ref infcx, goal, canonical_inference_vars) =
-        tcx.infer_ctxt().build_with_canonical(DUMMY_SP, &canonical_goal);
-    let tcx = infcx.tcx;
-    let ParamEnvAnd { param_env, value: for_ty } = goal;
-
-    let mut result = DropckOutlivesResult { kinds: vec![], overflows: vec![] };
-
-    // A stack of types left to process. Each round, we pop
-    // something from the stack and invoke
-    // `dtorck_constraint_for_ty`. This may produce new types that
-    // have to be pushed on the stack. This continues until we have explored
-    // all the reachable types from the type `for_ty`.
-    //
-    // Example: Imagine that we have the following code:
-    //
-    // ```rust
-    // struct A {
-    //     value: B,
-    //     children: Vec<A>,
-    // }
-    //
-    // struct B {
-    //     value: u32
-    // }
-    //
-    // fn f() {
-    //   let a: A = ...;
-    //   ..
-    // } // here, `a` is dropped
-    // ```
-    //
-    // at the point where `a` is dropped, we need to figure out
-    // which types inside of `a` contain region data that may be
-    // accessed by any destructors in `a`. We begin by pushing `A`
-    // onto the stack, as that is the type of `a`. We will then
-    // invoke `dtorck_constraint_for_ty` which will expand `A`
-    // into the types of its fields `(B, Vec<A>)`. These will get
-    // pushed onto the stack. Eventually, expanding `Vec<A>` will
-    // lead to us trying to push `A` a second time -- to prevent
-    // infinite recursion, we notice that `A` was already pushed
-    // once and stop.
-    let mut ty_stack = vec![(for_ty, 0)];
-
-    // Set used to detect infinite recursion.
-    let mut ty_set = FxHashSet::default();
-
-    let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
-
-    let cause = ObligationCause::dummy();
-    let mut constraints = DropckConstraint::empty();
-    while let Some((ty, depth)) = ty_stack.pop() {
-        debug!(
-            "{} kinds, {} overflows, {} ty_stack",
-            result.kinds.len(),
-            result.overflows.len(),
-            ty_stack.len()
-        );
-        dtorck_constraint_for_ty(tcx, DUMMY_SP, for_ty, depth, ty, &mut constraints)?;
-
-        // "outlives" represent types/regions that may be touched
-        // by a destructor.
-        result.kinds.append(&mut constraints.outlives);
-        result.overflows.append(&mut constraints.overflows);
-
-        // If we have even one overflow, we should stop trying to evaluate further --
-        // chances are, the subsequent overflows for this evaluation won't provide useful
-        // information and will just decrease the speed at which we can emit these errors
-        // (since we'll be printing for just that much longer for the often enormous types
-        // that result here).
-        if !result.overflows.is_empty() {
-            break;
-        }
+    tcx.infer_ctxt().enter_canonical_trait_query(&canonical_goal, |ocx, goal| {
+        let tcx = ocx.infcx.tcx;
+        let ParamEnvAnd { param_env, value: for_ty } = goal;
+
+        let mut result = DropckOutlivesResult { kinds: vec![], overflows: vec![] };
+
+        // A stack of types left to process. Each round, we pop
+        // something from the stack and invoke
+        // `dtorck_constraint_for_ty`. This may produce new types that
+        // have to be pushed on the stack. This continues until we have explored
+        // all the reachable types from the type `for_ty`.
+        //
+        // Example: Imagine that we have the following code:
+        //
+        // ```rust
+        // struct A {
+        //     value: B,
+        //     children: Vec<A>,
+        // }
+        //
+        // struct B {
+        //     value: u32
+        // }
+        //
+        // fn f() {
+        //   let a: A = ...;
+        //   ..
+        // } // here, `a` is dropped
+        // ```
+        //
+        // at the point where `a` is dropped, we need to figure out
+        // which types inside of `a` contain region data that may be
+        // accessed by any destructors in `a`. We begin by pushing `A`
+        // onto the stack, as that is the type of `a`. We will then
+        // invoke `dtorck_constraint_for_ty` which will expand `A`
+        // into the types of its fields `(B, Vec<A>)`. These will get
+        // pushed onto the stack. Eventually, expanding `Vec<A>` will
+        // lead to us trying to push `A` a second time -- to prevent
+        // infinite recursion, we notice that `A` was already pushed
+        // once and stop.
+        let mut ty_stack = vec![(for_ty, 0)];
+
+        // Set used to detect infinite recursion.
+        let mut ty_set = FxHashSet::default();
+
+        let cause = ObligationCause::dummy();
+        let mut constraints = DropckConstraint::empty();
+        while let Some((ty, depth)) = ty_stack.pop() {
+            debug!(
+                "{} kinds, {} overflows, {} ty_stack",
+                result.kinds.len(),
+                result.overflows.len(),
+                ty_stack.len()
+            );
+            dtorck_constraint_for_ty(tcx, DUMMY_SP, for_ty, depth, ty, &mut constraints)?;
+
+            // "outlives" represent types/regions that may be touched
+            // by a destructor.
+            result.kinds.append(&mut constraints.outlives);
+            result.overflows.append(&mut constraints.overflows);
+
+            // If we have even one overflow, we should stop trying to evaluate further --
+            // chances are, the subsequent overflows for this evaluation won't provide useful
+            // information and will just decrease the speed at which we can emit these errors
+            // (since we'll be printing for just that much longer for the often enormous types
+            // that result here).
+            if !result.overflows.is_empty() {
+                break;
+            }
 
-        // dtorck types are "types that will get dropped but which
-        // do not themselves define a destructor", more or less. We have
-        // to push them onto the stack to be expanded.
-        for ty in constraints.dtorck_types.drain(..) {
-            match infcx.at(&cause, param_env).normalize(ty) {
-                Ok(Normalized { value: ty, obligations }) => {
-                    fulfill_cx.register_predicate_obligations(infcx, obligations);
-
-                    debug!("dropck_outlives: ty from dtorck_types = {:?}", ty);
-
-                    match ty.kind() {
-                        // All parameters live for the duration of the
-                        // function.
-                        ty::Param(..) => {}
-
-                        // A projection that we couldn't resolve - it
-                        // might have a destructor.
-                        ty::Projection(..) | ty::Opaque(..) => {
-                            result.kinds.push(ty.into());
-                        }
+            // dtorck types are "types that will get dropped but which
+            // do not themselves define a destructor", more or less. We have
+            // to push them onto the stack to be expanded.
+            for ty in constraints.dtorck_types.drain(..) {
+                let Normalized { value: ty, obligations } =
+                    ocx.infcx.at(&cause, param_env).normalize(ty)?;
+                ocx.register_obligations(obligations);
+
+                debug!("dropck_outlives: ty from dtorck_types = {:?}", ty);
+
+                match ty.kind() {
+                    // All parameters live for the duration of the
+                    // function.
+                    ty::Param(..) => {}
+
+                    // A projection that we couldn't resolve - it
+                    // might have a destructor.
+                    ty::Projection(..) | ty::Opaque(..) => {
+                        result.kinds.push(ty.into());
+                    }
 
-                        _ => {
-                            if ty_set.insert(ty) {
-                                ty_stack.push((ty, depth + 1));
-                            }
+                    _ => {
+                        if ty_set.insert(ty) {
+                            ty_stack.push((ty, depth + 1));
                         }
                     }
                 }
-
-                // We don't actually expect to fail to normalize.
-                // That implies a WF error somewhere else.
-                Err(NoSolution) => {
-                    return Err(NoSolution);
-                }
             }
         }
-    }
-
-    debug!("dropck_outlives: result = {:#?}", result);
 
-    infcx.make_canonicalized_query_response(canonical_inference_vars, result, &mut *fulfill_cx)
+        debug!("dropck_outlives: result = {:#?}", result);
+        Ok(result)
+    })
 }
 
 /// Returns a set of constraints that needs to be satisfied in
diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs
index 2850d84acc3..32bdc26bc51 100644
--- a/library/core/src/macros/mod.rs
+++ b/library/core/src/macros/mod.rs
@@ -1464,6 +1464,19 @@ pub(crate) mod builtin {
         /* compiler built-in */
     }
 
+    /// Attribute macro used to apply derive macros for implementing traits
+    /// in a const context.
+    ///
+    /// See [the reference] for more info.
+    ///
+    /// [the reference]: ../../../reference/attributes/derive.html
+    #[unstable(feature = "derive_const", issue = "none")]
+    #[rustc_builtin_macro]
+    #[cfg(not(bootstrap))]
+    pub macro derive_const($item:item) {
+        /* compiler built-in */
+    }
+
     /// Attribute macro applied to a function to turn it into a unit test.
     ///
     /// See [the reference] for more info.
diff --git a/library/core/src/prelude/v1.rs b/library/core/src/prelude/v1.rs
index 804a179bdb3..d3d255a802d 100644
--- a/library/core/src/prelude/v1.rs
+++ b/library/core/src/prelude/v1.rs
@@ -81,6 +81,10 @@ pub use crate::macros::builtin::alloc_error_handler;
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
 pub use crate::macros::builtin::{bench, derive, global_allocator, test, test_case};
 
+#[unstable(feature = "derive_const", issue = "none")]
+#[cfg(not(bootstrap))]
+pub use crate::macros::builtin::derive_const;
+
 #[unstable(
     feature = "cfg_accessible",
     issue = "64797",
diff --git a/library/std/src/prelude/v1.rs b/library/std/src/prelude/v1.rs
index 36d9e8921ef..d5ac16e6b94 100644
--- a/library/std/src/prelude/v1.rs
+++ b/library/std/src/prelude/v1.rs
@@ -65,6 +65,10 @@ pub use core::prelude::v1::alloc_error_handler;
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
 pub use core::prelude::v1::{bench, derive, global_allocator, test, test_case};
 
+#[unstable(feature = "derive_const", issue = "none")]
+#[cfg(not(bootstrap))]
+pub use core::prelude::v1::derive_const;
+
 // Do not `doc(no_inline)` either.
 #[unstable(
     feature = "cfg_accessible",
diff --git a/src/librustdoc/html/static/css/settings.css b/src/librustdoc/html/static/css/settings.css
index 83939f63b4e..1f6fb961e91 100644
--- a/src/librustdoc/html/static/css/settings.css
+++ b/src/librustdoc/html/static/css/settings.css
@@ -8,7 +8,8 @@
 	flex-wrap: wrap;
 }
 
-.setting-line .radio-line input {
+.setting-line .radio-line input,
+.setting-line .toggle input {
 	margin-right: 0.3em;
 	height: 1.2rem;
 	width: 1.2rem;
@@ -17,9 +18,18 @@
 	outline: none;
 	-webkit-appearance: none;
 	cursor: pointer;
+}
+.setting-line .radio-line input {
 	border-radius: 50%;
 }
-.setting-line .radio-line input + span {
+.setting-line .toggle input:checked {
+	content: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40">\
+		<path d="M7,25L17,32L33,12" fill="none" stroke="black" stroke-width="5"/>\
+		<path d="M7,23L17,30L33,10" fill="none" stroke="white" stroke-width="5"/></svg>');
+}
+
+.setting-line .radio-line input + span,
+.setting-line .toggle span {
 	padding-bottom: 1px;
 }
 
@@ -49,37 +59,6 @@
 	cursor: pointer;
 }
 
-.toggle input {
-	opacity: 0;
-	position: absolute;
-}
-
-.slider {
-	position: relative;
-	width: 45px;
-	min-width: 45px;
-	display: block;
-	height: 28px;
-	margin-right: 20px;
-	cursor: pointer;
-	background-color: #ccc;
-	transition: .3s;
-}
-
-.slider:before {
-	position: absolute;
-	content: "";
-	height: 19px;
-	width: 19px;
-	left: 4px;
-	bottom: 4px;
-	transition: .3s;
-}
-
-input:checked + .slider:before {
-	transform: translateX(19px);
-}
-
 .setting-line > .sub-settings {
 	padding-left: 42px;
 	width: 100%;
@@ -94,7 +73,11 @@ input:checked + .slider:before {
 	box-shadow: inset 0 0 0 3px var(--main-background-color);
 	background-color: var(--settings-input-color);
 }
-.setting-line .radio-line input:focus {
+.setting-line .toggle input:checked {
+	background-color: var(--settings-input-color);
+}
+.setting-line .radio-line input:focus,
+.setting-line .toggle input:focus {
 	box-shadow: 0 0 1px 1px var(--settings-input-color);
 }
 /* In here we combine both `:focus` and `:checked` properties. */
@@ -102,9 +85,7 @@ input:checked + .slider:before {
 	box-shadow: inset 0 0 0 3px var(--main-background-color),
 		0 0 2px 2px var(--settings-input-color);
 }
-.setting-line .radio-line input:hover {
+.setting-line .radio-line input:hover,
+.setting-line .toggle input:hover {
 	border-color: var(--settings-input-color) !important;
 }
-input:checked + .slider {
-	background-color: var(--settings-input-color);
-}
diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css
index 2fa1fa39d63..4beca56b66a 100644
--- a/src/librustdoc/html/static/css/themes/ayu.css
+++ b/src/librustdoc/html/static/css/themes/ayu.css
@@ -77,16 +77,6 @@ Original by Dempfi (https://github.com/dempfi/ayu)
 	--crate-search-hover-border: #e0e0e0;
 }
 
-.slider {
-	background-color: #ccc;
-}
-.slider:before {
-	background-color: white;
-}
-input:focus + .slider {
-	box-shadow: 0 0 0 2px #0a84ff, 0 0 0 6px rgba(10, 132, 255, 0.3);
-}
-
 h1, h2, h3, h4 {
 	color: white;
 }
diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css
index 43f8dd42ab3..9b0bd8c8f0a 100644
--- a/src/librustdoc/html/static/css/themes/dark.css
+++ b/src/librustdoc/html/static/css/themes/dark.css
@@ -72,16 +72,6 @@
 	--crate-search-hover-border: #2196f3;
 }
 
-.slider {
-	background-color: #ccc;
-}
-.slider:before {
-	background-color: white;
-}
-input:focus + .slider {
-	box-shadow: 0 0 0 2px #0a84ff, 0 0 0 6px rgba(10, 132, 255, 0.3);
-}
-
 .content .item-info::before { color: #ccc; }
 
 body.source .example-wrap pre.rust a {
diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css
index c8c5289ab54..f12fb61d879 100644
--- a/src/librustdoc/html/static/css/themes/light.css
+++ b/src/librustdoc/html/static/css/themes/light.css
@@ -69,15 +69,6 @@
 	--crate-search-hover-border: #717171;
 }
 
-.slider {
-	background-color: #ccc;
-}
-.slider:before {
-	background-color: white;
-}
-input:focus + .slider {
-	box-shadow: 0 0 0 2px #0a84ff, 0 0 0 6px rgba(10, 132, 255, 0.3);
-}
 
 .content .item-info::before { color: #ccc; }
 
diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js
index 141563bd46a..95cc265f1bd 100644
--- a/src/librustdoc/html/static/js/settings.js
+++ b/src/librustdoc/html/static/js/settings.js
@@ -66,8 +66,7 @@
 
     function setEvents(settingsElement) {
         updateLightAndDark();
-        onEachLazy(settingsElement.getElementsByClassName("slider"), elem => {
-            const toggle = elem.previousElementSibling;
+        onEachLazy(settingsElement.querySelectorAll("input[type=\"checkbox\"]"), toggle => {
             const settingId = toggle.id;
             const settingValue = getSettingValue(settingId);
             if (settingValue !== null) {
@@ -139,7 +138,6 @@
                 const checked = setting["default"] === true ? " checked" : "";
                 output += `<label class="toggle">\
                         <input type="checkbox" id="${js_data_name}"${checked}>\
-                        <span class="slider"></span>\
                         <span class="label">${setting_name}</span>\
                     </label>`;
             }
diff --git a/src/test/rustdoc-gui/docblock-code-block-line-number.goml b/src/test/rustdoc-gui/docblock-code-block-line-number.goml
index 911ee34be94..fec21ad35c3 100644
--- a/src/test/rustdoc-gui/docblock-code-block-line-number.goml
+++ b/src/test/rustdoc-gui/docblock-code-block-line-number.goml
@@ -30,10 +30,10 @@ wait-for: "#settings"
 assert-css: ("#settings", {"display": "block"})
 
 // Then, click the toggle button.
-click: "input#line-numbers + .slider"
+click: "input#line-numbers"
 wait-for: 100 // wait-for-false does not exist
 assert-false: "pre.example-line-numbers"
 
 // Finally, turn it on again.
-click: "input#line-numbers + .slider"
+click: "input#line-numbers"
 wait-for: "pre.example-line-numbers"
diff --git a/src/test/rustdoc-gui/settings.goml b/src/test/rustdoc-gui/settings.goml
index f258f4d2a83..7e7971d47fb 100644
--- a/src/test/rustdoc-gui/settings.goml
+++ b/src/test/rustdoc-gui/settings.goml
@@ -48,7 +48,8 @@ assert: ".setting-line.hidden #preferred-light-theme"
 assert-property: ("#theme .choices #theme-dark", {"checked": "true"})
 
 // Some style checks...
-// First we check the "default" display.
+move-cursor-to: "#settings-menu > a"
+// First we check the "default" display for radio buttons.
 assert-css: (
     "#theme-dark",
     {
@@ -57,7 +58,7 @@ assert-css: (
     },
 )
 assert-css: ("#theme-light", {"border-color": "rgb(221, 221, 221)", "box-shadow": "none"})
-// Let's start with the hover.
+// Let's start with the hover for radio buttons.
 move-cursor-to: "#theme-dark"
 assert-css: (
     "#theme-dark",
@@ -69,7 +70,7 @@ assert-css: (
 move-cursor-to: "#theme-light"
 assert-css: ("#theme-light", {"border-color": "rgb(33, 150, 243)", "box-shadow": "none"})
 move-cursor-to: "#theme-ayu"
-// Let's now check with the focus.
+// Let's now check with the focus for radio buttons.
 focus: "#theme-dark"
 assert-css: (
     "#theme-dark",
@@ -86,7 +87,7 @@ assert-css: (
         "box-shadow": "rgb(33, 150, 243) 0px 0px 1px 1px",
     },
 )
-// Now we check we both focus and hover.
+// Now we check we both focus and hover for radio buttons.
 move-cursor-to: "#theme-dark"
 focus: "#theme-dark"
 assert-css: (
@@ -106,6 +107,80 @@ assert-css: (
     },
 )
 
+// First we check the "default" display for toggles.
+assert-css: (
+    "#auto-hide-large-items",
+    {
+        "background-color": "rgb(33, 150, 243)",
+        "border-color": "rgb(221, 221, 221)",
+    },
+)
+assert-css: (
+    "#use-system-theme",
+    {
+        "background-color": "rgba(0, 0, 0, 0)",
+        "border-color": "rgb(221, 221, 221)",
+    }
+)
+// Let's start with the hover for toggles.
+move-cursor-to: "#auto-hide-large-items"
+assert-css: (
+    "#auto-hide-large-items",
+    {
+        "background-color": "rgb(33, 150, 243)",
+        "border-color": "rgb(33, 150, 243)",
+    },
+)
+move-cursor-to: "#use-system-theme"
+assert-css: (
+    "#use-system-theme",
+    {
+        "background-color": "rgba(0, 0, 0, 0)",
+        "border-color": "rgb(33, 150, 243)",
+    }
+)
+move-cursor-to: "#settings-menu > a"
+// Let's now check with the focus for toggles.
+focus: "#auto-hide-large-items"
+assert-css: (
+    "#auto-hide-large-items",
+    {
+        "background-color": "rgb(33, 150, 243)",
+        "border-color": "rgb(221, 221, 221)",
+        "box-shadow": "rgb(33, 150, 243) 0px 0px 1px 1px",
+    },
+)
+focus: "#use-system-theme"
+assert-css: (
+    "#use-system-theme",
+    {
+        "background-color": "rgba(0, 0, 0, 0)",
+        "border-color": "rgb(221, 221, 221)",
+        "box-shadow": "rgb(33, 150, 243) 0px 0px 1px 1px",
+    },
+)
+// Now we check we both focus and hover for toggles.
+move-cursor-to: "#auto-hide-large-items"
+focus: "#auto-hide-large-items"
+assert-css: (
+    "#auto-hide-large-items",
+    {
+        "background-color": "rgb(33, 150, 243)",
+        "border-color": "rgb(33, 150, 243)",
+        "box-shadow": "rgb(33, 150, 243) 0px 0px 1px 1px",
+    },
+)
+move-cursor-to: "#use-system-theme"
+focus: "#use-system-theme"
+assert-css: (
+    "#use-system-theme",
+    {
+        "background-color": "rgba(0, 0, 0, 0)",
+        "border-color": "rgb(33, 150, 243)",
+        "box-shadow": "rgb(33, 150, 243) 0px 0px 1px 1px",
+    },
+)
+
 // We now switch the display.
 click: "#use-system-theme"
 // Wait for the hidden element to show up.
@@ -118,7 +193,7 @@ assert: ".setting-line.hidden #theme"
 assert-text: ("#preferred-dark-theme .setting-name", "Preferred dark theme")
 assert-text: ("#preferred-light-theme .setting-name", "Preferred light theme")
 
-// We now check that clicking on the "sliders"' text is like clicking on the slider.
+// We now check that clicking on the toggles' text is like clicking on the checkbox.
 // To test it, we use the "Disable keyboard shortcuts".
 local-storage: {"rustdoc-disable-shortcuts": "false"}
 click: ".setting-line:last-child .toggle .label"
@@ -141,10 +216,7 @@ assert-css: ("#settings-menu .popover", {"display": "none"})
 // Now we go to the settings page to check that the CSS is loaded as expected.
 goto: "file://" + |DOC_PATH| + "/settings.html"
 wait-for: "#settings"
-assert-css: (
-    ".setting-line .toggle .slider",
-    {"width": "45px", "margin-right": "20px", "border": "0px none rgb(0, 0, 0)"},
-)
+assert-css: (".setting-line", {"position": "relative"})
 
 assert-attribute-false: ("#settings", {"class": "popover"}, CONTAINS)
 compare-elements-position: (".sub form", "#settings", ("x"))
@@ -162,4 +234,4 @@ reload:
 size: (300, 1000)
 click: "#settings-menu"
 wait-for: "#settings"
-assert-css: ("#settings .slider", {"width": "45px"}, ALL)
+assert-css: (".setting-line", {"position": "relative"})
diff --git a/src/test/ui/asm/naked-invalid-attr.stderr b/src/test/ui/asm/naked-invalid-attr.stderr
index 58344be9334..e8ddccc854a 100644
--- a/src/test/ui/asm/naked-invalid-attr.stderr
+++ b/src/test/ui/asm/naked-invalid-attr.stderr
@@ -36,7 +36,7 @@ error: attribute should be applied to a function definition
   --> $DIR/naked-invalid-attr.rs:5:1
    |
 LL | #![naked]
-   | ^^^^^^^^^
+   | ^^^^^^^^^ cannot be applied to crates
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr
index 5a645cf4ef9..78767040421 100644
--- a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr
+++ b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr
@@ -110,19 +110,19 @@ error: attribute should be applied to an `extern crate` item
   --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:25:1
    |
 LL | #![no_link]
-   | ^^^^^^^^^^^
+   | ^^^^^^^^^^^ not an `extern crate` item
 
 error: attribute should be applied to a free function, impl method or static
   --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:27:1
    |
 LL | #![export_name = "2200"]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^ not a free function, impl method or static
 
 error[E0518]: attribute should be applied to function or closure
   --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:29:1
    |
 LL | #![inline]
-   | ^^^^^^^^^^
+   | ^^^^^^^^^^ not a function or closure
 
 error: `macro_export` attribute cannot be used at crate level
   --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:12:1
diff --git a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs
index 8db12e55d25..1fa315f3d21 100644
--- a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs
+++ b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs
@@ -1,6 +1,6 @@
 //~ NOTE not a function
 //~| NOTE not a foreign function or static
-//~| NOTE not a function or static
+//~| NOTE cannot be applied to crates
 //~| NOTE not an `extern` block
 // This test enumerates as many compiler-builtin ungated attributes as
 // possible (that is, all the mutually compatible ones), and checks
diff --git a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr
index 310d1f720eb..30039267979 100644
--- a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr
+++ b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr
@@ -403,7 +403,7 @@ warning: attribute should be applied to a function definition
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:62:1
    |
 LL | #![cold]
-   | ^^^^^^^^
+   | ^^^^^^^^ cannot be applied to crates
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
@@ -411,7 +411,7 @@ warning: attribute should be applied to an `extern` block with non-Rust ABI
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:64:1
    |
 LL | #![link()]
-   | ^^^^^^^^^^
+   | ^^^^^^^^^^ not an `extern` block
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
@@ -419,7 +419,7 @@ warning: attribute should be applied to a foreign function or static
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:66:1
    |
 LL | #![link_name = "1900"]
-   | ^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^ not a foreign function or static
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
@@ -427,7 +427,7 @@ warning: attribute should be applied to a function or static
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:69:1
    |
 LL | #![link_section = "1800"]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^ not a function or static
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
diff --git a/src/test/ui/impl-trait/in-trait/method-signature-matches.rs b/src/test/ui/impl-trait/in-trait/method-signature-matches.rs
new file mode 100644
index 00000000000..c848ee3f643
--- /dev/null
+++ b/src/test/ui/impl-trait/in-trait/method-signature-matches.rs
@@ -0,0 +1,51 @@
+// edition: 2021
+
+#![feature(return_position_impl_trait_in_trait, async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+trait Uwu {
+    fn owo(x: ()) -> impl Sized;
+}
+
+impl Uwu for () {
+    fn owo(_: u8) {}
+    //~^ ERROR method `owo` has an incompatible type for trait
+}
+
+trait AsyncUwu {
+    async fn owo(x: ()) {}
+}
+
+impl AsyncUwu for () {
+    async fn owo(_: u8) {}
+    //~^ ERROR method `owo` has an incompatible type for trait
+}
+
+trait TooMuch {
+    fn calm_down_please() -> impl Sized;
+}
+
+impl TooMuch for () {
+    fn calm_down_please(_: (), _: (), _: ()) {}
+    //~^ ERROR method `calm_down_please` has 3 parameters but the declaration in trait `TooMuch::calm_down_please` has 0
+}
+
+trait TooLittle {
+    fn come_on_a_little_more_effort(_: (), _: (), _: ()) -> impl Sized;
+}
+
+impl TooLittle for () {
+    fn come_on_a_little_more_effort() {}
+    //~^ ERROR method `come_on_a_little_more_effort` has 0 parameters but the declaration in trait `TooLittle::come_on_a_little_more_effort` has 3
+}
+
+trait Lifetimes {
+    fn early<'early, T>(x: &'early T) -> impl Sized;
+}
+
+impl Lifetimes for () {
+    fn early<'late, T>(_: &'late ()) {}
+    //~^ ERROR method `early` has an incompatible type for trait
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/in-trait/method-signature-matches.stderr b/src/test/ui/impl-trait/in-trait/method-signature-matches.stderr
new file mode 100644
index 00000000000..2b32c52c829
--- /dev/null
+++ b/src/test/ui/impl-trait/in-trait/method-signature-matches.stderr
@@ -0,0 +1,84 @@
+error[E0053]: method `owo` has an incompatible type for trait
+  --> $DIR/method-signature-matches.rs:11:15
+   |
+LL |     fn owo(_: u8) {}
+   |               ^^
+   |               |
+   |               expected `()`, found `u8`
+   |               help: change the parameter type to match the trait: `()`
+   |
+note: type in trait
+  --> $DIR/method-signature-matches.rs:7:15
+   |
+LL |     fn owo(x: ()) -> impl Sized;
+   |               ^^
+   = note: expected fn pointer `fn(())`
+              found fn pointer `fn(u8)`
+
+error[E0053]: method `owo` has an incompatible type for trait
+  --> $DIR/method-signature-matches.rs:20:21
+   |
+LL |     async fn owo(_: u8) {}
+   |                     ^^
+   |                     |
+   |                     expected `()`, found `u8`
+   |                     help: change the parameter type to match the trait: `()`
+   |
+note: while checking the return type of the `async fn`
+  --> $DIR/method-signature-matches.rs:20:25
+   |
+LL |     async fn owo(_: u8) {}
+   |                         ^ checked the `Output` of this `async fn`, expected opaque type
+note: while checking the return type of the `async fn`
+  --> $DIR/method-signature-matches.rs:20:25
+   |
+LL |     async fn owo(_: u8) {}
+   |                         ^ checked the `Output` of this `async fn`, found opaque type
+note: type in trait
+  --> $DIR/method-signature-matches.rs:16:21
+   |
+LL |     async fn owo(x: ()) {}
+   |                     ^^
+   = note: expected fn pointer `fn(()) -> _`
+              found fn pointer `fn(u8) -> _`
+
+error[E0050]: method `calm_down_please` has 3 parameters but the declaration in trait `TooMuch::calm_down_please` has 0
+  --> $DIR/method-signature-matches.rs:29:28
+   |
+LL |     fn calm_down_please() -> impl Sized;
+   |     ------------------------------------ trait requires 0 parameters
+...
+LL |     fn calm_down_please(_: (), _: (), _: ()) {}
+   |                            ^^^^^^^^^^^^^^^^ expected 0 parameters, found 3
+
+error[E0050]: method `come_on_a_little_more_effort` has 0 parameters but the declaration in trait `TooLittle::come_on_a_little_more_effort` has 3
+  --> $DIR/method-signature-matches.rs:38:5
+   |
+LL |     fn come_on_a_little_more_effort(_: (), _: (), _: ()) -> impl Sized;
+   |                                        ---------------- trait requires 3 parameters
+...
+LL |     fn come_on_a_little_more_effort() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 3 parameters, found 0
+
+error[E0053]: method `early` has an incompatible type for trait
+  --> $DIR/method-signature-matches.rs:47:27
+   |
+LL |     fn early<'late, T>(_: &'late ()) {}
+   |                     -     ^^^^^^^^^
+   |                     |     |
+   |                     |     expected type parameter `T`, found `()`
+   |                     |     help: change the parameter type to match the trait: `&'early T`
+   |                     this type parameter
+   |
+note: type in trait
+  --> $DIR/method-signature-matches.rs:43:28
+   |
+LL |     fn early<'early, T>(x: &'early T) -> impl Sized;
+   |                            ^^^^^^^^^
+   = note: expected fn pointer `fn(&'early T)`
+              found fn pointer `fn(&())`
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0050, E0053.
+For more information about an error, try `rustc --explain E0050`.
diff --git a/src/test/ui/issues/issue-32655.stderr b/src/test/ui/issues/issue-32655.stderr
index 2d9ce430a46..5a758c7002b 100644
--- a/src/test/ui/issues/issue-32655.stderr
+++ b/src/test/ui/issues/issue-32655.stderr
@@ -2,18 +2,28 @@ error: cannot find attribute `derive_Clone` in this scope
   --> $DIR/issue-32655.rs:3:11
    |
 LL |         #[derive_Clone]
-   |           ^^^^^^^^^^^^
+   |           ^^^^^^^^^^^^ help: an attribute macro with a similar name exists: `derive_const`
 ...
 LL | foo!();
    | ------ in this macro invocation
    |
+  ::: $SRC_DIR/core/src/macros/mod.rs:LL:COL
+   |
+LL |     pub macro derive_const($item:item) {
+   |     ---------------------- similarly named attribute macro `derive_const` defined here
+   |
    = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: cannot find attribute `derive_Clone` in this scope
   --> $DIR/issue-32655.rs:15:7
    |
 LL |     #[derive_Clone]
-   |       ^^^^^^^^^^^^
+   |       ^^^^^^^^^^^^ help: an attribute macro with a similar name exists: `derive_const`
+   |
+  ::: $SRC_DIR/core/src/macros/mod.rs:LL:COL
+   |
+LL |     pub macro derive_const($item:item) {
+   |     ---------------------- similarly named attribute macro `derive_const` defined here
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr b/src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr
index f581429a281..89aeafebac4 100644
--- a/src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr
+++ b/src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr
@@ -2,10 +2,7 @@ error[E0428]: the name `A` is defined multiple times
   --> $DIR/issue-69396-const-no-type-in-macro.rs:4:13
    |
 LL |               const A = "A".$fn();
-   |               ^^^^^^^^^^^^^^^^^^^^
-   |               |
-   |               `A` redefined here
-   |               previous definition of the value `A` here
+   |               ^^^^^^^^^^^^^^^^^^^^ `A` redefined here
 ...
 LL | / suite! {
 LL | |     len;
diff --git a/src/test/ui/iterators/collect-into-array.rs b/src/test/ui/iterators/collect-into-array.rs
index 7d35da82532..4c424999b75 100644
--- a/src/test/ui/iterators/collect-into-array.rs
+++ b/src/test/ui/iterators/collect-into-array.rs
@@ -1,5 +1,4 @@
 fn main() {
-    //~^ NOTE required by a bound in this
     let whatever: [u32; 10] = (0..10).collect();
     //~^ ERROR an array of type `[u32; 10]` cannot be built directly from an iterator
     //~| NOTE try collecting into a `Vec<{integer}>`, then using `.try_into()`
diff --git a/src/test/ui/iterators/collect-into-array.stderr b/src/test/ui/iterators/collect-into-array.stderr
index 7fe9707e6d2..a23a36a88ab 100644
--- a/src/test/ui/iterators/collect-into-array.stderr
+++ b/src/test/ui/iterators/collect-into-array.stderr
@@ -1,5 +1,5 @@
 error[E0277]: an array of type `[u32; 10]` cannot be built directly from an iterator
-  --> $DIR/collect-into-array.rs:3:31
+  --> $DIR/collect-into-array.rs:2:31
    |
 LL |     let whatever: [u32; 10] = (0..10).collect();
    |                               ^^^^^^^ ------- required by a bound introduced by this call
diff --git a/src/test/ui/iterators/collect-into-slice.rs b/src/test/ui/iterators/collect-into-slice.rs
index 5eade075613..09832c260d0 100644
--- a/src/test/ui/iterators/collect-into-slice.rs
+++ b/src/test/ui/iterators/collect-into-slice.rs
@@ -1,6 +1,4 @@
 fn process_slice(data: &[i32]) {
-    //~^ NOTE required by a bound in this
-    //~| NOTE required by a bound in this
     todo!()
 }
 
diff --git a/src/test/ui/iterators/collect-into-slice.stderr b/src/test/ui/iterators/collect-into-slice.stderr
index bce40118bdf..bc152467ce3 100644
--- a/src/test/ui/iterators/collect-into-slice.stderr
+++ b/src/test/ui/iterators/collect-into-slice.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the size for values of type `[i32]` cannot be known at compilation time
-  --> $DIR/collect-into-slice.rs:8:9
+  --> $DIR/collect-into-slice.rs:6:9
    |
 LL |     let some_generated_vec = (0..10).collect();
    |         ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -9,7 +9,7 @@ LL |     let some_generated_vec = (0..10).collect();
    = help: unsized locals are gated as an unstable feature
 
 error[E0277]: the size for values of type `[i32]` cannot be known at compilation time
-  --> $DIR/collect-into-slice.rs:8:38
+  --> $DIR/collect-into-slice.rs:6:38
    |
 LL |     let some_generated_vec = (0..10).collect();
    |                                      ^^^^^^^ doesn't have a size known at compile-time
@@ -22,7 +22,7 @@ LL |     fn collect<B: FromIterator<Self::Item>>(self) -> B
    |                ^ required by this bound in `collect`
 
 error[E0277]: a slice of type `[i32]` cannot be built since `[i32]` has no definite size
-  --> $DIR/collect-into-slice.rs:8:30
+  --> $DIR/collect-into-slice.rs:6:30
    |
 LL |     let some_generated_vec = (0..10).collect();
    |                              ^^^^^^^ ------- required by a bound introduced by this call
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-gate.rs b/src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-gate.rs
new file mode 100644
index 00000000000..348ca0ab190
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-gate.rs
@@ -0,0 +1,4 @@
+#[derive_const(Default)] //~ ERROR use of unstable library feature
+pub struct S;
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-gate.stderr b/src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-gate.stderr
new file mode 100644
index 00000000000..cc9bdd2715f
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-gate.stderr
@@ -0,0 +1,11 @@
+error[E0658]: use of unstable library feature 'derive_const'
+  --> $DIR/derive-const-gate.rs:1:3
+   |
+LL | #[derive_const(Default)]
+   |   ^^^^^^^^^^^^
+   |
+   = help: add `#![feature(derive_const)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.rs b/src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.rs
new file mode 100644
index 00000000000..92843a8a2da
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.rs
@@ -0,0 +1,13 @@
+#![feature(derive_const)]
+
+pub struct A;
+
+impl Default for A {
+    fn default() -> A { A }
+}
+
+#[derive_const(Default)]
+pub struct S(A);
+//~^ cannot call non-const fn
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.stderr b/src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.stderr
new file mode 100644
index 00000000000..d463c774e28
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-non-const-type.stderr
@@ -0,0 +1,14 @@
+error[E0015]: cannot call non-const fn `<A as Default>::default` in constant functions
+  --> $DIR/derive-const-non-const-type.rs:10:14
+   |
+LL | #[derive_const(Default)]
+   |                ------- in this derive macro expansion
+LL | pub struct S(A);
+   |              ^
+   |
+   = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+   = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0015`.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-use.rs b/src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-use.rs
new file mode 100644
index 00000000000..d1fbeac8598
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const_derives/derive-const-use.rs
@@ -0,0 +1,19 @@
+// check-pass
+#![feature(const_trait_impl, const_cmp, const_default_impls, derive_const)]
+
+pub struct A;
+
+impl const Default for A {
+    fn default() -> A { A }
+}
+
+impl const PartialEq for A {
+    fn eq(&self, _: &A) -> bool { true }
+}
+
+#[derive_const(Default, PartialEq)]
+pub struct S((), A);
+
+const _: () = assert!(S((), A) == S::default());
+
+fn main() {}
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 9286a1beba5b28b115bad67de2ae91fb1c61eb0
+Subproject a3dfea71ca0c888a88111086898aa833c291d49
diff --git a/triagebot.toml b/triagebot.toml
index d3f9efcc41c..8efd9af41a4 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -573,6 +573,7 @@ fallback = [
 "/src/llvm-project" =                        ["@cuviper"]
 "/src/rustdoc-json-types" =                  ["rustdoc"]
 "/src/stage0.json" =                         ["bootstrap"]
+"/src/test/ui" =                             ["compiler"]
 "/src/tools/cargo" =                         ["@ehuss", "@joshtriplett"]
 "/src/tools/compiletest" =                   ["bootstrap"]
 "/src/tools/linkchecker" =                   ["@ehuss"]