diff --git a/Cargo.lock b/Cargo.lock
index bdfb51761760f..424f44e34f8e4 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4457,6 +4457,7 @@ dependencies = [
  "rustc_index",
  "rustc_infer",
  "rustc_lint",
+ "rustc_lint_defs",
  "rustc_macros",
  "rustc_middle",
  "rustc_serialize",
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index e9fa33f656f31..68f98c1a5c03d 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -2011,7 +2011,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                         }
                     }
 
-                    CastKind::Pointer(PointerCast::UnsafeFnPointer) => {
+                    CastKind::Pointer(
+                        ptr_cast @ (PointerCast::UnsafeFnPointer
+                        | PointerCast::DeprecatedSafeFnPointer),
+                    ) => {
                         let fn_sig = op.ty(body, tcx).fn_sig(tcx);
 
                         // The type that we see in the fcx is like
@@ -2021,7 +2024,14 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                         // and hence may contain unnormalized results.
                         let fn_sig = self.normalize(fn_sig, location);
 
-                        let ty_fn_ptr_from = tcx.safe_to_unsafe_fn_ty(fn_sig);
+                        let ty_fn_ptr_from = match ptr_cast {
+                            PointerCast::UnsafeFnPointer => tcx.safe_to_unsafe_fn_ty(fn_sig),
+                            PointerCast::DeprecatedSafeFnPointer => {
+                                tcx.unsafe_to_safe_fn_ty(fn_sig)
+                            }
+                            // parent match arm matches only these two variants
+                            _ => unreachable!(),
+                        };
 
                         if let Err(terr) = self.eq_types(
                             *ty,
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index a9ff710c91ed6..1d29873b8d847 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -585,6 +585,11 @@ fn codegen_stmt<'tcx>(
                     ref operand,
                     to_ty,
                 )
+                | Rvalue::Cast(
+                    CastKind::Pointer(PointerCast::DeprecatedSafeFnPointer),
+                    ref operand,
+                    to_ty,
+                )
                 | Rvalue::Cast(
                     CastKind::Pointer(PointerCast::MutToConstPointer),
                     ref operand,
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index fd29c9e281b92..08eba40cdd6b5 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -212,7 +212,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                             _ => bug!("{} cannot be cast to a fn ptr", operand.layout.ty),
                         }
                     }
-                    mir::CastKind::Pointer(PointerCast::UnsafeFnPointer) => {
+                    mir::CastKind::Pointer(
+                        PointerCast::UnsafeFnPointer | PointerCast::DeprecatedSafeFnPointer,
+                    ) => {
                         // This is a no-op at the LLVM level.
                         operand.val
                     }
diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs
index a244b79ed0754..a10c48304ca6f 100644
--- a/compiler/rustc_const_eval/src/interpret/cast.rs
+++ b/compiler/rustc_const_eval/src/interpret/cast.rs
@@ -63,14 +63,27 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 }
             }
 
-            Pointer(PointerCast::UnsafeFnPointer) => {
+            Pointer(
+                ptr_cast @ (PointerCast::UnsafeFnPointer | PointerCast::DeprecatedSafeFnPointer),
+            ) => {
                 let src = self.read_immediate(src)?;
                 match cast_ty.kind() {
                     ty::FnPtr(_) => {
                         // No change to value
                         self.write_immediate(*src, dest)?;
                     }
-                    _ => span_bug!(self.cur_span(), "fn to unsafe fn cast on {:?}", cast_ty),
+                    _ => {
+                        match ptr_cast {
+                            PointerCast::UnsafeFnPointer => {
+                                span_bug!(self.cur_span(), "fn to unsafe fn cast on {:?}", cast_ty)
+                            }
+                            PointerCast::DeprecatedSafeFnPointer => {
+                                span_bug!(self.cur_span(), "unsafe fn to fn cast on {:?}", cast_ty)
+                            }
+                            // parent match arm matches only these two variants
+                            _ => unreachable!(),
+                        };
+                    }
                 }
             }
 
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
index e203c79030d20..b5d689027d7c9 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -545,6 +545,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
             Rvalue::Cast(
                 CastKind::Pointer(
                     PointerCast::UnsafeFnPointer
+                    | PointerCast::DeprecatedSafeFnPointer
                     | PointerCast::ClosureFnPointer(_)
                     | PointerCast::ReifyFnPointer,
                 ),
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 7c53f839a92e4..ee05695057146 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -454,7 +454,13 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     ),
     // lang-team MCP 147
     gated!(
-        deprecated_safe, Normal, template!(List: r#"since = "version", note = "...""#), ErrorFollowing,
+        deprecated_safe, Normal,
+        template!(
+            Word,
+            List: r#"/*opt*/ since = "version", /*opt*/ note = "reason", /*opt*/ unsafe_edition = "edition""#,
+            NameValueStr: "reason"
+        ),
+        ErrorFollowing,
         experimental!(deprecated_safe),
     ),
 
diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs
index 09b02ba74a8de..a51410d156ee1 100644
--- a/compiler/rustc_infer/src/infer/at.rs
+++ b/compiler/rustc_infer/src/infer/at.rs
@@ -77,6 +77,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             err_count_on_creation: self.err_count_on_creation,
             in_snapshot: self.in_snapshot.clone(),
             universe: self.universe.clone(),
+            query_mode: self.query_mode.clone(),
         }
     }
 }
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 2524bd78355a1..e09aa18596d06 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -354,6 +354,30 @@ pub struct InferCtxt<'a, 'tcx> {
     /// when we enter into a higher-ranked (`for<..>`) type or trait
     /// bound.
     universe: Cell<ty::UniverseIndex>,
+
+    // FIXME(skippy) specifically needs reviewer feedback
+    // FIXME(skippy) this is added so that i can detect when enter_with_canonical()
+    //               is used, as a way to know that obligations will be coming in
+    //               with bad cause spans that can't be used
+    // FIXME(skippy) what i really want (i think) is something like
+    //               if !during_borrowck && !during_codegen
+    /// The mode that trait queries run in, which informs our error handling
+    /// policy. In essence, canonicalized queries need their errors propagated
+    /// rather than immediately reported because we do not have accurate spans.
+    pub query_mode: TraitQueryMode,
+}
+
+/// The mode that trait queries run in.
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+pub enum TraitQueryMode {
+    /// Standard/un-canonicalized queries get accurate
+    /// spans etc. passed in and hence can do reasonable
+    /// error reporting on their own.
+    Standard,
+    /// Canonicalized queries get dummy spans and hence
+    /// must generally propagate errors to
+    /// pre-canonicalization callsites.
+    Canonical,
 }
 
 /// See the `error_reporting` module for more details.
@@ -615,14 +639,26 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
     where
         T: TypeFoldable<'tcx>,
     {
-        self.enter(|infcx| {
-            let (value, subst) =
-                infcx.instantiate_canonical_with_fresh_inference_vars(span, canonical);
-            f(infcx, value, subst)
-        })
+        self.enter_with_query_mode(
+            |infcx| {
+                let (value, subst) =
+                    infcx.instantiate_canonical_with_fresh_inference_vars(span, canonical);
+                f(infcx, value, subst)
+            },
+            TraitQueryMode::Canonical,
+        )
     }
 
     pub fn enter<R>(&mut self, f: impl for<'a> FnOnce(InferCtxt<'a, 'tcx>) -> R) -> R {
+        self.enter_with_query_mode(f, TraitQueryMode::Standard)
+    }
+
+    // FIXME(skippy) specifically needs reviewer feedback (see query_mode field)
+    fn enter_with_query_mode<R>(
+        &mut self,
+        f: impl for<'a> FnOnce(InferCtxt<'a, 'tcx>) -> R,
+        query_mode: TraitQueryMode,
+    ) -> R {
         let InferCtxtBuilder { tcx, defining_use_anchor, ref fresh_typeck_results } = *self;
         let in_progress_typeck_results = fresh_typeck_results.as_ref();
         f(InferCtxt {
@@ -640,6 +676,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
             in_snapshot: Cell::new(false),
             skip_leak_check: Cell::new(false),
             universe: Cell::new(ty::UniverseIndex::ROOT),
+            query_mode,
         })
     }
 }
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 5704c6ed3b25d..65720a93fcca3 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -3129,6 +3129,7 @@ declare_lint_pass! {
         UNEXPECTED_CFGS,
         DEPRECATED_WHERE_CLAUSE_LOCATION,
         TEST_UNSTABLE_LINT,
+        DEPRECATED_SAFE,
     ]
 }
 
@@ -3794,3 +3795,47 @@ declare_lint! {
     "this unstable lint is only for testing",
     @feature_gate = sym::test_unstable_lint;
 }
+
+declare_lint! {
+    /// The `deprecated_safe` lint detects safe, unsound usage of items that are now marked ```[unsafe]```,
+    /// with safe usage being deprecated.
+    ///
+    /// ### Example
+    ///
+    /// ```rust
+    /// #![feature(deprecated_safe)]
+    ///
+    /// #[deprecated_safe(since = "1.61.0", note = "reason")]
+    /// unsafe fn previously_safe_function() {}
+    ///
+    /// fn main() {
+    ///     previously_safe_function();
+    /// }
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// FIXME(skippy) broken link: [`deprecated_safe` attribute]
+    /// Items may be marked "deprecated_safe" with the [`deprecated_safe` attribute] to
+    /// indicate that they should no longer be used. Usually the attribute
+    /// should include a note on what to use instead, or check the
+    /// documentation.
+    ///
+    /// [`deprecated_safe` attribute]: https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-deprecated_safe-attribute
+    /// [`unsafe fn`]: https://doc.rust-lang.org/reference/unsafe-functions.html
+    /// [`unsafe` trait]: https://doc.rust-lang.org/reference/items/traits.html#unsafe-traits
+    /// [`unsafe` block]: https://doc.rust-lang.org/reference/expressions/block-expr.html#unsafe-blocks
+    /// [unsafe]: https://doc.rust-lang.org/reference/unsafety.html
+    pub DEPRECATED_SAFE,
+    Warn,
+    "detects unsound use of items that are now marked unsafe, when safe use is deprecated",
+    report_in_external_macro
+    // FIXME(skippy) use future_incompatible?
+    /*
+    @future_incompatible = FutureIncompatibleInfo {
+        reference: "issue #94978 <https://github.com/rust-lang/rust/issues/94978>",
+    };
+    */
+}
diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs
index fd6e241346db8..1ceaa7b79c475 100644
--- a/compiler/rustc_middle/src/middle/stability.rs
+++ b/compiler/rustc_middle/src/middle/stability.rs
@@ -4,23 +4,27 @@
 pub use self::StabilityLevel::*;
 
 use crate::ty::{self, DefIdTree, TyCtxt};
-use rustc_ast::NodeId;
+use rustc_ast::{Attribute, MetaItem, MetaItemKind, NestedMetaItem, NodeId};
 use rustc_attr::{self as attr, ConstStability, Deprecation, Stability};
 use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::{Applicability, Diagnostic};
+use rustc_errors::{struct_span_err, Applicability, Diagnostic};
 use rustc_feature::GateIssue;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_INDEX};
 use rustc_hir::{self, HirId};
 use rustc_middle::ty::print::with_no_trimmed_paths;
-use rustc_session::lint::builtin::{DEPRECATED, DEPRECATED_IN_FUTURE, SOFT_UNSTABLE};
+use rustc_session::lint::builtin::{
+    DEPRECATED, DEPRECATED_IN_FUTURE, DEPRECATED_SAFE, SOFT_UNSTABLE,
+};
 use rustc_session::lint::{BuiltinLintDiagnostics, Level, Lint, LintBuffer};
 use rustc_session::parse::feature_err_issue;
 use rustc_session::Session;
+use rustc_span::edition::Edition;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
 use std::num::NonZeroU32;
+use std::str::FromStr;
 
 #[derive(PartialEq, Clone, Copy, Debug)]
 pub enum StabilityLevel {
@@ -247,6 +251,262 @@ fn late_report_deprecation(
     });
 }
 
