diff --git a/compiler/rustc_hir_analysis/src/check/entry.rs b/compiler/rustc_hir_analysis/src/check/entry.rs
index fcaefe0261b0b..27af10af8e6f5 100644
--- a/compiler/rustc_hir_analysis/src/check/entry.rs
+++ b/compiler/rustc_hir_analysis/src/check/entry.rs
@@ -11,8 +11,8 @@ use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode};
 
 use std::ops::Not;
 
+use super::check_function_signature;
 use crate::errors;
-use crate::require_same_types;
 
 pub(crate) fn check_for_entry_fn(tcx: TyCtxt<'_>) {
     match tcx.entry_fn(()) {
@@ -162,33 +162,33 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
             error = true;
         }
         // now we can take the return type of the given main function
-        expected_return_type = main_fnsig.output();
+        expected_return_type = norm_return_ty;
     } else {
         // standard () main return type
-        expected_return_type = ty::Binder::dummy(Ty::new_unit(tcx));
+        expected_return_type = tcx.types.unit;
     }
 
     if error {
         return;
     }
 
-    let se_ty = Ty::new_fn_ptr(
-        tcx,
-        expected_return_type.map_bound(|expected_return_type| {
-            tcx.mk_fn_sig([], expected_return_type, false, hir::Unsafety::Normal, Abi::Rust)
-        }),
-    );
+    let expected_sig = ty::Binder::dummy(tcx.mk_fn_sig(
+        [],
+        expected_return_type,
+        false,
+        hir::Unsafety::Normal,
+        Abi::Rust,
+    ));
 
-    require_same_types(
+    check_function_signature(
         tcx,
-        &ObligationCause::new(
+        ObligationCause::new(
             main_span,
             main_diagnostics_def_id,
             ObligationCauseCode::MainFunctionType,
         ),
-        param_env,
-        se_ty,
-        Ty::new_fn_ptr(tcx, main_fnsig),
+        main_def_id,
+        expected_sig,
     );
 }
 
@@ -247,27 +247,23 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) {
                 }
             }
 
-            let se_ty = Ty::new_fn_ptr(
-                tcx,
-                ty::Binder::dummy(tcx.mk_fn_sig(
-                    [tcx.types.isize, Ty::new_imm_ptr(tcx, Ty::new_imm_ptr(tcx, tcx.types.u8))],
-                    tcx.types.isize,
-                    false,
-                    hir::Unsafety::Normal,
-                    Abi::Rust,
-                )),
-            );
+            let expected_sig = ty::Binder::dummy(tcx.mk_fn_sig(
+                [tcx.types.isize, Ty::new_imm_ptr(tcx, Ty::new_imm_ptr(tcx, tcx.types.u8))],
+                tcx.types.isize,
+                false,
+                hir::Unsafety::Normal,
+                Abi::Rust,
+            ));
 
-            require_same_types(
+            check_function_signature(
                 tcx,
-                &ObligationCause::new(
+                ObligationCause::new(
                     start_span,
                     start_def_id,
                     ObligationCauseCode::StartFunctionType,
                 ),
-                ty::ParamEnv::empty(), // start should not have any where bounds.
-                se_ty,
-                Ty::new_fn_ptr(tcx, tcx.fn_sig(start_def_id).instantiate_identity()),
+                start_def_id.into(),
+                expected_sig,
             );
         }
         _ => {
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index f89e2e5c25bf2..444103ffe8f33 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -1,11 +1,11 @@
 //! Type-checking for the rust-intrinsic and platform-intrinsic
 //! intrinsics that the compiler exposes.
 
+use crate::check::check_function_signature;
 use crate::errors::{
     UnrecognizedAtomicOperation, UnrecognizedIntrinsicFunction,
     WrongNumberOfGenericArgumentsToIntrinsic,
 };
-use crate::require_same_types;
 
 use hir::def_id::DefId;
 use rustc_errors::{struct_span_err, DiagnosticMessage};
@@ -53,15 +53,12 @@ fn equate_intrinsic_type<'tcx>(
         && gen_count_ok(own_counts.types, n_tps, "type")
         && gen_count_ok(own_counts.consts, 0, "const")
     {
-        let fty = Ty::new_fn_ptr(tcx, sig);
         let it_def_id = it.owner_id.def_id;
-        let cause = ObligationCause::new(it.span, it_def_id, ObligationCauseCode::IntrinsicType);
-        require_same_types(
+        check_function_signature(
             tcx,
-            &cause,
-            ty::ParamEnv::empty(), // FIXME: do all intrinsics have an empty param env?
-            Ty::new_fn_ptr(tcx, tcx.fn_sig(it.owner_id).instantiate_identity()),
-            fty,
+            ObligationCause::new(it.span, it_def_id, ObligationCauseCode::IntrinsicType),
+            it_def_id.into(),
+            sig,
         );
     }
 }
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index d833166136669..0cf3cee66b56e 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -73,23 +73,31 @@ pub mod wfcheck;
 
 pub use check::check_abi;
 
+use std::num::NonZeroU32;
+
 use check::check_mod_item_types;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::{pluralize, struct_span_err, Diagnostic, DiagnosticBuilder};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::Visitor;
 use rustc_index::bit_set::BitSet;
+use rustc_infer::infer::error_reporting::ObligationCauseExt as _;
+use rustc_infer::infer::outlives::env::OutlivesEnvironment;
+use rustc_infer::infer::{self, TyCtxtInferExt as _};
+use rustc_infer::traits::ObligationCause;
 use rustc_middle::query::Providers;
+use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_middle::ty::{GenericArgs, GenericArgsRef};
 use rustc_session::parse::feature_err;
 use rustc_span::source_map::DUMMY_SP;
 use rustc_span::symbol::{kw, Ident};
-use rustc_span::{self, BytePos, Span, Symbol};
+use rustc_span::{self, def_id::CRATE_DEF_ID, BytePos, Span, Symbol};
 use rustc_target::abi::VariantIdx;
 use rustc_target::spec::abi::Abi;
 use rustc_trait_selection::traits::error_reporting::suggestions::ReturnsVisitor;
-use std::num::NonZeroU32;
+use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
+use rustc_trait_selection::traits::ObligationCtxt;
 
 use crate::errors;
 use crate::require_c_abi_if_c_variadic;
@@ -546,3 +554,79 @@ fn bad_non_zero_sized_fields<'tcx>(
 pub fn potentially_plural_count(count: usize, word: &str) -> String {
     format!("{} {}{}", count, word, pluralize!(count))
 }
+
+pub fn check_function_signature<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    mut cause: ObligationCause<'tcx>,
+    fn_id: DefId,
+    expected_sig: ty::PolyFnSig<'tcx>,
+) {
+    let local_id = fn_id.as_local().unwrap_or(CRATE_DEF_ID);
+
+    let param_env = ty::ParamEnv::empty();
+
+    let infcx = &tcx.infer_ctxt().build();
+    let ocx = ObligationCtxt::new(infcx);
+
+    let actual_sig = tcx.fn_sig(fn_id).instantiate_identity();
+
+    let norm_cause = ObligationCause::misc(cause.span, local_id);
+    let actual_sig = ocx.normalize(&norm_cause, param_env, actual_sig);
+
+    let expected_ty = Ty::new_fn_ptr(tcx, expected_sig);
+    let actual_ty = Ty::new_fn_ptr(tcx, actual_sig);
+
+    match ocx.eq(&cause, param_env, expected_ty, actual_ty) {
+        Ok(()) => {
+            let errors = ocx.select_all_or_error();
+            if !errors.is_empty() {
+                infcx.err_ctxt().report_fulfillment_errors(&errors);
+                return;
+            }
+        }
+        Err(err) => {
+            let err_ctxt = infcx.err_ctxt();
+            if fn_id.is_local() {
+                cause.span = extract_span_for_error_reporting(tcx, err, &cause, local_id);
+            }
+            let failure_code = cause.as_failure_code_diag(err, cause.span, vec![]);
+            let mut diag = tcx.sess.create_err(failure_code);
+            err_ctxt.note_type_err(
+                &mut diag,
+                &cause,
+                None,
+                Some(infer::ValuePairs::Sigs(ExpectedFound {
+                    expected: tcx.liberate_late_bound_regions(fn_id, expected_sig),
+                    found: tcx.liberate_late_bound_regions(fn_id, actual_sig),
+                })),
+                err,
+                false,
+                false,
+            );
+            diag.emit();
+            return;
+        }
+    }
+
+    let outlives_env = OutlivesEnvironment::new(param_env);
+    let _ = ocx.resolve_regions_and_report_errors(local_id, &outlives_env);
+
+    fn extract_span_for_error_reporting<'tcx>(
+        tcx: TyCtxt<'tcx>,
+        err: TypeError<'_>,
+        cause: &ObligationCause<'tcx>,
+        fn_id: LocalDefId,
+    ) -> rustc_span::Span {
+        let mut args = {
+            let node = tcx.hir().expect_owner(fn_id);
+            let decl = node.fn_decl().unwrap_or_else(|| bug!("expected fn decl, found {:?}", node));
+            decl.inputs.iter().map(|t| t.span).chain(std::iter::once(decl.output.span()))
+        };
+
+        match err {
+            TypeError::ArgumentMutability(i)
+            | TypeError::ArgumentSorts(ExpectedFound { .. }, i) => args.nth(i).unwrap(),
+            _ => cause.span(),
+        }
+    }
+}
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index ef788935efbae..03963925d3dbd 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -99,7 +99,6 @@ use rustc_errors::ErrorGuaranteed;
 use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
 use rustc_fluent_macro::fluent_messages;
 use rustc_hir as hir;
