about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock5
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsic.rs2
-rw-r--r--compiler/rustc_lint/src/map_unit_fn.rs11
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs7
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs10
-rw-r--r--compiler/rustc_middle/src/query/keys.rs4
-rw-r--r--compiler/rustc_mir_transform/src/lower_intrinsics.rs29
-rw-r--r--compiler/rustc_monomorphize/src/polymorphize.rs9
-rw-r--r--compiler/rustc_passes/Cargo.toml1
-rw-r--r--compiler/rustc_passes/messages.ftl21
-rw-r--r--compiler/rustc_passes/src/check_attr.rs173
-rw-r--r--compiler/rustc_passes/src/errors.rs45
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--config.example.toml3
-rw-r--r--library/core/src/intrinsics.rs10
-rw-r--r--library/core/src/ptr/mod.rs59
-rw-r--r--src/bootstrap/CHANGELOG.md1
-rw-r--r--src/bootstrap/config.rs3
-rw-r--r--src/bootstrap/defaults/config.codegen.toml2
-rw-r--r--src/bootstrap/lib.rs1
-rw-r--r--src/bootstrap/native.rs9
m---------src/tools/cargo0
-rw-r--r--tests/codegen-units/polymorphization/auxiliary/poly-dep.rs4
-rw-r--r--tests/codegen-units/polymorphization/poly-foreign.rs11
-rw-r--r--tests/codegen/issues/issue-106369.rs15
-rw-r--r--tests/codegen/issues/issue-73258.rs38
-rw-r--r--tests/codegen/mem-replace-big-type.rs36
-rw-r--r--tests/codegen/mem-replace-direct-memcpy.rs21
-rw-r--r--tests/codegen/ptr-read-metadata.rs96
-rw-r--r--tests/mir-opt/lower_intrinsics.read_via_copy_primitive.LowerIntrinsics.diff27
-rw-r--r--tests/mir-opt/lower_intrinsics.read_via_copy_uninhabited.LowerIntrinsics.diff21
-rw-r--r--tests/mir-opt/lower_intrinsics.rs12
-rw-r--r--tests/ui/const-ptr/out_of_bounds_read.stderr6
-rw-r--r--tests/ui/consts/const-eval/ub-ref-ptr.stderr24
-rw-r--r--tests/ui/consts/issue-miri-1910.stderr2
-rw-r--r--tests/ui/lint/issue-109152.rs7
-rw-r--r--tests/ui/lint/issue-109152.stderr23
-rw-r--r--tests/ui/proc-macro/bad-projection.rs15
-rw-r--r--tests/ui/proc-macro/bad-projection.stderr9
-rw-r--r--tests/ui/proc-macro/proc-macro-abi.rs6
-rw-r--r--tests/ui/proc-macro/proc-macro-abi.stderr21
-rw-r--r--tests/ui/proc-macro/signature-proc-macro-attribute.rs10
-rw-r--r--tests/ui/proc-macro/signature-proc-macro-attribute.stderr46
-rw-r--r--tests/ui/proc-macro/signature-proc-macro-derive.rs9
-rw-r--r--tests/ui/proc-macro/signature-proc-macro-derive.stderr40
-rw-r--r--tests/ui/proc-macro/signature-proc-macro.rs9
-rw-r--r--tests/ui/proc-macro/signature-proc-macro.stderr40
-rw-r--r--tests/ui/proc-macro/signature.rs6
-rw-r--r--tests/ui/proc-macro/signature.stderr35
-rw-r--r--triagebot.toml1
50 files changed, 652 insertions, 344 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 51332919fe7..0c0b5d6ab3b 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -353,7 +353,7 @@ dependencies = [
 
 [[package]]
 name = "cargo"
-version = "0.70.0"
+version = "0.71.0"
 dependencies = [
  "anyhow",
  "base64",
@@ -1001,7 +1001,7 @@ dependencies = [
 
 [[package]]
 name = "crates-io"
-version = "0.35.1"
+version = "0.36.0"
 dependencies = [
  "anyhow",
  "curl",
@@ -5139,6 +5139,7 @@ dependencies = [
  "rustc_session",
  "rustc_span",
  "rustc_target",
+ "rustc_trait_selection",
  "tracing",
 ]
 
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index 20b6561f8b2..8c364a4f3b2 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -363,6 +363,8 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
             sym::likely => (0, vec![tcx.types.bool], tcx.types.bool),
             sym::unlikely => (0, vec![tcx.types.bool], tcx.types.bool),
 
+            sym::read_via_copy => (1, vec![tcx.mk_imm_ptr(param(0))], param(0)),
+
             sym::discriminant_value => {
                 let assoc_items = tcx.associated_item_def_ids(
                     tcx.require_lang_item(hir::LangItem::DiscriminantKind, None),
diff --git a/compiler/rustc_lint/src/map_unit_fn.rs b/compiler/rustc_lint/src/map_unit_fn.rs
index 62e8b4fe9e4..7c692fee333 100644
--- a/compiler/rustc_lint/src/map_unit_fn.rs
+++ b/compiler/rustc_lint/src/map_unit_fn.rs
@@ -56,6 +56,7 @@ impl<'tcx> LateLintPass<'tcx> for MapUnitFn {
                         return;
                     }
                     let arg_ty = cx.typeck_results().expr_ty(&args[0]);
+                    let default_span = args[0].span;
                     if let ty::FnDef(id, _) = arg_ty.kind() {
                         let fn_ty = cx.tcx.fn_sig(id).skip_binder();
                         let ret_ty = fn_ty.output().skip_binder();
@@ -64,7 +65,10 @@ impl<'tcx> LateLintPass<'tcx> for MapUnitFn {
                                 MAP_UNIT_FN,
                                 span,
                                 MappingToUnit {
-                                    function_label: cx.tcx.span_of_impl(*id).unwrap(),
+                                    function_label: cx
+                                        .tcx
+                                        .span_of_impl(*id)
+                                        .unwrap_or(default_span),
                                     argument_label: args[0].span,
                                     map_label: arg_ty.default_span(cx.tcx),
                                     suggestion: path.ident.span,
@@ -80,7 +84,10 @@ impl<'tcx> LateLintPass<'tcx> for MapUnitFn {
                                 MAP_UNIT_FN,
                                 span,
                                 MappingToUnit {
-                                    function_label: cx.tcx.span_of_impl(*id).unwrap(),
+                                    function_label: cx
+                                        .tcx
+                                        .span_of_impl(*id)
+                                        .unwrap_or(default_span),
                                     argument_label: args[0].span,
                                     map_label: arg_ty.default_span(cx.tcx),
                                     suggestion: path.ident.span,
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 46ec1a2dca1..91966e75b5f 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -1026,12 +1026,13 @@ declare_lint! {
     /// ### Example
     ///
     /// ```rust,compile_fail
-    /// #![feature(const_ptr_read)]
+    /// #![feature(const_mut_refs)]
     /// const FOO: () = unsafe {
     ///     let x = &[0_u8; 4];
     ///     let y = x.as_ptr().cast::<u32>();
-    ///     y.read(); // the address of a `u8` array is unknown and thus we don't know if
-    ///     // it is aligned enough for reading a `u32`.
+    ///     let mut z = 123;
+    ///     y.copy_to_nonoverlapping(&mut z, 1); // the address of a `u8` array is unknown
+    ///     // and thus we don't know if it is aligned enough for copying a `u32`.
     /// };
     /// ```
     ///
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index 6c5e8863010..a9843395336 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -226,7 +226,15 @@ provide! { tcx, def_id, other, cdata,
     lookup_default_body_stability => { table }
     lookup_deprecation_entry => { table }
     params_in_repr => { table }
-    unused_generic_params => { table }
+    // FIXME: Could be defaulted, but `LazyValue<UnusedGenericParams>` is not `FixedSizeEncoding`..
+    unused_generic_params => {
+        cdata
+            .root
+            .tables
+            .unused_generic_params
+            .get(cdata, def_id.index)
+            .map_or_else(|| ty::UnusedGenericParams::new_all_used(), |lazy| lazy.decode((cdata, tcx)))
+    }
     opt_def_kind => { table_direct }
     impl_parent => { table }
     impl_polarity => { table_direct }
diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs
index 78ee8a6a8fd..6e961a775c1 100644
--- a/compiler/rustc_middle/src/query/keys.rs
+++ b/compiler/rustc_middle/src/query/keys.rs
@@ -63,7 +63,7 @@ impl<'tcx> Key for ty::InstanceDef<'tcx> {
 
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
-        true
+        self.def_id().is_local()
     }
 
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
@@ -76,7 +76,7 @@ impl<'tcx> Key for ty::Instance<'tcx> {
 
     #[inline(always)]
     fn query_crate_is_local(&self) -> bool {
-        true
+        self.def_id().is_local()
     }
 
     fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs
index f596cc1808f..5d7382305ae 100644
--- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs
+++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs
@@ -149,6 +149,35 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
                             terminator.kind = TerminatorKind::Goto { target };
                         }
                     }
+                    sym::read_via_copy => {
+                        let [arg] = args.as_slice() else {
+                            span_bug!(terminator.source_info.span, "Wrong number of arguments");
+                        };
+                        let derefed_place =
+                            if let Some(place) = arg.place() && let Some(local) = place.as_local() {
+                                tcx.mk_place_deref(local.into())
+                            } else {
+                                span_bug!(terminator.source_info.span, "Only passing a local is supported");
+                            };
+                        terminator.kind = match *target {
+                            None => {
+                                // No target means this read something uninhabited,
+                                // so it must be unreachable, and we don't need to
+                                // preserve the assignment either.
+                                TerminatorKind::Unreachable
+                            }
+                            Some(target) => {
+                                block.statements.push(Statement {
+                                    source_info: terminator.source_info,
+                                    kind: StatementKind::Assign(Box::new((
+                                        *destination,
+                                        Rvalue::Use(Operand::Copy(derefed_place)),
+                                    ))),
+                                });
+                                TerminatorKind::Goto { target }
+                            }
+                        }
+                    }
                     sym::discriminant_value => {
                         if let (Some(target), Some(arg)) = (*target, args[0].place()) {
                             let arg = tcx.mk_place_deref(arg);
diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs
index b7c3dbcc091..63263a642ac 100644
--- a/compiler/rustc_monomorphize/src/polymorphize.rs
+++ b/compiler/rustc_monomorphize/src/polymorphize.rs
@@ -36,6 +36,8 @@ fn unused_generic_params<'tcx>(
     tcx: TyCtxt<'tcx>,
     instance: ty::InstanceDef<'tcx>,
 ) -> UnusedGenericParams {
+    assert!(instance.def_id().is_local());
+
     if !tcx.sess.opts.unstable_opts.polymorphize {
         // If polymorphization disabled, then all parameters are used.
         return UnusedGenericParams::new_all_used();
@@ -100,13 +102,6 @@ fn should_polymorphize<'tcx>(
         return false;
     }
 
-    // Polymorphization results are stored in cross-crate metadata only when there are unused
-    // parameters, so assume that non-local items must have only used parameters (else this query
-    // would not be invoked, and the cross-crate metadata used instead).
-    if !def_id.is_local() {
-        return false;
-    }
-
     // Foreign items have no bodies to analyze.
     if tcx.is_foreign_item(def_id) {
         return false;
diff --git a/compiler/rustc_passes/Cargo.toml b/compiler/rustc_passes/Cargo.toml
index faa9c493d88..44f991f8c15 100644
--- a/compiler/rustc_passes/Cargo.toml
+++ b/compiler/rustc_passes/Cargo.toml
@@ -22,3 +22,4 @@ rustc_span = { path = "../rustc_span" }
 rustc_lexer = { path = "../rustc_lexer" }
 rustc_ast_pretty = { path = "../rustc_ast_pretty" }
 rustc_feature = { path = "../rustc_feature" }
+rustc_trait_selection = { path = "../rustc_trait_selection" }
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index 3fa78efc290..d063b51c8b8 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -720,26 +720,7 @@ passes_ignored_derived_impls =
      *[other] traits {$trait_list}, but these are
     } intentionally ignored during dead code analysis
 
-passes_proc_macro_typeerror = mismatched {$kind} signature
-    .label = found {$found}, expected type `proc_macro::TokenStream`
-    .note = {$kind}s must have a signature of `{$expected_signature}`
-
-passes_proc_macro_diff_arg_count = mismatched {$kind} signature
-    .label = found unexpected {$count ->
-      [one] argument
-     *[other] arguments
-    }
-    .note = {$kind}s must have a signature of `{$expected_signature}`
-
-passes_proc_macro_missing_args = mismatched {$kind} signature
-    .label = {$kind} must have {$expected_input_count ->
-      [one] one argument
-     *[other] two arguments
-    } of type `proc_macro::TokenStream`
-
-passes_proc_macro_invalid_abi = proc macro functions may not be `extern "{$abi}"`
-
-passes_proc_macro_unsafe = proc macro functions may not be `unsafe`
+passes_proc_macro_bad_sig = {$kind} has incorrect signature
 
 passes_skipping_const_checks = skipping const checks
 
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index c8d371dd084..8bed7888142 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -19,9 +19,10 @@ use rustc_hir::{
 use rustc_hir::{MethodKind, Target, Unsafety};
 use rustc_middle::hir::nested_filter;
 use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault;
-use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
+use rustc_middle::traits::ObligationCause;
+use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::{ParamEnv, TyCtxt};
+use rustc_middle::ty::{self, TyCtxt};
 use rustc_session::lint::builtin::{
     CONFLICTING_REPR_HINTS, INVALID_DOC_ATTRIBUTES, INVALID_MACRO_EXPORT_ARGUMENTS,
     UNUSED_ATTRIBUTES,
@@ -30,6 +31,9 @@ use rustc_session::parse::feature_err;
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::{Span, DUMMY_SP};
 use rustc_target::spec::abi::Abi;
+use rustc_trait_selection::infer::{TyCtxtInferExt, ValuePairs};
+use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
+use rustc_trait_selection::traits::ObligationCtxt;
 use std::cell::Cell;
 use std::collections::hash_map::Entry;
 
@@ -2188,100 +2192,99 @@ impl CheckAttrVisitor<'_> {
     ///
     /// If this best effort goes wrong, it will just emit a worse error later (see #102923)
     fn check_proc_macro(&self, hir_id: HirId, target: Target, kind: ProcMacroKind) {
-        let expected_input_count = match kind {
-            ProcMacroKind::Attribute => 2,
-            ProcMacroKind::Derive | ProcMacroKind::FunctionLike => 1,
-        };
-
-        let expected_signature = match kind {
-            ProcMacroKind::Attribute => "fn(TokenStream, TokenStream) -> TokenStream",
-            ProcMacroKind::Derive | ProcMacroKind::FunctionLike => "fn(TokenStream) -> TokenStream",
-        };
+        if target != Target::Fn {
+            return;
+        }
 
         let tcx = self.tcx;
-        if target == Target::Fn {
-            let Some(tokenstream) = tcx.get_diagnostic_item(sym::TokenStream) else {return};
-            let tokenstream = tcx.type_of(tokenstream).subst_identity();
-
-            let id = hir_id.expect_owner();
-            let hir_sig = tcx.hir().fn_sig_by_hir_id(hir_id).unwrap();
-
-            let sig =
-                tcx.liberate_late_bound_regions(id.to_def_id(), tcx.fn_sig(id).subst_identity());
-            let sig = tcx.normalize_erasing_regions(ParamEnv::empty(), sig);
-
-            // We don't currently require that the function signature is equal to
-            // `fn(TokenStream) -> TokenStream`, but instead monomorphizes to
-            // `fn(TokenStream) -> TokenStream` after some substitution of generic arguments.
-            //
-            // Properly checking this means pulling in additional `rustc` crates, so we don't.
-            let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::AsCandidateKey };
-
-            if sig.abi != Abi::Rust {
-                tcx.sess.emit_err(errors::ProcMacroInvalidAbi {
-                    span: hir_sig.span,
-                    abi: sig.abi.name(),
-                });
-                self.abort.set(true);
-            }
+        let Some(token_stream_def_id) = tcx.get_diagnostic_item(sym::TokenStream) else { return; };
+        let Some(token_stream) = tcx.type_of(token_stream_def_id).no_bound_vars() else { return; };
 
-            if sig.unsafety == Unsafety::Unsafe {
-                tcx.sess.emit_err(errors::ProcMacroUnsafe { span: hir_sig.span });
-                self.abort.set(true);
-            }
+        let def_id = hir_id.expect_owner().def_id;
+        let param_env = ty::ParamEnv::empty();
 
-            let output = sig.output();
+        let infcx = tcx.infer_ctxt().build();
+        let ocx = ObligationCtxt::new(&infcx);
 
-            // Typecheck the output
-            if !drcx.types_may_unify(output, tokenstream) {
-                tcx.sess.emit_err(errors::ProcMacroTypeError {
-                    span: hir_sig.decl.output.span(),
-                    found: output,
-                    kind,
-                    expected_signature,
-                });
-                self.abort.set(true);
-            }
+        let span = tcx.def_span(def_id);
+        let fresh_substs = infcx.fresh_substs_for_item(span, def_id.to_def_id());
+        let sig = tcx.liberate_late_bound_regions(
+            def_id.to_def_id(),
+            tcx.fn_sig(def_id).subst(tcx, fresh_substs),
+        );
 
-            if sig.inputs().len() < expected_input_count {
-                tcx.sess.emit_err(errors::ProcMacroMissingArguments {
-                    expected_input_count,
-                    span: hir_sig.span,
-                    kind,
-                    expected_signature,
-                });
-                self.abort.set(true);
-            }
+        let mut cause = ObligationCause::misc(span, def_id);
+        let sig = ocx.normalize(&cause, param_env, sig);
 
-            // Check that the inputs are correct, if there are enough.
-            if sig.inputs().len() >= expected_input_count {
-                for (arg, input) in
-                    sig.inputs().iter().zip(hir_sig.decl.inputs).take(expected_input_count)
-                {
-                    if !drcx.types_may_unify(*arg, tokenstream) {
-                        tcx.sess.emit_err(errors::ProcMacroTypeError {
-                            span: input.span,
-                            found: *arg,
-                            kind,
-                            expected_signature,
-                        });
-                        self.abort.set(true);
+        // proc macro is not WF.
+        let errors = ocx.select_where_possible();
+        if !errors.is_empty() {
+            return;
+        }
+
+        let expected_sig = tcx.mk_fn_sig(
+            std::iter::repeat(token_stream).take(match kind {
+                ProcMacroKind::Attribute => 2,
+                ProcMacroKind::Derive | ProcMacroKind::FunctionLike => 1,
+            }),
+            token_stream,
+            false,
+            Unsafety::Normal,
+            Abi::Rust,
+        );
+
+        if let Err(terr) = ocx.eq(&cause, param_env, expected_sig, sig) {
+            let mut diag = tcx.sess.create_err(errors::ProcMacroBadSig { span, kind });
+
+            let hir_sig = tcx.hir().fn_sig_by_hir_id(hir_id);
+            if let Some(hir_sig) = hir_sig {
+                match terr {
+                    TypeError::ArgumentMutability(idx) | TypeError::ArgumentSorts(_, idx) => {
+                        if let Some(ty) = hir_sig.decl.inputs.get(idx) {
+                            diag.set_span(ty.span);
+                            cause.span = ty.span;
+                        } else if idx == hir_sig.decl.inputs.len() {
+                            let span = hir_sig.decl.output.span();
+                            diag.set_span(span);
+                            cause.span = span;
+                        }
+                    }
+                    TypeError::ArgCount => {
+                        if let Some(ty) = hir_sig.decl.inputs.get(expected_sig.inputs().len()) {
+                            diag.set_span(ty.span);
+                            cause.span = ty.span;
+                        }
                     }
+                    TypeError::UnsafetyMismatch(_) => {
+                        // FIXME: Would be nice if we had a span here..
+                    }
+                    TypeError::AbiMismatch(_) => {
+                        // FIXME: Would be nice if we had a span here..
+                    }
+                    TypeError::VariadicMismatch(_) => {
+                        // FIXME: Would be nice if we had a span here..
+                    }
+                    _ => {}
                 }
             }
 
-            // Check that there are not too many arguments
-            let body_id = tcx.hir().body_owned_by(id.def_id);
-            let excess = tcx.hir().body(body_id).params.get(expected_input_count..);
-            if let Some(excess @ [begin @ end] | excess @ [begin, .., end]) = excess {
-                tcx.sess.emit_err(errors::ProcMacroDiffArguments {
-                    span: begin.span.to(end.span),
-                    count: excess.len(),
-                    kind,
-                    expected_signature,
-                });
-                self.abort.set(true);
-            }
+            infcx.err_ctxt().note_type_err(
+                &mut diag,
+                &cause,
+                None,
+                Some(ValuePairs::Sigs(ExpectedFound { expected: expected_sig, found: sig })),
+                terr,
+                false,
+                false,
+            );
+            diag.emit();
+            self.abort.set(true);
+        }
+
+        let errors = ocx.select_all_or_error();
+        if !errors.is_empty() {
+            infcx.err_ctxt().report_fulfillment_errors(&errors);
+            self.abort.set(true);
         }
     }
 }
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 9f1c0b5a0b7..1b0cd5d91ab 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -1546,52 +1546,11 @@ pub struct ChangeFieldsToBeOfUnitType {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_proc_macro_typeerror)]
-#[note]
-pub(crate) struct ProcMacroTypeError<'tcx> {
-    #[primary_span]
-    #[label]
-    pub span: Span,
-    pub found: Ty<'tcx>,
-    pub kind: ProcMacroKind,
-    pub expected_signature: &'static str,
-}
-
-#[derive(Diagnostic)]
-#[diag(passes_proc_macro_diff_arg_count)]
-pub(crate) struct ProcMacroDiffArguments {
-    #[primary_span]
-    #[label]
-    pub span: Span,
-    pub count: usize,
-    pub kind: ProcMacroKind,
-    pub expected_signature: &'static str,
-}
-
-#[derive(Diagnostic)]
-#[diag(passes_proc_macro_missing_args)]
-pub(crate) struct ProcMacroMissingArguments {
+#[diag(passes_proc_macro_bad_sig)]
+pub(crate) struct ProcMacroBadSig {
     #[primary_span]
-    #[label]
     pub span: Span,
-    pub expected_input_count: usize,
     pub kind: ProcMacroKind,
-    pub expected_signature: &'static str,
-}
-
-#[derive(Diagnostic)]
-#[diag(passes_proc_macro_invalid_abi)]
-pub(crate) struct ProcMacroInvalidAbi {
-    #[primary_span]
-    pub span: Span,
-    pub abi: &'static str,
-}
-
-#[derive(Diagnostic)]
-#[diag(passes_proc_macro_unsafe)]
-pub(crate) struct ProcMacroUnsafe {
-    #[primary_span]
-    pub span: Span,
 }
 
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index d8b5b25aaee..0154c719ef6 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1153,6 +1153,7 @@ symbols! {
         read_enum_variant_arg,
         read_struct,
         read_struct_field,
+        read_via_copy,
         readonly,
         realloc,
         reason,
diff --git a/config.example.toml b/config.example.toml
index dee0d8f254b..7ae46203f97 100644
--- a/config.example.toml
+++ b/config.example.toml
@@ -146,6 +146,9 @@ changelog-seen = 2
 # Whether to build the clang compiler.
 #clang = false
 
+# Whether to enable llvm compilation warnings.
+#enable-warnings = false
+
 # Custom CMake defines to set when building LLVM.
 #build-config = {}
 
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index c6321587adc..ee8846675ce 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -2020,6 +2020,16 @@ extern "rust-intrinsic" {
     #[rustc_safe_intrinsic]
     pub fn saturating_sub<T: Copy>(a: T, b: T) -> T;
 
+    /// This is an implementation detail of [`crate::ptr::read`] and should
+    /// not be used anywhere else.  See its comments for why this exists.
+    ///
+    /// This intrinsic can *only* be called where the argument is a local without
+    /// projections (`read_via_copy(p)`, not `read_via_copy(*p)`) so that it
+    /// trivially obeys runtime-MIR rules about derefs in operands.
+    #[cfg(not(bootstrap))]
+    #[rustc_const_unstable(feature = "const_ptr_read", issue = "80377")]
+    pub fn read_via_copy<T>(p: *const T) -> T;
+
     /// Returns the value of the discriminant for the variant in 'v';
     /// if `T` has no discriminant, returns `0`.
     ///
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index f41be46abc9..5884a8ca308 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -1135,27 +1135,58 @@ pub const unsafe fn replace<T>(dst: *mut T, mut src: T) -> T {
 #[rustc_const_unstable(feature = "const_ptr_read", issue = "80377")]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
 pub const unsafe fn read<T>(src: *const T) -> T {
-    // We are calling the intrinsics directly to avoid function calls in the generated code
-    // as `intrinsics::copy_nonoverlapping` is a wrapper function.
-    extern "rust-intrinsic" {
-        #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
-        fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
-    }
+    // It would be semantically correct to implement this via `copy_nonoverlapping`
+    // and `MaybeUninit`, as was done before PR #109035. Calling `assume_init`
+    // provides enough information to know that this is a typed operation.
 
-    let mut tmp = MaybeUninit::<T>::uninit();
-    // SAFETY: the caller must guarantee that `src` is valid for reads.
-    // `src` cannot overlap `tmp` because `tmp` was just allocated on
-    // the stack as a separate allocated object.
+    // However, as of March 2023 the compiler was not capable of taking advantage
+    // of that information.  Thus the implementation here switched to an intrinsic,
+    // which lowers to `_0 = *src` in MIR, to address a few issues:
     //
-    // Also, since we just wrote a valid value into `tmp`, it is guaranteed
-    // to be properly initialized.
+    // - Using `MaybeUninit::assume_init` after a `copy_nonoverlapping` was not
+    //   turning the untyped copy into a typed load. As such, the generated
+    //   `load` in LLVM didn't get various metadata, such as `!range` (#73258),
+    //   `!nonnull`, and `!noundef`, resulting in poorer optimization.
+    // - Going through the extra local resulted in multiple extra copies, even
+    //   in optimized MIR.  (Ignoring StorageLive/Dead, the intrinsic is one
+    //   MIR statement, while the previous implementation was eight.)  LLVM
+    //   could sometimes optimize them away, but because `read` is at the core
+    //   of so many things, not having them in the first place improves what we
+    //   hand off to the backend.  For example, `mem::replace::<Big>` previously
+    //   emitted 4 `alloca` and 6 `memcpy`s, but is now 1 `alloc` and 3 `memcpy`s.
+    // - In general, this approach keeps us from getting any more bugs (like
+    //   #106369) that boil down to "`read(p)` is worse than `*p`", as this
+    //   makes them look identical to the backend (or other MIR consumers).
+    //
+    // Future enhancements to MIR optimizations might well allow this to return
+    // to the previous implementation, rather than using an intrinsic.
+
+    // SAFETY: the caller must guarantee that `src` is valid for reads.
     unsafe {
         assert_unsafe_precondition!(
             "ptr::read requires that the pointer argument is aligned and non-null",
             [T](src: *const T) => is_aligned_and_not_null(src)
         );
-        copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
-        tmp.assume_init()
+
+        #[cfg(bootstrap)]
+        {
+            // We are calling the intrinsics directly to avoid function calls in the
+            // generated code as `intrinsics::copy_nonoverlapping` is a wrapper function.
+            extern "rust-intrinsic" {
+                #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
+                fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
+            }
+
+            // `src` cannot overlap `tmp` because `tmp` was just allocated on
+            // the stack as a separate allocated object.
+            let mut tmp = MaybeUninit::<T>::uninit();
+            copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
+            tmp.assume_init()
+        }
+        #[cfg(not(bootstrap))]
+        {
+            crate::intrinsics::read_via_copy(src)
+        }
     }
 }
 
diff --git a/src/bootstrap/CHANGELOG.md b/src/bootstrap/CHANGELOG.md
index 54d0d8a8ec2..654e03d0c3c 100644
--- a/src/bootstrap/CHANGELOG.md
+++ b/src/bootstrap/CHANGELOG.md
@@ -25,6 +25,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 - If you have Rust already installed, `x.py` will now infer the host target
   from the default rust toolchain. [#78513](https://github.com/rust-lang/rust/pull/78513)
 - Add options for enabling overflow checks, one for std (`overflow-checks-std`) and one for everything else (`overflow-checks`). Both default to false.
+- Add llvm option `enable-warnings` to have control on llvm compilation warnings. Default to false.
 
 
 ## [Version 2] - 2020-09-25
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index fc5aa8a245d..58729f396f0 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -133,6 +133,7 @@ pub struct Config {
     pub llvm_allow_old_toolchain: bool,
     pub llvm_polly: bool,
     pub llvm_clang: bool,
+    pub llvm_enable_warnings: bool,
     pub llvm_from_ci: bool,
     pub llvm_build_config: HashMap<String, String>,
 
@@ -688,6 +689,7 @@ define_config! {
         allow_old_toolchain: Option<bool> = "allow-old-toolchain",
         polly: Option<bool> = "polly",
         clang: Option<bool> = "clang",
+        enable_warnings: Option<bool> = "enable-warnings",
         download_ci_llvm: Option<StringOrBool> = "download-ci-llvm",
         build_config: Option<HashMap<String, String>> = "build-config",
     }
@@ -1184,6 +1186,7 @@ impl Config {
             config.llvm_allow_old_toolchain = llvm.allow_old_toolchain.unwrap_or(false);
             config.llvm_polly = llvm.polly.unwrap_or(false);
             config.llvm_clang = llvm.clang.unwrap_or(false);
+            config.llvm_enable_warnings = llvm.enable_warnings.unwrap_or(false);
             config.llvm_build_config = llvm.build_config.clone().unwrap_or(Default::default());
 
             let asserts = llvm_assertions.unwrap_or(false);
diff --git a/src/bootstrap/defaults/config.codegen.toml b/src/bootstrap/defaults/config.codegen.toml
index eb2afa555f1..20b2699c761 100644
--- a/src/bootstrap/defaults/config.codegen.toml
+++ b/src/bootstrap/defaults/config.codegen.toml
@@ -7,6 +7,8 @@ compiler-docs = true
 # This enables debug-assertions in LLVM,
 # catching logic errors in codegen much earlier in the process.
 assertions = true
+# enable warnings during the llvm compilation
+enable-warnings = true
 
 [rust]
 # This enables `RUSTC_LOG=debug`, avoiding confusing situations
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 22ddf872215..f136690592d 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -495,6 +495,7 @@ impl Build {
 
         // Make a symbolic link so we can use a consistent directory in the documentation.
         let build_triple = build.out.join(&build.build.triple);
+        t!(fs::create_dir_all(&build_triple));
         let host = build.out.join("host");
         if let Err(e) = symlink_dir(&build.config, &build_triple, &host) {
             if e.kind() != ErrorKind::AlreadyExists {
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index 040e36ea5f8..41ee5096553 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -304,6 +304,7 @@ impl Step for Llvm {
         let assertions = if builder.config.llvm_assertions { "ON" } else { "OFF" };
         let plugins = if builder.config.llvm_plugins { "ON" } else { "OFF" };
         let enable_tests = if builder.config.llvm_tests { "ON" } else { "OFF" };
+        let enable_warnings = if builder.config.llvm_enable_warnings { "ON" } else { "OFF" };
 
         cfg.out_dir(&out_dir)
             .profile(profile)
@@ -321,7 +322,8 @@ impl Step for Llvm {
             .define("LLVM_ENABLE_Z3_SOLVER", "OFF")
             .define("LLVM_PARALLEL_COMPILE_JOBS", builder.jobs().to_string())
             .define("LLVM_TARGET_ARCH", target_native.split('-').next().unwrap())
-            .define("LLVM_DEFAULT_TARGET_TRIPLE", target_native);
+            .define("LLVM_DEFAULT_TARGET_TRIPLE", target_native)
+            .define("LLVM_ENABLE_WARNINGS", enable_warnings);
 
         // Parts of our test suite rely on the `FileCheck` tool, which is built by default in
         // `build/$TARGET/llvm/build/bin` is but *not* then installed to `build/$TARGET/llvm/bin`.
@@ -483,11 +485,6 @@ impl Step for Llvm {
             cfg.define(key, val);
         }
 
-        // FIXME: we don't actually need to build all LLVM tools and all LLVM
-        //        libraries here, e.g., we just want a few components and a few
-        //        tools. Figure out how to filter them down and only build the right
-        //        tools and libs on all platforms.
-
         if builder.config.dry_run() {
             return res;
         }
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 7d3033d2e59383fd76193daf9423c3d141972a7
+Subproject 4a3c588b1f0a8e2dc8dd8789dbf3b6a71b02ed4
diff --git a/tests/codegen-units/polymorphization/auxiliary/poly-dep.rs b/tests/codegen-units/polymorphization/auxiliary/poly-dep.rs
new file mode 100644
index 00000000000..fdbfa1b096d
--- /dev/null
+++ b/tests/codegen-units/polymorphization/auxiliary/poly-dep.rs
@@ -0,0 +1,4 @@
+// compile-flags: -Zpolymorphize=on
+
+#[inline(never)]
+pub fn foo<T>() {}
diff --git a/tests/codegen-units/polymorphization/poly-foreign.rs b/tests/codegen-units/polymorphization/poly-foreign.rs
new file mode 100644
index 00000000000..9da082daf11
--- /dev/null
+++ b/tests/codegen-units/polymorphization/poly-foreign.rs
@@ -0,0 +1,11 @@
+// aux-build:poly-dep.rs
+// compile-flags: --crate-type=lib -Zprint-mono-items=eager -Zpolymorphize=on
+
+extern crate poly_dep;
+
+pub static FN1: fn() = poly_dep::foo::<i32>;
+pub static FN2: fn() = poly_dep::foo::<u32>;
+
+//~ MONO_ITEM static FN1
+//~ MONO_ITEM static FN2
+//~ MONO_ITEM fn poly_dep::foo::<T>
diff --git a/tests/codegen/issues/issue-106369.rs b/tests/codegen/issues/issue-106369.rs
new file mode 100644
index 00000000000..3fe7be4f144
--- /dev/null
+++ b/tests/codegen/issues/issue-106369.rs
@@ -0,0 +1,15 @@
+// compile-flags: -O
+// ignore-debug (the extra assertions get in the way)
+
+#![crate_type = "lib"]
+
+// From <https://github.com/rust-lang/rust/issues/106369#issuecomment-1369095304>
+
+// CHECK-LABEL: @issue_106369(
+#[no_mangle]
+pub unsafe fn issue_106369(ptr: *const &i32) -> bool {
+    // CHECK-NOT: icmp
+    // CHECK: ret i1 true
+    // CHECK-NOT: icmp
+    Some(std::ptr::read(ptr)).is_some()
+}
diff --git a/tests/codegen/issues/issue-73258.rs b/tests/codegen/issues/issue-73258.rs
new file mode 100644
index 00000000000..0134f929b29
--- /dev/null
+++ b/tests/codegen/issues/issue-73258.rs
@@ -0,0 +1,38 @@
+// compile-flags: -O
+// ignore-debug (the extra assertions get in the way)
+
+#![crate_type = "lib"]
+
+// Adapted from <https://github.com/rust-lang/rust/issues/73258#issue-637346014>
+
+#[derive(Clone, Copy)]
+#[repr(u8)]
+pub enum Foo {
+    A, B, C, D,
+}
+
+// CHECK-LABEL: @issue_73258(
+#[no_mangle]
+pub unsafe fn issue_73258(ptr: *const Foo) -> Foo {
+    // CHECK-NOT: icmp
+    // CHECK-NOT: call
+    // CHECK-NOT: br
+    // CHECK-NOT: select
+
+    // CHECK: %[[R:.+]] = load i8
+    // CHECK-SAME: !range !
+
+    // CHECK-NOT: icmp
+    // CHECK-NOT: call
+    // CHECK-NOT: br
+    // CHECK-NOT: select
+
+    // CHECK: ret i8 %[[R]]
+
+    // CHECK-NOT: icmp
+    // CHECK-NOT: call
+    // CHECK-NOT: br
+    // CHECK-NOT: select
+    let k: Option<Foo> = Some(ptr.read());
+    return k.unwrap();
+}
diff --git a/tests/codegen/mem-replace-big-type.rs b/tests/codegen/mem-replace-big-type.rs
new file mode 100644
index 00000000000..f6898e2f758
--- /dev/null
+++ b/tests/codegen/mem-replace-big-type.rs
@@ -0,0 +1,36 @@
+// This test ensures that `mem::replace::<T>` only ever calls `@llvm.memcpy`
+// with `size_of::<T>()` as the size, and never goes through any wrapper that
+// may e.g. multiply `size_of::<T>()` with a variable "count" (which is only
+// known to be `1` after inlining).
+
+// compile-flags: -C no-prepopulate-passes -Zinline-mir=no
+// ignore-debug: the debug assertions get in the way
+
+#![crate_type = "lib"]
+
+#[repr(C, align(8))]
+pub struct Big([u64; 7]);
+pub fn replace_big(dst: &mut Big, src: Big) -> Big {
+    // Before the `read_via_copy` intrinsic, this emitted six `memcpy`s.
+    std::mem::replace(dst, src)
+}
+
+// NOTE(eddyb) the `CHECK-NOT`s ensure that the only calls of `@llvm.memcpy` in
+// the entire output, are the direct calls we want, from `ptr::replace`.
+
+// CHECK-NOT: call void @llvm.memcpy
+
+// For a large type, we expect exactly three `memcpy`s
+// CHECK-LABEL: define internal void @{{.+}}mem{{.+}}replace{{.+}}sret(%Big)
+    // CHECK-NOT: alloca
+    // CHECK: alloca %Big
+    // CHECK-NOT: alloca
+    // CHECK-NOT: call void @llvm.memcpy
+    // CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 8 %{{.*}}, {{i8\*|ptr}} align 8 %{{.*}}, i{{.*}} 56, i1 false)
+    // CHECK-NOT: call void @llvm.memcpy
+    // CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 8 %{{.*}}, {{i8\*|ptr}} align 8 %{{.*}}, i{{.*}} 56, i1 false)
+    // CHECK-NOT: call void @llvm.memcpy
+    // CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 8 %{{.*}}, {{i8\*|ptr}} align 8 %{{.*}}, i{{.*}} 56, i1 false)
+    // CHECK-NOT: call void @llvm.memcpy
+
+// CHECK-NOT: call void @llvm.memcpy
diff --git a/tests/codegen/mem-replace-direct-memcpy.rs b/tests/codegen/mem-replace-direct-memcpy.rs
index e8bbf0e1bbd..83babab4f84 100644
--- a/tests/codegen/mem-replace-direct-memcpy.rs
+++ b/tests/codegen/mem-replace-direct-memcpy.rs
@@ -13,12 +13,21 @@ pub fn replace_byte(dst: &mut u8, src: u8) -> u8 {
 }
 
 // NOTE(eddyb) the `CHECK-NOT`s ensure that the only calls of `@llvm.memcpy` in
-// the entire output, are the two direct calls we want, from `ptr::replace`.
+// the entire output, are the direct calls we want, from `ptr::replace`.
 
 // CHECK-NOT: call void @llvm.memcpy
-// CHECK: ; core::mem::replace
-// CHECK-NOT: call void @llvm.memcpy
-// CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 1 %{{.*}}, {{i8\*|ptr}} align 1 %{{.*}}, i{{.*}} 1, i1 false)
-// CHECK-NOT: call void @llvm.memcpy
-// CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 1 %{{.*}}, {{i8\*|ptr}} align 1 %{{.*}}, i{{.*}} 1, i1 false)
+
+// For a small type, we expect one each of `load`/`store`/`memcpy` instead
+// CHECK-LABEL: define internal noundef i8 @{{.+}}mem{{.+}}replace
+    // CHECK-NOT: alloca
+    // CHECK: alloca i8
+    // CHECK-NOT: alloca
+    // CHECK-NOT: call void @llvm.memcpy
+    // CHECK: load i8
+    // CHECK-NOT: call void @llvm.memcpy
+    // CHECK: store i8
+    // CHECK-NOT: call void @llvm.memcpy
+    // CHECK: call void @llvm.memcpy.{{.+}}({{i8\*|ptr}} align 1 %{{.*}}, {{i8\*|ptr}} align 1 %{{.*}}, i{{.*}} 1, i1 false)
+    // CHECK-NOT: call void @llvm.memcpy
+
 // CHECK-NOT: call void @llvm.memcpy
diff --git a/tests/codegen/ptr-read-metadata.rs b/tests/codegen/ptr-read-metadata.rs
new file mode 100644
index 00000000000..e1e3272662c
--- /dev/null
+++ b/tests/codegen/ptr-read-metadata.rs
@@ -0,0 +1,96 @@
+// compile-flags: -O -Z merge-functions=disabled
+// no-system-llvm
+// ignore-debug (the extra assertions get in the way)
+
+#![crate_type = "lib"]
+
+// Ensure that various forms of reading pointers correctly annotate the `load`s
+// with `!noundef` and `!range` metadata to enable extra optimization.
+
+use std::mem::MaybeUninit;
+
+// CHECK-LABEL: define noundef i8 @copy_byte(
+#[no_mangle]
+pub unsafe fn copy_byte(p: *const u8) -> u8 {
+    // CHECK-NOT: load
+    // CHECK: load i8, ptr %p, align 1
+    // CHECK-SAME: !noundef !
+    // CHECK-NOT: load
+    *p
+}
+
+// CHECK-LABEL: define noundef i8 @read_byte(
+#[no_mangle]
+pub unsafe fn read_byte(p: *const u8) -> u8 {
+    // CHECK-NOT: load
+    // CHECK: load i8, ptr %p, align 1
+    // CHECK-SAME: !noundef !
+    // CHECK-NOT: load
+    p.read()
+}
+
+// CHECK-LABEL: define i8 @read_byte_maybe_uninit(
+#[no_mangle]
+pub unsafe fn read_byte_maybe_uninit(p: *const MaybeUninit<u8>) -> MaybeUninit<u8> {
+    // CHECK-NOT: load
+    // CHECK: load i8, ptr %p, align 1
+    // CHECK-NOT: noundef
+    // CHECK-NOT: load
+    p.read()
+}
+
+// CHECK-LABEL: define noundef i8 @read_byte_assume_init(
+#[no_mangle]
+pub unsafe fn read_byte_assume_init(p: &MaybeUninit<u8>) -> u8 {
+    // CHECK-NOT: load
+    // CHECK: load i8, ptr %p, align 1
+    // CHECK-SAME: !noundef !
+    // CHECK-NOT: load
+    p.assume_init_read()
+}
+
+// CHECK-LABEL: define noundef i32 @copy_char(
+#[no_mangle]
+pub unsafe fn copy_char(p: *const char) -> char {
+    // CHECK-NOT: load
+    // CHECK: load i32, ptr %p
+    // CHECK-SAME: !range ![[RANGE:[0-9]+]]
+    // CHECK-SAME: !noundef !
+    // CHECK-NOT: load
+    *p
+}
+
+// CHECK-LABEL: define noundef i32 @read_char(
+#[no_mangle]
+pub unsafe fn read_char(p: *const char) -> char {
+    // CHECK-NOT: load
+    // CHECK: load i32, ptr %p
+    // CHECK-SAME: !range ![[RANGE]]
+    // CHECK-SAME: !noundef !
+    // CHECK-NOT: load
+    p.read()
+}
+
+// CHECK-LABEL: define i32 @read_char_maybe_uninit(
+#[no_mangle]
+pub unsafe fn read_char_maybe_uninit(p: *const MaybeUninit<char>) -> MaybeUninit<char> {
+    // CHECK-NOT: load
+    // CHECK: load i32, ptr %p
+    // CHECK-NOT: range
+    // CHECK-NOT: noundef
+    // CHECK-NOT: load
+    p.read()
+}
+
+// CHECK-LABEL: define noundef i32 @read_char_assume_init(
+#[no_mangle]
+pub unsafe fn read_char_assume_init(p: &MaybeUninit<char>) -> char {
+    // CHECK-NOT: load
+    // CHECK: load i32, ptr %p
+    // CHECK-SAME: !range ![[RANGE]]
+    // CHECK-SAME: !noundef !
+    // CHECK-NOT: load
+    p.assume_init_read()
+}
+
+// CHECK: ![[RANGE]] = !{i32 0, i32 1114112}
diff --git a/tests/mir-opt/lower_intrinsics.read_via_copy_primitive.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.read_via_copy_primitive.LowerIntrinsics.diff
new file mode 100644
index 00000000000..27fceeedf6e
--- /dev/null
+++ b/tests/mir-opt/lower_intrinsics.read_via_copy_primitive.LowerIntrinsics.diff
@@ -0,0 +1,27 @@
+- // MIR for `read_via_copy_primitive` before LowerIntrinsics
++ // MIR for `read_via_copy_primitive` after LowerIntrinsics
+  
+  fn read_via_copy_primitive(_1: &i32) -> i32 {
+      debug r => _1;                       // in scope 0 at $DIR/lower_intrinsics.rs:+0:32: +0:33
+      let mut _0: i32;                     // return place in scope 0 at $DIR/lower_intrinsics.rs:+0:44: +0:47
+      let mut _2: *const i32;              // in scope 0 at $DIR/lower_intrinsics.rs:+1:46: +1:47
+      scope 1 {
+      }
+  
+      bb0: {
+          StorageLive(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:+1:46: +1:47
+          _2 = &raw const (*_1);           // scope 1 at $DIR/lower_intrinsics.rs:+1:46: +1:47
+-         _0 = read_via_copy::<i32>(move _2) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:48
+-                                          // mir::Constant
+-                                          // + span: $DIR/lower_intrinsics.rs:85:14: 85:45
+-                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(*const i32) -> i32 {read_via_copy::<i32>}, val: Value(<ZST>) }
++         _0 = (*_2);                      // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:48
++         goto -> bb1;                     // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:48
+      }
+  
+      bb1: {
+          StorageDead(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:+1:47: +1:48
+          return;                          // scope 0 at $DIR/lower_intrinsics.rs:+2:2: +2:2
+      }
+  }
+  
diff --git a/tests/mir-opt/lower_intrinsics.read_via_copy_uninhabited.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.read_via_copy_uninhabited.LowerIntrinsics.diff
new file mode 100644
index 00000000000..610c67d2fec
--- /dev/null
+++ b/tests/mir-opt/lower_intrinsics.read_via_copy_uninhabited.LowerIntrinsics.diff
@@ -0,0 +1,21 @@
+- // MIR for `read_via_copy_uninhabited` before LowerIntrinsics
++ // MIR for `read_via_copy_uninhabited` after LowerIntrinsics
+  
+  fn read_via_copy_uninhabited(_1: &Never) -> Never {
+      debug r => _1;                       // in scope 0 at $DIR/lower_intrinsics.rs:+0:34: +0:35
+      let mut _0: Never;                   // return place in scope 0 at $DIR/lower_intrinsics.rs:+0:48: +0:53
+      let mut _2: *const Never;            // in scope 0 at $DIR/lower_intrinsics.rs:+1:46: +1:47
+      scope 1 {
+      }
+  
+      bb0: {
+          StorageLive(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:+1:46: +1:47
+          _2 = &raw const (*_1);           // scope 1 at $DIR/lower_intrinsics.rs:+1:46: +1:47
+-         _0 = read_via_copy::<Never>(move _2); // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:48
+-                                          // mir::Constant
+-                                          // + span: $DIR/lower_intrinsics.rs:90:14: 90:45
+-                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(*const Never) -> Never {read_via_copy::<Never>}, val: Value(<ZST>) }
++         unreachable;                     // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:48
+      }
+  }
+  
diff --git a/tests/mir-opt/lower_intrinsics.rs b/tests/mir-opt/lower_intrinsics.rs
index 7147be43ca5..a0a1df4e5ca 100644
--- a/tests/mir-opt/lower_intrinsics.rs
+++ b/tests/mir-opt/lower_intrinsics.rs
@@ -79,3 +79,15 @@ pub fn with_overflow(a: i32, b: i32) {
     let _y = core::intrinsics::sub_with_overflow(a, b);
     let _z = core::intrinsics::mul_with_overflow(a, b);
 }
+
+// EMIT_MIR lower_intrinsics.read_via_copy_primitive.LowerIntrinsics.diff
+pub fn read_via_copy_primitive(r: &i32) -> i32 {
+    unsafe { core::intrinsics::read_via_copy(r) }
+}
+
+// EMIT_MIR lower_intrinsics.read_via_copy_uninhabited.LowerIntrinsics.diff
+pub fn read_via_copy_uninhabited(r: &Never) -> Never {
+    unsafe { core::intrinsics::read_via_copy(r) }
+}
+
+pub enum Never {}
diff --git a/tests/ui/const-ptr/out_of_bounds_read.stderr b/tests/ui/const-ptr/out_of_bounds_read.stderr
index 3e7b09a5982..89536f53f08 100644
--- a/tests/ui/const-ptr/out_of_bounds_read.stderr
+++ b/tests/ui/const-ptr/out_of_bounds_read.stderr
@@ -1,7 +1,7 @@
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |
-   = note: memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
+   = note: dereferencing pointer failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
    |
 note: inside `std::ptr::read::<u32>`
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
@@ -14,7 +14,7 @@ LL |     const _READ: u32 = unsafe { ptr::read(PAST_END_PTR) };
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |
-   = note: memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
+   = note: dereferencing pointer failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
    |
 note: inside `std::ptr::read::<u32>`
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
@@ -29,7 +29,7 @@ LL |     const _CONST_READ: u32 = unsafe { PAST_END_PTR.read() };
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |
-   = note: memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
+   = note: dereferencing pointer failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
    |
 note: inside `std::ptr::read::<u32>`
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
diff --git a/tests/ui/consts/const-eval/ub-ref-ptr.stderr b/tests/ui/consts/const-eval/ub-ref-ptr.stderr
index 6bd367b6469..080568b51ef 100644
--- a/tests/ui/consts/const-eval/ub-ref-ptr.stderr
+++ b/tests/ui/consts/const-eval/ub-ref-ptr.stderr
@@ -148,11 +148,11 @@ LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) };
                HEX_DUMP
            }
 
-error: accessing memory with alignment 1, but alignment 4 is required
+error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #68585 <https://github.com/rust-lang/rust/issues/104616>
+   = note: accessing memory with alignment 1, but alignment 4 is required
+   |
 note: inside `std::ptr::read::<u32>`
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
 note: inside `ptr::const_ptr::<impl *const u32>::read`
@@ -162,25 +162,7 @@ note: inside `UNALIGNED_READ`
    |
 LL |     ptr.read();
    |     ^^^^^^^^^^
-   = note: `#[deny(invalid_alignment)]` on by default
 
 error: aborting due to 15 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
-Future incompatibility report: Future breakage diagnostic:
-error: accessing memory with alignment 1, but alignment 4 is required
-  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #68585 <https://github.com/rust-lang/rust/issues/104616>
-note: inside `std::ptr::read::<u32>`
-  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-note: inside `ptr::const_ptr::<impl *const u32>::read`
-  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-note: inside `UNALIGNED_READ`
-  --> $DIR/ub-ref-ptr.rs:67:5
-   |
-LL |     ptr.read();
-   |     ^^^^^^^^^^
-   = note: `#[deny(invalid_alignment)]` on by default
-
diff --git a/tests/ui/consts/issue-miri-1910.stderr b/tests/ui/consts/issue-miri-1910.stderr
index 61865b1dad7..a10eea9de11 100644
--- a/tests/ui/consts/issue-miri-1910.stderr
+++ b/tests/ui/consts/issue-miri-1910.stderr
@@ -1,7 +1,7 @@
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |
-   = note: unable to copy parts of a pointer from memory at ALLOC
+   = note: unable to turn pointer into raw bytes
    |
    = help: this code performed an operation that depends on the underlying bytes representing a pointer
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
diff --git a/tests/ui/lint/issue-109152.rs b/tests/ui/lint/issue-109152.rs
new file mode 100644
index 00000000000..daf530e6d0b
--- /dev/null
+++ b/tests/ui/lint/issue-109152.rs
@@ -0,0 +1,7 @@
+#![deny(map_unit_fn)]
+
+#![crate_type = "lib"]
+fn _y() {
+    vec![42].iter().map(drop);
+    //~^ ERROR `Iterator::map` call that discard the iterator's values
+}
diff --git a/tests/ui/lint/issue-109152.stderr b/tests/ui/lint/issue-109152.stderr
new file mode 100644
index 00000000000..7db9e71a584
--- /dev/null
+++ b/tests/ui/lint/issue-109152.stderr
@@ -0,0 +1,23 @@
+error: `Iterator::map` call that discard the iterator's values
+  --> $DIR/issue-109152.rs:5:21
+   |
+LL |     vec![42].iter().map(drop);
+   |                     ^^^^----^
+   |                     |   |
+   |                     |   this function returns `()`, which is likely not what you wanted
+   |                     |   called `Iterator::map` with callable that returns `()`
+   |                     after this call to map, the resulting iterator is `impl Iterator<Item = ()>`, which means the only information carried by the iterator is the number of items
+   |
+   = note: `Iterator::map`, like many of the methods on `Iterator`, gets executed lazily, meaning that its effects won't be visible until it is iterated
+note: the lint level is defined here
+  --> $DIR/issue-109152.rs:1:9
+   |
+LL | #![deny(map_unit_fn)]
+   |         ^^^^^^^^^^^
+help: you might have meant to use `Iterator::for_each`
+   |
+LL |     vec![42].iter().for_each(drop);
+   |                     ~~~~~~~~
+
+error: aborting due to previous error
+
diff --git a/tests/ui/proc-macro/bad-projection.rs b/tests/ui/proc-macro/bad-projection.rs
new file mode 100644
index 00000000000..d214c7ac8b2
--- /dev/null
+++ b/tests/ui/proc-macro/bad-projection.rs
@@ -0,0 +1,15 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+#![allow(warnings)]
+
+extern crate proc_macro;
+
+trait Project {
+    type Assoc;
+}
+
+#[proc_macro]
+pub fn uwu() -> <() as Project>::Assoc {}
+//~^ ERROR the trait bound `(): Project` is not satisfied
diff --git a/tests/ui/proc-macro/bad-projection.stderr b/tests/ui/proc-macro/bad-projection.stderr
new file mode 100644
index 00000000000..8a8246376fe
--- /dev/null
+++ b/tests/ui/proc-macro/bad-projection.stderr
@@ -0,0 +1,9 @@
+error[E0277]: the trait bound `(): Project` is not satisfied
+  --> $DIR/bad-projection.rs:14:17
+   |
+LL | pub fn uwu() -> <() as Project>::Assoc {}
+   |                 ^^^^^^^^^^^^^^^^^^^^^^ the trait `Project` is not implemented for `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/proc-macro/proc-macro-abi.rs b/tests/ui/proc-macro/proc-macro-abi.rs
index 873660a5b3a..93a613e8b8f 100644
--- a/tests/ui/proc-macro/proc-macro-abi.rs
+++ b/tests/ui/proc-macro/proc-macro-abi.rs
@@ -9,19 +9,19 @@ use proc_macro::TokenStream;
 
 #[proc_macro]
 pub extern "C" fn abi(a: TokenStream) -> TokenStream {
-    //~^ ERROR proc macro functions may not be `extern "C"`
+    //~^ ERROR function-like proc macro has incorrect signature
     a
 }
 
 #[proc_macro]
 pub extern "system" fn abi2(a: TokenStream) -> TokenStream {
-    //~^ ERROR proc macro functions may not be `extern "system"`
+    //~^ ERROR function-like proc macro has incorrect signature
     a
 }
 
 #[proc_macro]
 pub extern fn abi3(a: TokenStream) -> TokenStream {
-    //~^ ERROR proc macro functions may not be `extern "C"`
+    //~^ ERROR function-like proc macro has incorrect signature
     a
 }
 
diff --git a/tests/ui/proc-macro/proc-macro-abi.stderr b/tests/ui/proc-macro/proc-macro-abi.stderr
index 9a781be0996..ccc72e5187e 100644
--- a/tests/ui/proc-macro/proc-macro-abi.stderr
+++ b/tests/ui/proc-macro/proc-macro-abi.stderr
@@ -1,20 +1,29 @@
-error: proc macro functions may not be `extern "C"`
+error: function-like proc macro has incorrect signature
   --> $DIR/proc-macro-abi.rs:11:1
    |
 LL | pub extern "C" fn abi(a: TokenStream) -> TokenStream {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected "Rust" fn, found "C" fn
+   |
+   = note: expected signature `fn(proc_macro::TokenStream) -> proc_macro::TokenStream`
+              found signature `extern "C" fn(proc_macro::TokenStream) -> proc_macro::TokenStream`
 
-error: proc macro functions may not be `extern "system"`
+error: function-like proc macro has incorrect signature
   --> $DIR/proc-macro-abi.rs:17:1
    |
 LL | pub extern "system" fn abi2(a: TokenStream) -> TokenStream {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected "Rust" fn, found "system" fn
+   |
+   = note: expected signature `fn(proc_macro::TokenStream) -> proc_macro::TokenStream`
+              found signature `extern "system" fn(proc_macro::TokenStream) -> proc_macro::TokenStream`
 
-error: proc macro functions may not be `extern "C"`
+error: function-like proc macro has incorrect signature
   --> $DIR/proc-macro-abi.rs:23:1
    |
 LL | pub extern fn abi3(a: TokenStream) -> TokenStream {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected "Rust" fn, found "C" fn
+   |
+   = note: expected signature `fn(proc_macro::TokenStream) -> proc_macro::TokenStream`
+              found signature `extern "C" fn(proc_macro::TokenStream) -> proc_macro::TokenStream`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/proc-macro/signature-proc-macro-attribute.rs b/tests/ui/proc-macro/signature-proc-macro-attribute.rs
index 51abc8e7d3e..fb48f748ce0 100644
--- a/tests/ui/proc-macro/signature-proc-macro-attribute.rs
+++ b/tests/ui/proc-macro/signature-proc-macro-attribute.rs
@@ -8,25 +8,23 @@ use proc_macro::TokenStream;
 
 #[proc_macro_attribute]
 pub fn bad_input(input: String) -> TokenStream {
-    //~^ ERROR mismatched attribute proc macro signature
+    //~^ ERROR attribute proc macro has incorrect signature
     ::proc_macro::TokenStream::new()
 }
 
 #[proc_macro_attribute]
 pub fn bad_output(input: TokenStream) -> String {
-    //~^ ERROR mismatched attribute proc macro signature
-    //~| ERROR mismatched attribute proc macro signature
+    //~^ ERROR attribute proc macro has incorrect signature
     String::from("blah")
 }
 
 #[proc_macro_attribute]
 pub fn bad_everything(input: String) -> String {
-    //~^ ERROR mismatched attribute proc macro signature
-    //~| ERROR mismatched attribute proc macro signature
+    //~^ ERROR attribute proc macro has incorrect signature
     input
 }
 
 #[proc_macro_attribute]
 pub fn too_many(a: TokenStream, b: TokenStream, c: String) -> TokenStream {
-    //~^ ERROR mismatched attribute proc macro signature
+    //~^ ERROR attribute proc macro has incorrect signature
 }
diff --git a/tests/ui/proc-macro/signature-proc-macro-attribute.stderr b/tests/ui/proc-macro/signature-proc-macro-attribute.stderr
index abf7a6f3ce9..ce832eaa5c7 100644
--- a/tests/ui/proc-macro/signature-proc-macro-attribute.stderr
+++ b/tests/ui/proc-macro/signature-proc-macro-attribute.stderr
@@ -1,42 +1,38 @@
-error: mismatched attribute proc macro signature
+error: attribute proc macro has incorrect signature
   --> $DIR/signature-proc-macro-attribute.rs:10:1
    |
 LL | pub fn bad_input(input: String) -> TokenStream {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attribute proc macro must have two arguments of type `proc_macro::TokenStream`
-
-error: mismatched attribute proc macro signature
-  --> $DIR/signature-proc-macro-attribute.rs:16:42
-   |
-LL | pub fn bad_output(input: TokenStream) -> String {
-   |                                          ^^^^^^ found std::string::String, expected type `proc_macro::TokenStream`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters
    |
-   = note: attribute proc macros must have a signature of `fn(TokenStream, TokenStream) -> TokenStream`
+   = note: expected signature `fn(proc_macro::TokenStream, proc_macro::TokenStream) -> proc_macro::TokenStream`
+              found signature `fn(std::string::String) -> proc_macro::TokenStream`
 
-error: mismatched attribute proc macro signature
+error: attribute proc macro has incorrect signature
   --> $DIR/signature-proc-macro-attribute.rs:16:1
    |
 LL | pub fn bad_output(input: TokenStream) -> String {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attribute proc macro must have two arguments of type `proc_macro::TokenStream`
-
-error: mismatched attribute proc macro signature
-  --> $DIR/signature-proc-macro-attribute.rs:23:41
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters
    |
-LL | pub fn bad_everything(input: String) -> String {
-   |                                         ^^^^^^ found std::string::String, expected type `proc_macro::TokenStream`
-   |
-   = note: attribute proc macros must have a signature of `fn(TokenStream, TokenStream) -> TokenStream`
+   = note: expected signature `fn(proc_macro::TokenStream, proc_macro::TokenStream) -> proc_macro::TokenStream`
+              found signature `fn(proc_macro::TokenStream) -> std::string::String`
 
-error: mismatched attribute proc macro signature
-  --> $DIR/signature-proc-macro-attribute.rs:23:1
+error: attribute proc macro has incorrect signature
+  --> $DIR/signature-proc-macro-attribute.rs:22:1
    |
 LL | pub fn bad_everything(input: String) -> String {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attribute proc macro must have two arguments of type `proc_macro::TokenStream`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters
+   |
+   = note: expected signature `fn(proc_macro::TokenStream, proc_macro::TokenStream) -> proc_macro::TokenStream`
+              found signature `fn(std::string::String) -> std::string::String`
 
-error: mismatched attribute proc macro signature
-  --> $DIR/signature-proc-macro-attribute.rs:30:49
+error: attribute proc macro has incorrect signature
+  --> $DIR/signature-proc-macro-attribute.rs:28:52
    |
 LL | pub fn too_many(a: TokenStream, b: TokenStream, c: String) -> TokenStream {
-   |                                                 ^^^^^^^^^ found unexpected argument
+   |                                                    ^^^^^^ incorrect number of function parameters
+   |
+   = note: expected signature `fn(proc_macro::TokenStream, proc_macro::TokenStream) -> proc_macro::TokenStream`
+              found signature `fn(proc_macro::TokenStream, proc_macro::TokenStream, std::string::String) -> proc_macro::TokenStream`
 
-error: aborting due to 6 previous errors
+error: aborting due to 4 previous errors
 
diff --git a/tests/ui/proc-macro/signature-proc-macro-derive.rs b/tests/ui/proc-macro/signature-proc-macro-derive.rs
index f2fd824b675..d294b159127 100644
--- a/tests/ui/proc-macro/signature-proc-macro-derive.rs
+++ b/tests/ui/proc-macro/signature-proc-macro-derive.rs
@@ -8,24 +8,23 @@ use proc_macro::TokenStream;
 
 #[proc_macro_derive(Blah)]
 pub fn bad_input(input: String) -> TokenStream {
-    //~^ ERROR mismatched derive proc macro signature
+    //~^ ERROR derive proc macro has incorrect signature
     TokenStream::new()
 }
 
 #[proc_macro_derive(Bleh)]
 pub fn bad_output(input: TokenStream) -> String {
-    //~^ ERROR mismatched derive proc macro signature
+    //~^ ERROR derive proc macro has incorrect signature
     String::from("blah")
 }
 
 #[proc_macro_derive(Bluh)]
 pub fn bad_everything(input: String) -> String {
-    //~^ ERROR mismatched derive proc macro signature
-    //~| ERROR mismatched derive proc macro signature
+    //~^ ERROR derive proc macro has incorrect signature
     input
 }
 
 #[proc_macro_derive(Blih)]
 pub fn too_many(a: TokenStream, b: TokenStream, c: String) -> TokenStream {
-    //~^ ERROR mismatched derive proc macro signature
+    //~^ ERROR derive proc macro has incorrect signature
 }
diff --git a/tests/ui/proc-macro/signature-proc-macro-derive.stderr b/tests/ui/proc-macro/signature-proc-macro-derive.stderr
index a358ae27703..03c6abad17d 100644
--- a/tests/ui/proc-macro/signature-proc-macro-derive.stderr
+++ b/tests/ui/proc-macro/signature-proc-macro-derive.stderr
@@ -1,40 +1,38 @@
-error: mismatched derive proc macro signature
+error: derive proc macro has incorrect signature
   --> $DIR/signature-proc-macro-derive.rs:10:25
    |
 LL | pub fn bad_input(input: String) -> TokenStream {
-   |                         ^^^^^^ found std::string::String, expected type `proc_macro::TokenStream`
+   |                         ^^^^^^ expected `proc_macro::TokenStream`, found `std::string::String`
    |
-   = note: derive proc macros must have a signature of `fn(TokenStream) -> TokenStream`
+   = note: expected signature `fn(proc_macro::TokenStream) -> proc_macro::TokenStream`
+              found signature `fn(std::string::String) -> proc_macro::TokenStream`
 
-error: mismatched derive proc macro signature
+error: derive proc macro has incorrect signature
   --> $DIR/signature-proc-macro-derive.rs:16:42
    |
 LL | pub fn bad_output(input: TokenStream) -> String {
-   |                                          ^^^^^^ found std::string::String, expected type `proc_macro::TokenStream`
+   |                                          ^^^^^^ expected `proc_macro::TokenStream`, found `std::string::String`
    |
-   = note: derive proc macros must have a signature of `fn(TokenStream) -> TokenStream`
+   = note: expected signature `fn(proc_macro::TokenStream) -> proc_macro::TokenStream`
+              found signature `fn(proc_macro::TokenStream) -> std::string::String`
 
-error: mismatched derive proc macro signature
-  --> $DIR/signature-proc-macro-derive.rs:22:41
-   |
-LL | pub fn bad_everything(input: String) -> String {
-   |                                         ^^^^^^ found std::string::String, expected type `proc_macro::TokenStream`
-   |
-   = note: derive proc macros must have a signature of `fn(TokenStream) -> TokenStream`
-
-error: mismatched derive proc macro signature
+error: derive proc macro has incorrect signature
   --> $DIR/signature-proc-macro-derive.rs:22:30
    |
 LL | pub fn bad_everything(input: String) -> String {
-   |                              ^^^^^^ found std::string::String, expected type `proc_macro::TokenStream`
+   |                              ^^^^^^ expected `proc_macro::TokenStream`, found `std::string::String`
    |
-   = note: derive proc macros must have a signature of `fn(TokenStream) -> TokenStream`
+   = note: expected signature `fn(proc_macro::TokenStream) -> proc_macro::TokenStream`
+              found signature `fn(std::string::String) -> std::string::String`
 
-error: mismatched derive proc macro signature
-  --> $DIR/signature-proc-macro-derive.rs:29:33
+error: derive proc macro has incorrect signature
+  --> $DIR/signature-proc-macro-derive.rs:28:36
    |
 LL | pub fn too_many(a: TokenStream, b: TokenStream, c: String) -> TokenStream {
-   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^ found unexpected arguments
+   |                                    ^^^^^^^^^^^ incorrect number of function parameters
+   |
+   = note: expected signature `fn(proc_macro::TokenStream) -> proc_macro::TokenStream`
+              found signature `fn(proc_macro::TokenStream, proc_macro::TokenStream, std::string::String) -> proc_macro::TokenStream`
 
-error: aborting due to 5 previous errors
+error: aborting due to 4 previous errors
 
diff --git a/tests/ui/proc-macro/signature-proc-macro.rs b/tests/ui/proc-macro/signature-proc-macro.rs
index 54770aacd1a..ca2509ed84b 100644
--- a/tests/ui/proc-macro/signature-proc-macro.rs
+++ b/tests/ui/proc-macro/signature-proc-macro.rs
@@ -8,24 +8,23 @@ use proc_macro::TokenStream;
 
 #[proc_macro]
 pub fn bad_input(input: String) -> TokenStream {
-    //~^ ERROR mismatched function-like proc macro signature
+    //~^ ERROR function-like proc macro has incorrect signature
     ::proc_macro::TokenStream::new()
 }
 
 #[proc_macro]
 pub fn bad_output(input: TokenStream) -> String {
-    //~^ ERROR mismatched function-like proc macro signature
+    //~^ ERROR function-like proc macro has incorrect signature
     String::from("blah")
 }
 
 #[proc_macro]
 pub fn bad_everything(input: String) -> String {
-    //~^ ERROR mismatched function-like proc macro signature
-    //~| ERROR mismatched function-like proc macro signature
+    //~^ ERROR function-like proc macro has incorrect signature
     input
 }
 
 #[proc_macro]
 pub fn too_many(a: TokenStream, b: TokenStream, c: String) -> TokenStream {
-    //~^ ERROR mismatched function-like proc macro signature
+    //~^ ERROR function-like proc macro has incorrect signature
 }
diff --git a/tests/ui/proc-macro/signature-proc-macro.stderr b/tests/ui/proc-macro/signature-proc-macro.stderr
index 4b14a54e675..dd2cb0570da 100644
--- a/tests/ui/proc-macro/signature-proc-macro.stderr
+++ b/tests/ui/proc-macro/signature-proc-macro.stderr
@@ -1,40 +1,38 @@
-error: mismatched function-like proc macro signature
+error: function-like proc macro has incorrect signature
   --> $DIR/signature-proc-macro.rs:10:25
    |
 LL | pub fn bad_input(input: String) -> TokenStream {
-   |                         ^^^^^^ found std::string::String, expected type `proc_macro::TokenStream`
+   |                         ^^^^^^ expected `proc_macro::TokenStream`, found `std::string::String`
    |
-   = note: function-like proc macros must have a signature of `fn(TokenStream) -> TokenStream`
+   = note: expected signature `fn(proc_macro::TokenStream) -> proc_macro::TokenStream`
+              found signature `fn(std::string::String) -> proc_macro::TokenStream`
 
-error: mismatched function-like proc macro signature
+error: function-like proc macro has incorrect signature
   --> $DIR/signature-proc-macro.rs:16:42
    |
 LL | pub fn bad_output(input: TokenStream) -> String {
-   |                                          ^^^^^^ found std::string::String, expected type `proc_macro::TokenStream`
+   |                                          ^^^^^^ expected `proc_macro::TokenStream`, found `std::string::String`
    |
-   = note: function-like proc macros must have a signature of `fn(TokenStream) -> TokenStream`
+   = note: expected signature `fn(proc_macro::TokenStream) -> proc_macro::TokenStream`
+              found signature `fn(proc_macro::TokenStream) -> std::string::String`
 
-error: mismatched function-like proc macro signature
-  --> $DIR/signature-proc-macro.rs:22:41
-   |
-LL | pub fn bad_everything(input: String) -> String {
-   |                                         ^^^^^^ found std::string::String, expected type `proc_macro::TokenStream`
-   |
-   = note: function-like proc macros must have a signature of `fn(TokenStream) -> TokenStream`
-
-error: mismatched function-like proc macro signature
+error: function-like proc macro has incorrect signature
   --> $DIR/signature-proc-macro.rs:22:30
    |
 LL | pub fn bad_everything(input: String) -> String {
-   |                              ^^^^^^ found std::string::String, expected type `proc_macro::TokenStream`
+   |                              ^^^^^^ expected `proc_macro::TokenStream`, found `std::string::String`
    |
-   = note: function-like proc macros must have a signature of `fn(TokenStream) -> TokenStream`
+   = note: expected signature `fn(proc_macro::TokenStream) -> proc_macro::TokenStream`
+              found signature `fn(std::string::String) -> std::string::String`
 
-error: mismatched function-like proc macro signature
-  --> $DIR/signature-proc-macro.rs:29:33
+error: function-like proc macro has incorrect signature
+  --> $DIR/signature-proc-macro.rs:28:36
    |
 LL | pub fn too_many(a: TokenStream, b: TokenStream, c: String) -> TokenStream {
-   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^ found unexpected arguments
+   |                                    ^^^^^^^^^^^ incorrect number of function parameters
+   |
+   = note: expected signature `fn(proc_macro::TokenStream) -> proc_macro::TokenStream`
+              found signature `fn(proc_macro::TokenStream, proc_macro::TokenStream, std::string::String) -> proc_macro::TokenStream`
 
-error: aborting due to 5 previous errors
+error: aborting due to 4 previous errors
 
diff --git a/tests/ui/proc-macro/signature.rs b/tests/ui/proc-macro/signature.rs
index 11187aa31bd..7b4982a6178 100644
--- a/tests/ui/proc-macro/signature.rs
+++ b/tests/ui/proc-macro/signature.rs
@@ -8,10 +8,6 @@ extern crate proc_macro;
 
 #[proc_macro_derive(A)]
 pub unsafe extern "C" fn foo(a: i32, b: u32) -> u32 {
-    //~^ ERROR: mismatched derive proc macro signature
-    //~| mismatched derive proc macro signature
-    //~| mismatched derive proc macro signature
-    //~| proc macro functions may not be `extern
-    //~| proc macro functions may not be `unsafe
+    //~^ ERROR: derive proc macro has incorrect signature
     loop {}
 }
diff --git a/tests/ui/proc-macro/signature.stderr b/tests/ui/proc-macro/signature.stderr
index 3dbe3f22a0d..ba5c8c1571e 100644
--- a/tests/ui/proc-macro/signature.stderr
+++ b/tests/ui/proc-macro/signature.stderr
@@ -1,36 +1,11 @@
-error: proc macro functions may not be `extern "C"`
+error: derive proc macro has incorrect signature
   --> $DIR/signature.rs:10:1
    |
 LL | pub unsafe extern "C" fn foo(a: i32, b: u32) -> u32 {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: proc macro functions may not be `unsafe`
-  --> $DIR/signature.rs:10:1
-   |
-LL | pub unsafe extern "C" fn foo(a: i32, b: u32) -> u32 {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: mismatched derive proc macro signature
-  --> $DIR/signature.rs:10:49
-   |
-LL | pub unsafe extern "C" fn foo(a: i32, b: u32) -> u32 {
-   |                                                 ^^^ found u32, expected type `proc_macro::TokenStream`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected normal fn, found unsafe fn
    |
-   = note: derive proc macros must have a signature of `fn(TokenStream) -> TokenStream`
-
-error: mismatched derive proc macro signature
-  --> $DIR/signature.rs:10:33
-   |
-LL | pub unsafe extern "C" fn foo(a: i32, b: u32) -> u32 {
-   |                                 ^^^ found i32, expected type `proc_macro::TokenStream`
-   |
-   = note: derive proc macros must have a signature of `fn(TokenStream) -> TokenStream`
-
-error: mismatched derive proc macro signature
-  --> $DIR/signature.rs:10:38
-   |
-LL | pub unsafe extern "C" fn foo(a: i32, b: u32) -> u32 {
-   |                                      ^^^^^^ found unexpected argument
+   = note: expected signature `fn(proc_macro::TokenStream) -> proc_macro::TokenStream`
+              found signature `unsafe extern "C" fn(i32, u32) -> u32`
 
-error: aborting due to 5 previous errors
+error: aborting due to previous error
 
diff --git a/triagebot.toml b/triagebot.toml
index a81f66fe168..9ffe2e72cab 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -492,7 +492,6 @@ compiler-team = [
     "@oli-obk",
     "@lcnr",
     "@wesleywiser",
-    "@michaelwoerister",
 ]
 compiler-team-contributors = [
     "@compiler-errors",