+// FIXME(skippy) specifically needs reviewer feedback
+// FIXME(skippy) is stability::* the right place for all this stuff?
+#[derive(Copy, Debug, Clone)]
+pub struct DeprecationAsSafe {
+    pub since: Option<Symbol>,
+    /// The note to issue a reason.
+    pub note: Option<Symbol>,
+
+    /// The edition where the item is treated as fully unsafe with
+    /// safe usage erroring instead of emitting a deprecated_safe lint
+    pub unsafe_edition: Option<Edition>,
+}
+
+pub enum DeprecationAsSafeKind {
+    FnCall { unsafe_op_in_unsafe_fn_allowed: bool },
+    FnPointerCoercion,
+    FnTraitCoercion,
+    TraitImpl,
+    TraitFnImpl,
+}
+
+// check whether this item should be treated as an unsafe item marked with #[deprecated_safe]
+// - in stable usage the item will always be marked unsafe
+// - in unstable usage the item will not be marked unsafe, but it will behave as if it is
+//   within libstd
+pub fn check_deprecation_as_safe(tcx: TyCtxt<'_>, def_id: DefId, span: Span) -> bool {
+    // #[deprecated_safe] is unstable, ignore it completely on stable rust
+    if !tcx.sess.is_nightly_build() {
+        return false;
+    }
+
+    // look up the atttribute
+    let Some(attr) = tcx.get_attrs(def_id).iter().find(|x| x.has_name(sym::deprecated_safe)) else {
+        return false;
+    };
+    let Some(depr_as_safe) = parse_deprecation_as_safe(tcx, attr) else {
+        bug!("invalid #[deprecated_safe] attribute during reporting");
+    };
+
+    // if the `unsafe_edition` has been reached, #[deprecated_safe] ceases to exist
+    // and the function/trait behaves fully unsafe with no escape hatch
+    // note: `unsafe_edition` is only checked once the ```since``` version is in effect
+    if let Some(unsafe_edition) = depr_as_safe.unsafe_edition
+        && span.edition() >= unsafe_edition
+    {
+        return false;
+    }
+
+    true
+}
+
+pub fn parse_deprecation_as_safe(tcx: TyCtxt<'_>, attr: &Attribute) -> Option<DeprecationAsSafe> {
+    let Some(meta_kind) = attr.meta_kind() else {
+        return None;
+    };
+
+    let mut since = None;
+    let mut note = None;
+    let mut unsafe_edition = None;
+
+    match &meta_kind {
+        MetaItemKind::Word => {}
+        MetaItemKind::NameValue(..) => note = attr.value_str(),
+        MetaItemKind::List(list) => {
+            let get = |meta: &MetaItem, item: &mut Option<Symbol>| {
+                if item.is_some() {
+                    struct_span_err!(
+                        tcx.sess,
+                        attr.span,
+                        E0538,
+                        "multiple '{}' items",
+                        &meta.name_or_empty()
+                    )
+                    .emit();
+                    return false;
+                }
+                if let Some(v) = meta.value_str() {
+                    *item = Some(v);
+                    true
+                } else {
+                    if let Some(lit) = meta.name_value_literal() {
+                        struct_span_err!(
+                            tcx.sess,
+                            lit.span,
+                            E0565,
+                            "literal in `deprecated_safe` value must be a string",
+                        )
+                        .emit();
+                    } else {
+                        struct_span_err!(
+                            tcx.sess,
+                            meta.span,
+                            E0551,
+                            "incorrect meta item '{}'",
+                            meta.name_or_empty()
+                        )
+                        .emit();
+                    }
+
+                    false
+                }
+            };
+
+            for meta in list {
+                match meta {
+                    NestedMetaItem::MetaItem(mi) => match mi.name_or_empty() {
+                        sym::since => {
+                            if !get(mi, &mut since) {
+                                return None;
+                            }
+                        }
+                        sym::note => {
+                            if !get(mi, &mut note) {
+                                return None;
+                            }
+                        }
+                        sym::unsafe_edition => {
+                            if !get(mi, &mut unsafe_edition) {
+                                return None;
+                            }
+                        }
+                        _ => {
+                            struct_span_err!(
+                                tcx.sess,
+                                mi.span,
+                                E0541,
+                                "unknown meta item '{}'",
+                                mi.name_or_empty()
+                            )
+                            .emit();
+                            return None;
+                        }
+                    },
+                    NestedMetaItem::Literal(lit) => {
+                        struct_span_err!(
+                            tcx.sess,
+                            lit.span,
+                            E0565,
+                            "item in `deprecated_safe` must be a key/value pair",
+                        )
+                        .emit();
+                        return None;
+                    }
+                }
+            }
+        }
+    }
+
+    let mut unsafe_edition_parsed = None;
+    if let Some(unsafe_edition) = unsafe_edition {
+        if let Ok(unsafe_edition) = Edition::from_str(unsafe_edition.as_str()) {
+            unsafe_edition_parsed = Some(unsafe_edition);
+        } else {
+            struct_span_err!(
+                tcx.sess,
+                attr.span,
+                // FIXME(skippy) wrong error code, need to create a new one
+                E0543,
+                "invalid 'unsafe_edition' specified"
+            )
+            .emit();
+            return None;
+        }
+    }
+
+    Some(DeprecationAsSafe { since, note, unsafe_edition: unsafe_edition_parsed })
+}
+
+pub fn report_deprecation_as_safe<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    kind: DeprecationAsSafeKind,
+    def_id: DefId,
+    lint_root: HirId,
+    span: Span,
+) {
+    let def_path = with_no_trimmed_paths!(tcx.def_path_str(def_id));
+    let def_kind = tcx.def_kind(def_id).descr(def_id);
+
+    // look up the atttribute
+    let Some(attr) = tcx.get_attrs(def_id).iter().find(|x| x.has_name(sym::deprecated_safe)) else {
+        bug!("missing #[deprecated_safe] attribute during reporting");
+    };
+    let Some(depr_as_safe) = parse_deprecation_as_safe(tcx, attr) else {
+        bug!("invalid #[deprecated_safe] attribute during reporting");
+    };
+
+    let (message, span_label) = match kind {
+        DeprecationAsSafeKind::FnCall { unsafe_op_in_unsafe_fn_allowed } => {
+            let fn_sugg = if unsafe_op_in_unsafe_fn_allowed { " function or" } else { "" };
+            (
+                format!(
+                    "use of {} `{}` without an unsafe{} block has been deprecated as it is now an unsafe {}",
+                    def_kind, def_path, fn_sugg, def_kind
+                ),
+                Some("call to unsafe function"),
+            )
+        }
+        DeprecationAsSafeKind::FnPointerCoercion => (
+            format!(
+                "use of {} `{}` as a normal fn pointer has been deprecated as it is now an unsafe {}",
+                def_kind, def_path, def_kind
+            ),
+            Some("expected normal fn pointer, found unsafe fn pointer"),
+        ),
+        DeprecationAsSafeKind::FnTraitCoercion => (
+            format!(
+                "use of {} `{}` as a closure has been deprecated as it is now an unsafe {}",
+                def_kind, def_path, def_kind
+            ),
+            None,
+        ),
+        DeprecationAsSafeKind::TraitImpl => (
+            format!(
+                "use of {} `{}` without an `unsafe impl` declaration has been deprecated as it is now an unsafe {}",
+                def_kind, def_path, def_kind
+            ),
+            None,
+        ),
+        DeprecationAsSafeKind::TraitFnImpl => (
+            format!(
+                "use of {} `{}` without an `unsafe fn` declaration has been deprecated as it is now an unsafe {}",
+                def_kind, def_path, def_kind
+            ),
+            None,
+        ),
+    };
+
+    tcx.struct_span_lint_hir(DEPRECATED_SAFE, lint_root, span, |lint| {
+        let mut diag = lint.build(&message);
+        if let Some(span_label) = span_label {
+            diag.span_label(span, span_label);
+        }
+
+        let since_message = if let Some(since) = depr_as_safe.since {
+            format!(" since {}", since)
+        } else {
+            "".to_owned()
+        };
+        diag.note(&format!(
+            "this {} was previously not marked unsafe, but has been marked unsafe{}",
+            def_kind, since_message,
+        ));
+
+        diag.note(&format!(
+            "consult the {}'s documentation for information on how to avoid undefined behavior",
+            def_kind
+        ));
+
+        if let Some(note) = depr_as_safe.note {
+            diag.note(note.as_str());
+        }
+
+        diag.emit();
+    });
+}
+
 /// Result of `TyCtxt::eval_stability`.
 pub enum EvalResult {
     /// We can use the item because it is stable or we provided the
diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs
index cee510a42413a..22496edd98cbc 100644
--- a/compiler/rustc_middle/src/mir/query.rs
+++ b/compiler/rustc_middle/src/mir/query.rs
@@ -25,6 +25,9 @@ pub enum UnsafetyViolationKind {
     /// Unsafe operation in an `unsafe fn` but outside an `unsafe` block.
     /// Has to be handled as a lint for backwards compatibility.
     UnsafeFn,
+    /// Unsafe operation that was previously marked safe but has been deprecated as such.
+    /// Has to be handled as a lint for backwards compatibility.
+    DeprecatedSafe { depr_as_safe: DefId },
 }
 
 #[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)]
diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs
index ffa70cddbd59c..3eb33e7df2263 100644
--- a/compiler/rustc_middle/src/traits/select.rs
+++ b/compiler/rustc_middle/src/traits/select.rs
@@ -130,6 +130,10 @@ pub enum SelectionCandidate<'tcx> {
     /// types generated for a fn pointer type (e.g., `fn(int) -> int`)
     FnPointerCandidate {
         is_const: bool,
+        // if a #[deprecated_safe] fn() is being used as a closure, this points
+        // to the FnDef of that fn(). a deprecated_safe lint must be emitted
+        // if this candidate is used
+        depr_as_safe: Option<DefId>,
     },
 
     /// Builtin implementation of `DiscriminantKind`.
@@ -152,7 +156,12 @@ pub enum SelectionCandidate<'tcx> {
 
     BuiltinObjectCandidate,
 
-    BuiltinUnsizeCandidate,
+    BuiltinUnsizeCandidate {
+        // if a #[deprecated_safe] fn() is being used as a closure, this points
+        // to the FnDef of that fn(). a deprecated_safe lint must be emitted
+        // if this candidate is used
+        depr_as_safe: Option<DefId>,
+    },
 
     /// Implementation of `const Destruct`, optionally from a custom `impl const Drop`.
     ConstDestructCandidate(Option<DefId>),
diff --git a/compiler/rustc_middle/src/ty/adjustment.rs b/compiler/rustc_middle/src/ty/adjustment.rs
index 2676b7ab521d8..2476c07b9ec0e 100644
--- a/compiler/rustc_middle/src/ty/adjustment.rs
+++ b/compiler/rustc_middle/src/ty/adjustment.rs
@@ -14,6 +14,10 @@ pub enum PointerCast {
     /// Go from a safe fn pointer to an unsafe fn pointer.
     UnsafeFnPointer,
 
+    /// Go from an unsafe fn pointer to a safe fn pointer.
+    /// This is unsound, but used for backwards compatibility by `#[deprecated_safe]`.
+    DeprecatedSafeFnPointer,
+
     /// Go from a non-capturing closure to an fn pointer or an unsafe fn pointer.
     /// It cannot convert a closure that requires unsafe.
     ClosureFnPointer(hir::Unsafety),
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 6ca8f8b1309fa..15b157637dc44 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -2186,13 +2186,21 @@ slice_interners!(
 
 impl<'tcx> TyCtxt<'tcx> {
     /// Given a `fn` type, returns an equivalent `unsafe fn` type;
-    /// that is, a `fn` type that is equivalent in every way for being
+    /// that is, a `fn` type that is equivalent in every way except for being
     /// unsafe.
     pub fn safe_to_unsafe_fn_ty(self, sig: PolyFnSig<'tcx>) -> Ty<'tcx> {
         assert_eq!(sig.unsafety(), hir::Unsafety::Normal);
         self.mk_fn_ptr(sig.map_bound(|sig| ty::FnSig { unsafety: hir::Unsafety::Unsafe, ..sig }))
     }
 
+    /// Given a `unsafe fn` type, returns an equivalent `fn` type;
+    /// that is, a `fn` type that is equivalent in every way except for being
+    /// safe. This is unsound, but used for backwards compatibility by `#[deprecated_safe]`.
+    pub fn unsafe_to_safe_fn_ty(self, sig: PolyFnSig<'tcx>) -> Ty<'tcx> {
+        assert_eq!(sig.unsafety(), hir::Unsafety::Unsafe);
+        self.mk_fn_ptr(sig.map_bound(|sig| ty::FnSig { unsafety: hir::Unsafety::Normal, ..sig }))
+    }
+
     /// Given the def_id of a Trait `trait_def_id` and the name of an associated item `assoc_name`
     /// returns true if the `trait_def_id` defines an associated item of name `assoc_name`.
     pub fn trait_may_define_assoc_type(self, trait_def_id: DefId, assoc_name: Ident) -> bool {
diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs
index eadce3dc9c467..0a232e5a69cfc 100644
--- a/compiler/rustc_mir_build/src/check_unsafety.rs
+++ b/compiler/rustc_mir_build/src/check_unsafety.rs
@@ -1,4 +1,5 @@
 use crate::build::ExprCategory;
+use rustc_middle::middle::stability::{self, DeprecationAsSafeKind};
 use rustc_middle::thir::visit::{self, Visitor};
 
 use rustc_errors::struct_span_err;
@@ -72,16 +73,28 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
     fn requires_unsafe(&mut self, span: Span, kind: UnsafeOpKind) {
         let (description, note) = kind.description_and_note();
         let unsafe_op_in_unsafe_fn_allowed = self.unsafe_op_in_unsafe_fn_allowed();
-        match self.safety_context {
-            SafetyContext::BuiltinUnsafeBlock => {}
-            SafetyContext::UnsafeBlock { ref mut used, .. } => {
+        match (&mut self.safety_context, kind) {
+            (SafetyContext::BuiltinUnsafeBlock, _) => {}
+            (SafetyContext::UnsafeBlock { ref mut used, .. }, _) => {
                 if !self.body_unsafety.is_unsafe() || !unsafe_op_in_unsafe_fn_allowed {
                     // Mark this block as useful
                     *used = true;
                 }
             }
-            SafetyContext::UnsafeFn if unsafe_op_in_unsafe_fn_allowed => {}
-            SafetyContext::UnsafeFn => {
+            (SafetyContext::UnsafeFn, _) if unsafe_op_in_unsafe_fn_allowed => {}
+            // check if this is a call to a #[deprecated_safe] fn() and lint if so
+            // instead of erroring
+            (
+                SafetyContext::UnsafeFn | SafetyContext::Safe,
+                CallToDeprecatedSafeFunction { depr_as_safe },
+            ) => stability::report_deprecation_as_safe(
+                self.tcx,
+                DeprecationAsSafeKind::FnCall { unsafe_op_in_unsafe_fn_allowed },
+                depr_as_safe,
+                self.hir_context,
+                span,
+            ),
+            (SafetyContext::UnsafeFn, _) => {
                 // unsafe_op_in_unsafe_fn is disallowed
                 self.tcx.struct_span_lint_hir(
                     UNSAFE_OP_IN_UNSAFE_FN,
@@ -98,7 +111,7 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
                     },
                 )
             }
-            SafetyContext::Safe => {
+            (SafetyContext::Safe, _) => {
                 let fn_sugg = if unsafe_op_in_unsafe_fn_allowed { " function or" } else { "" };
                 struct_span_err!(
                     self.tcx.sess,
@@ -350,8 +363,21 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
             }
             ExprKind::Call { fun, ty: _, args: _, from_hir_call: _, fn_span: _ } => {
                 if self.thir[fun].ty.fn_sig(self.tcx).unsafety() == hir::Unsafety::Unsafe {
-                    self.requires_unsafe(expr.span, CallToUnsafeFunction);
-                } else if let &ty::FnDef(func_did, _) = self.thir[fun].ty.kind() {
+                    // check if this is a call to a #[deprecated_safe] fn() and lint if so
+                    // instead of erroring
+                    if let ty::FnDef(func_id, _) = self.thir[fun].ty.kind()
+                        && stability::check_deprecation_as_safe(self.tcx, *func_id, expr.span)
+                    {
+                        self.requires_unsafe(
+                            expr.span,
+                            CallToDeprecatedSafeFunction { depr_as_safe: *func_id },
+                        );
+                    } else {
+                        self.requires_unsafe(expr.span, CallToUnsafeFunction);
+                    }
+                }
+
+                if let &ty::FnDef(func_did, _) = self.thir[fun].ty.kind() {
                     // If the called function has target features the calling function hasn't,
                     // the call requires `unsafe`. Don't check this on wasm
                     // targets, though. For more information on wasm see the
@@ -524,6 +550,7 @@ impl BodyUnsafety {
 #[derive(Clone, Copy, PartialEq)]
 enum UnsafeOpKind {
     CallToUnsafeFunction,
+    CallToDeprecatedSafeFunction { depr_as_safe: DefId },
     UseOfInlineAssembly,
     InitializingTypeWith,
     UseOfMutableStatic,
@@ -546,6 +573,8 @@ impl UnsafeOpKind {
                 "consult the function's documentation for information on how to avoid undefined \
                  behavior",
             ),
+            // unused, report_deprecation_as_safe is used instead
+            CallToDeprecatedSafeFunction { .. } => ("", ""),
             UseOfInlineAssembly => (
                 "use of inline assembly",
                 "inline assembly is entirely unchecked and can cause undefined behavior",
diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs
index f5d82315c4e38..463db7a5e3811 100644
--- a/compiler/rustc_mir_transform/src/check_unsafety.rs
+++ b/compiler/rustc_mir_transform/src/check_unsafety.rs
@@ -4,6 +4,7 @@ use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::hir_id::HirId;
 use rustc_hir::intravisit;
+use rustc_middle::middle::stability::{self, DeprecationAsSafeKind};
 use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, TyCtxt};
@@ -72,10 +73,27 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> {
                 let func_ty = func.ty(self.body, self.tcx);
                 let sig = func_ty.fn_sig(self.tcx);
                 if let hir::Unsafety::Unsafe = sig.unsafety() {
-                    self.require_unsafe(
-                        UnsafetyViolationKind::General,
-                        UnsafetyViolationDetails::CallToUnsafeFunction,
-                    )
+                    // check if this is a call to a #[deprecated_safe] fn() and lint if so
+                    // instead of erroring
+                    if let ty::FnDef(func_id, _) = func_ty.kind()
+                        && stability::check_deprecation_as_safe(
+                            self.tcx,
+                            *func_id,
+                            self.source_info.span,
+                        )
+                    {
+                        self.require_unsafe(
+                            UnsafetyViolationKind::DeprecatedSafe {
+                                depr_as_safe: *func_id,
+                            },
+                            UnsafetyViolationDetails::CallToUnsafeFunction,
+                        )
+                    } else {
+                        self.require_unsafe(
+                            UnsafetyViolationKind::General,
+                            UnsafetyViolationDetails::CallToUnsafeFunction,
+                        )
+                    }
                 }
 
                 if let ty::FnDef(func_id, _) = func_ty.kind() {
@@ -289,7 +307,8 @@ impl<'tcx> UnsafetyChecker<'_, 'tcx> {
             // `unsafe` blocks are required in safe code
             Safety::Safe => violations.into_iter().for_each(|&violation| {
                 match violation.kind {
-                    UnsafetyViolationKind::General => {}
+                    UnsafetyViolationKind::General
+                    | UnsafetyViolationKind::DeprecatedSafe { .. } => {}
                     UnsafetyViolationKind::UnsafeFn => {
                         bug!("`UnsafetyViolationKind::UnsafeFn` in an `Safe` context")
                     }
@@ -300,7 +319,15 @@ impl<'tcx> UnsafetyChecker<'_, 'tcx> {
             }),
             // With the RFC 2585, no longer allow `unsafe` operations in `unsafe fn`s
             Safety::FnUnsafe => violations.into_iter().for_each(|&(mut violation)| {
-                violation.kind = UnsafetyViolationKind::UnsafeFn;
+                if unsafe_op_in_unsafe_fn_allowed(self.tcx, violation.lint_root) {
+                    return;
+                }
+
+                // switch violation kind so that the unsafe_op_in_unsafe_fn lint is emitted instead,
+                // but preserve any deprecated_safe lint
+                if !matches!(violation.kind, UnsafetyViolationKind::DeprecatedSafe { .. }) {
+                    violation.kind = UnsafetyViolationKind::UnsafeFn;
+                }
                 if !self.violations.contains(&violation) {
                     self.violations.push(violation)
                 }
@@ -310,10 +337,10 @@ impl<'tcx> UnsafetyChecker<'_, 'tcx> {
                 update_entry(
                     self,
                     hir_id,
-                    match self.tcx.lint_level_at_node(UNSAFE_OP_IN_UNSAFE_FN, violation.lint_root).0
-                    {
-                        Level::Allow => AllAllowedInUnsafeFn(violation.lint_root),
-                        _ => SomeDisallowedInUnsafeFn,
+                    if unsafe_op_in_unsafe_fn_allowed(self.tcx, violation.lint_root) {
+                        AllAllowedInUnsafeFn(violation.lint_root)
+                    } else {
+                        SomeDisallowedInUnsafeFn
                     },
                 )
             }),
@@ -580,8 +607,8 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) {
         let (description, note) = details.description_and_note();
 
         // Report an error.
-        let unsafe_fn_msg =
-            if unsafe_op_in_unsafe_fn_allowed(tcx, lint_root) { " function or" } else { "" };
+        let unsafe_op_in_unsafe_fn_allowed = unsafe_op_in_unsafe_fn_allowed(tcx, lint_root);
+        let unsafe_fn_msg = if unsafe_op_in_unsafe_fn_allowed { " function or" } else { "" };
 
         match kind {
             UnsafetyViolationKind::General => {
@@ -612,6 +639,15 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) {
                     .emit();
                 },
             ),
+            UnsafetyViolationKind::DeprecatedSafe { depr_as_safe } => {
+                stability::report_deprecation_as_safe(
+                    tcx,
+                    DeprecationAsSafeKind::FnCall { unsafe_op_in_unsafe_fn_allowed },
+                    depr_as_safe,
+                    lint_root,
+                    source_info.span,
+                )
+            }
         }
     }
 
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 1f12f99efb3d5..0adc4cda28100 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -14,6 +14,7 @@ use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{self, FnSig, ForeignItem, HirId, Item, ItemKind, TraitItem, CRATE_HIR_ID};
 use rustc_hir::{MethodKind, Target};
 use rustc_middle::hir::nested_filter;
+use rustc_middle::middle::stability;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::lint::builtin::{
@@ -128,6 +129,7 @@ impl CheckAttrVisitor<'_> {
                 | sym::unstable
                 | sym::stable
                 | sym::rustc_promotable => self.check_stability_promotable(&attr, span, target),
+                sym::deprecated_safe => self.check_deprecated_safe(hir_id, &attr, span, target),
                 _ => true,
             };
             is_valid &= attr_is_valid;
@@ -2008,6 +2010,100 @@ impl CheckAttrVisitor<'_> {
                 .emit();
         });
     }
+
+    fn check_deprecated_safe(
+        &self,
+        hir_id: HirId,
+        attr: &Attribute,
+        span: Span,
+        _target: Target,
+    ) -> bool {
+        let node = self.tcx.hir().get(hir_id);
+        let def_id = self.tcx.hir().local_def_id(hir_id).to_def_id();
+
+        let mut unsafety = None;
+        if let hir::Node::Item(item) = node {
+            if let Some(fn_sig) = node.fn_sig() {
+                unsafety = Some(fn_sig.header.unsafety);
+            } else if let hir::ItemKind::Trait(_, trait_unsafety, ..) = item.kind {
+                unsafety = Some(trait_unsafety);
+            }
+        } else if let hir::Node::TraitItem(_) = node {
+            if let Some(fn_sig) = node.fn_sig() {
+                unsafety = Some(fn_sig.header.unsafety);
+            }
+        }
+
+        let Some(unsafety) = unsafety else {
+            struct_span_err!(
+                self.tcx.sess,
+                attr.span,
+                // FIXME(skippy) wrong error code, need to create a new one
+                E0543,
+                "this `#[deprecated_safe]` annotation has no effect"
+            )
+            .emit();
+            return false;
+        };
+
+        if let Some(depr_as_safe) = stability::parse_deprecation_as_safe(self.tcx, attr) {
+            if unsafety == hir::Unsafety::Normal {
+                struct_span_err!(
+                    self.tcx.sess,
+                    span,
+                    // FIXME(skippy) wrong error code, need to create a new one
+                    E0543,
+                    "item must be marked unsafe"
+                )
+                .emit();
+                return false;
+            }
+
+            let is_rustc =
+                self.tcx.features().staged_api || self.tcx.lookup_stability(def_id).is_some();
+            if is_rustc {
+                if depr_as_safe.since.is_none() {
+                    struct_span_err!(
+                        self.tcx.sess,
+                        attr.span,
+                        // FIXME(skippy) wrong error code, need to create a new one
+                        E0542,
+                        "missing 'since'"
+                    )
+                    .emit();
+                    return false;
+                }
+
+                if depr_as_safe.note.is_none() {
+                    struct_span_err!(
+                        self.tcx.sess,
+                        attr.span,
+                        // FIXME(skippy) wrong error code, need to create a new one
+                        E0543,
+                        "missing 'note'"
+                    )
+                    .emit();
+                    return false;
+                }
+            } else {
+                if depr_as_safe.unsafe_edition.is_some() {
+                    struct_span_err!(
+                        self.tcx.sess,
+                        attr.span,
+                        // FIXME(skippy) wrong error code, need to create a new one
+                        E0543,
+                        "'unsafe_edition' is invalid outside of rustc"
+                    )
+                    .emit();
+                    return false;
+                }
+            }
+
+            true
+        } else {
+            false
+        }
+    }
 }
 
 impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> {
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index f5803aaa0786e..7a9bed688f275 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1466,6 +1466,7 @@ symbols! {
         unrestricted_attribute_tokens,
         unsafe_block_in_unsafe_fn,
         unsafe_cell,
+        unsafe_edition,
         unsafe_no_drop_flag,
         unsafe_pin_internals,
         unsize,
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 9998c5bb087e1..d2a31e29a6acf 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -2051,7 +2051,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
                 );
                 let mut selcx = SelectionContext::with_query_mode(
                     &self,
-                    crate::traits::TraitQueryMode::Standard,
+                    crate::infer::TraitQueryMode::Standard,
                 );
                 match selcx.select_from_obligation(&obligation) {
                     Err(SelectionError::Ambiguous(impls)) if impls.len() > 1 => {
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index 053e871c14f6e..b60eb1e785e4a 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -5,6 +5,7 @@ use rustc_data_structures::obligation_forest::{Error, ForestObligation, Outcome}
 use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor};
 use rustc_infer::traits::ProjectionCacheKey;
 use rustc_infer::traits::{SelectionError, TraitEngine, TraitEngineExt as _, TraitObligation};
+use rustc_middle::middle::stability;
 use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::thir::abstract_const::NotConstEvaluatable;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
@@ -674,8 +675,30 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
         stalled_on: &mut Vec<TyOrConstInferVar<'tcx>>,
     ) -> ProcessResult<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>> {
         let infcx = self.selcx.infcx();
-        if obligation.predicate.is_global() {
-            // no type variables present, can use evaluation for better caching.
+        let is_global = obligation.predicate.is_global();
+
+        // FIXME(skippy) specifically needs reviewer feedback
+        // check if this predicate can't be treated as global due to this being a
+        // #[deprecated_safe] fn() to closure coercion, if evaluation is used there
+        // won't be a proper cause span to lint against
+        let mut is_depr_safe_fn_closure = false;
+        if is_global && let trait_ty = trait_obligation.self_ty().skip_binder()
+            && let ty::FnDef(func_id, _) = trait_ty.kind()
+            && self.selcx.tcx().fn_trait_kind_from_lang_item(
+                trait_obligation.predicate.skip_binder().trait_ref.def_id
+            ).is_some()
+            && stability::check_deprecation_as_safe(
+                self.selcx.tcx(),
+                *func_id,
+                obligation.cause.span,
+            )
+        {
+            is_depr_safe_fn_closure = true;
+        }
+
+        if is_global && !is_depr_safe_fn_closure {
+            // no type variables present and not a #[deprecated_safe] fn() to closure coercion,
+            // can use evaluation for better caching.
             // FIXME: consider caching errors too.
             if infcx.predicate_must_hold_considering_regions(obligation) {
                 debug!(
@@ -728,8 +751,31 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
     ) -> ProcessResult<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>> {
         let tcx = self.selcx.tcx();
 
-        if obligation.predicate.is_global() {
-            // no type variables present, can use evaluation for better caching.
+        let is_global = obligation.predicate.is_global();
+
+        // FIXME(skippy) specifically needs reviewer feedback
+        // check if this predicate can't be treated as global due to this being a
+        // #[deprecated_safe] fn() to closure coercion, if evaluation is used there
+        // won't be a proper cause span to lint against
+        let mut is_depr_safe_fn_closure = false;
+
+        if is_global && let trait_ty = project_obligation.predicate.skip_binder().projection_ty.self_ty()
+            && let ty::FnDef(func_id, _) = trait_ty.kind()
+            && self.selcx.tcx().fn_trait_kind_from_lang_item(
+                project_obligation.predicate.trait_def_id(self.selcx.tcx())
+            ).is_some()
+            && stability::check_deprecation_as_safe(
+                self.selcx.tcx(),
+                *func_id,
+                obligation.cause.span,
+            )
+        {
+            is_depr_safe_fn_closure = true;
+        }
+
+        if is_global && !is_depr_safe_fn_closure {
+            // no type variables present and not a #[deprecated_safe] fn() to closure coercion,
+            // can use evaluation for better caching.
             // FIXME: consider caching errors too.
             if self.selcx.infcx().predicate_must_hold_considering_regions(obligation) {
                 if let Some(key) = ProjectionCacheKey::from_poly_projection_predicate(
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 8240f5c542a61..4491bf75e21db 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -98,19 +98,6 @@ impl SkipLeakCheck {
     }
 }
 
-/// The mode that trait queries run in.
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
-pub enum TraitQueryMode {
-    /// Standard/un-canonicalized queries get accurate
-    /// spans etc. passed in and hence can do reasonable
-    /// error reporting on their own.
-    Standard,
-    /// Canonicalized queries get dummy spans and hence
-    /// must generally propagate errors to
-    /// pre-canonicalization callsites.
-    Canonical,
-}
-
 /// Creates predicate obligations from the generic bounds.
 pub fn predicates_for_generics<'tcx>(
     cause: ObligationCause<'tcx>,
diff --git a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs
index db45ee3fed7db..c341d63d4e1b3 100644
--- a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs
@@ -1,10 +1,8 @@
 use rustc_middle::ty;
 
 use crate::infer::canonical::OriginalQueryValues;
-use crate::infer::InferCtxt;
-use crate::traits::{
-    EvaluationResult, OverflowError, PredicateObligation, SelectionContext, TraitQueryMode,
-};
+use crate::infer::{InferCtxt, TraitQueryMode};
+use crate::traits::{EvaluationResult, OverflowError, PredicateObligation, SelectionContext};
 
 pub trait InferCtxtExt<'tcx> {
     fn predicate_may_hold(&self, obligation: &PredicateObligation<'tcx>) -> bool;
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index 06f5824099237..07bbec2a56d77 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -11,6 +11,7 @@ use rustc_hir::def_id::DefId;
 use rustc_infer::traits::TraitEngine;
 use rustc_infer::traits::{Obligation, SelectionError, TraitObligation};
 use rustc_lint_defs::builtin::DEREF_INTO_DYN_SUPERTRAIT;
+use rustc_middle::middle::stability;
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{self, ToPredicate, Ty, TypeFoldable};
 use rustc_target::spec::abi::Abi;
@@ -495,22 +496,34 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     ..
                 } = self_ty.fn_sig(self.tcx()).skip_binder()
                 {
-                    candidates.vec.push(FnPointerCandidate { is_const: false });
+                    candidates.vec.push(FnPointerCandidate { is_const: false, depr_as_safe: None });
                 }
             }
             // Provide an impl for suitable functions, rejecting `#[target_feature]` functions (RFC 2396).
             ty::FnDef(def_id, _) => {
-                if let ty::FnSig {
-                    unsafety: hir::Unsafety::Normal,
-                    abi: Abi::Rust,
-                    c_variadic: false,
-                    ..
-                } = self_ty.fn_sig(self.tcx()).skip_binder()
+                if let ty::FnSig { unsafety, abi: Abi::Rust, c_variadic: false, .. } =
+                    self_ty.fn_sig(self.tcx()).skip_binder()
                 {
                     if self.tcx().codegen_fn_attrs(def_id).target_features.is_empty() {
-                        candidates
-                            .vec
-                            .push(FnPointerCandidate { is_const: self.tcx().is_const_fn(def_id) });
+                        // check if a #[deprecated_safe] fn() is being used as a closure, a
+                        // deprecated_safe lint must be emitted if this candidate is used
+                        if unsafety == hir::Unsafety::Unsafe
+                            && stability::check_deprecation_as_safe(
+                                self.tcx(),
+                                def_id,
+                                obligation.cause.span,
+                            )
+                        {
+                            candidates.vec.push(FnPointerCandidate {
+                                is_const: self.tcx().is_const_fn(def_id),
+                                depr_as_safe: Some(def_id),
+                            });
+                        } else if unsafety == hir::Unsafety::Normal {
+                            candidates.vec.push(FnPointerCandidate {
+                                is_const: self.tcx().is_const_fn(def_id),
+                                depr_as_safe: None,
+                            });
+                        }
                     }
                 }
             }
@@ -792,7 +805,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     let principal_def_id_b = data_b.principal_def_id();
                     if principal_def_id_a == principal_def_id_b {
                         // no cyclic
-                        candidates.vec.push(BuiltinUnsizeCandidate);
+                        candidates.vec.push(BuiltinUnsizeCandidate { depr_as_safe: None });
                     } else if principal_def_id_a.is_some() && principal_def_id_b.is_some() {
                         // not casual unsizing, now check whether this is trait upcasting coercion.
                         let principal_a = data_a.principal().unwrap();
@@ -834,8 +847,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             }
 
             // `T` -> `Trait`
-            (_, &ty::Dynamic(..)) => {
-                candidates.vec.push(BuiltinUnsizeCandidate);
+            (from, &ty::Dynamic(to_preds, ..)) => {
+                // check if a #[deprecated_safe] fn() is being used as a closure, a
+                // deprecated_safe lint must be emitted if this candidate is used
+                if let ty::FnDef(def_id, _) = *from
+                    && source.fn_sig(self.tcx()).unsafety() == hir::Unsafety::Unsafe
+                    && let Some(trait_def_id) = to_preds.principal_def_id()
+                    && self.tcx().fn_trait_kind_from_lang_item(trait_def_id).is_some()
+                    && stability::check_deprecation_as_safe(
+                        self.tcx(),
+                        def_id,
+                        obligation.cause.span,
+                    )
+                {
+                    candidates.vec.push(BuiltinUnsizeCandidate { depr_as_safe: Some(def_id) });
+                } else {
+                    candidates.vec.push(BuiltinUnsizeCandidate { depr_as_safe: None });
+                }
             }
 
             // Ambiguous handling is below `T` -> `Trait`, because inference
@@ -848,20 +876,20 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
             // `[T; n]` -> `[T]`
             (&ty::Array(..), &ty::Slice(_)) => {
-                candidates.vec.push(BuiltinUnsizeCandidate);
+                candidates.vec.push(BuiltinUnsizeCandidate { depr_as_safe: None });
             }
 
             // `Struct<T>` -> `Struct<U>`
             (&ty::Adt(def_id_a, _), &ty::Adt(def_id_b, _)) if def_id_a.is_struct() => {
                 if def_id_a == def_id_b {
-                    candidates.vec.push(BuiltinUnsizeCandidate);
+                    candidates.vec.push(BuiltinUnsizeCandidate { depr_as_safe: None });
                 }
             }
 
             // `(.., T)` -> `(.., U)`
             (&ty::Tuple(tys_a), &ty::Tuple(tys_b)) => {
                 if tys_a.len() == tys_b.len() {
-                    candidates.vec.push(BuiltinUnsizeCandidate);
+                    candidates.vec.push(BuiltinUnsizeCandidate { depr_as_safe: None });
                 }
             }
 
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index b97ab39d991fe..938463b6377f1 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -9,8 +9,10 @@
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_hir::lang_items::LangItem;
 use rustc_index::bit_set::GrowableBitSet;
-use rustc_infer::infer::InferOk;
 use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType;
+use rustc_infer::infer::{InferOk, TraitQueryMode};
+use rustc_middle::middle::stability::{self, DeprecationAsSafeKind};
+use rustc_middle::traits;
 use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, SubstsRef};
 use rustc_middle::ty::{self, GenericParamDefKind, Ty};
 use rustc_middle::ty::{ToPolyTraitRef, ToPredicate};
@@ -115,8 +117,29 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 Ok(ImplSource::Generator(vtable_generator))
             }
 
-            FnPointerCandidate { .. } => {
+            FnPointerCandidate { depr_as_safe, .. } => {
                 let data = self.confirm_fn_pointer_candidate(obligation)?;
+                // FIXME(skippy) specifically needs reviewer feedback
+                // FIXME(skippy) the self.infcx.query_mode == TraitQueryMode::Standard is to
+                //               prevent lints during mir_borrowck, when there will be
+                //               DUMMY_SP cause spans
+                // FIXME(skippy) the param_env.reveal() == traits::Reveal::UserFacing is to prevent
+                //               lints during codegen, when there will be DUMMY_SP cause spans
+                // FIXME(skippy) this is all very ad-hoc
+                // emit deprecated_safe lint if this candidate is from a #[deprecated_safe] fn()
+                // to closure coercion
+                if let Some(depr_as_safe) = depr_as_safe
+                    && self.infcx.query_mode == TraitQueryMode::Standard
+                    && obligation.param_env.reveal() == traits::Reveal::UserFacing
+                {
+                    stability::report_deprecation_as_safe(
+                        self.tcx(),
+                        DeprecationAsSafeKind::FnTraitCoercion,
+                        depr_as_safe,
+                        obligation.cause.body_id,
+                        obligation.cause.span,
+                    );
+                }
                 Ok(ImplSource::FnPointer(data))
             }
 
@@ -138,8 +161,29 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 Ok(ImplSource::Param(Vec::new(), ty::BoundConstness::NotConst))
             }
 
-            BuiltinUnsizeCandidate => {
+            BuiltinUnsizeCandidate { depr_as_safe } => {
                 let data = self.confirm_builtin_unsize_candidate(obligation)?;
+                // FIXME(skippy) specifically needs reviewer feedback
+                // FIXME(skippy) the self.infcx.query_mode == TraitQueryMode::Standard is to
+                //               prevent lints during mir_borrowck, when there will be
+                //               DUMMY_SP cause spans
+                // FIXME(skippy) the param_env.reveal() == traits::Reveal::UserFacing is to prevent
+                //               lints during codegen, when there will be DUMMY_SP cause spans
+                // FIXME(skippy) this is all very ad-hoc
+                // emit deprecated_safe lint if this candidate is from a #[deprecated_safe] fn()
+                // to closure coercion
+                if let Some(depr_as_safe) = depr_as_safe
+                    && self.infcx.query_mode == TraitQueryMode::Standard
+                    && obligation.param_env.reveal() == traits::Reveal::UserFacing
+                {
+                    stability::report_deprecation_as_safe(
+                        self.tcx(),
+                        DeprecationAsSafeKind::FnTraitCoercion,
+                        depr_as_safe,
+                        obligation.cause.body_id,
+                        obligation.cause.span,
+                    );
+                }
                 Ok(ImplSource::Builtin(data))
             }
 
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index e69bf6eca90ef..e44859fd1c633 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -16,7 +16,7 @@ use super::wf;
 use super::{
     DerivedObligationCause, ErrorReporting, ImplDerivedObligation, ImplDerivedObligationCause,
     Normalized, Obligation, ObligationCause, ObligationCauseCode, Overflow, PredicateObligation,
-    Selection, SelectionError, SelectionResult, TraitObligation, TraitQueryMode,
+    Selection, SelectionError, SelectionResult, TraitObligation,
 };
 
 use crate::infer::{InferCtxt, InferOk, TypeFreshener};
@@ -29,7 +29,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_errors::{Diagnostic, ErrorGuaranteed};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
-use rustc_infer::infer::LateBoundRegionConversionTime;
+use rustc_infer::infer::{LateBoundRegionConversionTime, TraitQueryMode};
 use rustc_middle::dep_graph::{DepKind, DepNodeIndex};
 use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::thir::abstract_const::NotConstEvaluatable;
@@ -1159,7 +1159,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     // or ignore error with const_async_blocks feature
                     GeneratorCandidate => {}
                     // FnDef where the function is const
-                    FnPointerCandidate { is_const: true } => {}
+                    FnPointerCandidate { is_const: true, .. } => {}
                     ConstDestructCandidate(_) => {}
                     _ => {
                         // reject all other types of candidates
@@ -1623,7 +1623,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             }
 
             // Drop otherwise equivalent non-const fn pointer candidates
-            (FnPointerCandidate { .. }, FnPointerCandidate { is_const: false }) => true,
+            (FnPointerCandidate { .. }, FnPointerCandidate { is_const: false, .. }) => true,
 
             // If obligation is a sized predicate or the where-clause bound is
             // global, prefer the projection or object candidate. See issue
@@ -1647,7 +1647,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 | GeneratorCandidate
                 | FnPointerCandidate { .. }
                 | BuiltinObjectCandidate
-                | BuiltinUnsizeCandidate
+                | BuiltinUnsizeCandidate { .. }
                 | TraitUpcastingUnsizeCandidate(_)
                 | BuiltinCandidate { .. }
                 | TraitAliasCandidate(..),
@@ -1658,7 +1658,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 | GeneratorCandidate
                 | FnPointerCandidate { .. }
                 | BuiltinObjectCandidate
-                | BuiltinUnsizeCandidate
+                | BuiltinUnsizeCandidate { .. }
                 | TraitUpcastingUnsizeCandidate(_)
                 | BuiltinCandidate { has_nested: true }
                 | TraitAliasCandidate(..),
@@ -1688,7 +1688,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 | GeneratorCandidate
                 | FnPointerCandidate { .. }
                 | BuiltinObjectCandidate
-                | BuiltinUnsizeCandidate
+                | BuiltinUnsizeCandidate { .. }
                 | TraitUpcastingUnsizeCandidate(_)
                 | BuiltinCandidate { .. }
                 | TraitAliasCandidate(..),
@@ -1700,7 +1700,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 | GeneratorCandidate
                 | FnPointerCandidate { .. }
                 | BuiltinObjectCandidate
-                | BuiltinUnsizeCandidate
+                | BuiltinUnsizeCandidate { .. }
                 | TraitUpcastingUnsizeCandidate(_)
                 | BuiltinCandidate { .. }
                 | TraitAliasCandidate(..),
@@ -1781,7 +1781,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 | GeneratorCandidate
                 | FnPointerCandidate { .. }
                 | BuiltinObjectCandidate
-                | BuiltinUnsizeCandidate
+                | BuiltinUnsizeCandidate { .. }
                 | TraitUpcastingUnsizeCandidate(_)
                 | BuiltinCandidate { has_nested: true }
                 | TraitAliasCandidate(..),
@@ -1790,7 +1790,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 | GeneratorCandidate
                 | FnPointerCandidate { .. }
                 | BuiltinObjectCandidate
-                | BuiltinUnsizeCandidate
+                | BuiltinUnsizeCandidate { .. }
                 | TraitUpcastingUnsizeCandidate(_)
                 | BuiltinCandidate { has_nested: true }
                 | TraitAliasCandidate(..),
diff --git a/compiler/rustc_traits/src/evaluate_obligation.rs b/compiler/rustc_traits/src/evaluate_obligation.rs
index 2404b7ff4b54a..b617df71ba107 100644
--- a/compiler/rustc_traits/src/evaluate_obligation.rs
+++ b/compiler/rustc_traits/src/evaluate_obligation.rs
@@ -1,12 +1,11 @@
-use rustc_infer::infer::TyCtxtInferExt;
+use rustc_infer::infer::{TraitQueryMode, TyCtxtInferExt};
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
 use rustc_span::source_map::DUMMY_SP;
 use rustc_trait_selection::traits::query::CanonicalPredicateGoal;
 use rustc_trait_selection::traits::{
-    EvaluationResult, Obligation, ObligationCause, OverflowError, SelectionContext, TraitQueryMode,
+    EvaluationResult, Obligation, ObligationCause, OverflowError, SelectionContext,
 };
-
 crate fn provide(p: &mut Providers) {
     *p = Providers { evaluate_obligation, ..*p };
 }
diff --git a/compiler/rustc_typeck/Cargo.toml b/compiler/rustc_typeck/Cargo.toml
index 57930a28a35a1..723a9a23c5a3a 100644
--- a/compiler/rustc_typeck/Cargo.toml
+++ b/compiler/rustc_typeck/Cargo.toml
@@ -18,6 +18,7 @@ rustc_errors = { path = "../rustc_errors" }
 rustc_graphviz = { path = "../rustc_graphviz" }
 rustc_hir = { path = "../rustc_hir" }
 rustc_hir_pretty = { path = "../rustc_hir_pretty" }
+rustc_lint_defs = { path = "../rustc_lint_defs" }
 rustc_target = { path = "../rustc_target" }
 rustc_session = { path = "../rustc_session" }
 smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs
index 34fc177de6de0..bdb7d75235f6e 100644
--- a/compiler/rustc_typeck/src/check/coercion.rs
+++ b/compiler/rustc_typeck/src/check/coercion.rs
@@ -46,6 +46,7 @@ use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKi
 use rustc_infer::infer::{Coercion, InferOk, InferResult};
 use rustc_infer::traits::{Obligation, TraitEngine, TraitEngineExt};
 use rustc_middle::lint::in_external_macro;
+use rustc_middle::middle::stability::{self, DeprecationAsSafeKind};
 use rustc_middle::ty::adjustment::{
     Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCast,
 };
@@ -720,17 +721,20 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
         Ok(coercion)
     }
 
-    fn coerce_from_safe_fn<F, G>(
+    fn coerce_from_safe_fn<F, G, H>(
         &self,
         a: Ty<'tcx>,
         fn_ty_a: ty::PolyFnSig<'tcx>,
         b: Ty<'tcx>,
         to_unsafe: F,
         normal: G,
+        fn_def_id_a: Option<DefId>,
+        to_safe: H,
     ) -> CoerceResult<'tcx>
     where
         F: FnOnce(Ty<'tcx>) -> Vec<Adjustment<'tcx>>,
         G: FnOnce(Ty<'tcx>) -> Vec<Adjustment<'tcx>>,
+        H: FnOnce(Ty<'tcx>) -> Vec<Adjustment<'tcx>>,
     {
         if let ty::FnPtr(fn_ty_b) = b.kind() {
             if let (hir::Unsafety::Normal, hir::Unsafety::Unsafe) =
@@ -739,6 +743,24 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
                 let unsafe_a = self.tcx.safe_to_unsafe_fn_ty(fn_ty_a);
                 return self.unify_and(unsafe_a, b, to_unsafe);
             }
+            // check if this is a coercion from a #[deprecated_safe] fn() pointer
+            // to a safe fn() pointer and lint if so
+            else if let (hir::Unsafety::Unsafe, hir::Unsafety::Normal) =
+                (fn_ty_a.unsafety(), fn_ty_b.unsafety())
+                && let Some(fn_def_id_a) = fn_def_id_a
+                && stability::check_deprecation_as_safe(self.tcx(), fn_def_id_a, self.cause.span)
+            {
+                stability::report_deprecation_as_safe(
+                    self.tcx(),
+                    DeprecationAsSafeKind::FnPointerCoercion,
+                    fn_def_id_a,
+                    self.cause.body_id,
+                    self.cause.span,
+                );
+
+                let safe_a = self.tcx.unsafe_to_safe_fn_ty(fn_ty_a);
+                return self.unify_and(safe_a, b, to_safe);
+            }
         }
         self.unify_and(a, b, normal)
     }
@@ -762,6 +784,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
             b,
             simple(Adjust::Pointer(PointerCast::UnsafeFnPointer)),
             identity,
+            None,
+            |_| unreachable!(),
         )
     }
 
@@ -796,6 +820,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
                 obligations.extend(o1);
 
                 let a_fn_pointer = self.tcx.mk_fn_ptr(a_sig);
+                let a_fn_def_id =
+                    if let ty::FnDef(def_id, _) = *a.kind() { Some(def_id) } else { None };
                 let InferOk { value, obligations: o2 } = self.coerce_from_safe_fn(
                     a_fn_pointer,
                     a_sig,
@@ -813,6 +839,19 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
                         ]
                     },
                     simple(Adjust::Pointer(PointerCast::ReifyFnPointer)),
+                    a_fn_def_id,
+                    |safe_ty| {
+                        vec![
+                            Adjustment {
+                                kind: Adjust::Pointer(PointerCast::ReifyFnPointer),
+                                target: a_fn_pointer,
+                            },
+                            Adjustment {
+                                kind: Adjust::Pointer(PointerCast::DeprecatedSafeFnPointer),
+                                target: safe_ty,
+                            },
+                        ]
+                    },
                 )?;
 
                 obligations.extend(o2);
diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs
index 0bd5e018f4a38..27f9c9aadd3e2 100644
--- a/compiler/rustc_typeck/src/check/compare_method.rs
+++ b/compiler/rustc_typeck/src/check/compare_method.rs
@@ -7,6 +7,7 @@ use rustc_hir::intravisit;
 use rustc_hir::{GenericParamKind, ImplItemKind, TraitItemKind};
 use rustc_infer::infer::{self, InferOk, TyCtxtInferExt};
 use rustc_infer::traits::util;
+use rustc_middle::middle::stability::{self, DeprecationAsSafeKind};
 use rustc_middle::ty;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::subst::{InternalSubsts, Subst};
@@ -262,8 +263,6 @@ fn compare_predicate_entailment<'tcx>(
         );
         let impl_sig =
             inh.normalize_associated_types_in(impl_m_span, impl_m_hir_id, param_env, impl_sig);
-        let impl_fty = tcx.mk_fn_ptr(ty::Binder::dummy(impl_sig));
-        debug!("compare_impl_method: impl_fty={:?}", impl_fty);
 
         // First liberate late bound regions and subst placeholders
         let trait_sig = tcx.liberate_late_bound_regions(impl_m.def_id, tcx.fn_sig(trait_m.def_id));
@@ -272,8 +271,31 @@ fn compare_predicate_entailment<'tcx>(
             inh.normalize_associated_types_in(impl_m_span, impl_m_hir_id, param_env, trait_sig);
         // Add the resulting inputs and output as well-formed.
         wf_tys.extend(trait_sig.inputs_and_output.iter());
-        let trait_fty = tcx.mk_fn_ptr(ty::Binder::dummy(trait_sig));
 
+        // check if this is an impl of a #[deprecated_safe] trait function
+        // lint if the impl isn't unsafe and match up the FnSig's unsafety
+        // so there won't be an error
+        let impl_sig = if impl_sig.unsafety == hir::Unsafety::Normal
+            && trait_sig.unsafety == hir::Unsafety::Unsafe
+            && stability::check_deprecation_as_safe(tcx, trait_m.def_id, impl_m_span)
+        {
+            stability::report_deprecation_as_safe(
+                tcx,
+                DeprecationAsSafeKind::TraitFnImpl,
+                trait_m.def_id,
+                impl_m_hir_id,
+                impl_m_span,
+            );
+
+            ty::FnSig { unsafety: trait_sig.unsafety, ..impl_sig }
+        } else {
+            impl_sig
+        };
+
+        let impl_fty = tcx.mk_fn_ptr(ty::Binder::dummy(impl_sig));
+        debug!("compare_impl_method: impl_fty={:?}", impl_fty);
+
+        let trait_fty = tcx.mk_fn_ptr(ty::Binder::dummy(trait_sig));
         debug!("compare_impl_method: trait_fty={:?}", trait_fty);
 
         let sub_result = infcx.at(&cause, param_env).sup(trait_fty, impl_fty).map(
diff --git a/compiler/rustc_typeck/src/coherence/unsafety.rs b/compiler/rustc_typeck/src/coherence/unsafety.rs
index f7aabf2406f37..2c5032b31a4f1 100644
--- a/compiler/rustc_typeck/src/coherence/unsafety.rs
+++ b/compiler/rustc_typeck/src/coherence/unsafety.rs
@@ -5,6 +5,7 @@ use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::Unsafety;
+use rustc_middle::middle::stability::{self, DeprecationAsSafeKind};
 use rustc_middle::ty::TyCtxt;
 
 pub fn check(tcx: TyCtxt<'_>) {
@@ -42,14 +43,26 @@ impl<'tcx> UnsafetyChecker<'tcx> {
                 }
 
                 (Unsafety::Unsafe, _, Unsafety::Normal, hir::ImplPolarity::Positive) => {
-                    struct_span_err!(
-                        self.tcx.sess,
-                        item.span,
-                        E0200,
-                        "the trait `{}` requires an `unsafe impl` declaration",
-                        trait_ref.print_only_trait_path()
-                    )
-                    .emit();
+                    // check if this is a safe impl of a #[deprecated_safe] trait and lint if so
+                    // instead of erroring
+                    if stability::check_deprecation_as_safe(self.tcx, trait_ref.def_id, item.span) {
+                        stability::report_deprecation_as_safe(
+                            self.tcx,
+                            DeprecationAsSafeKind::TraitImpl,
+                            trait_ref.def_id,
+                            item.hir_id(),
+                            item.span,
+                        )
+                    } else {
+                        struct_span_err!(
+                            self.tcx.sess,
+                            item.span,
+                            E0200,
+                            "the trait `{}` requires an `unsafe impl` declaration",
+                            trait_ref.print_only_trait_path()
+                        )
+                        .emit();
+                    }
                 }
 
                 (
diff --git a/src/test/ui/deprecated-safe/auxiliary/deprecated-safe.rs b/src/test/ui/deprecated-safe/auxiliary/deprecated-safe.rs
new file mode 100644
index 0000000000000..887baf0e4a626
--- /dev/null
+++ b/src/test/ui/deprecated-safe/auxiliary/deprecated-safe.rs
@@ -0,0 +1,61 @@
+#![feature(deprecated_safe)]
+#![feature(staged_api)]
+#![stable(feature = "deprecated-safe-test", since = "1.61.0")]
+#![warn(unused_unsafe)]
+
+use std::ffi::OsStr;
+
+#[stable(feature = "deprecated-safe-test", since = "1.61.0")]
+#[deprecated_safe(since = "1.61.0", note = "reason")]
+pub unsafe fn depr_safe() {}
+
+#[stable(feature = "deprecated-safe-test", since = "1.61.0")]
+#[deprecated_safe(since = "1.61.0", note = "reason")]
+pub unsafe fn depr_safe_params(_: u32, _: u64) {}
+
+#[stable(feature = "deprecated-safe-test", since = "1.61.0")]
+#[deprecated_safe(since = "1.61.0", note = "reason")]
+pub unsafe fn depr_safe_generic<K: AsRef<OsStr>, V: AsRef<OsStr>>(key: K, value: V) {}
+
+#[stable(feature = "deprecated-safe-test", since = "1.61.0")]
+#[deprecated_safe(since = "1.61.0", note = "reason", unsafe_edition = "2015")]
+pub unsafe fn depr_safe_2015() {}
+
+#[stable(feature = "deprecated-safe-test", since = "1.61.0")]
+#[deprecated_safe(since = "1.61.0", note = "reason", unsafe_edition = "2018")]
+pub unsafe fn depr_safe_2018() {}
+
+#[stable(feature = "deprecated-safe-test", since = "1.61.0")]
+#[deprecated_safe(since = "1.61.0", note = "reason")]
+pub unsafe trait DeprSafe {}
+
+#[stable(feature = "deprecated-safe-test", since = "1.61.0")]
+#[deprecated_safe(since = "1.61.0", note = "reason", unsafe_edition = "2015")]
+pub unsafe trait DeprSafe2015 {}
+
+#[stable(feature = "deprecated-safe-test", since = "1.61.0")]
+#[deprecated_safe(since = "1.61.0", note = "reason", unsafe_edition = "2018")]
+pub unsafe trait DeprSafe2018 {}
+
+#[stable(feature = "deprecated-safe-test", since = "1.61.0")]
+pub trait DeprSafeFns {
+    #[stable(feature = "deprecated-safe-test", since = "1.61.0")]
+    #[deprecated_safe(since = "1.61.0", note = "reason")]
+    unsafe fn depr_safe_fn(&self) {}
+
+    #[stable(feature = "deprecated-safe-test", since = "1.61.0")]
+    #[deprecated_safe(since = "1.61.0", note = "reason")]
+    unsafe fn depr_safe_params(&self, _: u32, _: u64) {}
+
+    #[stable(feature = "deprecated-safe-test", since = "1.61.0")]
+    #[deprecated_safe(since = "1.61.0", note = "reason")]
+    unsafe fn depr_safe_fn_generic<K: AsRef<OsStr>, V: AsRef<OsStr>>(&self, key: K, value: V) {}
+
+    #[stable(feature = "deprecated-safe-test", since = "1.61.0")]
+    #[deprecated_safe(since = "1.61.0", note = "reason", unsafe_edition = "2015")]
+    unsafe fn depr_safe_fn_2015(&self) {}
+
+    #[stable(feature = "deprecated-safe-test", since = "1.61.0")]
+    #[deprecated_safe(since = "1.61.0", note = "reason", unsafe_edition = "2018")]
+    unsafe fn depr_safe_fn_2018(&self) {}
+}
diff --git a/src/test/ui/deprecated-safe/deprecated-safe-attr.mir.stderr b/src/test/ui/deprecated-safe/deprecated-safe-attr.mir.stderr
new file mode 100644
index 0000000000000..6449dbf2bc863
--- /dev/null
+++ b/src/test/ui/deprecated-safe/deprecated-safe-attr.mir.stderr
@@ -0,0 +1,76 @@
+error[E0543]: 'unsafe_edition' is invalid outside of rustc
+  --> $DIR/deprecated-safe-attr.rs:15:1
+   |
+LL | #[deprecated_safe(since = "1.61.0", unsafe_edition = "2015", note = "reason")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0543]: invalid 'unsafe_edition' specified
+  --> $DIR/deprecated-safe-attr.rs:18:1
+   |
+LL | #[deprecated_safe(since = "1.61.0", unsafe_edition = "BAD", note = "reason")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0543]: invalid 'unsafe_edition' specified
+  --> $DIR/deprecated-safe-attr.rs:21:1
+   |
+LL | #[deprecated_safe(since = "TBD", unsafe_edition = "BAD", note = "reason")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: multiple `deprecated_safe` attributes
+  --> $DIR/deprecated-safe-attr.rs:37:1
+   |
+LL | #[deprecated_safe(note = "reason")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
+   |
+note: attribute also specified here
+  --> $DIR/deprecated-safe-attr.rs:36:1
+   |
+LL | #[deprecated_safe(since = "1.61.0")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0541]: unknown meta item 'extra'
+  --> $DIR/deprecated-safe-attr.rs:40:37
+   |
+LL | #[deprecated_safe(since = "1.61.0", extra = "")]
+   |                                     ^^^^^^^^^^
+
+error[E0538]: multiple 'since' items
+  --> $DIR/deprecated-safe-attr.rs:43:1
+   |
+LL | #[deprecated_safe(since = "1.61.0", since = "1.61.0")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0551]: incorrect meta item 'since'
+  --> $DIR/deprecated-safe-attr.rs:46:19
+   |
+LL | #[deprecated_safe(since)]
+   |                   ^^^^^
+
+error[E0565]: literal in `deprecated_safe` value must be a string
+  --> $DIR/deprecated-safe-attr.rs:49:27
+   |
+LL | #[deprecated_safe(since = 1_61_0)]
+   |                           ^^^^^^
+
+error[E0565]: item in `deprecated_safe` must be a key/value pair
+  --> $DIR/deprecated-safe-attr.rs:52:19
+   |
+LL | #[deprecated_safe(1_61_0)]
+   |                   ^^^^^^
+
+error[E0543]: this `#[deprecated_safe]` annotation has no effect
+  --> $DIR/deprecated-safe-attr.rs:55:1
+   |
+LL | #[deprecated_safe(since = "1.61.0")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0543]: this `#[deprecated_safe]` annotation has no effect
+  --> $DIR/deprecated-safe-attr.rs:60:5
+   |
+LL |     #[deprecated_safe(since = "1.61.0", note = "reason")]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 11 previous errors
+
+Some errors have detailed explanations: E0538, E0541, E0543, E0551, E0565.
+For more information about an error, try `rustc --explain E0538`.
diff --git a/src/test/ui/deprecated-safe/deprecated-safe-attr.rs b/src/test/ui/deprecated-safe/deprecated-safe-attr.rs
new file mode 100644
index 0000000000000..be5ff1778bc24
--- /dev/null
+++ b/src/test/ui/deprecated-safe/deprecated-safe-attr.rs
@@ -0,0 +1,64 @@
+// aux-build:deprecated-safe.rs
+// revisions: mir thir
+// NOTE(skippy) these tests output many duplicates, so deduplicate or they become brittle to changes
+// [mir]compile-flags: -Zdeduplicate-diagnostics=yes
+// [thir]compile-flags: -Z thir-unsafeck -Zdeduplicate-diagnostics=yes
+
+#![feature(deprecated_safe)]
+#![feature(type_alias_impl_trait)]
+#![warn(unused_unsafe)]
+
+extern crate deprecated_safe;
+
+use deprecated_safe::DeprSafeFns;
+
+#[deprecated_safe(since = "1.61.0", unsafe_edition = "2015", note = "reason")] //~ ERROR 'unsafe_edition' is invalid outside of rustc
+unsafe fn foo0() {}
+
+#[deprecated_safe(since = "1.61.0", unsafe_edition = "BAD", note = "reason")] //~ ERROR invalid 'unsafe_edition' specified
+unsafe fn foo1() {}
+
+#[deprecated_safe(since = "TBD", unsafe_edition = "BAD", note = "reason")] //~ ERROR invalid 'unsafe_edition' specified
+unsafe fn foo2() {}
+
+#[deprecated_safe]
+unsafe fn foo3() {}
+
+#[deprecated_safe = "hi"]
+unsafe fn foo4() {}
+
+#[deprecated_safe(since = "1.61.0")]
+unsafe fn foo5() {}
+
+#[deprecated_safe(note = "reason")]
+unsafe fn foo6() {}
+
+#[deprecated_safe(since = "1.61.0")]
+#[deprecated_safe(note = "reason")] //~ ERROR multiple `deprecated_safe` attributes
+unsafe fn foo7() {}
+
+#[deprecated_safe(since = "1.61.0", extra = "")] //~ ERROR unknown meta item 'extra'
+unsafe fn foo8() {}
+
+#[deprecated_safe(since = "1.61.0", since = "1.61.0")] //~ ERROR multiple 'since' items
+unsafe fn foo9() {}
+
+#[deprecated_safe(since)] //~ ERROR incorrect meta item
+unsafe fn foo10() {}
+
+#[deprecated_safe(since = 1_61_0)] //~ ERROR literal in `deprecated_safe` value must be a string
+unsafe fn foo11() {}
+
+#[deprecated_safe(1_61_0)] //~ ERROR item in `deprecated_safe` must be a key/value pair
+unsafe fn foo12() {}
+
+#[deprecated_safe(since = "1.61.0")] //~ ERROR this `#[deprecated_safe]` annotation has no effect
+static FOO0: u32 = 0;
+
+struct BadAnnotation;
+impl DeprSafeFns for BadAnnotation {
+    #[deprecated_safe(since = "1.61.0", note = "reason")] //~ ERROR this `#[deprecated_safe]` annotation has no effect
+    unsafe fn depr_safe_fn(&self) {}
+}
+
+fn main() {}
diff --git a/src/test/ui/deprecated-safe/deprecated-safe-attr.thir.stderr b/src/test/ui/deprecated-safe/deprecated-safe-attr.thir.stderr
new file mode 100644
index 0000000000000..6449dbf2bc863
--- /dev/null
+++ b/src/test/ui/deprecated-safe/deprecated-safe-attr.thir.stderr
@@ -0,0 +1,76 @@
+error[E0543]: 'unsafe_edition' is invalid outside of rustc
+  --> $DIR/deprecated-safe-attr.rs:15:1
+   |
+LL | #[deprecated_safe(since = "1.61.0", unsafe_edition = "2015", note = "reason")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0543]: invalid 'unsafe_edition' specified
+  --> $DIR/deprecated-safe-attr.rs:18:1
+   |
+LL | #[deprecated_safe(since = "1.61.0", unsafe_edition = "BAD", note = "reason")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0543]: invalid 'unsafe_edition' specified
+  --> $DIR/deprecated-safe-attr.rs:21:1
+   |
+LL | #[deprecated_safe(since = "TBD", unsafe_edition = "BAD", note = "reason")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: multiple `deprecated_safe` attributes
+  --> $DIR/deprecated-safe-attr.rs:37:1
+   |
+LL | #[deprecated_safe(note = "reason")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
+   |
+note: attribute also specified here
+  --> $DIR/deprecated-safe-attr.rs:36:1
+   |
+LL | #[deprecated_safe(since = "1.61.0")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0541]: unknown meta item 'extra'
+  --> $DIR/deprecated-safe-attr.rs:40:37
+   |
+LL | #[deprecated_safe(since = "1.61.0", extra = "")]
+   |                                     ^^^^^^^^^^
+
+error[E0538]: multiple 'since' items
+  --> $DIR/deprecated-safe-attr.rs:43:1
+   |
+LL | #[deprecated_safe(since = "1.61.0", since = "1.61.0")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0551]: incorrect meta item 'since'
+  --> $DIR/deprecated-safe-attr.rs:46:19
+   |
+LL | #[deprecated_safe(since)]
+   |                   ^^^^^
+
+error[E0565]: literal in `deprecated_safe` value must be a string
+  --> $DIR/deprecated-safe-attr.rs:49:27
+   |
+LL | #[deprecated_safe(since = 1_61_0)]
+   |                           ^^^^^^
+
+error[E0565]: item in `deprecated_safe` must be a key/value pair
+  --> $DIR/deprecated-safe-attr.rs:52:19
+   |
+LL | #[deprecated_safe(1_61_0)]
+   |                   ^^^^^^
+
+error[E0543]: this `#[deprecated_safe]` annotation has no effect
+  --> $DIR/deprecated-safe-attr.rs:55:1
+   |
+LL | #[deprecated_safe(since = "1.61.0")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0543]: this `#[deprecated_safe]` annotation has no effect
+  --> $DIR/deprecated-safe-attr.rs:60:5
+   |
+LL |     #[deprecated_safe(since = "1.61.0", note = "reason")]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 11 previous errors
+
+Some errors have detailed explanations: E0538, E0541, E0543, E0551, E0565.
+For more information about an error, try `rustc --explain E0538`.
diff --git a/src/test/ui/deprecated-safe/deprecated-safe-mismatch.mir.stderr b/src/test/ui/deprecated-safe/deprecated-safe-mismatch.mir.stderr
new file mode 100644
index 0000000000000..499f504172214
--- /dev/null
+++ b/src/test/ui/deprecated-safe/deprecated-safe-mismatch.mir.stderr
@@ -0,0 +1,21 @@
+error[E0543]: item must be marked unsafe
+  --> $DIR/deprecated-safe-mismatch.rs:12:1
+   |
+LL | fn foo0() {}
+   | ^^^^^^^^^^^^
+
+error[E0543]: item must be marked unsafe
+  --> $DIR/deprecated-safe-mismatch.rs:15:1
+   |
+LL | trait PreviouslySafeTrait {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0543]: item must be marked unsafe
+  --> $DIR/deprecated-safe-mismatch.rs:19:5
+   |
+LL |     fn foo0();
+   |     ^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0543`.
diff --git a/src/test/ui/deprecated-safe/deprecated-safe-mismatch.rs b/src/test/ui/deprecated-safe/deprecated-safe-mismatch.rs
new file mode 100644
index 0000000000000..4159b210e5bb9
--- /dev/null
+++ b/src/test/ui/deprecated-safe/deprecated-safe-mismatch.rs
@@ -0,0 +1,22 @@
+// revisions: mir thir
+// NOTE(skippy) these tests output many duplicates, so deduplicate or they become brittle to changes
+// [mir]compile-flags: -Zdeduplicate-diagnostics=yes
+// [thir]compile-flags: -Z thir-unsafeck -Zdeduplicate-diagnostics=yes
+
+#![feature(deprecated_safe)]
+#![warn(unused_unsafe)]
+
+use std::ffi::{OsStr, OsString};
+
+#[deprecated_safe(since = "1.61.0", note = "reason")]
+fn foo0() {} //~ ERROR item must be marked unsafe
+
+#[deprecated_safe(since = "1.61.0", note = "reason")]
+trait PreviouslySafeTrait {} //~ ERROR item must be marked unsafe
+
+trait PreviouslySafeFunctions {
+    #[deprecated_safe(since = "1.61.0", note = "reason")]
+    fn foo0(); //~ ERROR item must be marked unsafe
+}
+
+fn main() {}
diff --git a/src/test/ui/deprecated-safe/deprecated-safe-mismatch.thir.stderr b/src/test/ui/deprecated-safe/deprecated-safe-mismatch.thir.stderr
new file mode 100644
index 0000000000000..499f504172214
--- /dev/null
+++ b/src/test/ui/deprecated-safe/deprecated-safe-mismatch.thir.stderr
@@ -0,0 +1,21 @@
+error[E0543]: item must be marked unsafe
+  --> $DIR/deprecated-safe-mismatch.rs:12:1
+   |
+LL | fn foo0() {}
+   | ^^^^^^^^^^^^
+
+error[E0543]: item must be marked unsafe
+  --> $DIR/deprecated-safe-mismatch.rs:15:1
+   |
+LL | trait PreviouslySafeTrait {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0543]: item must be marked unsafe
+  --> $DIR/deprecated-safe-mismatch.rs:19:5
+   |
+LL |     fn foo0();
+   |     ^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0543`.
diff --git a/src/test/ui/deprecated-safe/deprecated-safe-trait-fn.mir.stderr b/src/test/ui/deprecated-safe/deprecated-safe-trait-fn.mir.stderr
new file mode 100644
index 0000000000000..37fb3d640b13f
--- /dev/null
+++ b/src/test/ui/deprecated-safe/deprecated-safe-trait-fn.mir.stderr
@@ -0,0 +1,43 @@
+warning: use of associated function `deprecated_safe::DeprSafeFns::depr_safe_fn` without an `unsafe fn` declaration has been deprecated as it is now an unsafe associated function
+  --> $DIR/deprecated-safe-trait-fn.rs:17:5
+   |
+LL |     fn depr_safe_fn(&self) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(deprecated_safe)]` on by default
+   = note: this associated function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the associated function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of associated function `deprecated_safe::DeprSafeFns::depr_safe_fn_generic` without an `unsafe fn` declaration has been deprecated as it is now an unsafe associated function
+  --> $DIR/deprecated-safe-trait-fn.rs:18:5
+   |
+LL |     fn depr_safe_fn_generic<K: AsRef<OsStr>, V: AsRef<OsStr>>(&self, key: K, value: V) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this associated function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the associated function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+error[E0053]: method `depr_safe_fn_2015` has an incompatible type for trait
+  --> $DIR/deprecated-safe-trait-fn.rs:19:5
+   |
+LL |     fn depr_safe_fn_2015(&self) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected unsafe fn, found normal fn
+   |
+   = note: expected fn pointer `unsafe fn(&BadImpls)`
+              found fn pointer `fn(&BadImpls)`
+
+warning: use of associated function `deprecated_safe::DeprSafeFns::depr_safe_fn_2018` without an `unsafe fn` declaration has been deprecated as it is now an unsafe associated function
+  --> $DIR/deprecated-safe-trait-fn.rs:20:5
+   |
+LL |     fn depr_safe_fn_2018(&self) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this associated function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the associated function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+error: aborting due to previous error; 3 warnings emitted
+
+For more information about this error, try `rustc --explain E0053`.
diff --git a/src/test/ui/deprecated-safe/deprecated-safe-trait-fn.rs b/src/test/ui/deprecated-safe/deprecated-safe-trait-fn.rs
new file mode 100644
index 0000000000000..04fd8b4c35e73
--- /dev/null
+++ b/src/test/ui/deprecated-safe/deprecated-safe-trait-fn.rs
@@ -0,0 +1,31 @@
+// aux-build:deprecated-safe.rs
+// revisions: mir thir
+// NOTE(skippy) these tests output many duplicates, so deduplicate or they become brittle to changes
+// [mir]compile-flags: -Zdeduplicate-diagnostics=yes
+// [thir]compile-flags: -Z thir-unsafeck -Zdeduplicate-diagnostics=yes
+
+#![feature(deprecated_safe)]
+#![warn(unused_unsafe)]
+
+extern crate deprecated_safe;
+
+use deprecated_safe::DeprSafeFns;
+use std::ffi::OsStr;
+
+struct BadImpls;
+impl DeprSafeFns for BadImpls {
+    fn depr_safe_fn(&self) {} //~ WARN use of associated function `deprecated_safe::DeprSafeFns::depr_safe_fn` without an `unsafe fn` declaration has been deprecated as it is now an unsafe associated function
+    fn depr_safe_fn_generic<K: AsRef<OsStr>, V: AsRef<OsStr>>(&self, key: K, value: V) {} //~ WARN use of associated function `deprecated_safe::DeprSafeFns::depr_safe_fn_generic` without an `unsafe fn` declaration has been deprecated as it is now an unsafe associated function
+    fn depr_safe_fn_2015(&self) {} //~ ERROR method `depr_safe_fn_2015` has an incompatible type for trait
+    fn depr_safe_fn_2018(&self) {} //~ WARN use of associated function `deprecated_safe::DeprSafeFns::depr_safe_fn_2018` without an `unsafe fn` declaration has been deprecated as it is now an unsafe associated function
+}
+
+struct GoodImpls;
+impl DeprSafeFns for GoodImpls {
+    unsafe fn depr_safe_fn(&self) {}
+    unsafe fn depr_safe_fn_generic<K: AsRef<OsStr>, V: AsRef<OsStr>>(&self, key: K, value: V) {}
+    unsafe fn depr_safe_fn_2015(&self) {}
+    unsafe fn depr_safe_fn_2018(&self) {}
+}
+
+fn main() {}
diff --git a/src/test/ui/deprecated-safe/deprecated-safe-trait-fn.thir.stderr b/src/test/ui/deprecated-safe/deprecated-safe-trait-fn.thir.stderr
new file mode 100644
index 0000000000000..37fb3d640b13f
--- /dev/null
+++ b/src/test/ui/deprecated-safe/deprecated-safe-trait-fn.thir.stderr
@@ -0,0 +1,43 @@
+warning: use of associated function `deprecated_safe::DeprSafeFns::depr_safe_fn` without an `unsafe fn` declaration has been deprecated as it is now an unsafe associated function
+  --> $DIR/deprecated-safe-trait-fn.rs:17:5
+   |
+LL |     fn depr_safe_fn(&self) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(deprecated_safe)]` on by default
+   = note: this associated function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the associated function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of associated function `deprecated_safe::DeprSafeFns::depr_safe_fn_generic` without an `unsafe fn` declaration has been deprecated as it is now an unsafe associated function
+  --> $DIR/deprecated-safe-trait-fn.rs:18:5
+   |
+LL |     fn depr_safe_fn_generic<K: AsRef<OsStr>, V: AsRef<OsStr>>(&self, key: K, value: V) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this associated function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the associated function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+error[E0053]: method `depr_safe_fn_2015` has an incompatible type for trait
+  --> $DIR/deprecated-safe-trait-fn.rs:19:5
+   |
+LL |     fn depr_safe_fn_2015(&self) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected unsafe fn, found normal fn
+   |
+   = note: expected fn pointer `unsafe fn(&BadImpls)`
+              found fn pointer `fn(&BadImpls)`
+
+warning: use of associated function `deprecated_safe::DeprSafeFns::depr_safe_fn_2018` without an `unsafe fn` declaration has been deprecated as it is now an unsafe associated function
+  --> $DIR/deprecated-safe-trait-fn.rs:20:5
+   |
+LL |     fn depr_safe_fn_2018(&self) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this associated function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the associated function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+error: aborting due to previous error; 3 warnings emitted
+
+For more information about this error, try `rustc --explain E0053`.
diff --git a/src/test/ui/deprecated-safe/deprecated-safe-trait-impl.mir.stderr b/src/test/ui/deprecated-safe/deprecated-safe-trait-impl.mir.stderr
new file mode 100644
index 0000000000000..50c688d2ae34f
--- /dev/null
+++ b/src/test/ui/deprecated-safe/deprecated-safe-trait-impl.mir.stderr
@@ -0,0 +1,58 @@
+error[E0198]: negative impls cannot be unsafe
+  --> $DIR/deprecated-safe-trait-impl.rs:24:13
+   |
+LL | unsafe impl !DeprSafe for D {}
+   | ------      -^^^^^^^^
+   | |           |
+   | |           negative because of this
+   | unsafe because of this
+
+error[E0198]: negative impls cannot be unsafe
+  --> $DIR/deprecated-safe-trait-impl.rs:36:13
+   |
+LL | unsafe impl !DeprSafe2015 for L {}
+   | ------      -^^^^^^^^^^^^
+   | |           |
+   | |           negative because of this
+   | unsafe because of this
+
+error[E0198]: negative impls cannot be unsafe
+  --> $DIR/deprecated-safe-trait-impl.rs:48:13
+   |
+LL | unsafe impl !DeprSafe2018 for T {}
+   | ------      -^^^^^^^^^^^^
+   | |           |
+   | |           negative because of this
+   | unsafe because of this
+
+warning: use of trait `deprecated_safe::DeprSafe` without an `unsafe impl` declaration has been deprecated as it is now an unsafe trait
+  --> $DIR/deprecated-safe-trait-impl.rs:15:1
+   |
+LL | impl DeprSafe for A {}
+   | ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(deprecated_safe)]` on by default
+   = note: this trait was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the trait's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+error[E0200]: the trait `DeprSafe2015` requires an `unsafe impl` declaration
+  --> $DIR/deprecated-safe-trait-impl.rs:27:1
+   |
+LL | impl DeprSafe2015 for I {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of trait `deprecated_safe::DeprSafe2018` without an `unsafe impl` declaration has been deprecated as it is now an unsafe trait
+  --> $DIR/deprecated-safe-trait-impl.rs:39:1
+   |
+LL | impl DeprSafe2018 for M {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this trait was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the trait's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+error: aborting due to 4 previous errors; 2 warnings emitted
+
+Some errors have detailed explanations: E0198, E0200.
+For more information about an error, try `rustc --explain E0198`.
diff --git a/src/test/ui/deprecated-safe/deprecated-safe-trait-impl.rs b/src/test/ui/deprecated-safe/deprecated-safe-trait-impl.rs
new file mode 100644
index 0000000000000..c022a8f90ccc7
--- /dev/null
+++ b/src/test/ui/deprecated-safe/deprecated-safe-trait-impl.rs
@@ -0,0 +1,50 @@
+// aux-build:deprecated-safe.rs
+// revisions: mir thir
+// NOTE(skippy) these tests output many duplicates, so deduplicate or they become brittle to changes
+// [mir]compile-flags: -Zdeduplicate-diagnostics=yes
+// [thir]compile-flags: -Z thir-unsafeck -Zdeduplicate-diagnostics=yes
+
+#![feature(negative_impls)]
+#![warn(unused_unsafe)]
+
+extern crate deprecated_safe;
+
+use deprecated_safe::{DeprSafe, DeprSafe2015, DeprSafe2018};
+
+struct A;
+impl DeprSafe for A {} //~ WARN use of trait `deprecated_safe::DeprSafe` without an `unsafe impl` declaration has been deprecated as it is now an unsafe trait
+
+struct B;
+unsafe impl DeprSafe for B {}
+
+struct C;
+impl !DeprSafe for C {}
+
+struct D;
+unsafe impl !DeprSafe for D {} //~ ERROR negative impls cannot be unsafe
+
+struct I;
+impl DeprSafe2015 for I {} //~ ERROR the trait `DeprSafe2015` requires an `unsafe impl` declaration
+
+struct J;
+unsafe impl DeprSafe2015 for J {}
+
+struct K;
+impl !DeprSafe2015 for K {}
+
+struct L;
+unsafe impl !DeprSafe2015 for L {} //~ ERROR negative impls cannot be unsafe
+
+struct M;
+impl DeprSafe2018 for M {} //~ WARN use of trait `deprecated_safe::DeprSafe2018` without an `unsafe impl` declaration has been deprecated as it is now an unsafe trait
+
+struct R;
+unsafe impl DeprSafe2018 for R {}
+
+struct S;
+impl !DeprSafe2018 for S {}
+
+struct T;
+unsafe impl !DeprSafe2018 for T {} //~ ERROR negative impls cannot be unsafe
+
+fn main() {}
diff --git a/src/test/ui/deprecated-safe/deprecated-safe-trait-impl.thir.stderr b/src/test/ui/deprecated-safe/deprecated-safe-trait-impl.thir.stderr
new file mode 100644
index 0000000000000..50c688d2ae34f
--- /dev/null
+++ b/src/test/ui/deprecated-safe/deprecated-safe-trait-impl.thir.stderr
@@ -0,0 +1,58 @@
+error[E0198]: negative impls cannot be unsafe
+  --> $DIR/deprecated-safe-trait-impl.rs:24:13
+   |
+LL | unsafe impl !DeprSafe for D {}
+   | ------      -^^^^^^^^
+   | |           |
+   | |           negative because of this
+   | unsafe because of this
+
+error[E0198]: negative impls cannot be unsafe
+  --> $DIR/deprecated-safe-trait-impl.rs:36:13
+   |
+LL | unsafe impl !DeprSafe2015 for L {}
+   | ------      -^^^^^^^^^^^^
+   | |           |
+   | |           negative because of this
+   | unsafe because of this
+
+error[E0198]: negative impls cannot be unsafe
+  --> $DIR/deprecated-safe-trait-impl.rs:48:13
+   |
+LL | unsafe impl !DeprSafe2018 for T {}
+   | ------      -^^^^^^^^^^^^
+   | |           |
+   | |           negative because of this
+   | unsafe because of this
+
+warning: use of trait `deprecated_safe::DeprSafe` without an `unsafe impl` declaration has been deprecated as it is now an unsafe trait
+  --> $DIR/deprecated-safe-trait-impl.rs:15:1
+   |
+LL | impl DeprSafe for A {}
+   | ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(deprecated_safe)]` on by default
+   = note: this trait was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the trait's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+error[E0200]: the trait `DeprSafe2015` requires an `unsafe impl` declaration
+  --> $DIR/deprecated-safe-trait-impl.rs:27:1
+   |
+LL | impl DeprSafe2015 for I {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of trait `deprecated_safe::DeprSafe2018` without an `unsafe impl` declaration has been deprecated as it is now an unsafe trait
+  --> $DIR/deprecated-safe-trait-impl.rs:39:1
+   |
+LL | impl DeprSafe2018 for M {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this trait was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the trait's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+error: aborting due to 4 previous errors; 2 warnings emitted
+
+Some errors have detailed explanations: E0198, E0200.
+For more information about an error, try `rustc --explain E0198`.
diff --git a/src/test/ui/deprecated-safe/deprecated-safe-unsafe-edition-call.mir.stderr b/src/test/ui/deprecated-safe/deprecated-safe-unsafe-edition-call.mir.stderr
new file mode 100644
index 0000000000000..0c397228e769d
--- /dev/null
+++ b/src/test/ui/deprecated-safe/deprecated-safe-unsafe-edition-call.mir.stderr
@@ -0,0 +1,22 @@
+error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
+  --> $DIR/deprecated-safe-unsafe-edition-call.rs:18:5
+   |
+LL |     depr_safe_2015();
+   |     ^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+
+warning: use of function `deprecated_safe::depr_safe_2018` without an unsafe function or block has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-edition-call.rs:19:5
+   |
+LL |     depr_safe_2018();
+   |     ^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: `#[warn(deprecated_safe)]` on by default
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/deprecated-safe/deprecated-safe-unsafe-edition-call.rs b/src/test/ui/deprecated-safe/deprecated-safe-unsafe-edition-call.rs
new file mode 100644
index 0000000000000..51eea3cd8ad0a
--- /dev/null
+++ b/src/test/ui/deprecated-safe/deprecated-safe-unsafe-edition-call.rs
@@ -0,0 +1,26 @@
+// aux-build:deprecated-safe.rs
+// revisions: mir thir
+// NOTE(skippy) these tests output many duplicates, so deduplicate or they become brittle to changes
+// [mir]compile-flags: -Zdeduplicate-diagnostics=yes
+// [thir]compile-flags: -Z thir-unsafeck -Zdeduplicate-diagnostics=yes
+
+#![warn(unused_unsafe)]
+
+extern crate deprecated_safe;
+
+use deprecated_safe::{depr_safe_2015, depr_safe_2018};
+
+fn main() {
+    // NOTE: this test is separate from deprecated-safe-unsafe-edition as the other compiler
+    // errors will stop compilation before these calls are checked
+
+    // usage without unsafe should lint
+    depr_safe_2015(); //~ ERROR call to unsafe function is unsafe and requires unsafe function or block
+    depr_safe_2018(); //~ WARN use of function `deprecated_safe::depr_safe_2018` without an unsafe function or block has been deprecated as it is now an unsafe function
+
+    // these shouldn't lint, appropriate unsafe usage
+    unsafe {
+        depr_safe_2015();
+        depr_safe_2018();
+    }
+}
diff --git a/src/test/ui/deprecated-safe/deprecated-safe-unsafe-edition-call.thir.stderr b/src/test/ui/deprecated-safe/deprecated-safe-unsafe-edition-call.thir.stderr
new file mode 100644
index 0000000000000..0c397228e769d
--- /dev/null
+++ b/src/test/ui/deprecated-safe/deprecated-safe-unsafe-edition-call.thir.stderr
@@ -0,0 +1,22 @@
+error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
+  --> $DIR/deprecated-safe-unsafe-edition-call.rs:18:5
+   |
+LL |     depr_safe_2015();
+   |     ^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+
+warning: use of function `deprecated_safe::depr_safe_2018` without an unsafe function or block has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-edition-call.rs:19:5
+   |
+LL |     depr_safe_2018();
+   |     ^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: `#[warn(deprecated_safe)]` on by default
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/deprecated-safe/deprecated-safe-unsafe-edition-impl.mir.stderr b/src/test/ui/deprecated-safe/deprecated-safe-unsafe-edition-impl.mir.stderr
new file mode 100644
index 0000000000000..ed3f354335c52
--- /dev/null
+++ b/src/test/ui/deprecated-safe/deprecated-safe-unsafe-edition-impl.mir.stderr
@@ -0,0 +1,20 @@
+error[E0200]: the trait `DeprSafe2015` requires an `unsafe impl` declaration
+  --> $DIR/deprecated-safe-unsafe-edition-impl.rs:14:1
+   |
+LL | impl DeprSafe2015 for DeprSafeImpl {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of trait `deprecated_safe::DeprSafe2018` without an `unsafe impl` declaration has been deprecated as it is now an unsafe trait
+  --> $DIR/deprecated-safe-unsafe-edition-impl.rs:15:1
+   |
+LL | impl DeprSafe2018 for DeprSafeImpl {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(deprecated_safe)]` on by default
+   = note: this trait was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the trait's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0200`.
diff --git a/src/test/ui/deprecated-safe/deprecated-safe-unsafe-edition-impl.rs b/src/test/ui/deprecated-safe/deprecated-safe-unsafe-edition-impl.rs
new file mode 100644
index 0000000000000..6a8817ebe1697
--- /dev/null
+++ b/src/test/ui/deprecated-safe/deprecated-safe-unsafe-edition-impl.rs
@@ -0,0 +1,24 @@
+// aux-build:deprecated-safe.rs
+// revisions: mir thir
+// NOTE(skippy) these tests output many duplicates, so deduplicate or they become brittle to changes
+// [mir]compile-flags: -Zdeduplicate-diagnostics=yes
+// [thir]compile-flags: -Z thir-unsafeck -Zdeduplicate-diagnostics=yes
+
+#![warn(unused_unsafe)]
+
+extern crate deprecated_safe;
+
+use deprecated_safe::{DeprSafe2015, DeprSafe2018};
+
+struct DeprSafeImpl;
+impl DeprSafe2015 for DeprSafeImpl {} //~ ERROR the trait `DeprSafe2015` requires an `unsafe impl` declaration
+impl DeprSafe2018 for DeprSafeImpl {} //~ WARN use of trait `deprecated_safe::DeprSafe2018` without an `unsafe impl` declaration has been deprecated as it is now an unsafe trait
+
+struct DeprSafeUnsafeImpl;
+unsafe impl DeprSafe2015 for DeprSafeUnsafeImpl {}
+unsafe impl DeprSafe2018 for DeprSafeUnsafeImpl {}
+
+fn main() {
+    // NOTE: this test is separate from deprecated-safe-unsafe-edition as the other compiler
+    // errors will stop compilation before these calls are checked
+}
diff --git a/src/test/ui/deprecated-safe/deprecated-safe-unsafe-edition-impl.thir.stderr b/src/test/ui/deprecated-safe/deprecated-safe-unsafe-edition-impl.thir.stderr
new file mode 100644
index 0000000000000..ed3f354335c52
--- /dev/null
+++ b/src/test/ui/deprecated-safe/deprecated-safe-unsafe-edition-impl.thir.stderr
@@ -0,0 +1,20 @@
+error[E0200]: the trait `DeprSafe2015` requires an `unsafe impl` declaration
+  --> $DIR/deprecated-safe-unsafe-edition-impl.rs:14:1
+   |
+LL | impl DeprSafe2015 for DeprSafeImpl {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: use of trait `deprecated_safe::DeprSafe2018` without an `unsafe impl` declaration has been deprecated as it is now an unsafe trait
+  --> $DIR/deprecated-safe-unsafe-edition-impl.rs:15:1
+   |
+LL | impl DeprSafe2018 for DeprSafeImpl {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(deprecated_safe)]` on by default
+   = note: this trait was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the trait's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0200`.
diff --git a/src/test/ui/deprecated-safe/deprecated-safe-unsafe-edition.mir.stderr b/src/test/ui/deprecated-safe/deprecated-safe-unsafe-edition.mir.stderr
new file mode 100644
index 0000000000000..8f29122291cbb
--- /dev/null
+++ b/src/test/ui/deprecated-safe/deprecated-safe-unsafe-edition.mir.stderr
@@ -0,0 +1,453 @@
+error[E0277]: expected a `Fn<()>` closure, found `unsafe fn() {depr_safe_2015}`
+  --> $DIR/deprecated-safe-unsafe-edition.rs:23:34
+   |
+LL |     let fn_impl: Box<dyn Fn()> = Box::new(depr_safe_2015);
+   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }`
+   |
+   = help: the trait `Fn<()>` is not implemented for `unsafe fn() {depr_safe_2015}`
+   = note: wrap the `unsafe fn() {depr_safe_2015}` in a closure with no arguments: `|| { /* code */ }`
+   = note: required for the cast to the object type `dyn Fn()`
+
+error[E0277]: expected a `FnMut<()>` closure, found `unsafe fn() {depr_safe_2015}`
+  --> $DIR/deprecated-safe-unsafe-edition.rs:24:37
+   |
+LL |     let fn_impl: Box<dyn FnMut()> = Box::new(depr_safe_2015);
+   |                                     ^^^^^^^^^^^^^^^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }`
+   |
+   = help: the trait `FnMut<()>` is not implemented for `unsafe fn() {depr_safe_2015}`
+   = note: wrap the `unsafe fn() {depr_safe_2015}` in a closure with no arguments: `|| { /* code */ }`
+   = note: required for the cast to the object type `dyn FnMut()`
+
+error[E0277]: expected a `FnOnce<()>` closure, found `unsafe fn() {depr_safe_2015}`
+  --> $DIR/deprecated-safe-unsafe-edition.rs:25:38
+   |
+LL |     let fn_impl: Box<dyn FnOnce()> = Box::new(depr_safe_2015);
+   |                                      ^^^^^^^^^^^^^^^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }`
+   |
+   = help: the trait `FnOnce<()>` is not implemented for `unsafe fn() {depr_safe_2015}`
+   = note: wrap the `unsafe fn() {depr_safe_2015}` in a closure with no arguments: `|| { /* code */ }`
+   = note: required for the cast to the object type `dyn FnOnce()`
+
+error[E0277]: expected a `Fn<()>` closure, found `unsafe fn() {depr_safe_2015}`
+  --> $DIR/deprecated-safe-unsafe-edition.rs:28:27
+   |
+LL |     fn_taking_dyn_fn_impl(Box::new(depr_safe_2015));
+   |     --------------------- ^^^^^^^^^^^^^^^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }`
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `Fn<()>` is not implemented for `unsafe fn() {depr_safe_2015}`
+   = note: wrap the `unsafe fn() {depr_safe_2015}` in a closure with no arguments: `|| { /* code */ }`
+   = note: required for the cast to the object type `dyn Fn()`
+
+error[E0277]: expected a `FnMut<()>` closure, found `unsafe fn() {depr_safe_2015}`
+  --> $DIR/deprecated-safe-unsafe-edition.rs:29:30
+   |
+LL |     fn_taking_dyn_fnmut_impl(Box::new(depr_safe_2015));
+   |     ------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }`
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `FnMut<()>` is not implemented for `unsafe fn() {depr_safe_2015}`
+   = note: wrap the `unsafe fn() {depr_safe_2015}` in a closure with no arguments: `|| { /* code */ }`
+   = note: required for the cast to the object type `dyn FnMut()`
+
+error[E0277]: expected a `FnOnce<()>` closure, found `unsafe fn() {depr_safe_2015}`
+  --> $DIR/deprecated-safe-unsafe-edition.rs:30:31
+   |
+LL |     fn_taking_dyn_fnonce_impl(Box::new(depr_safe_2015));
+   |     ------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }`
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `FnOnce<()>` is not implemented for `unsafe fn() {depr_safe_2015}`
+   = note: wrap the `unsafe fn() {depr_safe_2015}` in a closure with no arguments: `|| { /* code */ }`
+   = note: required for the cast to the object type `dyn FnOnce()`
+
+error[E0277]: expected a `Fn<()>` closure, found `unsafe fn() {depr_safe_2015}`
+  --> $DIR/deprecated-safe-unsafe-edition.rs:33:23
+   |
+LL |     fn_taking_fn_impl(depr_safe_2015);
+   |     ----------------- ^^^^^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }`
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `Fn<()>` is not implemented for `unsafe fn() {depr_safe_2015}`
+   = note: wrap the `unsafe fn() {depr_safe_2015}` in a closure with no arguments: `|| { /* code */ }`
+note: required by a bound in `fn_taking_fn_impl`
+  --> $DIR/deprecated-safe-unsafe-edition.rs:109:30
+   |
+LL | fn fn_taking_fn_impl(_: impl Fn()) {}
+   |                              ^^^^ required by this bound in `fn_taking_fn_impl`
+
+error[E0277]: expected a `FnMut<()>` closure, found `unsafe fn() {depr_safe_2015}`
+  --> $DIR/deprecated-safe-unsafe-edition.rs:34:26
+   |
+LL |     fn_taking_fnmut_impl(depr_safe_2015);
+   |     -------------------- ^^^^^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }`
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `FnMut<()>` is not implemented for `unsafe fn() {depr_safe_2015}`
+   = note: wrap the `unsafe fn() {depr_safe_2015}` in a closure with no arguments: `|| { /* code */ }`
+note: required by a bound in `fn_taking_fnmut_impl`
+  --> $DIR/deprecated-safe-unsafe-edition.rs:110:33
+   |
+LL | fn fn_taking_fnmut_impl(_: impl FnMut()) {}
+   |                                 ^^^^^^^ required by this bound in `fn_taking_fnmut_impl`
+
+error[E0277]: expected a `FnOnce<()>` closure, found `unsafe fn() {depr_safe_2015}`
+  --> $DIR/deprecated-safe-unsafe-edition.rs:35:27
+   |
+LL |     fn_taking_fnonce_impl(depr_safe_2015);
+   |     --------------------- ^^^^^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }`
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `FnOnce<()>` is not implemented for `unsafe fn() {depr_safe_2015}`
+   = note: wrap the `unsafe fn() {depr_safe_2015}` in a closure with no arguments: `|| { /* code */ }`
+note: required by a bound in `fn_taking_fnonce_impl`
+  --> $DIR/deprecated-safe-unsafe-edition.rs:111:34
+   |
+LL | fn fn_taking_fnonce_impl(_: impl FnOnce()) {}
+   |                                  ^^^^^^^^ required by this bound in `fn_taking_fnonce_impl`
+
+error[E0308]: mismatched types
+  --> $DIR/deprecated-safe-unsafe-edition.rs:39:34
+   |
+LL |     let depr_safe_fn_ptr: fn() = depr_safe_2015;
+   |                           ----   ^^^^^^^^^^^^^^ expected normal fn, found unsafe fn
+   |                           |
+   |                           expected due to this
+   |
+   = note: expected fn pointer `fn()`
+                 found fn item `unsafe fn() {depr_safe_2015}`
+
+error[E0277]: expected a `Fn<()>` closure, found `unsafe fn() {depr_safe_2015}`
+  --> $DIR/deprecated-safe-unsafe-edition.rs:40:44
+   |
+LL |     let depr_safe_fn_impl: Box<dyn Fn()> = Box::new(depr_safe_2015);
+   |                                            ^^^^^^^^^^^^^^^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }`
+   |
+   = help: the trait `Fn<()>` is not implemented for `unsafe fn() {depr_safe_2015}`
+   = note: wrap the `unsafe fn() {depr_safe_2015}` in a closure with no arguments: `|| { /* code */ }`
+   = note: required for the cast to the object type `dyn Fn()`
+
+error[E0277]: expected a `FnMut<()>` closure, found `unsafe fn() {depr_safe_2015}`
+  --> $DIR/deprecated-safe-unsafe-edition.rs:41:54
+   |
+LL | ...impl: Box<dyn FnMut()> = Box::new(depr_safe_2015);
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }`
+   |
+   = help: the trait `FnMut<()>` is not implemented for `unsafe fn() {depr_safe_2015}`
+   = note: wrap the `unsafe fn() {depr_safe_2015}` in a closure with no arguments: `|| { /* code */ }`
+   = note: required for the cast to the object type `dyn FnMut()`
+
+error[E0277]: expected a `FnOnce<()>` closure, found `unsafe fn() {depr_safe_2015}`
+  --> $DIR/deprecated-safe-unsafe-edition.rs:42:52
+   |
+LL |     let depr_safe_fnonce_impl: Box<dyn FnOnce()> = Box::new(depr_safe_2015);
+   |                                                    ^^^^^^^^^^^^^^^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }`
+   |
+   = help: the trait `FnOnce<()>` is not implemented for `unsafe fn() {depr_safe_2015}`
+   = note: wrap the `unsafe fn() {depr_safe_2015}` in a closure with no arguments: `|| { /* code */ }`
+   = note: required for the cast to the object type `dyn FnOnce()`
+
+error[E0308]: mismatched types
+  --> $DIR/deprecated-safe-unsafe-edition.rs:52:22
+   |
+LL |     fn_taking_fn_ptr(depr_safe_2015);
+   |                      ^^^^^^^^^^^^^^ expected normal fn, found unsafe fn
+   |
+   = note: expected fn pointer `fn()`
+                 found fn item `unsafe fn() {depr_safe_2015}`
+
+error[E0277]: expected a `Fn<()>` closure, found `unsafe fn() {depr_safe_2015}`
+  --> $DIR/deprecated-safe-unsafe-edition.rs:53:27
+   |
+LL |     fn_taking_dyn_fn_impl(Box::new(depr_safe_2015));
+   |     --------------------- ^^^^^^^^^^^^^^^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }`
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `Fn<()>` is not implemented for `unsafe fn() {depr_safe_2015}`
+   = note: wrap the `unsafe fn() {depr_safe_2015}` in a closure with no arguments: `|| { /* code */ }`
+   = note: required for the cast to the object type `dyn Fn()`
+
+error[E0277]: expected a `FnMut<()>` closure, found `unsafe fn() {depr_safe_2015}`
+  --> $DIR/deprecated-safe-unsafe-edition.rs:54:30
+   |
+LL |     fn_taking_dyn_fnmut_impl(Box::new(depr_safe_2015));
+   |     ------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }`
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `FnMut<()>` is not implemented for `unsafe fn() {depr_safe_2015}`
+   = note: wrap the `unsafe fn() {depr_safe_2015}` in a closure with no arguments: `|| { /* code */ }`
+   = note: required for the cast to the object type `dyn FnMut()`
+
+error[E0277]: expected a `FnOnce<()>` closure, found `unsafe fn() {depr_safe_2015}`
+  --> $DIR/deprecated-safe-unsafe-edition.rs:55:31
+   |
+LL |     fn_taking_dyn_fnonce_impl(Box::new(depr_safe_2015));
+   |     ------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }`
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `FnOnce<()>` is not implemented for `unsafe fn() {depr_safe_2015}`
+   = note: wrap the `unsafe fn() {depr_safe_2015}` in a closure with no arguments: `|| { /* code */ }`
+   = note: required for the cast to the object type `dyn FnOnce()`
+
+error[E0277]: expected a `Fn<()>` closure, found `unsafe fn() {depr_safe_2015}`
+  --> $DIR/deprecated-safe-unsafe-edition.rs:56:23
+   |
+LL |     fn_taking_fn_impl(depr_safe_2015);
+   |     ----------------- ^^^^^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }`
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `Fn<()>` is not implemented for `unsafe fn() {depr_safe_2015}`
+   = note: wrap the `unsafe fn() {depr_safe_2015}` in a closure with no arguments: `|| { /* code */ }`
+note: required by a bound in `fn_taking_fn_impl`
+  --> $DIR/deprecated-safe-unsafe-edition.rs:109:30
+   |
+LL | fn fn_taking_fn_impl(_: impl Fn()) {}
+   |                              ^^^^ required by this bound in `fn_taking_fn_impl`
+
+error[E0277]: expected a `FnMut<()>` closure, found `unsafe fn() {depr_safe_2015}`
+  --> $DIR/deprecated-safe-unsafe-edition.rs:57:26
+   |
+LL |     fn_taking_fnmut_impl(depr_safe_2015);
+   |     -------------------- ^^^^^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }`
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `FnMut<()>` is not implemented for `unsafe fn() {depr_safe_2015}`
+   = note: wrap the `unsafe fn() {depr_safe_2015}` in a closure with no arguments: `|| { /* code */ }`
+note: required by a bound in `fn_taking_fnmut_impl`
+  --> $DIR/deprecated-safe-unsafe-edition.rs:110:33
+   |
+LL | fn fn_taking_fnmut_impl(_: impl FnMut()) {}
+   |                                 ^^^^^^^ required by this bound in `fn_taking_fnmut_impl`
+
+error[E0277]: expected a `FnOnce<()>` closure, found `unsafe fn() {depr_safe_2015}`
+  --> $DIR/deprecated-safe-unsafe-edition.rs:58:27
+   |
+LL |     fn_taking_fnonce_impl(depr_safe_2015);
+   |     --------------------- ^^^^^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }`
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `FnOnce<()>` is not implemented for `unsafe fn() {depr_safe_2015}`
+   = note: wrap the `unsafe fn() {depr_safe_2015}` in a closure with no arguments: `|| { /* code */ }`
+note: required by a bound in `fn_taking_fnonce_impl`
+  --> $DIR/deprecated-safe-unsafe-edition.rs:111:34
+   |
+LL | fn fn_taking_fnonce_impl(_: impl FnOnce()) {}
+   |                                  ^^^^^^^^ required by this bound in `fn_taking_fnonce_impl`
+
+warning: use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-edition.rs:64:34
+   |
+LL |     let fn_impl: Box<dyn Fn()> = Box::new(depr_safe_2018);
+   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(deprecated_safe)]` on by default
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-edition.rs:65:37
+   |
+LL |     let fn_impl: Box<dyn FnMut()> = Box::new(depr_safe_2018);
+   |                                     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-edition.rs:66:38
+   |
+LL |     let fn_impl: Box<dyn FnOnce()> = Box::new(depr_safe_2018);
+   |                                      ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-edition.rs:69:27
+   |
+LL |     fn_taking_dyn_fn_impl(Box::new(depr_safe_2018));
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-edition.rs:70:30
+   |
+LL |     fn_taking_dyn_fnmut_impl(Box::new(depr_safe_2018));
+   |                              ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-edition.rs:71:31
+   |
+LL |     fn_taking_dyn_fnonce_impl(Box::new(depr_safe_2018));
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-edition.rs:74:5
+   |
+LL |     fn_taking_fn_impl(depr_safe_2018);
+   |     ^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-edition.rs:75:5
+   |
+LL |     fn_taking_fnmut_impl(depr_safe_2018);
+   |     ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-edition.rs:76:5
+   |
+LL |     fn_taking_fnonce_impl(depr_safe_2018);
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_2018` as a normal fn pointer has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-edition.rs:80:34
+   |
+LL |     let depr_safe_fn_ptr: fn() = depr_safe_2018;
+   |                                  ^^^^^^^^^^^^^^ expected normal fn pointer, found unsafe fn pointer
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-edition.rs:81:44
+   |
+LL |     let depr_safe_fn_impl: Box<dyn Fn()> = Box::new(depr_safe_2018);
+   |                                            ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-edition.rs:82:54
+   |
+LL |     let mut depr_safe_fnmut_impl: Box<dyn FnMut()> = Box::new(depr_safe_2018);
+   |                                                      ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-edition.rs:83:52
+   |
+LL |     let depr_safe_fnonce_impl: Box<dyn FnOnce()> = Box::new(depr_safe_2018);
+   |                                                    ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_2018` as a normal fn pointer has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-edition.rs:93:22
+   |
+LL |     fn_taking_fn_ptr(depr_safe_2018);
+   |                      ^^^^^^^^^^^^^^ expected normal fn pointer, found unsafe fn pointer
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-edition.rs:94:27
+   |
+LL |     fn_taking_dyn_fn_impl(Box::new(depr_safe_2018));
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-edition.rs:95:30
+   |
+LL |     fn_taking_dyn_fnmut_impl(Box::new(depr_safe_2018));
+   |                              ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-edition.rs:96:31
+   |
+LL |     fn_taking_dyn_fnonce_impl(Box::new(depr_safe_2018));
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-edition.rs:97:5
+   |
+LL |     fn_taking_fn_impl(depr_safe_2018);
+   |     ^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-edition.rs:98:5
+   |
+LL |     fn_taking_fnmut_impl(depr_safe_2018);
+   |     ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-edition.rs:99:5
+   |
+LL |     fn_taking_fnonce_impl(depr_safe_2018);
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+error: aborting due to 20 previous errors; 20 warnings emitted
+
+Some errors have detailed explanations: E0277, E0308.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/deprecated-safe/deprecated-safe-unsafe-edition.rs b/src/test/ui/deprecated-safe/deprecated-safe-unsafe-edition.rs
new file mode 100644
index 0000000000000..a49fdc3e324ab
--- /dev/null
+++ b/src/test/ui/deprecated-safe/deprecated-safe-unsafe-edition.rs
@@ -0,0 +1,111 @@
+// aux-build:deprecated-safe.rs
+// revisions: mir thir
+// NOTE(skippy) these tests output many duplicates, so deduplicate or they become brittle to changes
+// [mir]compile-flags: -Zdeduplicate-diagnostics=yes
+// [thir]compile-flags: -Z thir-unsafeck -Zdeduplicate-diagnostics=yes
+
+#![feature(deprecated_safe)]
+#![warn(unused_unsafe)]
+
+extern crate deprecated_safe;
+
+use deprecated_safe::{depr_safe_2015, depr_safe_2018};
+use std::ffi::{OsStr, OsString};
+
+unsafe fn unsafe_fn() {
+    depr_safe_2015();
+    depr_safe_2018();
+}
+
+fn main() {
+    // test for dyn Fn() coercion where arguments don't match, where an
+    // intermediate fn() will be used
+    let fn_impl: Box<dyn Fn()> = Box::new(depr_safe_2015); //~ ERROR expected a `Fn<()>` closure, found `unsafe fn() {depr_safe_2015}`
+    let fn_impl: Box<dyn FnMut()> = Box::new(depr_safe_2015); //~ ERROR expected a `FnMut<()>` closure, found `unsafe fn() {depr_safe_2015}`
+    let fn_impl: Box<dyn FnOnce()> = Box::new(depr_safe_2015); //~ ERROR expected a `FnOnce<()>` closure, found `unsafe fn() {depr_safe_2015}`
+
+    // test variant where coercion occurs on a function argument instead of a variable
+    fn_taking_dyn_fn_impl(Box::new(depr_safe_2015)); //~ ERROR expected a `Fn<()>` closure, found `unsafe fn() {depr_safe_2015}`
+    fn_taking_dyn_fnmut_impl(Box::new(depr_safe_2015)); //~ ERROR expected a `FnMut<()>` closure, found `unsafe fn() {depr_safe_2015}`
+    fn_taking_dyn_fnonce_impl(Box::new(depr_safe_2015)); //~ ERROR expected a `FnOnce<()>` closure, found `unsafe fn() {depr_safe_2015}`
+
+    // test for non-dyn Fn() coercion (no unsizing)
+    fn_taking_fn_impl(depr_safe_2015); //~ ERROR expected a `Fn<()>` closure, found `unsafe fn() {depr_safe_2015}`
+    fn_taking_fnmut_impl(depr_safe_2015); //~ ERROR expected a `FnMut<()>` closure, found `unsafe fn() {depr_safe_2015}`
+    fn_taking_fnonce_impl(depr_safe_2015); //~ ERROR expected a `FnOnce<()>` closure, found `unsafe fn() {depr_safe_2015}`
+
+    // test for fn() coercion where arguments don't match, where an
+    // intermediate fn() will be used
+    let depr_safe_fn_ptr: fn() = depr_safe_2015; //~ ERROR mismatched types
+    let depr_safe_fn_impl: Box<dyn Fn()> = Box::new(depr_safe_2015); //~ ERROR expected a `Fn<()>` closure, found `unsafe fn() {depr_safe_2015}`
+    let mut depr_safe_fnmut_impl: Box<dyn FnMut()> = Box::new(depr_safe_2015); //~ ERROR expected a `FnMut<()>` closure, found `unsafe fn() {depr_safe_2015}`
+    let depr_safe_fnonce_impl: Box<dyn FnOnce()> = Box::new(depr_safe_2015); //~ ERROR expected a `FnOnce<()>` closure, found `unsafe fn() {depr_safe_2015}`
+
+    // these shouldn't lint, appropriate unsafe usage
+    let unsafe_depr_safe_fn_ptr: unsafe fn() = depr_safe_2015;
+    fn_taking_unsafe_fn_ptr(depr_safe_2015);
+    unsafe {
+        depr_safe_2015();
+    }
+
+    // all of these coercions should lint
+    fn_taking_fn_ptr(depr_safe_2015); //~ ERROR mismatched types
+    fn_taking_dyn_fn_impl(Box::new(depr_safe_2015)); //~ ERROR expected a `Fn<()>` closure, found `unsafe fn() {depr_safe_2015}`
+    fn_taking_dyn_fnmut_impl(Box::new(depr_safe_2015)); //~ ERROR expected a `FnMut<()>` closure, found `unsafe fn() {depr_safe_2015}`
+    fn_taking_dyn_fnonce_impl(Box::new(depr_safe_2015)); //~ ERROR expected a `FnOnce<()>` closure, found `unsafe fn() {depr_safe_2015}`
+    fn_taking_fn_impl(depr_safe_2015); //~ ERROR expected a `Fn<()>` closure, found `unsafe fn() {depr_safe_2015}`
+    fn_taking_fnmut_impl(depr_safe_2015); //~ ERROR expected a `FnMut<()>` closure, found `unsafe fn() {depr_safe_2015}`
+    fn_taking_fnonce_impl(depr_safe_2015); //~ ERROR expected a `FnOnce<()>` closure, found `unsafe fn() {depr_safe_2015}`
+}
+
+fn main_2018() {
+    // test for dyn Fn() coercion where arguments don't match, where an
+    // intermediate fn() will be used
+    let fn_impl: Box<dyn Fn()> = Box::new(depr_safe_2018); //~ WARN use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+    let fn_impl: Box<dyn FnMut()> = Box::new(depr_safe_2018); //~ WARN use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+    let fn_impl: Box<dyn FnOnce()> = Box::new(depr_safe_2018); //~ WARN use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+
+    // test variant where coercion occurs on a function argument instead of a variable
+    fn_taking_dyn_fn_impl(Box::new(depr_safe_2018)); //~ WARN use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+    fn_taking_dyn_fnmut_impl(Box::new(depr_safe_2018)); //~ WARN use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+    fn_taking_dyn_fnonce_impl(Box::new(depr_safe_2018)); //~ WARN use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+
+    // test for non-dyn Fn() coercion (no unsizing)
+    fn_taking_fn_impl(depr_safe_2018); //~ WARN use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+    fn_taking_fnmut_impl(depr_safe_2018); //~ WARN use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+    fn_taking_fnonce_impl(depr_safe_2018); //~ WARN use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+
+    // test for fn() coercion where arguments don't match, where an
+    // intermediate fn() will be used
+    let depr_safe_fn_ptr: fn() = depr_safe_2018; //~ WARN use of function `deprecated_safe::depr_safe_2018` as a normal fn pointer has been deprecated as it is now an unsafe function
+    let depr_safe_fn_impl: Box<dyn Fn()> = Box::new(depr_safe_2018); //~ WARN use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+    let mut depr_safe_fnmut_impl: Box<dyn FnMut()> = Box::new(depr_safe_2018); //~ WARN use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+    let depr_safe_fnonce_impl: Box<dyn FnOnce()> = Box::new(depr_safe_2018); //~ WARN use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+
+    // these shouldn't lint, appropriate unsafe usage
+    let unsafe_depr_safe_fn_ptr: unsafe fn() = depr_safe_2018;
+    fn_taking_unsafe_fn_ptr(depr_safe_2018);
+    unsafe {
+        depr_safe_2018();
+    }
+
+    // all of these coercions should lint
+    fn_taking_fn_ptr(depr_safe_2018); //~ WARN use of function `deprecated_safe::depr_safe_2018` as a normal fn pointer has been deprecated as it is now an unsafe function
+    fn_taking_dyn_fn_impl(Box::new(depr_safe_2018)); //~ WARN use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+    fn_taking_dyn_fnmut_impl(Box::new(depr_safe_2018)); //~ WARN use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+    fn_taking_dyn_fnonce_impl(Box::new(depr_safe_2018)); //~ WARN use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+    fn_taking_fn_impl(depr_safe_2018); //~ WARN use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+    fn_taking_fnmut_impl(depr_safe_2018); //~ WARN use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+    fn_taking_fnonce_impl(depr_safe_2018); //~ WARN use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+}
+
+fn fn_taking_fn_ptr(_: fn()) {}
+fn fn_taking_unsafe_fn_ptr(_: unsafe fn()) {}
+
+fn fn_taking_dyn_fn_impl(_: Box<dyn Fn()>) {}
+fn fn_taking_dyn_fnmut_impl(_: Box<dyn FnMut()>) {}
+fn fn_taking_dyn_fnonce_impl(_: Box<dyn FnOnce()>) {}
+
+fn fn_taking_fn_impl(_: impl Fn()) {}
+fn fn_taking_fnmut_impl(_: impl FnMut()) {}
+fn fn_taking_fnonce_impl(_: impl FnOnce()) {}
diff --git a/src/test/ui/deprecated-safe/deprecated-safe-unsafe-edition.thir.stderr b/src/test/ui/deprecated-safe/deprecated-safe-unsafe-edition.thir.stderr
new file mode 100644
index 0000000000000..8f29122291cbb
--- /dev/null
+++ b/src/test/ui/deprecated-safe/deprecated-safe-unsafe-edition.thir.stderr
@@ -0,0 +1,453 @@
+error[E0277]: expected a `Fn<()>` closure, found `unsafe fn() {depr_safe_2015}`
+  --> $DIR/deprecated-safe-unsafe-edition.rs:23:34
+   |
+LL |     let fn_impl: Box<dyn Fn()> = Box::new(depr_safe_2015);
+   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }`
+   |
+   = help: the trait `Fn<()>` is not implemented for `unsafe fn() {depr_safe_2015}`
+   = note: wrap the `unsafe fn() {depr_safe_2015}` in a closure with no arguments: `|| { /* code */ }`
+   = note: required for the cast to the object type `dyn Fn()`
+
+error[E0277]: expected a `FnMut<()>` closure, found `unsafe fn() {depr_safe_2015}`
+  --> $DIR/deprecated-safe-unsafe-edition.rs:24:37
+   |
+LL |     let fn_impl: Box<dyn FnMut()> = Box::new(depr_safe_2015);
+   |                                     ^^^^^^^^^^^^^^^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }`
+   |
+   = help: the trait `FnMut<()>` is not implemented for `unsafe fn() {depr_safe_2015}`
+   = note: wrap the `unsafe fn() {depr_safe_2015}` in a closure with no arguments: `|| { /* code */ }`
+   = note: required for the cast to the object type `dyn FnMut()`
+
+error[E0277]: expected a `FnOnce<()>` closure, found `unsafe fn() {depr_safe_2015}`
+  --> $DIR/deprecated-safe-unsafe-edition.rs:25:38
+   |
+LL |     let fn_impl: Box<dyn FnOnce()> = Box::new(depr_safe_2015);
+   |                                      ^^^^^^^^^^^^^^^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }`
+   |
+   = help: the trait `FnOnce<()>` is not implemented for `unsafe fn() {depr_safe_2015}`
+   = note: wrap the `unsafe fn() {depr_safe_2015}` in a closure with no arguments: `|| { /* code */ }`
+   = note: required for the cast to the object type `dyn FnOnce()`
+
+error[E0277]: expected a `Fn<()>` closure, found `unsafe fn() {depr_safe_2015}`
+  --> $DIR/deprecated-safe-unsafe-edition.rs:28:27
+   |
+LL |     fn_taking_dyn_fn_impl(Box::new(depr_safe_2015));
+   |     --------------------- ^^^^^^^^^^^^^^^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }`
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `Fn<()>` is not implemented for `unsafe fn() {depr_safe_2015}`
+   = note: wrap the `unsafe fn() {depr_safe_2015}` in a closure with no arguments: `|| { /* code */ }`
+   = note: required for the cast to the object type `dyn Fn()`
+
+error[E0277]: expected a `FnMut<()>` closure, found `unsafe fn() {depr_safe_2015}`
+  --> $DIR/deprecated-safe-unsafe-edition.rs:29:30
+   |
+LL |     fn_taking_dyn_fnmut_impl(Box::new(depr_safe_2015));
+   |     ------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }`
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `FnMut<()>` is not implemented for `unsafe fn() {depr_safe_2015}`
+   = note: wrap the `unsafe fn() {depr_safe_2015}` in a closure with no arguments: `|| { /* code */ }`
+   = note: required for the cast to the object type `dyn FnMut()`
+
+error[E0277]: expected a `FnOnce<()>` closure, found `unsafe fn() {depr_safe_2015}`
+  --> $DIR/deprecated-safe-unsafe-edition.rs:30:31
+   |
+LL |     fn_taking_dyn_fnonce_impl(Box::new(depr_safe_2015));
+   |     ------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }`
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `FnOnce<()>` is not implemented for `unsafe fn() {depr_safe_2015}`
+   = note: wrap the `unsafe fn() {depr_safe_2015}` in a closure with no arguments: `|| { /* code */ }`
+   = note: required for the cast to the object type `dyn FnOnce()`
+
+error[E0277]: expected a `Fn<()>` closure, found `unsafe fn() {depr_safe_2015}`
+  --> $DIR/deprecated-safe-unsafe-edition.rs:33:23
+   |
+LL |     fn_taking_fn_impl(depr_safe_2015);
+   |     ----------------- ^^^^^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }`
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `Fn<()>` is not implemented for `unsafe fn() {depr_safe_2015}`
+   = note: wrap the `unsafe fn() {depr_safe_2015}` in a closure with no arguments: `|| { /* code */ }`
+note: required by a bound in `fn_taking_fn_impl`
+  --> $DIR/deprecated-safe-unsafe-edition.rs:109:30
+   |
+LL | fn fn_taking_fn_impl(_: impl Fn()) {}
+   |                              ^^^^ required by this bound in `fn_taking_fn_impl`
+
+error[E0277]: expected a `FnMut<()>` closure, found `unsafe fn() {depr_safe_2015}`
+  --> $DIR/deprecated-safe-unsafe-edition.rs:34:26
+   |
+LL |     fn_taking_fnmut_impl(depr_safe_2015);
+   |     -------------------- ^^^^^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }`
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `FnMut<()>` is not implemented for `unsafe fn() {depr_safe_2015}`
+   = note: wrap the `unsafe fn() {depr_safe_2015}` in a closure with no arguments: `|| { /* code */ }`
+note: required by a bound in `fn_taking_fnmut_impl`
+  --> $DIR/deprecated-safe-unsafe-edition.rs:110:33
+   |
+LL | fn fn_taking_fnmut_impl(_: impl FnMut()) {}
+   |                                 ^^^^^^^ required by this bound in `fn_taking_fnmut_impl`
+
+error[E0277]: expected a `FnOnce<()>` closure, found `unsafe fn() {depr_safe_2015}`
+  --> $DIR/deprecated-safe-unsafe-edition.rs:35:27
+   |
+LL |     fn_taking_fnonce_impl(depr_safe_2015);
+   |     --------------------- ^^^^^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }`
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `FnOnce<()>` is not implemented for `unsafe fn() {depr_safe_2015}`
+   = note: wrap the `unsafe fn() {depr_safe_2015}` in a closure with no arguments: `|| { /* code */ }`
+note: required by a bound in `fn_taking_fnonce_impl`
+  --> $DIR/deprecated-safe-unsafe-edition.rs:111:34
+   |
+LL | fn fn_taking_fnonce_impl(_: impl FnOnce()) {}
+   |                                  ^^^^^^^^ required by this bound in `fn_taking_fnonce_impl`
+
+error[E0308]: mismatched types
+  --> $DIR/deprecated-safe-unsafe-edition.rs:39:34
+   |
+LL |     let depr_safe_fn_ptr: fn() = depr_safe_2015;
+   |                           ----   ^^^^^^^^^^^^^^ expected normal fn, found unsafe fn
+   |                           |
+   |                           expected due to this
+   |
+   = note: expected fn pointer `fn()`
+                 found fn item `unsafe fn() {depr_safe_2015}`
+
+error[E0277]: expected a `Fn<()>` closure, found `unsafe fn() {depr_safe_2015}`
+  --> $DIR/deprecated-safe-unsafe-edition.rs:40:44
+   |
+LL |     let depr_safe_fn_impl: Box<dyn Fn()> = Box::new(depr_safe_2015);
+   |                                            ^^^^^^^^^^^^^^^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }`
+   |
+   = help: the trait `Fn<()>` is not implemented for `unsafe fn() {depr_safe_2015}`
+   = note: wrap the `unsafe fn() {depr_safe_2015}` in a closure with no arguments: `|| { /* code */ }`
+   = note: required for the cast to the object type `dyn Fn()`
+
+error[E0277]: expected a `FnMut<()>` closure, found `unsafe fn() {depr_safe_2015}`
+  --> $DIR/deprecated-safe-unsafe-edition.rs:41:54
+   |
+LL | ...impl: Box<dyn FnMut()> = Box::new(depr_safe_2015);
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }`
+   |
+   = help: the trait `FnMut<()>` is not implemented for `unsafe fn() {depr_safe_2015}`
+   = note: wrap the `unsafe fn() {depr_safe_2015}` in a closure with no arguments: `|| { /* code */ }`
+   = note: required for the cast to the object type `dyn FnMut()`
+
+error[E0277]: expected a `FnOnce<()>` closure, found `unsafe fn() {depr_safe_2015}`
+  --> $DIR/deprecated-safe-unsafe-edition.rs:42:52
+   |
+LL |     let depr_safe_fnonce_impl: Box<dyn FnOnce()> = Box::new(depr_safe_2015);
+   |                                                    ^^^^^^^^^^^^^^^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }`
+   |
+   = help: the trait `FnOnce<()>` is not implemented for `unsafe fn() {depr_safe_2015}`
+   = note: wrap the `unsafe fn() {depr_safe_2015}` in a closure with no arguments: `|| { /* code */ }`
+   = note: required for the cast to the object type `dyn FnOnce()`
+
+error[E0308]: mismatched types
+  --> $DIR/deprecated-safe-unsafe-edition.rs:52:22
+   |
+LL |     fn_taking_fn_ptr(depr_safe_2015);
+   |                      ^^^^^^^^^^^^^^ expected normal fn, found unsafe fn
+   |
+   = note: expected fn pointer `fn()`
+                 found fn item `unsafe fn() {depr_safe_2015}`
+
+error[E0277]: expected a `Fn<()>` closure, found `unsafe fn() {depr_safe_2015}`
+  --> $DIR/deprecated-safe-unsafe-edition.rs:53:27
+   |
+LL |     fn_taking_dyn_fn_impl(Box::new(depr_safe_2015));
+   |     --------------------- ^^^^^^^^^^^^^^^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }`
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `Fn<()>` is not implemented for `unsafe fn() {depr_safe_2015}`
+   = note: wrap the `unsafe fn() {depr_safe_2015}` in a closure with no arguments: `|| { /* code */ }`
+   = note: required for the cast to the object type `dyn Fn()`
+
+error[E0277]: expected a `FnMut<()>` closure, found `unsafe fn() {depr_safe_2015}`
+  --> $DIR/deprecated-safe-unsafe-edition.rs:54:30
+   |
+LL |     fn_taking_dyn_fnmut_impl(Box::new(depr_safe_2015));
+   |     ------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }`
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `FnMut<()>` is not implemented for `unsafe fn() {depr_safe_2015}`
+   = note: wrap the `unsafe fn() {depr_safe_2015}` in a closure with no arguments: `|| { /* code */ }`
+   = note: required for the cast to the object type `dyn FnMut()`
+
+error[E0277]: expected a `FnOnce<()>` closure, found `unsafe fn() {depr_safe_2015}`
+  --> $DIR/deprecated-safe-unsafe-edition.rs:55:31
+   |
+LL |     fn_taking_dyn_fnonce_impl(Box::new(depr_safe_2015));
+   |     ------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }`
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `FnOnce<()>` is not implemented for `unsafe fn() {depr_safe_2015}`
+   = note: wrap the `unsafe fn() {depr_safe_2015}` in a closure with no arguments: `|| { /* code */ }`
+   = note: required for the cast to the object type `dyn FnOnce()`
+
+error[E0277]: expected a `Fn<()>` closure, found `unsafe fn() {depr_safe_2015}`
+  --> $DIR/deprecated-safe-unsafe-edition.rs:56:23
+   |
+LL |     fn_taking_fn_impl(depr_safe_2015);
+   |     ----------------- ^^^^^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }`
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `Fn<()>` is not implemented for `unsafe fn() {depr_safe_2015}`
+   = note: wrap the `unsafe fn() {depr_safe_2015}` in a closure with no arguments: `|| { /* code */ }`
+note: required by a bound in `fn_taking_fn_impl`
+  --> $DIR/deprecated-safe-unsafe-edition.rs:109:30
+   |
+LL | fn fn_taking_fn_impl(_: impl Fn()) {}
+   |                              ^^^^ required by this bound in `fn_taking_fn_impl`
+
+error[E0277]: expected a `FnMut<()>` closure, found `unsafe fn() {depr_safe_2015}`
+  --> $DIR/deprecated-safe-unsafe-edition.rs:57:26
+   |
+LL |     fn_taking_fnmut_impl(depr_safe_2015);
+   |     -------------------- ^^^^^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }`
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `FnMut<()>` is not implemented for `unsafe fn() {depr_safe_2015}`
+   = note: wrap the `unsafe fn() {depr_safe_2015}` in a closure with no arguments: `|| { /* code */ }`
+note: required by a bound in `fn_taking_fnmut_impl`
+  --> $DIR/deprecated-safe-unsafe-edition.rs:110:33
+   |
+LL | fn fn_taking_fnmut_impl(_: impl FnMut()) {}
+   |                                 ^^^^^^^ required by this bound in `fn_taking_fnmut_impl`
+
+error[E0277]: expected a `FnOnce<()>` closure, found `unsafe fn() {depr_safe_2015}`
+  --> $DIR/deprecated-safe-unsafe-edition.rs:58:27
+   |
+LL |     fn_taking_fnonce_impl(depr_safe_2015);
+   |     --------------------- ^^^^^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }`
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `FnOnce<()>` is not implemented for `unsafe fn() {depr_safe_2015}`
+   = note: wrap the `unsafe fn() {depr_safe_2015}` in a closure with no arguments: `|| { /* code */ }`
+note: required by a bound in `fn_taking_fnonce_impl`
+  --> $DIR/deprecated-safe-unsafe-edition.rs:111:34
+   |
+LL | fn fn_taking_fnonce_impl(_: impl FnOnce()) {}
+   |                                  ^^^^^^^^ required by this bound in `fn_taking_fnonce_impl`
+
+warning: use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-edition.rs:64:34
+   |
+LL |     let fn_impl: Box<dyn Fn()> = Box::new(depr_safe_2018);
+   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(deprecated_safe)]` on by default
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-edition.rs:65:37
+   |
+LL |     let fn_impl: Box<dyn FnMut()> = Box::new(depr_safe_2018);
+   |                                     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-edition.rs:66:38
+   |
+LL |     let fn_impl: Box<dyn FnOnce()> = Box::new(depr_safe_2018);
+   |                                      ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-edition.rs:69:27
+   |
+LL |     fn_taking_dyn_fn_impl(Box::new(depr_safe_2018));
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-edition.rs:70:30
+   |
+LL |     fn_taking_dyn_fnmut_impl(Box::new(depr_safe_2018));
+   |                              ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-edition.rs:71:31
+   |
+LL |     fn_taking_dyn_fnonce_impl(Box::new(depr_safe_2018));
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-edition.rs:74:5
+   |
+LL |     fn_taking_fn_impl(depr_safe_2018);
+   |     ^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-edition.rs:75:5
+   |
+LL |     fn_taking_fnmut_impl(depr_safe_2018);
+   |     ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-edition.rs:76:5
+   |
+LL |     fn_taking_fnonce_impl(depr_safe_2018);
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_2018` as a normal fn pointer has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-edition.rs:80:34
+   |
+LL |     let depr_safe_fn_ptr: fn() = depr_safe_2018;
+   |                                  ^^^^^^^^^^^^^^ expected normal fn pointer, found unsafe fn pointer
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-edition.rs:81:44
+   |
+LL |     let depr_safe_fn_impl: Box<dyn Fn()> = Box::new(depr_safe_2018);
+   |                                            ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-edition.rs:82:54
+   |
+LL |     let mut depr_safe_fnmut_impl: Box<dyn FnMut()> = Box::new(depr_safe_2018);
+   |                                                      ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-edition.rs:83:52
+   |
+LL |     let depr_safe_fnonce_impl: Box<dyn FnOnce()> = Box::new(depr_safe_2018);
+   |                                                    ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_2018` as a normal fn pointer has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-edition.rs:93:22
+   |
+LL |     fn_taking_fn_ptr(depr_safe_2018);
+   |                      ^^^^^^^^^^^^^^ expected normal fn pointer, found unsafe fn pointer
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-edition.rs:94:27
+   |
+LL |     fn_taking_dyn_fn_impl(Box::new(depr_safe_2018));
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-edition.rs:95:30
+   |
+LL |     fn_taking_dyn_fnmut_impl(Box::new(depr_safe_2018));
+   |                              ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-edition.rs:96:31
+   |
+LL |     fn_taking_dyn_fnonce_impl(Box::new(depr_safe_2018));
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-edition.rs:97:5
+   |
+LL |     fn_taking_fn_impl(depr_safe_2018);
+   |     ^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-edition.rs:98:5
+   |
+LL |     fn_taking_fnmut_impl(depr_safe_2018);
+   |     ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_2018` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-edition.rs:99:5
+   |
+LL |     fn_taking_fnonce_impl(depr_safe_2018);
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+error: aborting due to 20 previous errors; 20 warnings emitted
+
+Some errors have detailed explanations: E0277, E0308.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/deprecated-safe/deprecated-safe-unsafe-op-in-unsafe-fn.mir.stderr b/src/test/ui/deprecated-safe/deprecated-safe-unsafe-op-in-unsafe-fn.mir.stderr
new file mode 100644
index 0000000000000..e18dea3087a34
--- /dev/null
+++ b/src/test/ui/deprecated-safe/deprecated-safe-unsafe-op-in-unsafe-fn.mir.stderr
@@ -0,0 +1,119 @@
+warning: use of function `deprecated_safe::depr_safe` without an unsafe block has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-op-in-unsafe-fn.rs:17:5
+   |
+LL |     depr_safe();
+   |     ^^^^^^^^^^^ call to unsafe function
+   |
+   = note: `#[warn(deprecated_safe)]` on by default
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+error: call to unsafe function is unsafe and requires unsafe block (error E0133)
+  --> $DIR/deprecated-safe-unsafe-op-in-unsafe-fn.rs:23:5
+   |
+LL |     depr_safe_2015();
+   |     ^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+note: the lint level is defined here
+  --> $DIR/deprecated-safe-unsafe-op-in-unsafe-fn.rs:7:9
+   |
+LL | #![deny(unsafe_op_in_unsafe_fn)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+
+warning: use of function `deprecated_safe::depr_safe_2018` without an unsafe block has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-op-in-unsafe-fn.rs:29:5
+   |
+LL |     depr_safe_2018();
+   |     ^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: unnecessary `unsafe` block
+  --> $DIR/deprecated-safe-unsafe-op-in-unsafe-fn.rs:15:5
+   |
+LL |     unsafe {}
+   |     ^^^^^^ unnecessary `unsafe` block
+   |
+note: the lint level is defined here
+  --> $DIR/deprecated-safe-unsafe-op-in-unsafe-fn.rs:8:9
+   |
+LL | #![warn(unused_unsafe)]
+   |         ^^^^^^^^^^^^^
+
+warning: unnecessary `unsafe` block
+  --> $DIR/deprecated-safe-unsafe-op-in-unsafe-fn.rs:20:9
+   |
+LL |         unsafe {}
+   |         ^^^^^^ unnecessary `unsafe` block
+
+warning: unnecessary `unsafe` block
+  --> $DIR/deprecated-safe-unsafe-op-in-unsafe-fn.rs:26:9
+   |
+LL |         unsafe {}
+   |         ^^^^^^ unnecessary `unsafe` block
+
+warning: unnecessary `unsafe` block
+  --> $DIR/deprecated-safe-unsafe-op-in-unsafe-fn.rs:32:9
+   |
+LL |         unsafe {}
+   |         ^^^^^^ unnecessary `unsafe` block
+
+warning: use of function `deprecated_safe::depr_safe` without an unsafe block has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-op-in-unsafe-fn.rs:39:5
+   |
+LL |     depr_safe();
+   |     ^^^^^^^^^^^ call to unsafe function
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+error[E0133]: call to unsafe function is unsafe and requires unsafe block
+  --> $DIR/deprecated-safe-unsafe-op-in-unsafe-fn.rs:45:5
+   |
+LL |     depr_safe_2015();
+   |     ^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+
+warning: use of function `deprecated_safe::depr_safe_2018` without an unsafe block has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-op-in-unsafe-fn.rs:51:5
+   |
+LL |     depr_safe_2018();
+   |     ^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: unnecessary `unsafe` block
+  --> $DIR/deprecated-safe-unsafe-op-in-unsafe-fn.rs:37:5
+   |
+LL |     unsafe {}
+   |     ^^^^^^ unnecessary `unsafe` block
+
+warning: unnecessary `unsafe` block
+  --> $DIR/deprecated-safe-unsafe-op-in-unsafe-fn.rs:42:9
+   |
+LL |         unsafe {}
+   |         ^^^^^^ unnecessary `unsafe` block
+
+warning: unnecessary `unsafe` block
+  --> $DIR/deprecated-safe-unsafe-op-in-unsafe-fn.rs:48:9
+   |
+LL |         unsafe {}
+   |         ^^^^^^ unnecessary `unsafe` block
+
+warning: unnecessary `unsafe` block
+  --> $DIR/deprecated-safe-unsafe-op-in-unsafe-fn.rs:54:9
+   |
+LL |         unsafe {}
+   |         ^^^^^^ unnecessary `unsafe` block
+
+error: aborting due to 2 previous errors; 12 warnings emitted
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/deprecated-safe/deprecated-safe-unsafe-op-in-unsafe-fn.rs b/src/test/ui/deprecated-safe/deprecated-safe-unsafe-op-in-unsafe-fn.rs
new file mode 100644
index 0000000000000..97d8c4b1a203a
--- /dev/null
+++ b/src/test/ui/deprecated-safe/deprecated-safe-unsafe-op-in-unsafe-fn.rs
@@ -0,0 +1,56 @@
+// aux-build:deprecated-safe.rs
+// revisions: mir thir
+// NOTE(skippy) these tests output many duplicates, so deduplicate or they become brittle to changes
+// [mir]compile-flags: -Zdeduplicate-diagnostics=yes
+// [thir]compile-flags: -Z thir-unsafeck -Zdeduplicate-diagnostics=yes
+
+#![deny(unsafe_op_in_unsafe_fn)]
+#![warn(unused_unsafe)]
+
+extern crate deprecated_safe;
+
+use deprecated_safe::{depr_safe, depr_safe_2015, depr_safe_2018};
+
+unsafe fn unsafe_fn() {
+    unsafe {} //~ WARN unnecessary `unsafe` block
+
+    depr_safe(); //~ WARN use of function `deprecated_safe::depr_safe` without an unsafe block has been deprecated as it is now an unsafe function
+    unsafe {
+        depr_safe();
+        unsafe {} //~ WARN unnecessary `unsafe` block
+    }
+
+    depr_safe_2015(); //~ ERROR call to unsafe function is unsafe and requires unsafe block
+    unsafe {
+        depr_safe_2015();
+        unsafe {} //~ WARN unnecessary `unsafe` block
+    }
+
+    depr_safe_2018(); //~ WARN use of function `deprecated_safe::depr_safe_2018` without an unsafe block has been deprecated as it is now an unsafe function
+    unsafe {
+        depr_safe_2018();
+        unsafe {} //~ WARN unnecessary `unsafe` block
+    }
+}
+
+fn main() {
+    unsafe {} //~ WARN unnecessary `unsafe` block
+
+    depr_safe(); //~ WARN use of function `deprecated_safe::depr_safe` without an unsafe block has been deprecated as it is now an unsafe function
+    unsafe {
+        depr_safe();
+        unsafe {} //~ WARN unnecessary `unsafe` block
+    }
+
+    depr_safe_2015(); //~ ERROR call to unsafe function is unsafe and requires unsafe block
+    unsafe {
+        depr_safe_2015();
+        unsafe {} //~ WARN unnecessary `unsafe` block
+    }
+
+    depr_safe_2018(); //~ WARN use of function `deprecated_safe::depr_safe_2018` without an unsafe block has been deprecated as it is now an unsafe function
+    unsafe {
+        depr_safe_2018();
+        unsafe {} //~ WARN unnecessary `unsafe` block
+    }
+}
diff --git a/src/test/ui/deprecated-safe/deprecated-safe-unsafe-op-in-unsafe-fn.thir.stderr b/src/test/ui/deprecated-safe/deprecated-safe-unsafe-op-in-unsafe-fn.thir.stderr
new file mode 100644
index 0000000000000..d7774276d1ccd
--- /dev/null
+++ b/src/test/ui/deprecated-safe/deprecated-safe-unsafe-op-in-unsafe-fn.thir.stderr
@@ -0,0 +1,137 @@
+warning: unnecessary `unsafe` block
+  --> $DIR/deprecated-safe-unsafe-op-in-unsafe-fn.rs:15:5
+   |
+LL |     unsafe {}
+   |     ^^^^^^ unnecessary `unsafe` block
+   |
+note: the lint level is defined here
+  --> $DIR/deprecated-safe-unsafe-op-in-unsafe-fn.rs:8:9
+   |
+LL | #![warn(unused_unsafe)]
+   |         ^^^^^^^^^^^^^
+
+warning: use of function `deprecated_safe::depr_safe` without an unsafe block has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-op-in-unsafe-fn.rs:17:5
+   |
+LL |     depr_safe();
+   |     ^^^^^^^^^^^ call to unsafe function
+   |
+   = note: `#[warn(deprecated_safe)]` on by default
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: unnecessary `unsafe` block
+  --> $DIR/deprecated-safe-unsafe-op-in-unsafe-fn.rs:20:9
+   |
+LL |     unsafe {
+   |     ------ because it's nested under this `unsafe` block
+LL |         depr_safe();
+LL |         unsafe {}
+   |         ^^^^^^ unnecessary `unsafe` block
+
+error: call to unsafe function is unsafe and requires unsafe block (error E0133)
+  --> $DIR/deprecated-safe-unsafe-op-in-unsafe-fn.rs:23:5
+   |
+LL |     depr_safe_2015();
+   |     ^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+note: the lint level is defined here
+  --> $DIR/deprecated-safe-unsafe-op-in-unsafe-fn.rs:7:9
+   |
+LL | #![deny(unsafe_op_in_unsafe_fn)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+
+warning: unnecessary `unsafe` block
+  --> $DIR/deprecated-safe-unsafe-op-in-unsafe-fn.rs:26:9
+   |
+LL |     unsafe {
+   |     ------ because it's nested under this `unsafe` block
+LL |         depr_safe_2015();
+LL |         unsafe {}
+   |         ^^^^^^ unnecessary `unsafe` block
+
+warning: use of function `deprecated_safe::depr_safe_2018` without an unsafe block has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-op-in-unsafe-fn.rs:29:5
+   |
+LL |     depr_safe_2018();
+   |     ^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: unnecessary `unsafe` block
+  --> $DIR/deprecated-safe-unsafe-op-in-unsafe-fn.rs:32:9
+   |
+LL |     unsafe {
+   |     ------ because it's nested under this `unsafe` block
+LL |         depr_safe_2018();
+LL |         unsafe {}
+   |         ^^^^^^ unnecessary `unsafe` block
+
+warning: unnecessary `unsafe` block
+  --> $DIR/deprecated-safe-unsafe-op-in-unsafe-fn.rs:37:5
+   |
+LL |     unsafe {}
+   |     ^^^^^^ unnecessary `unsafe` block
+
+warning: use of function `deprecated_safe::depr_safe` without an unsafe block has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-op-in-unsafe-fn.rs:39:5
+   |
+LL |     depr_safe();
+   |     ^^^^^^^^^^^ call to unsafe function
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: unnecessary `unsafe` block
+  --> $DIR/deprecated-safe-unsafe-op-in-unsafe-fn.rs:42:9
+   |
+LL |     unsafe {
+   |     ------ because it's nested under this `unsafe` block
+LL |         depr_safe();
+LL |         unsafe {}
+   |         ^^^^^^ unnecessary `unsafe` block
+
+error[E0133]: call to unsafe function is unsafe and requires unsafe block
+  --> $DIR/deprecated-safe-unsafe-op-in-unsafe-fn.rs:45:5
+   |
+LL |     depr_safe_2015();
+   |     ^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+
+warning: unnecessary `unsafe` block
+  --> $DIR/deprecated-safe-unsafe-op-in-unsafe-fn.rs:48:9
+   |
+LL |     unsafe {
+   |     ------ because it's nested under this `unsafe` block
+LL |         depr_safe_2015();
+LL |         unsafe {}
+   |         ^^^^^^ unnecessary `unsafe` block
+
+warning: use of function `deprecated_safe::depr_safe_2018` without an unsafe block has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe-unsafe-op-in-unsafe-fn.rs:51:5
+   |
+LL |     depr_safe_2018();
+   |     ^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: unnecessary `unsafe` block
+  --> $DIR/deprecated-safe-unsafe-op-in-unsafe-fn.rs:54:9
+   |
+LL |     unsafe {
+   |     ------ because it's nested under this `unsafe` block
+LL |         depr_safe_2018();
+LL |         unsafe {}
+   |         ^^^^^^ unnecessary `unsafe` block
+
+error: aborting due to 2 previous errors; 12 warnings emitted
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/deprecated-safe/deprecated-safe.mir.stderr b/src/test/ui/deprecated-safe/deprecated-safe.mir.stderr
new file mode 100644
index 0000000000000..c3cdf5f312367
--- /dev/null
+++ b/src/test/ui/deprecated-safe/deprecated-safe.mir.stderr
@@ -0,0 +1,1238 @@
+warning: use of trait `deprecated_safe::DeprSafe` without an `unsafe impl` declaration has been deprecated as it is now an unsafe trait
+  --> $DIR/deprecated-safe.rs:108:1
+   |
+LL | impl DeprSafe for DeprSafeImpl {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(deprecated_safe)]` on by default
+   = note: this trait was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the trait's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:54:5
+   |
+LL |     depr_safe
+   |     ^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:57:14
+   |
+LL | fn foo2() -> impl FnOnce() {
+   |              ^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:57:28
+   |
+LL |   fn foo2() -> impl FnOnce() {
+   |  ____________________________^
+LL | |
+LL | |
+LL | |     depr_safe
+LL | | }
+   | |_^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_params` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:64:5
+   |
+LL |     depr_safe_params
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_params` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:67:14
+   |
+LL | fn foo4() -> impl FnOnce(u32, u64) {
+   |              ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_params` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:67:36
+   |
+LL |   fn foo4() -> impl FnOnce(u32, u64) {
+   |  ____________________________________^
+LL | |
+LL | |
+LL | |     depr_safe_params
+LL | | }
+   | |_^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:74:5
+   |
+LL |     depr_safe_generic
+   |     ^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:77:14
+   |
+LL | fn foo6() -> impl FnOnce(OsString, OsString) {
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:77:46
+   |
+LL |   fn foo6() -> impl FnOnce(OsString, OsString) {
+   |  ______________________________________________^
+LL | |
+LL | |
+LL | |     depr_safe_generic
+LL | | }
+   | |_^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:84:5
+   |
+LL |     Box::new(depr_safe)
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:88:5
+   |
+LL |     Box::new(depr_safe)
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_params` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:92:5
+   |
+LL |     Box::new(depr_safe_params)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_params` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:96:5
+   |
+LL |     Box::new(depr_safe_params)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:100:5
+   |
+LL |     Box::new(depr_safe_generic)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:104:5
+   |
+LL |     Box::new(depr_safe_generic)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:174:34
+   |
+LL |     let fn_impl: Box<dyn Fn()> = Box::new(depr_safe);
+   |                                  ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:175:37
+   |
+LL |     let fn_impl: Box<dyn FnMut()> = Box::new(depr_safe);
+   |                                     ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:176:38
+   |
+LL |     let fn_impl: Box<dyn FnOnce()> = Box::new(depr_safe);
+   |                                      ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:179:34
+   |
+LL |     let fn_impl: Box<dyn Fn()> = Box::new(depr_safe);
+   |                                  ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:180:37
+   |
+LL |     let fn_impl: Box<dyn FnMut()> = Box::new(depr_safe);
+   |                                     ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:181:38
+   |
+LL |     let fn_impl: Box<dyn FnOnce()> = Box::new(depr_safe);
+   |                                      ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:184:27
+   |
+LL |     fn_taking_dyn_fn_impl(Box::new(depr_safe));
+   |                           ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:185:30
+   |
+LL |     fn_taking_dyn_fnmut_impl(Box::new(depr_safe));
+   |                              ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:186:31
+   |
+LL |     fn_taking_dyn_fnonce_impl(Box::new(depr_safe));
+   |                               ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:189:27
+   |
+LL |     fn_taking_dyn_fn_impl(Box::new(depr_safe));
+   |                           ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:190:30
+   |
+LL |     fn_taking_dyn_fnmut_impl(Box::new(depr_safe));
+   |                              ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:191:31
+   |
+LL |     fn_taking_dyn_fnonce_impl(Box::new(depr_safe));
+   |                               ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:194:5
+   |
+LL |     fn_taking_fn_impl(depr_safe);
+   |     ^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:195:5
+   |
+LL |     fn_taking_fnmut_impl(depr_safe);
+   |     ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:196:5
+   |
+LL |     fn_taking_fnonce_impl(depr_safe);
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:199:5
+   |
+LL |     fn_taking_fn_impl(depr_safe);
+   |     ^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:200:5
+   |
+LL |     fn_taking_fnmut_impl(depr_safe);
+   |     ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:201:5
+   |
+LL |     fn_taking_fnonce_impl(depr_safe);
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a normal fn pointer has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:208:34
+   |
+LL |     let depr_safe_fn_ptr: fn() = depr_safe;
+   |                                  ^^^^^^^^^ expected normal fn pointer, found unsafe fn pointer
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a normal fn pointer has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:211:34
+   |
+LL |     let depr_safe_fn_ptr: fn() = depr_safe;
+   |                                  ^^^^^^^^^ expected normal fn pointer, found unsafe fn pointer
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a normal fn pointer has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:215:34
+   |
+LL |     let depr_safe_fn_ptr: fn() = depr_safe;
+   |                                  ^^^^^^^^^ expected normal fn pointer, found unsafe fn pointer
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:216:44
+   |
+LL |     let depr_safe_fn_impl: Box<dyn Fn()> = Box::new(depr_safe);
+   |                                            ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:217:54
+   |
+LL |     let mut depr_safe_fnmut_impl: Box<dyn FnMut()> = Box::new(depr_safe);
+   |                                                      ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:218:52
+   |
+LL |     let depr_safe_fnonce_impl: Box<dyn FnOnce()> = Box::new(depr_safe);
+   |                                                    ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a normal fn pointer has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:221:34
+   |
+LL |     let depr_safe_fn_ptr: fn() = depr_safe;
+   |                                  ^^^^^^^^^ expected normal fn pointer, found unsafe fn pointer
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:222:44
+   |
+LL |     let depr_safe_fn_impl: Box<dyn Fn()> = Box::new(depr_safe);
+   |                                            ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:223:54
+   |
+LL |     let mut depr_safe_fnmut_impl: Box<dyn FnMut()> = Box::new(depr_safe);
+   |                                                      ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:224:52
+   |
+LL |     let depr_safe_fnonce_impl: Box<dyn FnOnce()> = Box::new(depr_safe);
+   |                                                    ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a normal fn pointer has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:234:22
+   |
+LL |     fn_taking_fn_ptr(depr_safe);
+   |                      ^^^^^^^^^ expected normal fn pointer, found unsafe fn pointer
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:235:27
+   |
+LL |     fn_taking_dyn_fn_impl(Box::new(depr_safe));
+   |                           ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:236:30
+   |
+LL |     fn_taking_dyn_fnmut_impl(Box::new(depr_safe));
+   |                              ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:237:31
+   |
+LL |     fn_taking_dyn_fnonce_impl(Box::new(depr_safe));
+   |                               ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:238:5
+   |
+LL |     fn_taking_fn_impl(depr_safe);
+   |     ^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:239:5
+   |
+LL |     fn_taking_fnmut_impl(depr_safe);
+   |     ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:240:5
+   |
+LL |     fn_taking_fnonce_impl(depr_safe);
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a normal fn pointer has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:243:22
+   |
+LL |     fn_taking_fn_ptr(depr_safe);
+   |                      ^^^^^^^^^ expected normal fn pointer, found unsafe fn pointer
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:244:27
+   |
+LL |     fn_taking_dyn_fn_impl(Box::new(depr_safe));
+   |                           ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:245:30
+   |
+LL |     fn_taking_dyn_fnmut_impl(Box::new(depr_safe));
+   |                              ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:246:31
+   |
+LL |     fn_taking_dyn_fnonce_impl(Box::new(depr_safe));
+   |                               ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:247:5
+   |
+LL |     fn_taking_fn_impl(depr_safe);
+   |     ^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:248:5
+   |
+LL |     fn_taking_fnmut_impl(depr_safe);
+   |     ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:249:5
+   |
+LL |     fn_taking_fnonce_impl(depr_safe);
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:253:52
+   |
+LL |     let fn_impl: Box<dyn Fn(OsString, OsString)> = Box::new(depr_safe_generic);
+   |                                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:254:55
+   |
+LL |     let fn_impl: Box<dyn FnMut(OsString, OsString)> = Box::new(depr_safe_generic);
+   |                                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:255:56
+   |
+LL |     let fn_impl: Box<dyn FnOnce(OsString, OsString)> = Box::new(depr_safe_generic);
+   |                                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:258:52
+   |
+LL |     let fn_impl: Box<dyn Fn(OsString, OsString)> = Box::new(depr_safe_generic);
+   |                                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:259:55
+   |
+LL |     let fn_impl: Box<dyn FnMut(OsString, OsString)> = Box::new(depr_safe_generic);
+   |                                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:260:56
+   |
+LL |     let fn_impl: Box<dyn FnOnce(OsString, OsString)> = Box::new(depr_safe_generic);
+   |                                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:263:35
+   |
+LL |     fn_taking_dyn_fn_impl_generic(Box::new(depr_safe_generic));
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:264:38
+   |
+LL |     fn_taking_dyn_fnmut_impl_generic(Box::new(depr_safe_generic));
+   |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:265:39
+   |
+LL |     fn_taking_dyn_fnonce_impl_generic(Box::new(depr_safe_generic));
+   |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:268:35
+   |
+LL |     fn_taking_dyn_fn_impl_generic(Box::new(depr_safe_generic));
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:269:38
+   |
+LL |     fn_taking_dyn_fnmut_impl_generic(Box::new(depr_safe_generic));
+   |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:270:39
+   |
+LL |     fn_taking_dyn_fnonce_impl_generic(Box::new(depr_safe_generic));
+   |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:273:5
+   |
+LL |     fn_taking_fn_impl_generic(depr_safe_generic);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:274:5
+   |
+LL |     fn_taking_fnmut_impl_generic(depr_safe_generic);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:275:5
+   |
+LL |     fn_taking_fnonce_impl_generic(depr_safe_generic);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:278:5
+   |
+LL |     fn_taking_fn_impl_generic(depr_safe_generic);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:279:5
+   |
+LL |     fn_taking_fnmut_impl_generic(depr_safe_generic);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:280:5
+   |
+LL |     fn_taking_fnonce_impl_generic(depr_safe_generic);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a normal fn pointer has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:287:42
+   |
+LL |     let depr_safe_generic_fn_ptr: fn() = depr_safe;
+   |                                          ^^^^^^^^^ expected normal fn pointer, found unsafe fn pointer
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a normal fn pointer has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:290:42
+   |
+LL |     let depr_safe_generic_fn_ptr: fn() = depr_safe;
+   |                                          ^^^^^^^^^ expected normal fn pointer, found unsafe fn pointer
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a normal fn pointer has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:294:60
+   |
+LL |     let depr_safe_generic_fn_ptr: fn(OsString, OsString) = depr_safe_generic;
+   |                                                            ^^^^^^^^^^^^^^^^^ expected normal fn pointer, found unsafe fn pointer
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:295:70
+   |
+LL |     let depr_safe_generic_fn_impl: Box<dyn Fn(OsString, OsString)> = Box::new(depr_safe_generic);
+   |                                                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:297:9
+   |
+LL | ...   Box::new(depr_safe_generic);
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:299:9
+   |
+LL | ...   Box::new(depr_safe_generic);
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a normal fn pointer has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:302:60
+   |
+LL |     let depr_safe_generic_fn_ptr: fn(OsString, OsString) = depr_safe_generic;
+   |                                                            ^^^^^^^^^^^^^^^^^ expected normal fn pointer, found unsafe fn pointer
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:303:70
+   |
+LL |     let depr_safe_generic_fn_impl: Box<dyn Fn(OsString, OsString)> = Box::new(depr_safe_generic);
+   |                                                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:305:9
+   |
+LL | ...   Box::new(depr_safe_generic);
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:307:9
+   |
+LL | ...   Box::new(depr_safe_generic);
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a normal fn pointer has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:317:30
+   |
+LL |     fn_taking_fn_ptr_generic(depr_safe_generic);
+   |                              ^^^^^^^^^^^^^^^^^ expected normal fn pointer, found unsafe fn pointer
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:318:35
+   |
+LL |     fn_taking_dyn_fn_impl_generic(Box::new(depr_safe_generic));
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:319:38
+   |
+LL |     fn_taking_dyn_fnmut_impl_generic(Box::new(depr_safe_generic));
+   |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:320:39
+   |
+LL |     fn_taking_dyn_fnonce_impl_generic(Box::new(depr_safe_generic));
+   |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:321:5
+   |
+LL |     fn_taking_fn_impl_generic(depr_safe_generic);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:322:5
+   |
+LL |     fn_taking_fnmut_impl_generic(depr_safe_generic);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:323:5
+   |
+LL |     fn_taking_fnonce_impl_generic(depr_safe_generic);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a normal fn pointer has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:326:30
+   |
+LL |     fn_taking_fn_ptr_generic(depr_safe_generic);
+   |                              ^^^^^^^^^^^^^^^^^ expected normal fn pointer, found unsafe fn pointer
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:327:35
+   |
+LL |     fn_taking_dyn_fn_impl_generic(Box::new(depr_safe_generic));
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:328:38
+   |
+LL |     fn_taking_dyn_fnmut_impl_generic(Box::new(depr_safe_generic));
+   |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:329:39
+   |
+LL |     fn_taking_dyn_fnonce_impl_generic(Box::new(depr_safe_generic));
+   |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:330:5
+   |
+LL |     fn_taking_fn_impl_generic(depr_safe_generic);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:331:5
+   |
+LL |     fn_taking_fnmut_impl_generic(depr_safe_generic);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:332:5
+   |
+LL |     fn_taking_fnonce_impl_generic(depr_safe_generic);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:23:14
+   |
+LL | type Tait1 = impl FnOnce();
+   |              ^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_params` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:24:14
+   |
+LL | type Tait2 = impl FnOnce(u32, u64);
+   |              ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:25:14
+   |
+LL | type Tait3 = impl FnOnce(OsString, OsString);
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:60:5
+   |
+LL |     depr_safe
+   |     ^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_params` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:70:5
+   |
+LL |     depr_safe_params
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:80:5
+   |
+LL |     depr_safe_generic
+   |     ^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of associated function `deprecated_safe::DeprSafeFns::depr_safe_fn` without an `unsafe fn` declaration has been deprecated as it is now an unsafe associated function
+  --> $DIR/deprecated-safe.rs:133:5
+   |
+LL |     fn depr_safe_fn(&self) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this associated function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the associated function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of associated function `deprecated_safe::DeprSafeFns::depr_safe_params` without an `unsafe fn` declaration has been deprecated as it is now an unsafe associated function
+  --> $DIR/deprecated-safe.rs:135:5
+   |
+LL |     fn depr_safe_params(&self, _: u32, _: u64) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this associated function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the associated function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of associated function `deprecated_safe::DeprSafeFns::depr_safe_fn_generic` without an `unsafe fn` declaration has been deprecated as it is now an unsafe associated function
+  --> $DIR/deprecated-safe.rs:137:5
+   |
+LL |     fn depr_safe_fn_generic<K: AsRef<OsStr>, V: AsRef<OsStr>>(&self, key: K, value: V) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this associated function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the associated function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of associated function `deprecated_safe::DeprSafeFns::depr_safe_fn_2018` without an `unsafe fn` declaration has been deprecated as it is now an unsafe associated function
+  --> $DIR/deprecated-safe.rs:141:5
+   |
+LL |     fn depr_safe_fn_2018(&self) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this associated function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the associated function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of associated function `deprecated_safe::DeprSafeFns::depr_safe_fn` without an unsafe function or block has been deprecated as it is now an unsafe associated function
+  --> $DIR/deprecated-safe.rs:146:5
+   |
+LL |     good.depr_safe_fn();
+   |     ^^^^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: this associated function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the associated function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of associated function `deprecated_safe::DeprSafeFns::depr_safe_params` without an unsafe function or block has been deprecated as it is now an unsafe associated function
+  --> $DIR/deprecated-safe.rs:147:5
+   |
+LL |     good.depr_safe_params(0, 0);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: this associated function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the associated function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of associated function `deprecated_safe::DeprSafeFns::depr_safe_fn_generic` without an unsafe function or block has been deprecated as it is now an unsafe associated function
+  --> $DIR/deprecated-safe.rs:148:5
+   |
+LL |     good.depr_safe_fn_generic("", "");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: this associated function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the associated function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of associated function `deprecated_safe::DeprSafeFns::depr_safe_fn_2018` without an unsafe function or block has been deprecated as it is now an unsafe associated function
+  --> $DIR/deprecated-safe.rs:152:5
+   |
+LL |     good.depr_safe_fn_2018();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: this associated function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the associated function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of associated function `deprecated_safe::DeprSafeFns::depr_safe_fn` without an unsafe function or block has been deprecated as it is now an unsafe associated function
+  --> $DIR/deprecated-safe.rs:155:5
+   |
+LL |     bad.depr_safe_fn();
+   |     ^^^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: this associated function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the associated function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of associated function `deprecated_safe::DeprSafeFns::depr_safe_params` without an unsafe function or block has been deprecated as it is now an unsafe associated function
+  --> $DIR/deprecated-safe.rs:156:5
+   |
+LL |     bad.depr_safe_params(0, 0);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: this associated function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the associated function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of associated function `deprecated_safe::DeprSafeFns::depr_safe_fn_generic` without an unsafe function or block has been deprecated as it is now an unsafe associated function
+  --> $DIR/deprecated-safe.rs:157:5
+   |
+LL |     bad.depr_safe_fn_generic("", "");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: this associated function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the associated function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of associated function `deprecated_safe::DeprSafeFns::depr_safe_fn_2018` without an unsafe function or block has been deprecated as it is now an unsafe associated function
+  --> $DIR/deprecated-safe.rs:161:5
+   |
+LL |     bad.depr_safe_fn_2018();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: this associated function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the associated function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` without an unsafe function or block has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:204:5
+   |
+LL |     depr_safe();
+   |     ^^^^^^^^^^^ call to unsafe function
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` without an unsafe function or block has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:205:5
+   |
+LL |     depr_safe();
+   |     ^^^^^^^^^^^ call to unsafe function
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` without an unsafe function or block has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:283:5
+   |
+LL |     depr_safe_generic("", "");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` without an unsafe function or block has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:284:5
+   |
+LL |     depr_safe_generic("", "");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: 122 warnings emitted
+
diff --git a/src/test/ui/deprecated-safe/deprecated-safe.rs b/src/test/ui/deprecated-safe/deprecated-safe.rs
new file mode 100644
index 0000000000000..1db94f77ea239
--- /dev/null
+++ b/src/test/ui/deprecated-safe/deprecated-safe.rs
@@ -0,0 +1,355 @@
+// aux-build:deprecated-safe.rs
+// check-pass
+// revisions: mir thir
+// NOTE(skippy) these tests output many duplicates, so deduplicate or they become brittle to changes
+// [mir]compile-flags: -Zdeduplicate-diagnostics=yes
+// [thir]compile-flags: -Z thir-unsafeck -Zdeduplicate-diagnostics=yes
+
+// FIXME(skippy) add tests in combination with #[target_feature], ensure #[deprecated_safe]
+// doesn't silence these accidentally
+
+#![feature(type_alias_impl_trait)]
+#![warn(unused_unsafe)]
+
+extern crate deprecated_safe;
+
+use deprecated_safe::{depr_safe, depr_safe_generic, depr_safe_params, DeprSafe, DeprSafeFns};
+use std::ffi::{OsStr, OsString};
+
+trait Bla {
+    type T;
+}
+
+type Tait1 = impl FnOnce(); //~ WARN use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+type Tait2 = impl FnOnce(u32, u64); //~ WARN use of function `deprecated_safe::depr_safe_params` as a closure has been deprecated as it is now an unsafe function
+type Tait3 = impl FnOnce(OsString, OsString); //~ WARN use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+type Tait5 = Box<dyn FnOnce()>;
+type Tait6 = Box<dyn FnOnce(u32, u64)>;
+type Tait7 = Box<dyn FnOnce(OsString, OsString)>;
+type Tait8 = Box<dyn FnOnce()>;
+
+impl Bla for u8 {
+    type T = Tait1;
+}
+impl Bla for u16 {
+    type T = Tait2;
+}
+impl Bla for u32 {
+    type T = Tait3;
+}
+impl Bla for i8 {
+    type T = Tait5;
+}
+impl Bla for i16 {
+    type T = Tait6;
+}
+impl Bla for i32 {
+    type T = Tait7;
+}
+impl Bla for i64 {
+    type T = Tait8;
+}
+
+fn foo1() -> Tait1 {
+    depr_safe //~ WARN use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+}
+
+fn foo2() -> impl FnOnce() {
+    //~^ WARN use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+    //~| WARN use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+    depr_safe //~ WARN use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+}
+
+fn foo3() -> Tait2 {
+    depr_safe_params //~ WARN use of function `deprecated_safe::depr_safe_params` as a closure has been deprecated as it is now an unsafe function
+}
+
+fn foo4() -> impl FnOnce(u32, u64) {
+    //~^ WARN use of function `deprecated_safe::depr_safe_params` as a closure has been deprecated as it is now an unsafe function
+    //~| WARN use of function `deprecated_safe::depr_safe_params` as a closure has been deprecated as it is now an unsafe function
+    depr_safe_params //~ WARN use of function `deprecated_safe::depr_safe_params` as a closure has been deprecated as it is now an unsafe function
+}
+
+fn foo5() -> Tait3 {
+    depr_safe_generic //~ WARN use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+}
+
+fn foo6() -> impl FnOnce(OsString, OsString) {
+    //~^ WARN use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+    //~| WARN use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+    depr_safe_generic //~ WARN use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+}
+
+fn foo10() -> Tait5 {
+    Box::new(depr_safe) //~ WARN use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+}
+
+fn foo11() -> Box<dyn FnOnce()> {
+    Box::new(depr_safe) //~ WARN use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+}
+
+fn foo12() -> Tait6 {
+    Box::new(depr_safe_params) //~ WARN use of function `deprecated_safe::depr_safe_params` as a closure has been deprecated as it is now an unsafe function
+}
+
+fn foo13() -> Box<dyn FnOnce(u32, u64)> {
+    Box::new(depr_safe_params) //~ WARN use of function `deprecated_safe::depr_safe_params` as a closure has been deprecated as it is now an unsafe function
+}
+
+fn foo14() -> Tait7 {
+    Box::new(depr_safe_generic) //~ WARN use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+}
+
+fn foo15() -> Box<dyn FnOnce(OsString, OsString)> {
+    Box::new(depr_safe_generic) //~ WARN use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+}
+
+struct DeprSafeImpl;
+impl DeprSafe for DeprSafeImpl {} //~ WARN use of trait `deprecated_safe::DeprSafe` without an `unsafe impl` declaration has been deprecated as it is now an unsafe trait
+
+struct DeprSafeUnsafeImpl;
+unsafe impl DeprSafe for DeprSafeUnsafeImpl {}
+
+unsafe fn unsafe_fn() {
+    depr_safe();
+    depr_safe_generic("", "");
+}
+
+struct DeprSafeFnsGood;
+impl DeprSafeFns for DeprSafeFnsGood {
+    unsafe fn depr_safe_fn(&self) {}
+
+    unsafe fn depr_safe_params(&self, _: u32, _: u64) {}
+
+    unsafe fn depr_safe_fn_generic<K: AsRef<OsStr>, V: AsRef<OsStr>>(&self, key: K, value: V) {}
+
+    unsafe fn depr_safe_fn_2015(&self) {}
+
+    unsafe fn depr_safe_fn_2018(&self) {}
+}
+
+struct DeprSafeFnsBad;
+impl DeprSafeFns for DeprSafeFnsBad {
+    fn depr_safe_fn(&self) {} //~ WARN use of associated function `deprecated_safe::DeprSafeFns::depr_safe_fn` without an `unsafe fn` declaration has been deprecated as it is now an unsafe associated function
+
+    fn depr_safe_params(&self, _: u32, _: u64) {} //~ WARN use of associated function `deprecated_safe::DeprSafeFns::depr_safe_params` without an `unsafe fn` declaration has been deprecated as it is now an unsafe associated function
+
+    fn depr_safe_fn_generic<K: AsRef<OsStr>, V: AsRef<OsStr>>(&self, key: K, value: V) {} //~ WARN use of associated function `deprecated_safe::DeprSafeFns::depr_safe_fn_generic` without an `unsafe fn` declaration has been deprecated as it is now an unsafe associated function
+
+    unsafe fn depr_safe_fn_2015(&self) {}
+
+    fn depr_safe_fn_2018(&self) {} //~ WARN use of associated function `deprecated_safe::DeprSafeFns::depr_safe_fn_2018` without an `unsafe fn` declaration has been deprecated as it is now an unsafe associated function
+}
+
+fn foo0() {
+    let good = DeprSafeFnsGood;
+    good.depr_safe_fn(); //~ WARN use of associated function `deprecated_safe::DeprSafeFns::depr_safe_fn` without an unsafe function or block has been deprecated as it is now an unsafe associated function
+    good.depr_safe_params(0, 0); //~ WARN use of associated function `deprecated_safe::DeprSafeFns::depr_safe_params` without an unsafe function or block has been deprecated as it is now an unsafe associated function
+    good.depr_safe_fn_generic("", ""); //~ WARN use of associated function `deprecated_safe::DeprSafeFns::depr_safe_fn_generic` without an unsafe function or block has been deprecated as it is now an unsafe associated function
+    unsafe {
+        good.depr_safe_fn_2015();
+    }
+    good.depr_safe_fn_2018(); //~ WARN use of associated function `deprecated_safe::DeprSafeFns::depr_safe_fn_2018` without an unsafe function or block has been deprecated as it is now an unsafe associated function
+
+    let bad = DeprSafeFnsBad;
+    bad.depr_safe_fn(); //~ WARN use of associated function `deprecated_safe::DeprSafeFns::depr_safe_fn` without an unsafe function or block has been deprecated as it is now an unsafe associated function
+    bad.depr_safe_params(0, 0); //~ WARN use of associated function `deprecated_safe::DeprSafeFns::depr_safe_params` without an unsafe function or block has been deprecated as it is now an unsafe associated function
+    bad.depr_safe_fn_generic("", ""); //~ WARN use of associated function `deprecated_safe::DeprSafeFns::depr_safe_fn_generic` without an unsafe function or block has been deprecated as it is now an unsafe associated function
+    unsafe {
+        bad.depr_safe_fn_2015();
+    }
+    bad.depr_safe_fn_2018(); //~ WARN use of associated function `deprecated_safe::DeprSafeFns::depr_safe_fn_2018` without an unsafe function or block has been deprecated as it is now an unsafe associated function
+
+    unsafe {
+        good.depr_safe_fn();
+        good.depr_safe_params(0, 0);
+        good.depr_safe_fn_generic("", "");
+        good.depr_safe_fn_2015();
+        good.depr_safe_fn_2018();
+    }
+}
+
+fn main() {
+    // test for dyn Fn() coercion where arguments match (no args)
+    let fn_impl: Box<dyn Fn()> = Box::new(depr_safe); //~ WARN use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+    let fn_impl: Box<dyn FnMut()> = Box::new(depr_safe); //~ WARN use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+    let fn_impl: Box<dyn FnOnce()> = Box::new(depr_safe); //~ WARN use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+
+    // test that second usage still lints
+    let fn_impl: Box<dyn Fn()> = Box::new(depr_safe); //~ WARN use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+    let fn_impl: Box<dyn FnMut()> = Box::new(depr_safe); //~ WARN use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+    let fn_impl: Box<dyn FnOnce()> = Box::new(depr_safe); //~ WARN use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+
+    // test variant where coercion occurs on a function argument instead of a variable
+    fn_taking_dyn_fn_impl(Box::new(depr_safe)); //~ WARN use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+    fn_taking_dyn_fnmut_impl(Box::new(depr_safe)); //~ WARN use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+    fn_taking_dyn_fnonce_impl(Box::new(depr_safe)); //~ WARN use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+
+    // test that second usage still lints
+    fn_taking_dyn_fn_impl(Box::new(depr_safe)); //~ WARN use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+    fn_taking_dyn_fnmut_impl(Box::new(depr_safe)); //~ WARN use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+    fn_taking_dyn_fnonce_impl(Box::new(depr_safe)); //~ WARN use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+
+    // test for non-dyn Fn() coercion (no unsizing)
+    fn_taking_fn_impl(depr_safe); //~ WARN use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+    fn_taking_fnmut_impl(depr_safe); //~ WARN use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+    fn_taking_fnonce_impl(depr_safe); //~ WARN use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+
+    // test that second usage still lints
+    fn_taking_fn_impl(depr_safe); //~ WARN use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+    fn_taking_fnmut_impl(depr_safe); //~ WARN use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+    fn_taking_fnonce_impl(depr_safe); //~ WARN use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+
+    // usage without unsafe should lint
+    depr_safe(); //~ WARN use of function `deprecated_safe::depr_safe` without an unsafe function or block has been deprecated as it is now an unsafe function
+    depr_safe(); //~ WARN use of function `deprecated_safe::depr_safe` without an unsafe function or block has been deprecated as it is now an unsafe function
+
+    // test for fn() coercion where arguments match (no args)
+    let depr_safe_fn_ptr: fn() = depr_safe; //~ WARN use of function `deprecated_safe::depr_safe` as a normal fn pointer has been deprecated as it is now an unsafe function
+
+    // test that second usage still lints
+    let depr_safe_fn_ptr: fn() = depr_safe; //~ WARN use of function `deprecated_safe::depr_safe` as a normal fn pointer has been deprecated as it is now an unsafe function
+
+    // test for fn() coercion where arguments don't match, where an
+    // intermediate fn() will be used
+    let depr_safe_fn_ptr: fn() = depr_safe; //~ WARN use of function `deprecated_safe::depr_safe` as a normal fn pointer has been deprecated as it is now an unsafe function
+    let depr_safe_fn_impl: Box<dyn Fn()> = Box::new(depr_safe); //~ WARN use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+    let mut depr_safe_fnmut_impl: Box<dyn FnMut()> = Box::new(depr_safe); //~ WARN use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+    let depr_safe_fnonce_impl: Box<dyn FnOnce()> = Box::new(depr_safe); //~ WARN use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+
+    // test that second usage still lints
+    let depr_safe_fn_ptr: fn() = depr_safe; //~ WARN use of function `deprecated_safe::depr_safe` as a normal fn pointer has been deprecated as it is now an unsafe function
+    let depr_safe_fn_impl: Box<dyn Fn()> = Box::new(depr_safe); //~ WARN use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+    let mut depr_safe_fnmut_impl: Box<dyn FnMut()> = Box::new(depr_safe); //~ WARN use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+    let depr_safe_fnonce_impl: Box<dyn FnOnce()> = Box::new(depr_safe); //~ WARN use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+
+    // these shouldn't lint, appropriate unsafe usage
+    let unsafe_depr_safe_fn_ptr: unsafe fn() = depr_safe;
+    fn_taking_unsafe_fn_ptr(depr_safe);
+    unsafe {
+        depr_safe();
+    }
+
+    // all of these coercions should lint
+    fn_taking_fn_ptr(depr_safe); //~ WARN use of function `deprecated_safe::depr_safe` as a normal fn pointer has been deprecated as it is now an unsafe function
+    fn_taking_dyn_fn_impl(Box::new(depr_safe)); //~ WARN use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+    fn_taking_dyn_fnmut_impl(Box::new(depr_safe)); //~ WARN use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+    fn_taking_dyn_fnonce_impl(Box::new(depr_safe)); //~ WARN use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+    fn_taking_fn_impl(depr_safe); //~ WARN use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+    fn_taking_fnmut_impl(depr_safe); //~ WARN use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+    fn_taking_fnonce_impl(depr_safe); //~ WARN use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+
+    // ensure lint still fires if coerced again
+    fn_taking_fn_ptr(depr_safe); //~ WARN use of function `deprecated_safe::depr_safe` as a normal fn pointer has been deprecated as it is now an unsafe function
+    fn_taking_dyn_fn_impl(Box::new(depr_safe)); //~ WARN use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+    fn_taking_dyn_fnmut_impl(Box::new(depr_safe)); //~ WARN use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+    fn_taking_dyn_fnonce_impl(Box::new(depr_safe)); //~ WARN use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+    fn_taking_fn_impl(depr_safe); //~ WARN use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+    fn_taking_fnmut_impl(depr_safe); //~ WARN use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+    fn_taking_fnonce_impl(depr_safe); //~ WARN use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+
+    // test for dyn Fn() coercion where arguments don't match, where an
+    // intermediate fn() will be used
+    let fn_impl: Box<dyn Fn(OsString, OsString)> = Box::new(depr_safe_generic); //~ WARN use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+    let fn_impl: Box<dyn FnMut(OsString, OsString)> = Box::new(depr_safe_generic); //~ WARN use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+    let fn_impl: Box<dyn FnOnce(OsString, OsString)> = Box::new(depr_safe_generic); //~ WARN use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+
+    // test that second usage still lints
+    let fn_impl: Box<dyn Fn(OsString, OsString)> = Box::new(depr_safe_generic); //~ WARN use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+    let fn_impl: Box<dyn FnMut(OsString, OsString)> = Box::new(depr_safe_generic); //~ WARN use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+    let fn_impl: Box<dyn FnOnce(OsString, OsString)> = Box::new(depr_safe_generic); //~ WARN use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+
+    // test variant where coercion occurs on a function argument instead of a variable
+    fn_taking_dyn_fn_impl_generic(Box::new(depr_safe_generic)); //~ WARN use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+    fn_taking_dyn_fnmut_impl_generic(Box::new(depr_safe_generic)); //~ WARN use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+    fn_taking_dyn_fnonce_impl_generic(Box::new(depr_safe_generic)); //~ WARN use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+
+    // test that second usage still lints
+    fn_taking_dyn_fn_impl_generic(Box::new(depr_safe_generic)); //~ WARN use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+    fn_taking_dyn_fnmut_impl_generic(Box::new(depr_safe_generic)); //~ WARN use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+    fn_taking_dyn_fnonce_impl_generic(Box::new(depr_safe_generic)); //~ WARN use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+
+    // test for non-dyn Fn() coercion (no unsizing)
+    fn_taking_fn_impl_generic(depr_safe_generic); //~ WARN use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+    fn_taking_fnmut_impl_generic(depr_safe_generic); //~ WARN use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+    fn_taking_fnonce_impl_generic(depr_safe_generic); //~ WARN use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+
+    // test that second usage still lints
+    fn_taking_fn_impl_generic(depr_safe_generic); //~ WARN use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+    fn_taking_fnmut_impl_generic(depr_safe_generic); //~ WARN use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+    fn_taking_fnonce_impl_generic(depr_safe_generic); //~ WARN use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+
+    // usage without unsafe should lint
+    depr_safe_generic("", ""); //~ WARN use of function `deprecated_safe::depr_safe_generic` without an unsafe function or block has been deprecated as it is now an unsafe function
+    depr_safe_generic("", ""); //~ WARN use of function `deprecated_safe::depr_safe_generic` without an unsafe function or block has been deprecated as it is now an unsafe function
+
+    // test for fn() coercion where arguments match (no args)
+    let depr_safe_generic_fn_ptr: fn() = depr_safe; //~ WARN use of function `deprecated_safe::depr_safe` as a normal fn pointer has been deprecated as it is now an unsafe function
+
+    // test that second usage still lints
+    let depr_safe_generic_fn_ptr: fn() = depr_safe; //~ WARN use of function `deprecated_safe::depr_safe` as a normal fn pointer has been deprecated as it is now an unsafe function
+
+    // test for fn() coercion where arguments don't match, where an
+    // intermediate fn() will be used
+    let depr_safe_generic_fn_ptr: fn(OsString, OsString) = depr_safe_generic; //~ WARN use of function `deprecated_safe::depr_safe_generic` as a normal fn pointer has been deprecated as it is now an unsafe function
+    let depr_safe_generic_fn_impl: Box<dyn Fn(OsString, OsString)> = Box::new(depr_safe_generic); //~ WARN use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+    let mut depr_safe_generic_fnmut_impl: Box<dyn FnMut(OsString, OsString)> =
+        Box::new(depr_safe_generic); //~ WARN use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+    let depr_safe_generic_fnonce_impl: Box<dyn FnOnce(OsString, OsString)> =
+        Box::new(depr_safe_generic); //~ WARN use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+
+    // test that second usage still lints
+    let depr_safe_generic_fn_ptr: fn(OsString, OsString) = depr_safe_generic; //~ WARN use of function `deprecated_safe::depr_safe_generic` as a normal fn pointer has been deprecated as it is now an unsafe function
+    let depr_safe_generic_fn_impl: Box<dyn Fn(OsString, OsString)> = Box::new(depr_safe_generic); //~ WARN use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+    let mut depr_safe_generic_fnmut_impl: Box<dyn FnMut(OsString, OsString)> =
+        Box::new(depr_safe_generic); //~ WARN use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+    let depr_safe_generic_fnonce_impl: Box<dyn FnOnce(OsString, OsString)> =
+        Box::new(depr_safe_generic); //~ WARN use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+
+    // these shouldn't lint, appropriate unsafe usage
+    let unsafe_depr_safe_generic_fn_ptr: unsafe fn(OsString, OsString) = depr_safe_generic;
+    fn_taking_unsafe_fn_ptr_generic(depr_safe_generic);
+    unsafe {
+        depr_safe_generic("", "");
+    }
+
+    // all of these coercions should lint
+    fn_taking_fn_ptr_generic(depr_safe_generic); //~ WARN use of function `deprecated_safe::depr_safe_generic` as a normal fn pointer has been deprecated as it is now an unsafe function
+    fn_taking_dyn_fn_impl_generic(Box::new(depr_safe_generic)); //~ WARN use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+    fn_taking_dyn_fnmut_impl_generic(Box::new(depr_safe_generic)); //~ WARN use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+    fn_taking_dyn_fnonce_impl_generic(Box::new(depr_safe_generic)); //~ WARN use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+    fn_taking_fn_impl_generic(depr_safe_generic); //~ WARN use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+    fn_taking_fnmut_impl_generic(depr_safe_generic); //~ WARN use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+    fn_taking_fnonce_impl_generic(depr_safe_generic); //~ WARN use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+
+    // ensure lint still fires if coerced again
+    fn_taking_fn_ptr_generic(depr_safe_generic); //~ WARN use of function `deprecated_safe::depr_safe_generic` as a normal fn pointer has been deprecated as it is now an unsafe function
+    fn_taking_dyn_fn_impl_generic(Box::new(depr_safe_generic)); //~ WARN use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+    fn_taking_dyn_fnmut_impl_generic(Box::new(depr_safe_generic)); //~ WARN use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+    fn_taking_dyn_fnonce_impl_generic(Box::new(depr_safe_generic)); //~ WARN use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+    fn_taking_fn_impl_generic(depr_safe_generic); //~ WARN use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+    fn_taking_fnmut_impl_generic(depr_safe_generic); //~ WARN use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+    fn_taking_fnonce_impl_generic(depr_safe_generic); //~ WARN use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+}
+
+fn fn_taking_fn_ptr(_: fn()) {}
+fn fn_taking_unsafe_fn_ptr(_: unsafe fn()) {}
+
+fn fn_taking_dyn_fn_impl(_: Box<dyn Fn()>) {}
+fn fn_taking_dyn_fnmut_impl(_: Box<dyn FnMut()>) {}
+fn fn_taking_dyn_fnonce_impl(_: Box<dyn FnOnce()>) {}
+
+fn fn_taking_fn_impl(_: impl Fn()) {}
+fn fn_taking_fnmut_impl(_: impl FnMut()) {}
+fn fn_taking_fnonce_impl(_: impl FnOnce()) {}
+
+fn fn_taking_fn_ptr_generic(_: fn(OsString, OsString)) {}
+fn fn_taking_unsafe_fn_ptr_generic(_: unsafe fn(OsString, OsString)) {}
+
+fn fn_taking_dyn_fn_impl_generic(_: Box<dyn Fn(OsString, OsString)>) {}
+fn fn_taking_dyn_fnmut_impl_generic(_: Box<dyn FnMut(OsString, OsString)>) {}
+fn fn_taking_dyn_fnonce_impl_generic(_: Box<dyn FnOnce(OsString, OsString)>) {}
+
+fn fn_taking_fn_impl_generic(_: impl Fn(OsString, OsString)) {}
+fn fn_taking_fnmut_impl_generic(_: impl FnMut(OsString, OsString)) {}
+fn fn_taking_fnonce_impl_generic(_: impl FnOnce(OsString, OsString)) {}
diff --git a/src/test/ui/deprecated-safe/deprecated-safe.thir.stderr b/src/test/ui/deprecated-safe/deprecated-safe.thir.stderr
new file mode 100644
index 0000000000000..c3cdf5f312367
--- /dev/null
+++ b/src/test/ui/deprecated-safe/deprecated-safe.thir.stderr
@@ -0,0 +1,1238 @@
+warning: use of trait `deprecated_safe::DeprSafe` without an `unsafe impl` declaration has been deprecated as it is now an unsafe trait
+  --> $DIR/deprecated-safe.rs:108:1
+   |
+LL | impl DeprSafe for DeprSafeImpl {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(deprecated_safe)]` on by default
+   = note: this trait was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the trait's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:54:5
+   |
+LL |     depr_safe
+   |     ^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:57:14
+   |
+LL | fn foo2() -> impl FnOnce() {
+   |              ^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:57:28
+   |
+LL |   fn foo2() -> impl FnOnce() {
+   |  ____________________________^
+LL | |
+LL | |
+LL | |     depr_safe
+LL | | }
+   | |_^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_params` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:64:5
+   |
+LL |     depr_safe_params
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_params` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:67:14
+   |
+LL | fn foo4() -> impl FnOnce(u32, u64) {
+   |              ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_params` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:67:36
+   |
+LL |   fn foo4() -> impl FnOnce(u32, u64) {
+   |  ____________________________________^
+LL | |
+LL | |
+LL | |     depr_safe_params
+LL | | }
+   | |_^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:74:5
+   |
+LL |     depr_safe_generic
+   |     ^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:77:14
+   |
+LL | fn foo6() -> impl FnOnce(OsString, OsString) {
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:77:46
+   |
+LL |   fn foo6() -> impl FnOnce(OsString, OsString) {
+   |  ______________________________________________^
+LL | |
+LL | |
+LL | |     depr_safe_generic
+LL | | }
+   | |_^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:84:5
+   |
+LL |     Box::new(depr_safe)
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:88:5
+   |
+LL |     Box::new(depr_safe)
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_params` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:92:5
+   |
+LL |     Box::new(depr_safe_params)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_params` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:96:5
+   |
+LL |     Box::new(depr_safe_params)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:100:5
+   |
+LL |     Box::new(depr_safe_generic)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:104:5
+   |
+LL |     Box::new(depr_safe_generic)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:174:34
+   |
+LL |     let fn_impl: Box<dyn Fn()> = Box::new(depr_safe);
+   |                                  ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:175:37
+   |
+LL |     let fn_impl: Box<dyn FnMut()> = Box::new(depr_safe);
+   |                                     ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:176:38
+   |
+LL |     let fn_impl: Box<dyn FnOnce()> = Box::new(depr_safe);
+   |                                      ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:179:34
+   |
+LL |     let fn_impl: Box<dyn Fn()> = Box::new(depr_safe);
+   |                                  ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:180:37
+   |
+LL |     let fn_impl: Box<dyn FnMut()> = Box::new(depr_safe);
+   |                                     ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:181:38
+   |
+LL |     let fn_impl: Box<dyn FnOnce()> = Box::new(depr_safe);
+   |                                      ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:184:27
+   |
+LL |     fn_taking_dyn_fn_impl(Box::new(depr_safe));
+   |                           ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:185:30
+   |
+LL |     fn_taking_dyn_fnmut_impl(Box::new(depr_safe));
+   |                              ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:186:31
+   |
+LL |     fn_taking_dyn_fnonce_impl(Box::new(depr_safe));
+   |                               ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:189:27
+   |
+LL |     fn_taking_dyn_fn_impl(Box::new(depr_safe));
+   |                           ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:190:30
+   |
+LL |     fn_taking_dyn_fnmut_impl(Box::new(depr_safe));
+   |                              ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:191:31
+   |
+LL |     fn_taking_dyn_fnonce_impl(Box::new(depr_safe));
+   |                               ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:194:5
+   |
+LL |     fn_taking_fn_impl(depr_safe);
+   |     ^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:195:5
+   |
+LL |     fn_taking_fnmut_impl(depr_safe);
+   |     ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:196:5
+   |
+LL |     fn_taking_fnonce_impl(depr_safe);
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:199:5
+   |
+LL |     fn_taking_fn_impl(depr_safe);
+   |     ^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:200:5
+   |
+LL |     fn_taking_fnmut_impl(depr_safe);
+   |     ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:201:5
+   |
+LL |     fn_taking_fnonce_impl(depr_safe);
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a normal fn pointer has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:208:34
+   |
+LL |     let depr_safe_fn_ptr: fn() = depr_safe;
+   |                                  ^^^^^^^^^ expected normal fn pointer, found unsafe fn pointer
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a normal fn pointer has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:211:34
+   |
+LL |     let depr_safe_fn_ptr: fn() = depr_safe;
+   |                                  ^^^^^^^^^ expected normal fn pointer, found unsafe fn pointer
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a normal fn pointer has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:215:34
+   |
+LL |     let depr_safe_fn_ptr: fn() = depr_safe;
+   |                                  ^^^^^^^^^ expected normal fn pointer, found unsafe fn pointer
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:216:44
+   |
+LL |     let depr_safe_fn_impl: Box<dyn Fn()> = Box::new(depr_safe);
+   |                                            ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:217:54
+   |
+LL |     let mut depr_safe_fnmut_impl: Box<dyn FnMut()> = Box::new(depr_safe);
+   |                                                      ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:218:52
+   |
+LL |     let depr_safe_fnonce_impl: Box<dyn FnOnce()> = Box::new(depr_safe);
+   |                                                    ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a normal fn pointer has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:221:34
+   |
+LL |     let depr_safe_fn_ptr: fn() = depr_safe;
+   |                                  ^^^^^^^^^ expected normal fn pointer, found unsafe fn pointer
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:222:44
+   |
+LL |     let depr_safe_fn_impl: Box<dyn Fn()> = Box::new(depr_safe);
+   |                                            ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:223:54
+   |
+LL |     let mut depr_safe_fnmut_impl: Box<dyn FnMut()> = Box::new(depr_safe);
+   |                                                      ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:224:52
+   |
+LL |     let depr_safe_fnonce_impl: Box<dyn FnOnce()> = Box::new(depr_safe);
+   |                                                    ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a normal fn pointer has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:234:22
+   |
+LL |     fn_taking_fn_ptr(depr_safe);
+   |                      ^^^^^^^^^ expected normal fn pointer, found unsafe fn pointer
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:235:27
+   |
+LL |     fn_taking_dyn_fn_impl(Box::new(depr_safe));
+   |                           ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:236:30
+   |
+LL |     fn_taking_dyn_fnmut_impl(Box::new(depr_safe));
+   |                              ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:237:31
+   |
+LL |     fn_taking_dyn_fnonce_impl(Box::new(depr_safe));
+   |                               ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:238:5
+   |
+LL |     fn_taking_fn_impl(depr_safe);
+   |     ^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:239:5
+   |
+LL |     fn_taking_fnmut_impl(depr_safe);
+   |     ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:240:5
+   |
+LL |     fn_taking_fnonce_impl(depr_safe);
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a normal fn pointer has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:243:22
+   |
+LL |     fn_taking_fn_ptr(depr_safe);
+   |                      ^^^^^^^^^ expected normal fn pointer, found unsafe fn pointer
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:244:27
+   |
+LL |     fn_taking_dyn_fn_impl(Box::new(depr_safe));
+   |                           ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:245:30
+   |
+LL |     fn_taking_dyn_fnmut_impl(Box::new(depr_safe));
+   |                              ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:246:31
+   |
+LL |     fn_taking_dyn_fnonce_impl(Box::new(depr_safe));
+   |                               ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:247:5
+   |
+LL |     fn_taking_fn_impl(depr_safe);
+   |     ^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:248:5
+   |
+LL |     fn_taking_fnmut_impl(depr_safe);
+   |     ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:249:5
+   |
+LL |     fn_taking_fnonce_impl(depr_safe);
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:253:52
+   |
+LL |     let fn_impl: Box<dyn Fn(OsString, OsString)> = Box::new(depr_safe_generic);
+   |                                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:254:55
+   |
+LL |     let fn_impl: Box<dyn FnMut(OsString, OsString)> = Box::new(depr_safe_generic);
+   |                                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:255:56
+   |
+LL |     let fn_impl: Box<dyn FnOnce(OsString, OsString)> = Box::new(depr_safe_generic);
+   |                                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:258:52
+   |
+LL |     let fn_impl: Box<dyn Fn(OsString, OsString)> = Box::new(depr_safe_generic);
+   |                                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:259:55
+   |
+LL |     let fn_impl: Box<dyn FnMut(OsString, OsString)> = Box::new(depr_safe_generic);
+   |                                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:260:56
+   |
+LL |     let fn_impl: Box<dyn FnOnce(OsString, OsString)> = Box::new(depr_safe_generic);
+   |                                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:263:35
+   |
+LL |     fn_taking_dyn_fn_impl_generic(Box::new(depr_safe_generic));
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:264:38
+   |
+LL |     fn_taking_dyn_fnmut_impl_generic(Box::new(depr_safe_generic));
+   |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:265:39
+   |
+LL |     fn_taking_dyn_fnonce_impl_generic(Box::new(depr_safe_generic));
+   |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:268:35
+   |
+LL |     fn_taking_dyn_fn_impl_generic(Box::new(depr_safe_generic));
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:269:38
+   |
+LL |     fn_taking_dyn_fnmut_impl_generic(Box::new(depr_safe_generic));
+   |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:270:39
+   |
+LL |     fn_taking_dyn_fnonce_impl_generic(Box::new(depr_safe_generic));
+   |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:273:5
+   |
+LL |     fn_taking_fn_impl_generic(depr_safe_generic);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:274:5
+   |
+LL |     fn_taking_fnmut_impl_generic(depr_safe_generic);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:275:5
+   |
+LL |     fn_taking_fnonce_impl_generic(depr_safe_generic);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:278:5
+   |
+LL |     fn_taking_fn_impl_generic(depr_safe_generic);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:279:5
+   |
+LL |     fn_taking_fnmut_impl_generic(depr_safe_generic);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:280:5
+   |
+LL |     fn_taking_fnonce_impl_generic(depr_safe_generic);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a normal fn pointer has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:287:42
+   |
+LL |     let depr_safe_generic_fn_ptr: fn() = depr_safe;
+   |                                          ^^^^^^^^^ expected normal fn pointer, found unsafe fn pointer
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a normal fn pointer has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:290:42
+   |
+LL |     let depr_safe_generic_fn_ptr: fn() = depr_safe;
+   |                                          ^^^^^^^^^ expected normal fn pointer, found unsafe fn pointer
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a normal fn pointer has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:294:60
+   |
+LL |     let depr_safe_generic_fn_ptr: fn(OsString, OsString) = depr_safe_generic;
+   |                                                            ^^^^^^^^^^^^^^^^^ expected normal fn pointer, found unsafe fn pointer
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:295:70
+   |
+LL |     let depr_safe_generic_fn_impl: Box<dyn Fn(OsString, OsString)> = Box::new(depr_safe_generic);
+   |                                                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:297:9
+   |
+LL | ...   Box::new(depr_safe_generic);
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:299:9
+   |
+LL | ...   Box::new(depr_safe_generic);
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a normal fn pointer has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:302:60
+   |
+LL |     let depr_safe_generic_fn_ptr: fn(OsString, OsString) = depr_safe_generic;
+   |                                                            ^^^^^^^^^^^^^^^^^ expected normal fn pointer, found unsafe fn pointer
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:303:70
+   |
+LL |     let depr_safe_generic_fn_impl: Box<dyn Fn(OsString, OsString)> = Box::new(depr_safe_generic);
+   |                                                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:305:9
+   |
+LL | ...   Box::new(depr_safe_generic);
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:307:9
+   |
+LL | ...   Box::new(depr_safe_generic);
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a normal fn pointer has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:317:30
+   |
+LL |     fn_taking_fn_ptr_generic(depr_safe_generic);
+   |                              ^^^^^^^^^^^^^^^^^ expected normal fn pointer, found unsafe fn pointer
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:318:35
+   |
+LL |     fn_taking_dyn_fn_impl_generic(Box::new(depr_safe_generic));
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:319:38
+   |
+LL |     fn_taking_dyn_fnmut_impl_generic(Box::new(depr_safe_generic));
+   |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:320:39
+   |
+LL |     fn_taking_dyn_fnonce_impl_generic(Box::new(depr_safe_generic));
+   |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:321:5
+   |
+LL |     fn_taking_fn_impl_generic(depr_safe_generic);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:322:5
+   |
+LL |     fn_taking_fnmut_impl_generic(depr_safe_generic);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:323:5
+   |
+LL |     fn_taking_fnonce_impl_generic(depr_safe_generic);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a normal fn pointer has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:326:30
+   |
+LL |     fn_taking_fn_ptr_generic(depr_safe_generic);
+   |                              ^^^^^^^^^^^^^^^^^ expected normal fn pointer, found unsafe fn pointer
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:327:35
+   |
+LL |     fn_taking_dyn_fn_impl_generic(Box::new(depr_safe_generic));
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:328:38
+   |
+LL |     fn_taking_dyn_fnmut_impl_generic(Box::new(depr_safe_generic));
+   |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:329:39
+   |
+LL |     fn_taking_dyn_fnonce_impl_generic(Box::new(depr_safe_generic));
+   |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:330:5
+   |
+LL |     fn_taking_fn_impl_generic(depr_safe_generic);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:331:5
+   |
+LL |     fn_taking_fnmut_impl_generic(depr_safe_generic);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:332:5
+   |
+LL |     fn_taking_fnonce_impl_generic(depr_safe_generic);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:23:14
+   |
+LL | type Tait1 = impl FnOnce();
+   |              ^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_params` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:24:14
+   |
+LL | type Tait2 = impl FnOnce(u32, u64);
+   |              ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:25:14
+   |
+LL | type Tait3 = impl FnOnce(OsString, OsString);
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:60:5
+   |
+LL |     depr_safe
+   |     ^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_params` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:70:5
+   |
+LL |     depr_safe_params
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` as a closure has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:80:5
+   |
+LL |     depr_safe_generic
+   |     ^^^^^^^^^^^^^^^^^
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of associated function `deprecated_safe::DeprSafeFns::depr_safe_fn` without an `unsafe fn` declaration has been deprecated as it is now an unsafe associated function
+  --> $DIR/deprecated-safe.rs:133:5
+   |
+LL |     fn depr_safe_fn(&self) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this associated function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the associated function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of associated function `deprecated_safe::DeprSafeFns::depr_safe_params` without an `unsafe fn` declaration has been deprecated as it is now an unsafe associated function
+  --> $DIR/deprecated-safe.rs:135:5
+   |
+LL |     fn depr_safe_params(&self, _: u32, _: u64) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this associated function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the associated function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of associated function `deprecated_safe::DeprSafeFns::depr_safe_fn_generic` without an `unsafe fn` declaration has been deprecated as it is now an unsafe associated function
+  --> $DIR/deprecated-safe.rs:137:5
+   |
+LL |     fn depr_safe_fn_generic<K: AsRef<OsStr>, V: AsRef<OsStr>>(&self, key: K, value: V) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this associated function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the associated function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of associated function `deprecated_safe::DeprSafeFns::depr_safe_fn_2018` without an `unsafe fn` declaration has been deprecated as it is now an unsafe associated function
+  --> $DIR/deprecated-safe.rs:141:5
+   |
+LL |     fn depr_safe_fn_2018(&self) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this associated function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the associated function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of associated function `deprecated_safe::DeprSafeFns::depr_safe_fn` without an unsafe function or block has been deprecated as it is now an unsafe associated function
+  --> $DIR/deprecated-safe.rs:146:5
+   |
+LL |     good.depr_safe_fn();
+   |     ^^^^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: this associated function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the associated function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of associated function `deprecated_safe::DeprSafeFns::depr_safe_params` without an unsafe function or block has been deprecated as it is now an unsafe associated function
+  --> $DIR/deprecated-safe.rs:147:5
+   |
+LL |     good.depr_safe_params(0, 0);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: this associated function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the associated function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of associated function `deprecated_safe::DeprSafeFns::depr_safe_fn_generic` without an unsafe function or block has been deprecated as it is now an unsafe associated function
+  --> $DIR/deprecated-safe.rs:148:5
+   |
+LL |     good.depr_safe_fn_generic("", "");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: this associated function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the associated function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of associated function `deprecated_safe::DeprSafeFns::depr_safe_fn_2018` without an unsafe function or block has been deprecated as it is now an unsafe associated function
+  --> $DIR/deprecated-safe.rs:152:5
+   |
+LL |     good.depr_safe_fn_2018();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: this associated function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the associated function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of associated function `deprecated_safe::DeprSafeFns::depr_safe_fn` without an unsafe function or block has been deprecated as it is now an unsafe associated function
+  --> $DIR/deprecated-safe.rs:155:5
+   |
+LL |     bad.depr_safe_fn();
+   |     ^^^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: this associated function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the associated function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of associated function `deprecated_safe::DeprSafeFns::depr_safe_params` without an unsafe function or block has been deprecated as it is now an unsafe associated function
+  --> $DIR/deprecated-safe.rs:156:5
+   |
+LL |     bad.depr_safe_params(0, 0);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: this associated function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the associated function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of associated function `deprecated_safe::DeprSafeFns::depr_safe_fn_generic` without an unsafe function or block has been deprecated as it is now an unsafe associated function
+  --> $DIR/deprecated-safe.rs:157:5
+   |
+LL |     bad.depr_safe_fn_generic("", "");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: this associated function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the associated function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of associated function `deprecated_safe::DeprSafeFns::depr_safe_fn_2018` without an unsafe function or block has been deprecated as it is now an unsafe associated function
+  --> $DIR/deprecated-safe.rs:161:5
+   |
+LL |     bad.depr_safe_fn_2018();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: this associated function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the associated function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` without an unsafe function or block has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:204:5
+   |
+LL |     depr_safe();
+   |     ^^^^^^^^^^^ call to unsafe function
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe` without an unsafe function or block has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:205:5
+   |
+LL |     depr_safe();
+   |     ^^^^^^^^^^^ call to unsafe function
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` without an unsafe function or block has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:283:5
+   |
+LL |     depr_safe_generic("", "");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: use of function `deprecated_safe::depr_safe_generic` without an unsafe function or block has been deprecated as it is now an unsafe function
+  --> $DIR/deprecated-safe.rs:284:5
+   |
+LL |     depr_safe_generic("", "");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: this function was previously not marked unsafe, but has been marked unsafe since 1.61.0
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: reason
+
+warning: 122 warnings emitted
+
diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
index 891531951c1a0..a9c3ac1d4596b 100644
--- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
+++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
@@ -142,7 +142,7 @@ fn check_rvalue<'tcx>(
         },
         Rvalue::Cast(
             CastKind::Pointer(
-                PointerCast::UnsafeFnPointer | PointerCast::ClosureFnPointer(_) | PointerCast::ReifyFnPointer,
+                PointerCast::UnsafeFnPointer | PointerCast::DeprecatedSafeFnPointer | PointerCast::ClosureFnPointer(_) | PointerCast::ReifyFnPointer,
             ),
             _,
             _,