-use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::middle;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, Ty, TyCtxt};
@@ -107,8 +106,7 @@ use rustc_middle::util;
 use rustc_session::parse::feature_err;
 use rustc_span::{symbol::sym, Span, DUMMY_SP};
 use rustc_target::spec::abi::Abi;
-use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
-use rustc_trait_selection::traits::{self, ObligationCause, ObligationCtxt};
+use rustc_trait_selection::traits;
 
 use astconv::{AstConv, OnlySelfBounds};
 use bounds::Bounds;
@@ -151,28 +149,6 @@ fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi
     tcx.sess.emit_err(errors::VariadicFunctionCompatibleConvention { span, conventions });
 }
 
-fn require_same_types<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    cause: &ObligationCause<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    expected: Ty<'tcx>,
-    actual: Ty<'tcx>,
-) {
-    let infcx = &tcx.infer_ctxt().build();
-    let ocx = ObligationCtxt::new(infcx);
-    match ocx.eq(cause, param_env, expected, actual) {
-        Ok(()) => {
-            let errors = ocx.select_all_or_error();
-            if !errors.is_empty() {
-                infcx.err_ctxt().report_fulfillment_errors(&errors);
-            }
-        }
-        Err(err) => {
-            infcx.err_ctxt().report_mismatched_types(cause, expected, actual, err).emit();
-        }
-    }
-}
-
 pub fn provide(providers: &mut Providers) {
     collect::provide(providers);
     coherence::provide(providers);
diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl
index 921a5f5154a14..9950a226333e8 100644
--- a/compiler/rustc_hir_typeck/messages.ftl
+++ b/compiler/rustc_hir_typeck/messages.ftl
@@ -83,16 +83,6 @@ hir_typeck_int_to_fat_label_nightly = consider casting this expression to `*cons
 
 hir_typeck_invalid_callee = expected function, found {$ty}
 
-hir_typeck_lang_start_expected_sig_note = the `start` lang item should have the signature `fn(fn() -> T, isize, *const *const u8, u8) -> isize`
-hir_typeck_lang_start_incorrect_number_params = incorrect number of parameters for the `start` lang item
-hir_typeck_lang_start_incorrect_number_params_note_expected_count = the `start` lang item should have four parameters, but found {$found_param_count}
-
-hir_typeck_lang_start_incorrect_param = parameter {$param_num} of the `start` lang item is incorrect
-    .suggestion = change the type from `{$found_ty}` to `{$expected_ty}`
-
-hir_typeck_lang_start_incorrect_ret_ty = the return type of the `start` lang item is incorrect
-    .suggestion = change the type from `{$found_ty}` to `{$expected_ty}`
-
 hir_typeck_lossy_provenance_int2ptr =
     strict provenance disallows casting integer `{$expr_ty}` to pointer `{$cast_ty}`
     .suggestion = use `.with_addr()` to adjust a valid pointer in the same allocation, to this address
diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs
index 1fc1e5aca2b3c..041cc1abd54e4 100644
--- a/compiler/rustc_hir_typeck/src/check.rs
+++ b/compiler/rustc_hir_typeck/src/check.rs
@@ -1,7 +1,6 @@
+use std::cell::RefCell;
+
 use crate::coercion::CoerceMany;
-use crate::errors::{
-    LangStartIncorrectNumberArgs, LangStartIncorrectParam, LangStartIncorrectRetTy,
-};
 use crate::gather_locals::GatherLocalsVisitor;
 use crate::FnCtxt;
 use crate::GeneratorTypes;
@@ -9,14 +8,15 @@ use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::lang_items::LangItem;
-use rustc_hir_analysis::check::fn_maybe_err;
+use rustc_hir_analysis::check::{check_function_signature, fn_maybe_err};
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::infer::RegionVariableOrigin;
 use rustc_middle::ty::{self, Binder, Ty, TyCtxt};
 use rustc_span::def_id::LocalDefId;
+use rustc_span::symbol::sym;
 use rustc_target::spec::abi::Abi;
 use rustc_trait_selection::traits;
-use std::cell::RefCell;
+use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode};
 
 /// Helper used for fns and closures. Does the grungy work of checking a function
 /// body and returns the function context used for that purpose, since in the case of a fn item
@@ -166,52 +166,17 @@ pub(super) fn check_fn<'a, 'tcx>(
     if let Some(panic_impl_did) = tcx.lang_items().panic_impl()
         && panic_impl_did == fn_def_id.to_def_id()
     {
-        check_panic_info_fn(tcx, panic_impl_did.expect_local(), fn_sig, decl, declared_ret_ty);
+        check_panic_info_fn(tcx, panic_impl_did.expect_local(), fn_sig);
     }
 
     if let Some(lang_start_defid) = tcx.lang_items().start_fn() && lang_start_defid == fn_def_id.to_def_id() {
-        check_lang_start_fn(tcx, fn_sig, decl, fn_def_id);
+        check_lang_start_fn(tcx, fn_sig, fn_def_id);
     }
 
     gen_ty
 }
 
-fn check_panic_info_fn(
-    tcx: TyCtxt<'_>,
-    fn_id: LocalDefId,
-    fn_sig: ty::FnSig<'_>,
-    decl: &hir::FnDecl<'_>,
-    declared_ret_ty: Ty<'_>,
-) {
-    let Some(panic_info_did) = tcx.lang_items().panic_info() else {
-        tcx.sess.err("language item required, but not found: `panic_info`");
-        return;
-    };
-
-    if *declared_ret_ty.kind() != ty::Never {
-        tcx.sess.span_err(decl.output.span(), "return type should be `!`");
-    }
-
-    let inputs = fn_sig.inputs();
-    if inputs.len() != 1 {
-        tcx.sess.span_err(tcx.def_span(fn_id), "function should have one argument");
-        return;
-    }
-
-    let arg_is_panic_info = match *inputs[0].kind() {
-        ty::Ref(region, ty, mutbl) => match *ty.kind() {
-            ty::Adt(ref adt, _) => {
-                adt.did() == panic_info_did && mutbl.is_not() && !region.is_static()
-            }
-            _ => false,
-        },
-        _ => false,
-    };
-
-    if !arg_is_panic_info {
-        tcx.sess.span_err(decl.inputs[0].span, "argument should be `&PanicInfo`");
-    }
-
+fn check_panic_info_fn(tcx: TyCtxt<'_>, fn_id: LocalDefId, fn_sig: ty::FnSig<'_>) {
     let DefKind::Fn = tcx.def_kind(fn_id) else {
         let span = tcx.def_span(fn_id);
         tcx.sess.span_err(span, "should be a function");
@@ -227,125 +192,87 @@ fn check_panic_info_fn(
         let span = tcx.def_span(fn_id);
         tcx.sess.span_err(span, "should have no const parameters");
     }
-}
-
-fn check_lang_start_fn<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    fn_sig: ty::FnSig<'tcx>,
-    decl: &'tcx hir::FnDecl<'tcx>,
-    def_id: LocalDefId,
-) {
-    let inputs = fn_sig.inputs();
-
-    let arg_count = inputs.len();
-    if arg_count != 4 {
-        tcx.sess.emit_err(LangStartIncorrectNumberArgs {
-            params_span: tcx.def_span(def_id),
-            found_param_count: arg_count,
-        });
-    }
 
-    // only check args if they should exist by checking the count
-    // note: this does not handle args being shifted or their order swapped very nicely
-    // but it's a lang item, users shouldn't frequently encounter this
-
-    // first arg is `main: fn() -> T`
-    if let Some(&main_arg) = inputs.get(0) {
-        // make a Ty for the generic on the fn for diagnostics
-        // FIXME: make the lang item generic checks check for the right generic *kind*
-        // for example `start`'s generic should be a type parameter
-        let generics = tcx.generics_of(def_id);
-        let fn_generic = generics.param_at(0, tcx);
-        let generic_ty = Ty::new_param(tcx, fn_generic.index, fn_generic.name);
-        let expected_fn_sig =
-            tcx.mk_fn_sig([], generic_ty, false, hir::Unsafety::Normal, Abi::Rust);
-        let expected_ty = Ty::new_fn_ptr(tcx, Binder::dummy(expected_fn_sig));
-
-        // we emit the same error to suggest changing the arg no matter what's wrong with the arg
-        let emit_main_fn_arg_err = || {
-            tcx.sess.emit_err(LangStartIncorrectParam {
-                param_span: decl.inputs[0].span,
-                param_num: 1,
-                expected_ty: expected_ty,
-                found_ty: main_arg,
-            });
-        };
-
-        if let ty::FnPtr(main_fn_sig) = main_arg.kind() {
-            let main_fn_inputs = main_fn_sig.inputs();
-            if main_fn_inputs.iter().count() != 0 {
-                emit_main_fn_arg_err();
-            }
-
-            let output = main_fn_sig.output();
-            output.map_bound(|ret_ty| {
-                // if the output ty is a generic, it's probably the right one
-                if !matches!(ret_ty.kind(), ty::Param(_)) {
-                    emit_main_fn_arg_err();
-                }
-            });
-        } else {
-            emit_main_fn_arg_err();
-        }
-    }
-
-    // second arg is isize
-    if let Some(&argc_arg) = inputs.get(1) {
-        if argc_arg != tcx.types.isize {
-            tcx.sess.emit_err(LangStartIncorrectParam {
-                param_span: decl.inputs[1].span,
-                param_num: 2,
-                expected_ty: tcx.types.isize,
-                found_ty: argc_arg,
-            });
-        }
-    }
-
-    // third arg is `*const *const u8`
-    if let Some(&argv_arg) = inputs.get(2) {
-        let mut argv_is_okay = false;
-        if let ty::RawPtr(outer_ptr) = argv_arg.kind() {
-            if outer_ptr.mutbl.is_not() {
-                if let ty::RawPtr(inner_ptr) = outer_ptr.ty.kind() {
-                    if inner_ptr.mutbl.is_not() && inner_ptr.ty == tcx.types.u8 {
-                        argv_is_okay = true;
-                    }
-                }
-            }
-        }
-
-        if !argv_is_okay {
-            let inner_ptr_ty =
-                Ty::new_ptr(tcx, ty::TypeAndMut { mutbl: hir::Mutability::Not, ty: tcx.types.u8 });
-            let expected_ty =
-                Ty::new_ptr(tcx, ty::TypeAndMut { mutbl: hir::Mutability::Not, ty: inner_ptr_ty });
-            tcx.sess.emit_err(LangStartIncorrectParam {
-                param_span: decl.inputs[2].span,
-                param_num: 3,
-                expected_ty,
-                found_ty: argv_arg,
-            });
-        }
-    }
+    let Some(panic_info_did) = tcx.lang_items().panic_info() else {
+        tcx.sess.err("language item required, but not found: `panic_info`");
+        return;
+    };
 
-    // fourth arg is `sigpipe: u8`
-    if let Some(&sigpipe_arg) = inputs.get(3) {
-        if sigpipe_arg != tcx.types.u8 {
-            tcx.sess.emit_err(LangStartIncorrectParam {
-                param_span: decl.inputs[3].span,
-                param_num: 4,
-                expected_ty: tcx.types.u8,
-                found_ty: sigpipe_arg,
-            });
-        }
-    }
+    // build type `for<'a, 'b> fn(&'a PanicInfo<'b>) -> !`
+    let panic_info_ty = tcx.type_of(panic_info_did).instantiate(
+        tcx,
+        &[ty::GenericArg::from(ty::Region::new_late_bound(
+            tcx,
+            ty::INNERMOST,
+            ty::BoundRegion { var: ty::BoundVar::from_u32(1), kind: ty::BrAnon(None) },
+        ))],
+    );
+    let panic_info_ref_ty = Ty::new_imm_ref(
+        tcx,
+        ty::Region::new_late_bound(
+            tcx,
+            ty::INNERMOST,
+            ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(None) },
+        ),
+        panic_info_ty,
+    );
+
+    let bounds = tcx.mk_bound_variable_kinds(&[
+        ty::BoundVariableKind::Region(ty::BrAnon(None)),
+        ty::BoundVariableKind::Region(ty::BrAnon(None)),
+    ]);
+    let expected_sig = ty::Binder::bind_with_vars(
+        tcx.mk_fn_sig([panic_info_ref_ty], tcx.types.never, false, fn_sig.unsafety, Abi::Rust),
+        bounds,
+    );
+
+    check_function_signature(
+        tcx,
+        ObligationCause::new(
+            tcx.def_span(fn_id),
+            fn_id,
+            ObligationCauseCode::LangFunctionType(sym::panic_impl),
+        ),
+        fn_id.into(),
+        expected_sig,
+    );
+}
 
-    // output type is isize
-    if fn_sig.output() != tcx.types.isize {
-        tcx.sess.emit_err(LangStartIncorrectRetTy {
-            ret_span: decl.output.span(),
-            expected_ty: tcx.types.isize,
-            found_ty: fn_sig.output(),
-        });
-    }
+fn check_lang_start_fn<'tcx>(tcx: TyCtxt<'tcx>, fn_sig: ty::FnSig<'tcx>, def_id: LocalDefId) {
+    // build type `fn(main: fn() -> T, argc: isize, argv: *const *const u8, sigpipe: u8)`
+
+    // make a Ty for the generic on the fn for diagnostics
+    // FIXME: make the lang item generic checks check for the right generic *kind*
+    // for example `start`'s generic should be a type parameter
+    let generics = tcx.generics_of(def_id);
+    let fn_generic = generics.param_at(0, tcx);
+    let generic_ty = Ty::new_param(tcx, fn_generic.index, fn_generic.name);
+    let main_fn_ty = Ty::new_fn_ptr(
+        tcx,
+        Binder::dummy(tcx.mk_fn_sig([], generic_ty, false, hir::Unsafety::Normal, Abi::Rust)),
+    );
+
+    let expected_sig = ty::Binder::dummy(tcx.mk_fn_sig(
+        [
+            main_fn_ty,
+            tcx.types.isize,
+            Ty::new_imm_ptr(tcx, Ty::new_imm_ptr(tcx, tcx.types.u8)),
+            tcx.types.u8,
+        ],
+        tcx.types.isize,
+        false,
+        fn_sig.unsafety,
+        Abi::Rust,
+    ));
+
+    check_function_signature(
+        tcx,
+        ObligationCause::new(
+            tcx.def_span(def_id),
+            def_id,
+            ObligationCauseCode::LangFunctionType(sym::start),
+        ),
+        def_id.into(),
+        expected_sig,
+    );
 }
diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs
index 7152585d44087..1526988fbd926 100644
--- a/compiler/rustc_hir_typeck/src/errors.rs
+++ b/compiler/rustc_hir_typeck/src/errors.rs
@@ -236,39 +236,6 @@ impl AddToDiagnostic for TypeMismatchFruTypo {
     }
 }
 
-#[derive(Diagnostic)]
-#[diag(hir_typeck_lang_start_incorrect_number_params)]
-#[note(hir_typeck_lang_start_incorrect_number_params_note_expected_count)]
-#[note(hir_typeck_lang_start_expected_sig_note)]
-pub struct LangStartIncorrectNumberArgs {
-    #[primary_span]
-    pub params_span: Span,
-    pub found_param_count: usize,
-}
-
-#[derive(Diagnostic)]
-#[diag(hir_typeck_lang_start_incorrect_param)]
-pub struct LangStartIncorrectParam<'tcx> {
-    #[primary_span]
-    #[suggestion(style = "short", code = "{expected_ty}", applicability = "machine-applicable")]
-    pub param_span: Span,
-
-    pub param_num: usize,
-    pub expected_ty: Ty<'tcx>,
-    pub found_ty: Ty<'tcx>,
-}
-
-#[derive(Diagnostic)]
-#[diag(hir_typeck_lang_start_incorrect_ret_ty)]
-pub struct LangStartIncorrectRetTy<'tcx> {
-    #[primary_span]
-    #[suggestion(style = "short", code = "{expected_ty}", applicability = "machine-applicable")]
-    pub ret_span: Span,
-
-    pub expected_ty: Ty<'tcx>,
-    pub found_ty: Ty<'tcx>,
-}
-
 #[derive(LintDiagnostic)]
 #[diag(hir_typeck_lossy_provenance_int2ptr)]
 #[help]
diff --git a/compiler/rustc_infer/messages.ftl b/compiler/rustc_infer/messages.ftl
index 4d0e770636721..46558997f7236 100644
--- a/compiler/rustc_infer/messages.ftl
+++ b/compiler/rustc_infer/messages.ftl
@@ -198,6 +198,10 @@ infer_nothing = {""}
 infer_oc_cant_coerce = cannot coerce intrinsics to function pointers
 infer_oc_closure_selfref = closure/generator type that references itself
 infer_oc_const_compat = const not compatible with trait
+infer_oc_fn_lang_correct_type = {$lang_item_name ->
+        [panic_impl] `#[panic_handler]`
+        *[lang_item_name] lang item `{$lang_item_name}`
+    } function has wrong type
 infer_oc_fn_main_correct_type = `main` function has wrong type
 infer_oc_fn_start_correct_type = `#[start]` function has wrong type
 infer_oc_generic = mismatched types
@@ -337,6 +341,7 @@ infer_subtype = ...so that the {$requirement ->
     [no_else] `if` missing an `else` returns `()`
     [fn_main_correct_type] `main` function has the correct type
     [fn_start_correct_type] `#[start]` function has the correct type
+    [fn_lang_correct_type] lang item function has the correct type
     [intrinsic_correct_type] intrinsic has the correct type
     [method_correct_type] method receiver has the correct type
     *[other] types are compatible
@@ -350,6 +355,7 @@ infer_subtype_2 = ...so that {$requirement ->
     [no_else] `if` missing an `else` returns `()`
     [fn_main_correct_type] `main` function has the correct type
     [fn_start_correct_type] `#[start]` function has the correct type
+    [fn_lang_correct_type] lang item function has the correct type
     [intrinsic_correct_type] intrinsic has the correct type
     [method_correct_type] method receiver has the correct type
     *[other] types are compatible
diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs
index a7e045e1e8946..38910e45eccc7 100644
--- a/compiler/rustc_infer/src/errors/mod.rs
+++ b/compiler/rustc_infer/src/errors/mod.rs
@@ -1463,6 +1463,14 @@ pub enum ObligationCauseFailureCode {
         #[subdiagnostic]
         subdiags: Vec<TypeErrorAdditionalDiags>,
     },
+    #[diag(infer_oc_fn_lang_correct_type, code = "E0308")]
+    FnLangCorrectType {
+        #[primary_span]
+        span: Span,
+        #[subdiagnostic]
+        subdiags: Vec<TypeErrorAdditionalDiags>,
+        lang_item_name: Symbol,
+    },
     #[diag(infer_oc_intrinsic_correct_type, code = "E0308")]
     IntrinsicCorrectType {
         #[primary_span]
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 6dba5d2945dbe..2ca5b7d657dd3 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -2927,6 +2927,7 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> {
             | IfExpression { .. }
             | LetElse
             | StartFunctionType
+            | LangFunctionType(_)
             | IntrinsicType
             | MethodReceiver => Error0308,
 
@@ -2971,6 +2972,9 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> {
             LetElse => ObligationCauseFailureCode::NoDiverge { span, subdiags },
             MainFunctionType => ObligationCauseFailureCode::FnMainCorrectType { span },
             StartFunctionType => ObligationCauseFailureCode::FnStartCorrectType { span, subdiags },
+            &LangFunctionType(lang_item_name) => {
+                ObligationCauseFailureCode::FnLangCorrectType { span, subdiags, lang_item_name }
+            }
             IntrinsicType => ObligationCauseFailureCode::IntrinsicCorrectType { span, subdiags },
             MethodReceiver => ObligationCauseFailureCode::MethodCorrectType { span, subdiags },
 
@@ -3006,6 +3010,7 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> {
             IfExpressionWithNoElse => "`if` missing an `else` returns `()`",
             MainFunctionType => "`main` function has the correct type",
             StartFunctionType => "`#[start]` function has the correct type",
+            LangFunctionType(_) => "lang item function has the correct type",
             IntrinsicType => "intrinsic has the correct type",
             MethodReceiver => "method receiver has the correct type",
             _ => "types are compatible",
@@ -3028,6 +3033,7 @@ impl IntoDiagnosticArg for ObligationCauseAsDiagArg<'_> {
             IfExpressionWithNoElse => "no_else",
             MainFunctionType => "fn_main_correct_type",
             StartFunctionType => "fn_start_correct_type",
+            LangFunctionType(_) => "fn_lang_correct_type",
             IntrinsicType => "intrinsic_correct_type",
             MethodReceiver => "method_correct_type",
             _ => "other",
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index 1340e674568f4..eef193a657de8 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -378,6 +378,9 @@ pub enum ObligationCauseCode<'tcx> {
     /// `start` has wrong type
     StartFunctionType,
 
+    /// language function has wrong type
+    LangFunctionType(Symbol),
+
     /// Intrinsic has wrong type
     IntrinsicType,
 
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 a08ebe5a9ea8d..64d1308b83f97 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -2711,6 +2711,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             | ObligationCauseCode::IfExpressionWithNoElse
             | ObligationCauseCode::MainFunctionType
             | ObligationCauseCode::StartFunctionType
+            | ObligationCauseCode::LangFunctionType(_)
             | ObligationCauseCode::IntrinsicType
             | ObligationCauseCode::MethodReceiver
             | ObligationCauseCode::ReturnNoExpression
diff --git a/tests/ui/associated-inherent-types/issue-111879-1.stderr b/tests/ui/associated-inherent-types/issue-111879-1.stderr
index 689b45e09aaac..bf35f2bb5b532 100644
--- a/tests/ui/associated-inherent-types/issue-111879-1.stderr
+++ b/tests/ui/associated-inherent-types/issue-111879-1.stderr
@@ -4,8 +4,8 @@ error[E0580]: `main` function has wrong type
 LL | fn main(_: for<'a> fn(Foo<fn(&'a ())>::Assoc)) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters
    |
-   = note: expected fn pointer `fn()`
-              found fn pointer `fn(for<'a> fn(Foo<fn(&'a ())>::Assoc))`
+   = note: expected signature `fn()`
+              found signature `fn(for<'a> fn(&'a ()))`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/borrowck/issue-92157.rs b/tests/ui/borrowck/issue-92157.rs
index 6ee2320a603ad..3a6f8908b219f 100644
--- a/tests/ui/borrowck/issue-92157.rs
+++ b/tests/ui/borrowck/issue-92157.rs
@@ -9,7 +9,7 @@ extern {}
 
 #[lang = "start"]
 fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isize {
-    //~^ ERROR: incorrect number of parameters for the `start` lang item
+    //~^ ERROR lang item `start` function has wrong type [E0308]
     40+2
 }
 
diff --git a/tests/ui/borrowck/issue-92157.stderr b/tests/ui/borrowck/issue-92157.stderr
index a4010d73d057a..a46b1288911dc 100644
--- a/tests/ui/borrowck/issue-92157.stderr
+++ b/tests/ui/borrowck/issue-92157.stderr
@@ -1,11 +1,12 @@
-error: incorrect number of parameters for the `start` lang item
+error[E0308]: lang item `start` function has wrong type
   --> $DIR/issue-92157.rs:11:1
    |
 LL | fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isize {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters
    |
-   = note: the `start` lang item should have four parameters, but found 3
-   = note: the `start` lang item should have the signature `fn(fn() -> T, isize, *const *const u8, u8) -> isize`
+   = note: expected signature `fn(fn() -> T, isize, *const *const u8, u8) -> _`
+              found signature `fn(fn() -> T, isize, *const *const u8) -> _`
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/entry-point/auxiliary/bad_main_functions.rs b/tests/ui/entry-point/auxiliary/bad_main_functions.rs
new file mode 100644
index 0000000000000..4649be99e6f27
--- /dev/null
+++ b/tests/ui/entry-point/auxiliary/bad_main_functions.rs
@@ -0,0 +1,2 @@
+pub fn boilerplate(x: u8) {}
+//~^ ERROR: `main` function has wrong type [E0580]
diff --git a/tests/ui/entry-point/imported_main_from_extern_crate_wrong_type.rs b/tests/ui/entry-point/imported_main_from_extern_crate_wrong_type.rs
new file mode 100644
index 0000000000000..0a115dd3b0810
--- /dev/null
+++ b/tests/ui/entry-point/imported_main_from_extern_crate_wrong_type.rs
@@ -0,0 +1,6 @@
+// aux-build:bad_main_functions.rs
+
+#![feature(imported_main)]
+
+extern crate bad_main_functions;
+pub use bad_main_functions::boilerplate as main;
diff --git a/tests/ui/entry-point/imported_main_from_extern_crate_wrong_type.stderr b/tests/ui/entry-point/imported_main_from_extern_crate_wrong_type.stderr
new file mode 100644
index 0000000000000..3c68933101c87
--- /dev/null
+++ b/tests/ui/entry-point/imported_main_from_extern_crate_wrong_type.stderr
@@ -0,0 +1,12 @@
+error[E0580]: `main` function has wrong type
+  --> $DIR/auxiliary/bad_main_functions.rs:1:1
+   |
+LL | pub fn boilerplate(x: u8) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters
+   |
+   = note: expected signature `fn()`
+              found signature `fn(u8)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0580`.
diff --git a/tests/ui/error-codes/E0308.stderr b/tests/ui/error-codes/E0308.stderr
index 187b775f92dc0..141abed6032eb 100644
--- a/tests/ui/error-codes/E0308.stderr
+++ b/tests/ui/error-codes/E0308.stderr
@@ -1,11 +1,11 @@
 error[E0308]: intrinsic has wrong type
-  --> $DIR/E0308.rs:6:5
+  --> $DIR/E0308.rs:6:20
    |
 LL |     fn size_of<T>();
-   |     ^^^^^^^^^^^^^^^^ expected `()`, found `usize`
+   |                    ^ expected `usize`, found `()`
    |
-   = note: expected fn pointer `extern "rust-intrinsic" fn()`
-              found fn pointer `extern "rust-intrinsic" fn() -> usize`
+   = note: expected signature `extern "rust-intrinsic" fn() -> usize`
+              found signature `extern "rust-intrinsic" fn()`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/extern/extern-main-fn.stderr b/tests/ui/extern/extern-main-fn.stderr
index 136c957538248..846102670a83f 100644
--- a/tests/ui/extern/extern-main-fn.stderr
+++ b/tests/ui/extern/extern-main-fn.stderr
@@ -4,8 +4,8 @@ error[E0580]: `main` function has wrong type
 LL | extern "C" fn main() {}
    | ^^^^^^^^^^^^^^^^^^^^ expected "Rust" fn, found "C" fn
    |
-   = note: expected fn pointer `fn()`
-              found fn pointer `extern "C" fn()`
+   = note: expected signature `fn()`
+              found signature `extern "C" fn()`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/fn/bad-main.stderr b/tests/ui/fn/bad-main.stderr
index 675b66d057838..65140a0794f84 100644
--- a/tests/ui/fn/bad-main.stderr
+++ b/tests/ui/fn/bad-main.stderr
@@ -4,8 +4,8 @@ error[E0580]: `main` function has wrong type
 LL | fn main(x: isize) { }
    | ^^^^^^^^^^^^^^^^^ incorrect number of function parameters
    |
-   = note: expected fn pointer `fn()`
-              found fn pointer `fn(isize)`
+   = note: expected signature `fn()`
+              found signature `fn(isize)`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/issues/issue-9575.stderr b/tests/ui/issues/issue-9575.stderr
index 5b8ce84a07168..e49eac3babf8c 100644
--- a/tests/ui/issues/issue-9575.stderr
+++ b/tests/ui/issues/issue-9575.stderr
@@ -4,8 +4,8 @@ error[E0308]: `#[start]` function has wrong type
 LL | fn start(argc: isize, argv: *const *const u8, crate_map: *const u8) -> isize {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters
    |
-   = note: expected fn pointer `fn(isize, *const *const u8) -> _`
-              found fn pointer `fn(isize, *const *const u8, *const u8) -> _`
+   = note: expected signature `fn(isize, *const *const u8) -> _`
+              found signature `fn(isize, *const *const u8, *const u8) -> _`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/lang-items/start_lang_item_args.argc.stderr b/tests/ui/lang-items/start_lang_item_args.argc.stderr
index 65c99a93c7511..66d4397a2935a 100644
--- a/tests/ui/lang-items/start_lang_item_args.argc.stderr
+++ b/tests/ui/lang-items/start_lang_item_args.argc.stderr
@@ -1,8 +1,12 @@
-error: parameter 2 of the `start` lang item is incorrect
+error[E0308]: lang item `start` function has wrong type
   --> $DIR/start_lang_item_args.rs:75:38
    |
 LL | fn start<T>(_main: fn() -> T, _argc: i8, _argv: *const *const u8, _sigpipe: u8) -> isize {
-   |                                      ^^ help: change the type from `i8` to `isize`
+   |                                      ^^ expected `isize`, found `i8`
+   |
+   = note: expected signature `fn(fn() -> _, isize, _, _) -> _`
+              found signature `fn(fn() -> _, i8, _, _) -> _`
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/lang-items/start_lang_item_args.argv.stderr b/tests/ui/lang-items/start_lang_item_args.argv.stderr
index f0947a9b3e933..53d776cd846a4 100644
--- a/tests/ui/lang-items/start_lang_item_args.argv.stderr
+++ b/tests/ui/lang-items/start_lang_item_args.argv.stderr
@@ -1,8 +1,12 @@
-error: parameter 3 of the `start` lang item is incorrect
+error[E0308]: lang item `start` function has wrong type
   --> $DIR/start_lang_item_args.rs:89:52
    |
 LL | fn start<T>(_main: fn() -> T, _argc: isize, _argv: u8, _sigpipe: u8) -> isize {
-   |                                                    ^^ help: change the type from `u8` to `*const *const u8`
+   |                                                    ^^ expected `*const *const u8`, found `u8`
+   |
+   = note: expected signature `fn(fn() -> _, _, *const *const u8, _) -> _`
+              found signature `fn(fn() -> _, _, u8, _) -> _`
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/lang-items/start_lang_item_args.argv_inner_ptr.stderr b/tests/ui/lang-items/start_lang_item_args.argv_inner_ptr.stderr
index 08efd5088f99b..7d002e090b5a8 100644
--- a/tests/ui/lang-items/start_lang_item_args.argv_inner_ptr.stderr
+++ b/tests/ui/lang-items/start_lang_item_args.argv_inner_ptr.stderr
@@ -1,13 +1,12 @@
-error: parameter 3 of the `start` lang item is incorrect
+error[E0308]: lang item `start` function has wrong type
   --> $DIR/start_lang_item_args.rs:82:52
    |
 LL | fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const usize, _sigpipe: u8) -> isize {
-   |                                                    ^^^^^^^^^^^^^^^^^^^
+   |                                                    ^^^^^^^^^^^^^^^^^^^ expected `u8`, found `usize`
    |
-help: change the type from `*const *const usize` to `*const *const u8`
-   |
-LL | fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize {
-   |                                                    ~~~~~~~~~~~~~~~~
+   = note: expected signature `fn(fn() -> _, _, *const *const u8, _) -> _`
+              found signature `fn(fn() -> _, _, *const *const usize, _) -> _`
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/lang-items/start_lang_item_args.main_args.stderr b/tests/ui/lang-items/start_lang_item_args.main_args.stderr
index c20a744661d49..91994b9d74296 100644
--- a/tests/ui/lang-items/start_lang_item_args.main_args.stderr
+++ b/tests/ui/lang-items/start_lang_item_args.main_args.stderr
@@ -1,13 +1,12 @@
-error: parameter 1 of the `start` lang item is incorrect
-  --> $DIR/start_lang_item_args.rs:61:20
+error[E0308]: lang item `start` function has wrong type
+  --> $DIR/start_lang_item_args.rs:61:1
    |
 LL | fn start<T>(_main: fn(i32) -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize {
-   |                    ^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters
    |
-help: change the type from `fn(i32) -> T` to `fn() -> T`
-   |
-LL | fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize {
-   |                    ~~~~~~~~~
+   = note: expected signature `fn(fn() -> _, _, _, _) -> _`
+              found signature `fn(fn(i32) -> _, _, _, _) -> _`
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/lang-items/start_lang_item_args.main_ret.stderr b/tests/ui/lang-items/start_lang_item_args.main_ret.stderr
index 8f967252f49be..4582b69850cf7 100644
--- a/tests/ui/lang-items/start_lang_item_args.main_ret.stderr
+++ b/tests/ui/lang-items/start_lang_item_args.main_ret.stderr
@@ -1,13 +1,14 @@
-error: parameter 1 of the `start` lang item is incorrect
+error[E0308]: lang item `start` function has wrong type
   --> $DIR/start_lang_item_args.rs:68:20
    |
 LL | fn start<T>(_main: fn() -> u16, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize {
-   |                    ^^^^^^^^^^^
+   |          -         ^^^^^^^^^^^ expected type parameter `T`, found `u16`
+   |          |
+   |          this type parameter
    |
-help: change the type from `fn() -> u16` to `fn() -> T`
-   |
-LL | fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize {
-   |                    ~~~~~~~~~
+   = note: expected signature `fn(fn() -> T, _, _, _) -> _`
+              found signature `fn(fn() -> u16, _, _, _) -> _`
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/lang-items/start_lang_item_args.main_ty.stderr b/tests/ui/lang-items/start_lang_item_args.main_ty.stderr
index deb37b868ea89..87940d05e785f 100644
--- a/tests/ui/lang-items/start_lang_item_args.main_ty.stderr
+++ b/tests/ui/lang-items/start_lang_item_args.main_ty.stderr
@@ -1,8 +1,12 @@
-error: parameter 1 of the `start` lang item is incorrect
+error[E0308]: lang item `start` function has wrong type
   --> $DIR/start_lang_item_args.rs:54:20
    |
 LL | fn start<T>(_main: u64, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize {
-   |                    ^^^ help: change the type from `u64` to `fn() -> T`
+   |                    ^^^ expected fn pointer, found `u64`
+   |
+   = note: expected signature `fn(fn() -> T, _, _, _) -> _`
+              found signature `fn(u64, _, _, _) -> _`
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/lang-items/start_lang_item_args.missing_all_args.stderr b/tests/ui/lang-items/start_lang_item_args.missing_all_args.stderr
index 004c2a67f62f1..5363871e20223 100644
--- a/tests/ui/lang-items/start_lang_item_args.missing_all_args.stderr
+++ b/tests/ui/lang-items/start_lang_item_args.missing_all_args.stderr
@@ -1,11 +1,12 @@
-error: incorrect number of parameters for the `start` lang item
+error[E0308]: lang item `start` function has wrong type
   --> $DIR/start_lang_item_args.rs:15:1
    |
 LL | fn start<T>() -> isize {
-   | ^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters
    |
-   = note: the `start` lang item should have four parameters, but found 0
-   = note: the `start` lang item should have the signature `fn(fn() -> T, isize, *const *const u8, u8) -> isize`
+   = note: expected signature `fn(fn() -> T, isize, *const *const u8, u8) -> _`
+              found signature `fn() -> _`
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/lang-items/start_lang_item_args.missing_ret.stderr b/tests/ui/lang-items/start_lang_item_args.missing_ret.stderr
index 1d8285b59000a..2bb29f911a125 100644
--- a/tests/ui/lang-items/start_lang_item_args.missing_ret.stderr
+++ b/tests/ui/lang-items/start_lang_item_args.missing_ret.stderr
@@ -1,8 +1,12 @@
-error: the return type of the `start` lang item is incorrect
+error[E0308]: lang item `start` function has wrong type
   --> $DIR/start_lang_item_args.rs:29:84
    |
 LL | fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) {}
-   |                                                                                    ^ help: change the type from `()` to `isize`
+   |                                                                                    ^ expected `isize`, found `()`
+   |
+   = note: expected signature `fn(fn() -> _, _, _, _) -> isize`
+              found signature `fn(fn() -> _, _, _, _)`
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/lang-items/start_lang_item_args.missing_sigpipe_arg.stderr b/tests/ui/lang-items/start_lang_item_args.missing_sigpipe_arg.stderr
index e545a750f24a9..f873f7614bdce 100644
--- a/tests/ui/lang-items/start_lang_item_args.missing_sigpipe_arg.stderr
+++ b/tests/ui/lang-items/start_lang_item_args.missing_sigpipe_arg.stderr
@@ -1,11 +1,12 @@
-error: incorrect number of parameters for the `start` lang item
+error[E0308]: lang item `start` function has wrong type
   --> $DIR/start_lang_item_args.rs:22:1
    |
 LL | fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isize {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters
    |
-   = note: the `start` lang item should have four parameters, but found 3
-   = note: the `start` lang item should have the signature `fn(fn() -> T, isize, *const *const u8, u8) -> isize`
+   = note: expected signature `fn(fn() -> T, isize, *const *const u8, u8) -> _`
+              found signature `fn(fn() -> T, isize, *const *const u8) -> _`
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/lang-items/start_lang_item_args.rs b/tests/ui/lang-items/start_lang_item_args.rs
index 0dbfba39cb605..4a0302bcb1528 100644
--- a/tests/ui/lang-items/start_lang_item_args.rs
+++ b/tests/ui/lang-items/start_lang_item_args.rs
@@ -13,33 +13,33 @@ pub trait Sized {}
 #[cfg(missing_all_args)]
 #[lang = "start"]
 fn start<T>() -> isize {
-    //[missing_all_args]~^ ERROR incorrect number of parameters
+    //[missing_all_args]~^ ERROR lang item `start` function has wrong type [E0308]
     100
 }
 
 #[cfg(missing_sigpipe_arg)]
 #[lang = "start"]
 fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isize {
-    //[missing_sigpipe_arg]~^ ERROR incorrect number of parameters
+    //[missing_sigpipe_arg]~^ ERROR lang item `start` function has wrong type [E0308]
     100
 }
 
 #[cfg(missing_ret)]
 #[lang = "start"]
 fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) {}
-//[missing_ret]~^ ERROR the return type of the `start` lang item is incorrect
+//[missing_ret]~^ ERROR lang item `start` function has wrong type [E0308]
 
 #[cfg(start_ret)]
 #[lang = "start"]
 fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> u8 {
-    //[start_ret]~^ ERROR the return type of the `start` lang item is incorrect
+    //[start_ret]~^ ERROR lang item `start` function has wrong type [E0308]
     100
 }
 
 #[cfg(too_many_args)]
 #[lang = "start"]
 fn start<T>(
-    //[too_many_args]~^ ERROR incorrect number of parameters
+    //[too_many_args]~^ ERROR lang item `start` function has wrong type [E0308]
     _main: fn() -> T,
     _argc: isize,
     _argv: *const *const u8,
@@ -52,49 +52,49 @@ fn start<T>(
 #[cfg(main_ty)]
 #[lang = "start"]
 fn start<T>(_main: u64, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize {
-    //[main_ty]~^ ERROR parameter 1 of the `start` lang item is incorrect
+    //[main_ty]~^ ERROR lang item `start` function has wrong type [E0308]
     100
 }
 
 #[cfg(main_args)]
 #[lang = "start"]
 fn start<T>(_main: fn(i32) -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize {
-    //[main_args]~^ ERROR parameter 1 of the `start` lang item is incorrect
+    //[main_args]~^ ERROR lang item `start` function has wrong type [E0308]
     100
 }
 
 #[cfg(main_ret)]
 #[lang = "start"]
 fn start<T>(_main: fn() -> u16, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize {
-    //[main_ret]~^ ERROR parameter 1 of the `start` lang item is incorrect
+    //[main_ret]~^ ERROR lang item `start` function has wrong type [E0308]
     100
 }
 
 #[cfg(argc)]
 #[lang = "start"]
 fn start<T>(_main: fn() -> T, _argc: i8, _argv: *const *const u8, _sigpipe: u8) -> isize {
-    //[argc]~^ ERROR parameter 2 of the `start` lang item is incorrect
+    //[argc]~^ ERROR lang item `start` function has wrong type [E0308]
     100
 }
 
 #[cfg(argv_inner_ptr)]
 #[lang = "start"]
 fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const usize, _sigpipe: u8) -> isize {
-    //[argv_inner_ptr]~^ ERROR parameter 3 of the `start` lang item is incorrect
+    //[argv_inner_ptr]~^ ERROR lang item `start` function has wrong type [E0308]
     100
 }
 
 #[cfg(argv)]
 #[lang = "start"]
 fn start<T>(_main: fn() -> T, _argc: isize, _argv: u8, _sigpipe: u8) -> isize {
-    //[argv]~^ ERROR parameter 3 of the `start` lang item is incorrect
+    //[argv]~^ ERROR lang item `start` function has wrong type [E0308]
     100
 }
 
 #[cfg(sigpipe)]
 #[lang = "start"]
 fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: i64) -> isize {
-    //[sigpipe]~^ ERROR parameter 4 of the `start` lang item is incorrect
+    //[sigpipe]~^ ERROR lang item `start` function has wrong type [E0308]
     100
 }
 
diff --git a/tests/ui/lang-items/start_lang_item_args.sigpipe.stderr b/tests/ui/lang-items/start_lang_item_args.sigpipe.stderr
index b20ae31280133..280d423bd7e1b 100644
--- a/tests/ui/lang-items/start_lang_item_args.sigpipe.stderr
+++ b/tests/ui/lang-items/start_lang_item_args.sigpipe.stderr
@@ -1,8 +1,12 @@
-error: parameter 4 of the `start` lang item is incorrect
+error[E0308]: lang item `start` function has wrong type
   --> $DIR/start_lang_item_args.rs:96:80
    |
 LL | fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: i64) -> isize {
-   |                                                                                ^^^ help: change the type from `i64` to `u8`
+   |                                                                                ^^^ expected `u8`, found `i64`
+   |
+   = note: expected signature `fn(fn() -> _, _, _, u8) -> _`
+              found signature `fn(fn() -> _, _, _, i64) -> _`
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/lang-items/start_lang_item_args.start_ret.stderr b/tests/ui/lang-items/start_lang_item_args.start_ret.stderr
index 935d5f3c8b426..4e4f8a5cdb39e 100644
--- a/tests/ui/lang-items/start_lang_item_args.start_ret.stderr
+++ b/tests/ui/lang-items/start_lang_item_args.start_ret.stderr
@@ -1,8 +1,12 @@
-error: the return type of the `start` lang item is incorrect
+error[E0308]: lang item `start` function has wrong type
   --> $DIR/start_lang_item_args.rs:34:87
    |
 LL | fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> u8 {
-   |                                                                                       ^^ help: change the type from `u8` to `isize`
+   |                                                                                       ^^ expected `isize`, found `u8`
+   |
+   = note: expected signature `fn(fn() -> _, _, _, _) -> isize`
+              found signature `fn(fn() -> _, _, _, _) -> u8`
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/lang-items/start_lang_item_args.too_many_args.stderr b/tests/ui/lang-items/start_lang_item_args.too_many_args.stderr
index 30a7ed18a3d23..085d4b1f238e3 100644
--- a/tests/ui/lang-items/start_lang_item_args.too_many_args.stderr
+++ b/tests/ui/lang-items/start_lang_item_args.too_many_args.stderr
@@ -1,4 +1,4 @@
-error: incorrect number of parameters for the `start` lang item
+error[E0308]: lang item `start` function has wrong type
   --> $DIR/start_lang_item_args.rs:41:1
    |
 LL | / fn start<T>(
@@ -8,10 +8,11 @@ LL | |     _argc: isize,
 ...  |
 LL | |     _extra_arg: (),
 LL | | ) -> isize {
-   | |__________^
+   | |__________^ incorrect number of function parameters
    |
-   = note: the `start` lang item should have four parameters, but found 5
-   = note: the `start` lang item should have the signature `fn(fn() -> T, isize, *const *const u8, u8) -> isize`
+   = note: expected signature `fn(fn() -> T, isize, *const *const u8, u8) -> _`
+              found signature `fn(fn() -> T, isize, *const *const u8, u8, ()) -> _`
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/main-wrong-type.stderr b/tests/ui/main-wrong-type.stderr
index 43efaf884e3a7..1e5f368758e6a 100644
--- a/tests/ui/main-wrong-type.stderr
+++ b/tests/ui/main-wrong-type.stderr
@@ -4,8 +4,8 @@ error[E0580]: `main` function has wrong type
 LL | fn main(foo: S) {
    | ^^^^^^^^^^^^^^^ incorrect number of function parameters
    |
-   = note: expected fn pointer `fn()`
-              found fn pointer `fn(S)`
+   = note: expected signature `fn()`
+              found signature `fn(S)`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/panic-handler/panic-handler-bad-signature-1.rs b/tests/ui/panic-handler/panic-handler-bad-signature-1.rs
index 775961d3fd740..ae27db7a83524 100644
--- a/tests/ui/panic-handler/panic-handler-bad-signature-1.rs
+++ b/tests/ui/panic-handler/panic-handler-bad-signature-1.rs
@@ -6,8 +6,5 @@
 use core::panic::PanicInfo;
 
 #[panic_handler]
-fn panic(
-    info: PanicInfo, //~ ERROR argument should be `&PanicInfo`
-) -> () //~ ERROR return type should be `!`
-{
-}
+fn panic(info: PanicInfo) -> () {}
+//~^ `#[panic_handler]` function has wrong type [E0308]
diff --git a/tests/ui/panic-handler/panic-handler-bad-signature-1.stderr b/tests/ui/panic-handler/panic-handler-bad-signature-1.stderr
index 8b044f7669c72..d12bfbf269eb7 100644
--- a/tests/ui/panic-handler/panic-handler-bad-signature-1.stderr
+++ b/tests/ui/panic-handler/panic-handler-bad-signature-1.stderr
@@ -1,14 +1,12 @@
-error: return type should be `!`
-  --> $DIR/panic-handler-bad-signature-1.rs:11:6
+error[E0308]: `#[panic_handler]` function has wrong type
+  --> $DIR/panic-handler-bad-signature-1.rs:9:16
    |
-LL | ) -> ()
-   |      ^^
-
-error: argument should be `&PanicInfo`
-  --> $DIR/panic-handler-bad-signature-1.rs:10:11
+LL | fn panic(info: PanicInfo) -> () {}
+   |                ^^^^^^^^^ expected `&PanicInfo<'_>`, found `PanicInfo<'_>`
    |
-LL |     info: PanicInfo,
-   |           ^^^^^^^^^
+   = note: expected signature `fn(&PanicInfo<'_>) -> !`
+              found signature `fn(PanicInfo<'_>)`
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/panic-handler/panic-handler-bad-signature-2.rs b/tests/ui/panic-handler/panic-handler-bad-signature-2.rs
index 727934000589a..3c3f1513f6fe8 100644
--- a/tests/ui/panic-handler/panic-handler-bad-signature-2.rs
+++ b/tests/ui/panic-handler/panic-handler-bad-signature-2.rs
@@ -6,9 +6,8 @@
 use core::panic::PanicInfo;
 
 #[panic_handler]
-fn panic(
-    info: &'static PanicInfo, //~ ERROR argument should be `&PanicInfo`
-) -> !
+fn panic(info: &'static PanicInfo) -> !
+//~^ #[panic_handler]` function has wrong type [E0308]
 {
     loop {}
 }
diff --git a/tests/ui/panic-handler/panic-handler-bad-signature-2.stderr b/tests/ui/panic-handler/panic-handler-bad-signature-2.stderr
index 5ab6934202e94..06e32d5fb84a3 100644
--- a/tests/ui/panic-handler/panic-handler-bad-signature-2.stderr
+++ b/tests/ui/panic-handler/panic-handler-bad-signature-2.stderr
@@ -1,8 +1,12 @@
-error: argument should be `&PanicInfo`
-  --> $DIR/panic-handler-bad-signature-2.rs:10:11
+error[E0308]: `#[panic_handler]` function has wrong type
+  --> $DIR/panic-handler-bad-signature-2.rs:9:1
    |
-LL |     info: &'static PanicInfo,
-   |           ^^^^^^^^^^^^^^^^^^
+LL | fn panic(info: &'static PanicInfo) -> !
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
+   |
+   = note: expected fn pointer `for<'a, 'b> fn(&'a PanicInfo<'b>) -> _`
+              found fn pointer `for<'a> fn(&'static PanicInfo<'a>) -> _`
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/panic-handler/panic-handler-bad-signature-3.rs b/tests/ui/panic-handler/panic-handler-bad-signature-3.rs
index ab9c9d7f4177c..9e17e32fbb4cb 100644
--- a/tests/ui/panic-handler/panic-handler-bad-signature-3.rs
+++ b/tests/ui/panic-handler/panic-handler-bad-signature-3.rs
@@ -6,6 +6,6 @@
 use core::panic::PanicInfo;
 
 #[panic_handler]
-fn panic() -> ! { //~ ERROR function should have one argument
+fn panic() -> ! { //~ #[panic_handler]` function has wrong type [E0308]
     loop {}
 }
diff --git a/tests/ui/panic-handler/panic-handler-bad-signature-3.stderr b/tests/ui/panic-handler/panic-handler-bad-signature-3.stderr
index 0a70181fdace9..8365f5769ebe3 100644
--- a/tests/ui/panic-handler/panic-handler-bad-signature-3.stderr
+++ b/tests/ui/panic-handler/panic-handler-bad-signature-3.stderr
@@ -1,8 +1,12 @@
-error: function should have one argument
+error[E0308]: `#[panic_handler]` function has wrong type
   --> $DIR/panic-handler-bad-signature-3.rs:9:1
    |
 LL | fn panic() -> ! {
-   | ^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^ incorrect number of function parameters
+   |
+   = note: expected signature `fn(&PanicInfo<'_>) -> _`
+              found signature `fn() -> _`
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/panic-handler/panic-handler-bad-signature-5.rs b/tests/ui/panic-handler/panic-handler-bad-signature-5.rs
new file mode 100644
index 0000000000000..97307d1b2a462
--- /dev/null
+++ b/tests/ui/panic-handler/panic-handler-bad-signature-5.rs
@@ -0,0 +1,13 @@
+// compile-flags:-C panic=abort
+
+#![no_std]
+#![no_main]
+
+use core::panic::PanicInfo;
+
+#[panic_handler]
+fn panic(info: &PanicInfo<'static>) -> !
+//~^ #[panic_handler]` function has wrong type [E0308]
+{
+    loop {}
+}
diff --git a/tests/ui/panic-handler/panic-handler-bad-signature-5.stderr b/tests/ui/panic-handler/panic-handler-bad-signature-5.stderr
new file mode 100644
index 0000000000000..22b8d5ca81151
--- /dev/null
+++ b/tests/ui/panic-handler/panic-handler-bad-signature-5.stderr
@@ -0,0 +1,12 @@
+error[E0308]: `#[panic_handler]` function has wrong type
+  --> $DIR/panic-handler-bad-signature-5.rs:9:1
+   |
+LL | fn panic(info: &PanicInfo<'static>) -> !
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
+   |
+   = note: expected fn pointer `for<'a, 'b> fn(&'a PanicInfo<'b>) -> _`
+              found fn pointer `for<'a> fn(&'a PanicInfo<'static>) -> _`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/range/issue-54505-no-std.rs b/tests/ui/range/issue-54505-no-std.rs
index db455fada3bd8..a15956853729a 100644
--- a/tests/ui/range/issue-54505-no-std.rs
+++ b/tests/ui/range/issue-54505-no-std.rs
@@ -17,9 +17,9 @@ extern "C" fn eh_personality() {}
 static EH_CATCH_TYPEINFO: u8 = 0;
 
 #[panic_handler]
-fn panic_handler() {}
-//~^ ERROR return type should be `!`
-//~| ERROR function should have one argument
+fn panic_handler(_: &core::panic::PanicInfo) -> ! {
+    unimplemented!();
+}
 
 // take a reference to any built-in range
 fn take_range(_r: &impl RangeBounds<i8>) {}
diff --git a/tests/ui/range/issue-54505-no-std.stderr b/tests/ui/range/issue-54505-no-std.stderr
index 13563d1940cb6..1694d514f4251 100644
--- a/tests/ui/range/issue-54505-no-std.stderr
+++ b/tests/ui/range/issue-54505-no-std.stderr
@@ -1,15 +1,3 @@
-error: return type should be `!`
-  --> $DIR/issue-54505-no-std.rs:20:20
-   |
-LL | fn panic_handler() {}
-   |                    ^
-
-error: function should have one argument
-  --> $DIR/issue-54505-no-std.rs:20:1
-   |
-LL | fn panic_handler() {}
-   | ^^^^^^^^^^^^^^^^^^
-
 error[E0308]: mismatched types
   --> $DIR/issue-54505-no-std.rs:29:16
    |
@@ -130,6 +118,6 @@ help: consider borrowing here
 LL |     take_range(&(..=42));
    |                ++     +
 
-error: aborting due to 8 previous errors
+error: aborting due to 6 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/resolve/bad-expr-path.stderr b/tests/ui/resolve/bad-expr-path.stderr
index 411130913c8f0..0392c1fa23993 100644
--- a/tests/ui/resolve/bad-expr-path.stderr
+++ b/tests/ui/resolve/bad-expr-path.stderr
@@ -16,8 +16,8 @@ error[E0580]: `main` function has wrong type
 LL | fn main(arguments: Vec<String>) {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters
    |
-   = note: expected fn pointer `fn()`
-              found fn pointer `fn(Vec<String>)`
+   = note: expected signature `fn()`
+              found signature `fn(Vec<String>)`
 
 error[E0425]: cannot find function `log` in this scope
   --> $DIR/bad-expr-path.rs:4:5
diff --git a/tests/ui/resolve/bad-expr-path2.stderr b/tests/ui/resolve/bad-expr-path2.stderr
index af3ca99c51024..9238b1f7023e5 100644
--- a/tests/ui/resolve/bad-expr-path2.stderr
+++ b/tests/ui/resolve/bad-expr-path2.stderr
@@ -16,8 +16,8 @@ error[E0580]: `main` function has wrong type
 LL | fn main(arguments: Vec<String>) {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters
    |
-   = note: expected fn pointer `fn()`
-              found fn pointer `fn(Vec<String>)`
+   = note: expected signature `fn()`
+              found signature `fn(Vec<String>)`
 
 error[E0425]: cannot find function `log` in this scope
   --> $DIR/bad-expr-path2.rs:6:5