diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 48cd9c268a1..0a4f32c9585 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -671,68 +671,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         err
     }
 
-    fn ty_kind_suggestion(&self, ty: Ty<'tcx>) -> Option<String> {
-        // Keep in sync with `rustc_hir_analysis/src/check/mod.rs:ty_kind_suggestion`.
-        // FIXME: deduplicate the above.
-        let tcx = self.infcx.tcx;
-        let implements_default = |ty| {
-            let Some(default_trait) = tcx.get_diagnostic_item(sym::Default) else {
-                return false;
-            };
-            self.infcx
-                .type_implements_trait(default_trait, [ty], self.param_env)
-                .must_apply_modulo_regions()
-        };
-
-        Some(match ty.kind() {
-            ty::Never | ty::Error(_) => return None,
-            ty::Bool => "false".to_string(),
-            ty::Char => "\'x\'".to_string(),
-            ty::Int(_) | ty::Uint(_) => "42".into(),
-            ty::Float(_) => "3.14159".into(),
-            ty::Slice(_) => "[]".to_string(),
-            ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::Vec) => {
-                "vec![]".to_string()
-            }
-            ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::String) => {
-                "String::new()".to_string()
-            }
-            ty::Adt(def, args) if def.is_box() => {
-                format!("Box::new({})", self.ty_kind_suggestion(args[0].expect_ty())?)
-            }
-            ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::Option) => {
-                "None".to_string()
-            }
-            ty::Adt(def, args) if Some(def.did()) == tcx.get_diagnostic_item(sym::Result) => {
-                format!("Ok({})", self.ty_kind_suggestion(args[0].expect_ty())?)
-            }
-            ty::Adt(_, _) if implements_default(ty) => "Default::default()".to_string(),
-            ty::Ref(_, ty, mutability) => {
-                if let (ty::Str, hir::Mutability::Not) = (ty.kind(), mutability) {
-                    "\"\"".to_string()
-                } else {
-                    let Some(ty) = self.ty_kind_suggestion(*ty) else {
-                        return None;
-                    };
-                    format!("&{}{ty}", mutability.prefix_str())
-                }
-            }
-            ty::Array(ty, len) => format!(
-                "[{}; {}]",
-                self.ty_kind_suggestion(*ty)?,
-                len.eval_target_usize(tcx, ty::ParamEnv::reveal_all()),
-            ),
-            ty::Tuple(tys) => format!(
-                "({})",
-                tys.iter()
-                    .map(|ty| self.ty_kind_suggestion(ty))
-                    .collect::<Option<Vec<String>>>()?
-                    .join(", ")
-            ),
-            _ => "value".to_string(),
-        })
-    }
-
     fn suggest_assign_value(
         &self,
         err: &mut Diag<'_>,
@@ -742,7 +680,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         let ty = moved_place.ty(self.body, self.infcx.tcx).ty;
         debug!("ty: {:?}, kind: {:?}", ty, ty.kind());
 
-        let Some(assign_value) = self.ty_kind_suggestion(ty) else {
+        let Some(assign_value) = self.infcx.err_ctxt().ty_kind_suggestion(self.param_env, ty)
+        else {
             return;
         };
 
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index 024a0433b8c..eb0ffc19d45 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -81,7 +81,6 @@ use rustc_errors::ErrorGuaranteed;
 use rustc_errors::{pluralize, struct_span_code_err, Diag};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::Visitor;
-use rustc_hir::Mutability;
 use rustc_index::bit_set::BitSet;
 use rustc_infer::infer::error_reporting::ObligationCauseExt as _;
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
@@ -96,8 +95,9 @@ use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::{def_id::CRATE_DEF_ID, BytePos, Span, Symbol, DUMMY_SP};
 use rustc_target::abi::VariantIdx;
 use rustc_target::spec::abi::Abi;
-use rustc_trait_selection::infer::InferCtxtExt;
-use rustc_trait_selection::traits::error_reporting::suggestions::ReturnsVisitor;
+use rustc_trait_selection::traits::error_reporting::suggestions::{
+    ReturnsVisitor, TypeErrCtxtExt as _,
+};
 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
 use rustc_trait_selection::traits::ObligationCtxt;
 
@@ -467,67 +467,6 @@ fn fn_sig_suggestion<'tcx>(
     )
 }
 
-pub fn ty_kind_suggestion<'tcx>(ty: Ty<'tcx>, tcx: TyCtxt<'tcx>) -> Option<String> {
-    // Keep in sync with `rustc_borrowck/src/diagnostics/conflict_errors.rs:ty_kind_suggestion`.
-    // FIXME: deduplicate the above.
-    let implements_default = |ty| {
-        let Some(default_trait) = tcx.get_diagnostic_item(sym::Default) else {
-            return false;
-        };
-        let infcx = tcx.infer_ctxt().build();
-        infcx
-            .type_implements_trait(default_trait, [ty], ty::ParamEnv::reveal_all())
-            .must_apply_modulo_regions()
-    };
-    Some(match ty.kind() {
-        ty::Never | ty::Error(_) => return None,
-        ty::Bool => "false".to_string(),
-        ty::Char => "\'x\'".to_string(),
-        ty::Int(_) | ty::Uint(_) => "42".into(),
-        ty::Float(_) => "3.14159".into(),
-        ty::Slice(_) => "[]".to_string(),
-        ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::Vec) => {
-            "vec![]".to_string()
-        }
-        ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::String) => {
-            "String::new()".to_string()
-        }
-        ty::Adt(def, args) if def.is_box() => {
-            format!("Box::new({})", ty_kind_suggestion(args[0].expect_ty(), tcx)?)
-        }
-        ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::Option) => {
-            "None".to_string()
-        }
-        ty::Adt(def, args) if Some(def.did()) == tcx.get_diagnostic_item(sym::Result) => {
-            format!("Ok({})", ty_kind_suggestion(args[0].expect_ty(), tcx)?)
-        }
-        ty::Adt(_, _) if implements_default(ty) => "Default::default()".to_string(),
-        ty::Ref(_, ty, mutability) => {
-            if let (ty::Str, Mutability::Not) = (ty.kind(), mutability) {
-                "\"\"".to_string()
-            } else {
-                let Some(ty) = ty_kind_suggestion(*ty, tcx) else {
-                    return None;
-                };
-                format!("&{}{ty}", mutability.prefix_str())
-            }
-        }
-        ty::Array(ty, len) => format!(
-            "[{}; {}]",
-            ty_kind_suggestion(*ty, tcx)?,
-            len.eval_target_usize(tcx, ty::ParamEnv::reveal_all()),
-        ),
-        ty::Tuple(tys) => format!(
-            "({})",
-            tys.iter()
-                .map(|ty| ty_kind_suggestion(ty, tcx))
-                .collect::<Option<Vec<String>>>()?
-                .join(", ")
-        ),
-        _ => "value".to_string(),
-    })
-}
-
 /// Return placeholder code for the given associated item.
 /// Similar to `ty::AssocItem::suggestion`, but appropriate for use as the code snippet of a
 /// structured suggestion.
@@ -562,7 +501,12 @@ fn suggestion_signature<'tcx>(
         }
         ty::AssocKind::Const => {
             let ty = tcx.type_of(assoc.def_id).instantiate_identity();
-            let val = ty_kind_suggestion(ty, tcx).unwrap_or_else(|| "value".to_string());
+            let val = tcx
+                .infer_ctxt()
+                .build()
+                .err_ctxt()
+                .ty_kind_suggestion(tcx.param_env(assoc.def_id), ty)
+                .unwrap_or_else(|| "value".to_string());
             format!("const {}: {} = {};", assoc.name, ty, val)
         }
     }
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index 720f4927ea8..079cca82408 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -63,6 +63,7 @@ use rustc_span::DesugaringKind;
 use rustc_span::{BytePos, Span};
 use rustc_target::spec::abi::Abi;
 use rustc_trait_selection::infer::InferCtxtExt as _;
+use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt;
 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
 use rustc_trait_selection::traits::TraitEngineExt as _;
@@ -1616,6 +1617,15 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
                             E0069,
                             "`return;` in a function whose return type is not `()`"
                         );
+                        if let Some(value) = fcx.err_ctxt().ty_kind_suggestion(fcx.param_env, found)
+                        {
+                            err.span_suggestion_verbose(
+                                cause.span.shrink_to_hi(),
+                                "give the `return` a value of the expected type",
+                                format!(" {value}"),
+                                Applicability::HasPlaceholders,
+                            );
+                        }
                         err.span_label(cause.span, "return type is not `()`");
                     }
                     ObligationCauseCode::BlockTailExpression(blk_id, ..) => {
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 8f30c3fd377..64590ca542d 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -35,7 +35,6 @@ use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::{ExprKind, HirId, QPath};
-use rustc_hir_analysis::check::ty_kind_suggestion;
 use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer as _;
 use rustc_infer::infer;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
@@ -57,6 +56,7 @@ use rustc_span::Span;
 use rustc_target::abi::{FieldIdx, FIRST_VARIANT};
 use rustc_target::spec::abi::Abi::RustIntrinsic;
 use rustc_trait_selection::infer::InferCtxtExt;
+use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt as _;
 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
 use rustc_trait_selection::traits::ObligationCtxt;
 use rustc_trait_selection::traits::{self, ObligationCauseCode};
@@ -694,7 +694,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             );
                             let error = Some(Sorts(ExpectedFound { expected: ty, found: e_ty }));
                             self.annotate_loop_expected_due_to_inference(err, expr, error);
-                            if let Some(val) = ty_kind_suggestion(ty, tcx) {
+                            if let Some(val) =
+                                self.err_ctxt().ty_kind_suggestion(self.param_env, ty)
+                            {
                                 err.span_suggestion_verbose(
                                     expr.span.shrink_to_hi(),
                                     "give the `break` a value of the expected type",
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
index a9a5a89a413..789cc52169b 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
@@ -367,7 +367,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }),
         ) = error.code
             && let ty::Closure(def_id, _) | ty::Coroutine(def_id, ..) =
-                expected_trait_ref.skip_binder().self_ty().kind()
+                expected_trait_ref.self_ty().kind()
             && span.overlaps(self.tcx.def_span(*def_id))
         {
             true
diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs
index f2222eec76a..f14bbe74890 100644
--- a/compiler/rustc_infer/src/infer/at.rs
+++ b/compiler/rustc_infer/src/infer/at.rs
@@ -424,25 +424,7 @@ impl<'tcx> ToTrace<'tcx> for ty::TraitRef<'tcx> {
     ) -> TypeTrace<'tcx> {
         TypeTrace {
             cause: cause.clone(),
-            values: PolyTraitRefs(ExpectedFound::new(
-                a_is_expected,
-                ty::Binder::dummy(a),
-                ty::Binder::dummy(b),
-            )),
-        }
-    }
-}
-
-impl<'tcx> ToTrace<'tcx> for ty::PolyTraitRef<'tcx> {
-    fn to_trace(
-        cause: &ObligationCause<'tcx>,
-        a_is_expected: bool,
-        a: Self,
-        b: Self,
-    ) -> TypeTrace<'tcx> {
-        TypeTrace {
-            cause: cause.clone(),
-            values: PolyTraitRefs(ExpectedFound::new(a_is_expected, a, b)),
+            values: TraitRefs(ExpectedFound::new(a_is_expected, a, b)),
         }
     }
 }
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 0911e4f5063..29c9f08a166 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -1653,7 +1653,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                             .report(diag);
                         (false, Mismatch::Fixed("signature"))
                     }
-                    ValuePairs::PolyTraitRefs(_) => (false, Mismatch::Fixed("trait")),
+                    ValuePairs::TraitRefs(_) => (false, Mismatch::Fixed("trait")),
                     ValuePairs::Aliases(infer::ExpectedFound { expected, .. }) => {
                         (false, Mismatch::Fixed(self.tcx.def_descr(expected.def_id)))
                     }
@@ -1969,8 +1969,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             self.note_and_explain_type_err(diag, exp_found, cause, span, cause.body_id.to_def_id());
         }
 
-        if let Some(ValuePairs::PolyTraitRefs(exp_found)) = values
-            && let ty::Closure(def_id, _) = exp_found.expected.skip_binder().self_ty().kind()
+        if let Some(ValuePairs::TraitRefs(exp_found)) = values
+            && let ty::Closure(def_id, _) = exp_found.expected.self_ty().kind()
             && let Some(def_id) = def_id.as_local()
             && terr.involves_regions()
         {
@@ -2188,7 +2188,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             infer::Aliases(exp_found) => self.expected_found_str(exp_found),
             infer::ExistentialTraitRef(exp_found) => self.expected_found_str(exp_found),
             infer::ExistentialProjection(exp_found) => self.expected_found_str(exp_found),
-            infer::PolyTraitRefs(exp_found) => {
+            infer::TraitRefs(exp_found) => {
                 let pretty_exp_found = ty::error::ExpectedFound {
                     expected: exp_found.expected.print_trait_sugared(),
                     found: exp_found.found.print_trait_sugared(),
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs
index 98719e240bd..01e75d59f4d 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs
@@ -195,13 +195,13 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
         value_pairs: &ValuePairs<'tcx>,
     ) -> Option<Diag<'tcx>> {
         let (expected_args, found_args, trait_def_id) = match value_pairs {
-            ValuePairs::PolyTraitRefs(ExpectedFound { expected, found })
-                if expected.def_id() == found.def_id() =>
+            ValuePairs::TraitRefs(ExpectedFound { expected, found })
+                if expected.def_id == found.def_id =>
             {
                 // It's possible that the placeholders come from a binder
                 // outside of this value pair. Use `no_bound_vars` as a
                 // simple heuristic for that.
-                (expected.no_bound_vars()?.args, found.no_bound_vars()?.args, expected.def_id())
+                (expected.args, found.args, expected.def_id)
             }
             _ => return None,
         };
diff --git a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
index 7855031e705..bf470bb1e3f 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
@@ -599,7 +599,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         &self,
         span: Span,
         hir: hir::Node<'_>,
-        exp_found: &ty::error::ExpectedFound<ty::PolyTraitRef<'tcx>>,
+        exp_found: &ty::error::ExpectedFound<ty::TraitRef<'tcx>>,
         diag: &mut Diag<'_>,
     ) {
         // 0. Extract fn_decl from hir
@@ -614,10 +614,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
 
         // 1. Get the args of the closure.
         // 2. Assume exp_found is FnOnce / FnMut / Fn, we can extract function parameters from [1].
-        let Some(expected) = exp_found.expected.skip_binder().args.get(1) else {
+        let Some(expected) = exp_found.expected.args.get(1) else {
             return;
         };
-        let Some(found) = exp_found.found.skip_binder().args.get(1) else {
+        let Some(found) = exp_found.found.args.get(1) else {
             return;
         };
         let expected = expected.unpack();
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 0b8061104ab..f2fd50a47d5 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -403,7 +403,7 @@ pub enum ValuePairs<'tcx> {
     Regions(ExpectedFound<ty::Region<'tcx>>),
     Terms(ExpectedFound<ty::Term<'tcx>>),
     Aliases(ExpectedFound<ty::AliasTy<'tcx>>),
-    PolyTraitRefs(ExpectedFound<ty::PolyTraitRef<'tcx>>),
+    TraitRefs(ExpectedFound<ty::TraitRef<'tcx>>),
     PolySigs(ExpectedFound<ty::PolyFnSig<'tcx>>),
     ExistentialTraitRef(ExpectedFound<ty::PolyExistentialTraitRef<'tcx>>),
     ExistentialProjection(ExpectedFound<ty::PolyExistentialProjection<'tcx>>),
@@ -1882,15 +1882,15 @@ impl<'tcx> TypeTrace<'tcx> {
         }
     }
 
-    pub fn poly_trait_refs(
+    pub fn trait_refs(
         cause: &ObligationCause<'tcx>,
         a_is_expected: bool,
-        a: ty::PolyTraitRef<'tcx>,
-        b: ty::PolyTraitRef<'tcx>,
+        a: ty::TraitRef<'tcx>,
+        b: ty::TraitRef<'tcx>,
     ) -> TypeTrace<'tcx> {
         TypeTrace {
             cause: cause.clone(),
-            values: PolyTraitRefs(ExpectedFound::new(a_is_expected, a, b)),
+            values: TraitRefs(ExpectedFound::new(a_is_expected, a, b)),
         }
     }
 
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index d51e86c909c..790e11b8e4b 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -620,11 +620,10 @@ pub enum SelectionError<'tcx> {
     OpaqueTypeAutoTraitLeakageUnknown(DefId),
 }
 
-// FIXME(@lcnr): The `Binder` here should be unnecessary. Just use `TraitRef` instead.
 #[derive(Clone, Debug, TypeVisitable)]
 pub struct SignatureMismatchData<'tcx> {
-    pub found_trait_ref: ty::PolyTraitRef<'tcx>,
-    pub expected_trait_ref: ty::PolyTraitRef<'tcx>,
+    pub found_trait_ref: ty::TraitRef<'tcx>,
+    pub expected_trait_ref: ty::TraitRef<'tcx>,
     pub terr: ty::error::TypeError<'tcx>,
 }
 
diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs
index b5fb710e4cc..057d00aeae8 100644
--- a/compiler/rustc_trait_selection/src/lib.rs
+++ b/compiler/rustc_trait_selection/src/lib.rs
@@ -22,6 +22,7 @@
 #![feature(box_patterns)]
 #![feature(control_flow_enum)]
 #![feature(extract_if)]
+#![feature(if_let_guard)]
 #![feature(let_chains)]
 #![feature(option_take_if)]
 #![feature(never_type)]
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 2067956d0f5..af8713ba3ff 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -1879,19 +1879,19 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         &self,
         span: Span,
         found_span: Option<Span>,
-        found: ty::PolyTraitRef<'tcx>,
-        expected: ty::PolyTraitRef<'tcx>,
+        found: ty::TraitRef<'tcx>,
+        expected: ty::TraitRef<'tcx>,
         cause: &ObligationCauseCode<'tcx>,
         found_node: Option<Node<'_>>,
         param_env: ty::ParamEnv<'tcx>,
     ) -> Diag<'tcx> {
         pub(crate) fn build_fn_sig_ty<'tcx>(
             infcx: &InferCtxt<'tcx>,
-            trait_ref: ty::PolyTraitRef<'tcx>,
+            trait_ref: ty::TraitRef<'tcx>,
         ) -> Ty<'tcx> {
-            let inputs = trait_ref.skip_binder().args.type_at(1);
+            let inputs = trait_ref.args.type_at(1);
             let sig = match inputs.kind() {
-                ty::Tuple(inputs) if infcx.tcx.is_fn_trait(trait_ref.def_id()) => {
+                ty::Tuple(inputs) if infcx.tcx.is_fn_trait(trait_ref.def_id) => {
                     infcx.tcx.mk_fn_sig(
                         *inputs,
                         infcx.next_ty_var(TypeVariableOrigin {
@@ -1915,10 +1915,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 ),
             };
 
-            Ty::new_fn_ptr(infcx.tcx, trait_ref.rebind(sig))
+            Ty::new_fn_ptr(infcx.tcx, ty::Binder::dummy(sig))
         }
 
-        let argument_kind = match expected.skip_binder().self_ty().kind() {
+        let argument_kind = match expected.self_ty().kind() {
             ty::Closure(..) => "closure",
             ty::Coroutine(..) => "coroutine",
             _ => "function",
@@ -4540,6 +4540,61 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             Applicability::MachineApplicable,
         );
     }
+
+    fn ty_kind_suggestion(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> Option<String> {
+        let tcx = self.infcx.tcx;
+        let implements_default = |ty| {
+            let Some(default_trait) = tcx.get_diagnostic_item(sym::Default) else {
+                return false;
+            };
+            self.type_implements_trait(default_trait, [ty], param_env).must_apply_modulo_regions()
+        };
+
+        Some(match ty.kind() {
+            ty::Never | ty::Error(_) => return None,
+            ty::Bool => "false".to_string(),
+            ty::Char => "\'x\'".to_string(),
+            ty::Int(_) | ty::Uint(_) => "42".into(),
+            ty::Float(_) => "3.14159".into(),
+            ty::Slice(_) => "[]".to_string(),
+            ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::Vec) => {
+                "vec![]".to_string()
+            }
+            ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::String) => {
+                "String::new()".to_string()
+            }
+            ty::Adt(def, args) if def.is_box() => {
+                format!("Box::new({})", self.ty_kind_suggestion(param_env, args[0].expect_ty())?)
+            }
+            ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::Option) => {
+                "None".to_string()
+            }
+            ty::Adt(def, args) if Some(def.did()) == tcx.get_diagnostic_item(sym::Result) => {
+                format!("Ok({})", self.ty_kind_suggestion(param_env, args[0].expect_ty())?)
+            }
+            ty::Adt(_, _) if implements_default(ty) => "Default::default()".to_string(),
+            ty::Ref(_, ty, mutability) => {
+                if let (ty::Str, hir::Mutability::Not) = (ty.kind(), mutability) {
+                    "\"\"".to_string()
+                } else {
+                    let ty = self.ty_kind_suggestion(param_env, *ty)?;
+                    format!("&{}{ty}", mutability.prefix_str())
+                }
+            }
+            ty::Array(ty, len) if let Some(len) = len.try_eval_target_usize(tcx, param_env) => {
+                format!("[{}; {}]", self.ty_kind_suggestion(param_env, *ty)?, len)
+            }
+            ty::Tuple(tys) => format!(
+                "({}{})",
+                tys.iter()
+                    .map(|ty| self.ty_kind_suggestion(param_env, ty))
+                    .collect::<Option<Vec<String>>>()?
+                    .join(", "),
+                if tys.len() == 1 { "," } else { "" }
+            ),
+            _ => "value".to_string(),
+        })
+    }
 }
 
 /// Add a hint to add a missing borrow or remove an unnecessary one.
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
index 3819ea68e96..6be4589d380 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
@@ -3380,11 +3380,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
     fn report_cyclic_signature_error(
         &self,
         obligation: &PredicateObligation<'tcx>,
-        found_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
-        expected_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
+        found_trait_ref: ty::TraitRef<'tcx>,
+        expected_trait_ref: ty::TraitRef<'tcx>,
         terr: TypeError<'tcx>,
     ) -> Diag<'tcx> {
-        let self_ty = found_trait_ref.self_ty().skip_binder();
+        let self_ty = found_trait_ref.self_ty();
         let (cause, terr) = if let ty::Closure(def_id, _) = self_ty.kind() {
             (
                 ObligationCause::dummy_with_span(self.tcx.def_span(def_id)),
@@ -3394,7 +3394,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             (obligation.cause.clone(), terr)
         };
         self.report_and_explain_type_error(
-            TypeTrace::poly_trait_refs(&cause, true, expected_trait_ref, found_trait_ref),
+            TypeTrace::trait_refs(&cause, true, expected_trait_ref, found_trait_ref),
             terr,
         )
     }
@@ -3434,17 +3434,14 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         &self,
         obligation: &PredicateObligation<'tcx>,
         span: Span,
-        found_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
-        expected_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
+        found_trait_ref: ty::TraitRef<'tcx>,
+        expected_trait_ref: ty::TraitRef<'tcx>,
     ) -> Result<Diag<'tcx>, ErrorGuaranteed> {
         let found_trait_ref = self.resolve_vars_if_possible(found_trait_ref);
         let expected_trait_ref = self.resolve_vars_if_possible(expected_trait_ref);
 
         expected_trait_ref.self_ty().error_reported()?;
-
-        let Some(found_trait_ty) = found_trait_ref.self_ty().no_bound_vars() else {
-            self.dcx().bug("bound vars outside binder");
-        };
+        let found_trait_ty = found_trait_ref.self_ty();
 
         let found_did = match *found_trait_ty.kind() {
             ty::Closure(did, _) | ty::FnDef(did, _) | ty::Coroutine(did, ..) => Some(did),
@@ -3462,7 +3459,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
 
         let mut not_tupled = false;
 
-        let found = match found_trait_ref.skip_binder().args.type_at(1).kind() {
+        let found = match found_trait_ref.args.type_at(1).kind() {
             ty::Tuple(tys) => vec![ArgKind::empty(); tys.len()],
             _ => {
                 not_tupled = true;
@@ -3470,7 +3467,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             }
         };
 
-        let expected_ty = expected_trait_ref.skip_binder().args.type_at(1);
+        let expected_ty = expected_trait_ref.args.type_at(1);
         let expected = match expected_ty.kind() {
             ty::Tuple(tys) => {
                 tys.iter().map(|t| ArgKind::from_expected_ty(t, Some(span))).collect()
@@ -3487,11 +3484,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         // traits manually, but don't make it more confusing when it does
         // happen.
         Ok(
-            if Some(expected_trait_ref.def_id()) != self.tcx.lang_items().coroutine_trait()
+            if Some(expected_trait_ref.def_id) != self.tcx.lang_items().coroutine_trait()
                 && not_tupled
             {
                 self.report_and_explain_type_error(
-                    TypeTrace::poly_trait_refs(
+                    TypeTrace::trait_refs(
                         &obligation.cause,
                         true,
                         expected_trait_ref,
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 25ba985397e..716b9a49ab5 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -1079,8 +1079,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             })
             .map_err(|terr| {
                 SignatureMismatch(Box::new(SignatureMismatchData {
-                    expected_trait_ref: ty::Binder::dummy(obligation_trait_ref),
-                    found_trait_ref: ty::Binder::dummy(found_trait_ref),
+                    expected_trait_ref: obligation_trait_ref,
+                    found_trait_ref,
                     terr,
                 }))
             })
diff --git a/library/std/src/sys/pal/zkvm/args.rs b/library/std/src/sys/pal/zkvm/args.rs
index 7753cf63840..583c16e3a47 100644
--- a/library/std/src/sys/pal/zkvm/args.rs
+++ b/library/std/src/sys/pal/zkvm/args.rs
@@ -1,6 +1,7 @@
 use super::{abi, WORD_SIZE};
 use crate::ffi::OsString;
 use crate::fmt;
+use crate::sys::os_str;
 use crate::sys_common::FromInner;
 
 pub struct Args {
@@ -33,7 +34,7 @@ impl Args {
         // "os_str".
         let arg_bytes: &[u8] =
             unsafe { crate::slice::from_raw_parts(words.cast() as *const u8, arg_len) };
-        OsString::from_inner(super::os_str::Buf { inner: arg_bytes.to_vec() })
+        OsString::from_inner(os_str::Buf { inner: arg_bytes.to_vec() })
     }
 }
 
diff --git a/library/std/src/sys/pal/zkvm/os.rs b/library/std/src/sys/pal/zkvm/os.rs
index d8739ee3824..759beb2d306 100644
--- a/library/std/src/sys/pal/zkvm/os.rs
+++ b/library/std/src/sys/pal/zkvm/os.rs
@@ -5,6 +5,7 @@ use crate::fmt;
 use crate::io;
 use crate::marker::PhantomData;
 use crate::path::{self, PathBuf};
+use crate::sys::os_str;
 use crate::sys_common::FromInner;
 
 pub fn errno() -> i32 {
@@ -111,7 +112,7 @@ pub fn getenv(varname: &OsStr) -> Option<OsString> {
     // reimplement "os_str" instead of just using the generic unix
     // "os_str".
     let u8s: &[u8] = unsafe { crate::slice::from_raw_parts(words.cast() as *const u8, nbytes) };
-    Some(OsString::from_inner(super::os_str::Buf { inner: u8s.to_vec() }))
+    Some(OsString::from_inner(os_str::Buf { inner: u8s.to_vec() }))
 }
 
 pub fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> {
diff --git a/tests/ui-fulldeps/regions-mock-tcx.rs b/tests/ui-fulldeps/regions-mock-tcx.rs
index 970f08377a6..71c0aa2d596 100644
--- a/tests/ui-fulldeps/regions-mock-tcx.rs
+++ b/tests/ui-fulldeps/regions-mock-tcx.rs
@@ -9,10 +9,9 @@
 // - Multiple lifetime parameters
 // - Arenas
 
-#![feature(rustc_private, libc)]
+#![feature(rustc_private)]
 
 extern crate rustc_arena;
-extern crate libc;
 
 // Necessary to pull in object code as the rest of the rustc crates are shipped only as rmeta
 // files.
diff --git a/tests/ui/abi/c-stack-returning-int64.rs b/tests/ui/abi/c-stack-returning-int64.rs
index 1fd7fe417a5..05c8af90ab3 100644
--- a/tests/ui/abi/c-stack-returning-int64.rs
+++ b/tests/ui/abi/c-stack-returning-int64.rs
@@ -1,14 +1,10 @@
 //@ run-pass
 //@ ignore-sgx no libc
 
-#![feature(rustc_private)]
-
-extern crate libc;
-
 use std::ffi::CString;
 
 mod mlibc {
-    use libc::{c_char, c_long, c_longlong};
+    use std::ffi::{c_char, c_long, c_longlong};
 
     extern "C" {
         pub fn atol(x: *const c_char) -> c_long;
diff --git a/tests/ui/abi/statics/static-mut-foreign.rs b/tests/ui/abi/statics/static-mut-foreign.rs
index 33a7194c102..167b7a4e36e 100644
--- a/tests/ui/abi/statics/static-mut-foreign.rs
+++ b/tests/ui/abi/statics/static-mut-foreign.rs
@@ -3,19 +3,17 @@
 // statics cannot. This ensures that there's some form of error if this is
 // attempted.
 
-#![feature(rustc_private)]
-
-extern crate libc;
+use std::ffi::c_int;
 
 #[link(name = "rust_test_helpers", kind = "static")]
 extern "C" {
-    static mut rust_dbg_static_mut: libc::c_int;
+    static mut rust_dbg_static_mut: c_int;
     pub fn rust_dbg_static_mut_check_four();
 }
 
-unsafe fn static_bound(_: &'static libc::c_int) {}
+unsafe fn static_bound(_: &'static c_int) {}
 
-fn static_bound_set(a: &'static mut libc::c_int) {
+fn static_bound_set(a: &'static mut c_int) {
     *a = 3;
 }
 
diff --git a/tests/ui/abi/statics/static-mut-foreign.stderr b/tests/ui/abi/statics/static-mut-foreign.stderr
index 4d5f26ac08c..983325c1abd 100644
--- a/tests/ui/abi/statics/static-mut-foreign.stderr
+++ b/tests/ui/abi/statics/static-mut-foreign.stderr
@@ -1,5 +1,5 @@
 warning: creating a shared reference to mutable static is discouraged
-  --> $DIR/static-mut-foreign.rs:33:18
+  --> $DIR/static-mut-foreign.rs:31:18
    |
 LL |     static_bound(&rust_dbg_static_mut);
    |                  ^^^^^^^^^^^^^^^^^^^^ shared reference to mutable static
@@ -14,7 +14,7 @@ LL |     static_bound(addr_of!(rust_dbg_static_mut));
    |                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 warning: creating a mutable reference to mutable static is discouraged
-  --> $DIR/static-mut-foreign.rs:35:22
+  --> $DIR/static-mut-foreign.rs:33:22
    |
 LL |     static_bound_set(&mut rust_dbg_static_mut);
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^ mutable reference to mutable static
diff --git a/tests/ui/array-slice-vec/vec-macro-no-std.rs b/tests/ui/array-slice-vec/vec-macro-no-std.rs
index 76a1b4951d6..1b5ab536dcb 100644
--- a/tests/ui/array-slice-vec/vec-macro-no-std.rs
+++ b/tests/ui/array-slice-vec/vec-macro-no-std.rs
@@ -7,8 +7,6 @@
 
 extern crate std as other;
 
-extern crate libc;
-
 #[macro_use]
 extern crate alloc;
 
diff --git a/tests/ui/auxiliary/check_static_recursion_foreign_helper.rs b/tests/ui/auxiliary/check_static_recursion_foreign_helper.rs
index 5330b7a92a3..bcab5f238c3 100644
--- a/tests/ui/auxiliary/check_static_recursion_foreign_helper.rs
+++ b/tests/ui/auxiliary/check_static_recursion_foreign_helper.rs
@@ -5,7 +5,7 @@
 #![crate_name = "check_static_recursion_foreign_helper"]
 #![crate_type = "lib"]
 
-extern crate libc;
+use std::ffi::c_int;
 
 #[no_mangle]
-pub static test_static: libc::c_int = 0;
+pub static test_static: c_int = 0;
diff --git a/tests/ui/check-static-recursion-foreign.rs b/tests/ui/check-static-recursion-foreign.rs
index 97db47d0bd6..5a0ff7b5962 100644
--- a/tests/ui/check-static-recursion-foreign.rs
+++ b/tests/ui/check-static-recursion-foreign.rs
@@ -6,12 +6,9 @@
 
 //@ pretty-expanded FIXME #23616
 
-#![feature(rustc_private)]
-
 extern crate check_static_recursion_foreign_helper;
-extern crate libc;
 
-use libc::c_int;
+use std::ffi::c_int;
 
 extern "C" {
     static test_static: c_int;
diff --git a/tests/ui/consts/value-suggestion-ice-123906.rs b/tests/ui/consts/value-suggestion-ice-123906.rs
new file mode 100644
index 00000000000..531bbc15852
--- /dev/null
+++ b/tests/ui/consts/value-suggestion-ice-123906.rs
@@ -0,0 +1,8 @@
+fn as_chunks<const N: usize>() -> [u8; N] {
+    loop {
+        break;
+        //~^ ERROR mismatched types
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/consts/value-suggestion-ice-123906.stderr b/tests/ui/consts/value-suggestion-ice-123906.stderr
new file mode 100644
index 00000000000..8e2c316400d
--- /dev/null
+++ b/tests/ui/consts/value-suggestion-ice-123906.stderr
@@ -0,0 +1,18 @@
+error[E0308]: mismatched types
+  --> $DIR/value-suggestion-ice-123906.rs:3:9
+   |
+LL | fn as_chunks<const N: usize>() -> [u8; N] {
+   |                                   ------- expected `[u8; ]` because of this return type
+LL |     loop {
+   |     ---- this loop is expected to be of type `[u8; N]`
+LL |         break;
+   |         ^^^^^ expected `[u8; N]`, found `()`
+   |
+help: give the `break` a value of the expected type
+   |
+LL |         break value;
+   |               +++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/error-codes/E0069.stderr b/tests/ui/error-codes/E0069.stderr
index 20ff8c258a0..ef6c411ae58 100644
--- a/tests/ui/error-codes/E0069.stderr
+++ b/tests/ui/error-codes/E0069.stderr
@@ -5,6 +5,11 @@ LL | fn foo() -> u8 {
    |             -- expected `u8` because of this return type
 LL |     return;
    |     ^^^^^^ return type is not `()`
+   |
+help: give the `return` a value of the expected type
+   |
+LL |     return 42;
+   |            ++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/extern/extern-const.fixed b/tests/ui/extern/extern-const.fixed
index 9f695eaafd0..be3a893e669 100644
--- a/tests/ui/extern/extern-const.fixed
+++ b/tests/ui/extern/extern-const.fixed
@@ -6,12 +6,12 @@
 
 //@ run-rustfix
 //@ compile-flags: -g
-#![feature(rustc_private)]
-extern crate libc;
+
+use std::ffi::c_int;
 
 #[link(name = "rust_test_helpers", kind = "static")]
 extern "C" {
-    static rust_dbg_static_mut: libc::c_int; //~ ERROR extern items cannot be `const`
+    static rust_dbg_static_mut: c_int; //~ ERROR extern items cannot be `const`
 }
 
 fn main() {
diff --git a/tests/ui/extern/extern-const.rs b/tests/ui/extern/extern-const.rs
index e412dff8895..4c9e26d693f 100644
--- a/tests/ui/extern/extern-const.rs
+++ b/tests/ui/extern/extern-const.rs
@@ -6,12 +6,12 @@
 
 //@ run-rustfix
 //@ compile-flags: -g
-#![feature(rustc_private)]
-extern crate libc;
+
+use std::ffi::c_int;
 
 #[link(name = "rust_test_helpers", kind = "static")]
 extern "C" {
-    const rust_dbg_static_mut: libc::c_int; //~ ERROR extern items cannot be `const`
+    const rust_dbg_static_mut: c_int; //~ ERROR extern items cannot be `const`
 }
 
 fn main() {
diff --git a/tests/ui/extern/extern-const.stderr b/tests/ui/extern/extern-const.stderr
index 07485cf9994..31954ca2c84 100644
--- a/tests/ui/extern/extern-const.stderr
+++ b/tests/ui/extern/extern-const.stderr
@@ -1,7 +1,7 @@
 error: extern items cannot be `const`
   --> $DIR/extern-const.rs:14:11
    |
-LL |     const rust_dbg_static_mut: libc::c_int;
+LL |     const rust_dbg_static_mut: c_int;
    |     ------^^^^^^^^^^^^^^^^^^^
    |     |
    |     help: try using a static value: `static`
diff --git a/tests/ui/internal-lints/existing_doc_keyword.rs b/tests/ui/internal-lints/existing_doc_keyword.rs
index 16c350287b2..8f60b931591 100644
--- a/tests/ui/internal-lints/existing_doc_keyword.rs
+++ b/tests/ui/internal-lints/existing_doc_keyword.rs
@@ -1,6 +1,5 @@
 //@ compile-flags: -Z unstable-options
 
-#![feature(rustc_private)]
 #![feature(rustdoc_internals)]
 
 #![crate_type = "lib"]
diff --git a/tests/ui/internal-lints/existing_doc_keyword.stderr b/tests/ui/internal-lints/existing_doc_keyword.stderr
index 8f519fe6b5f..5573e7ce4d0 100644
--- a/tests/ui/internal-lints/existing_doc_keyword.stderr
+++ b/tests/ui/internal-lints/existing_doc_keyword.stderr
@@ -1,12 +1,12 @@
 error: found non-existing keyword `tadam` used in `#[doc(keyword = "...")]`
-  --> $DIR/existing_doc_keyword.rs:10:1
+  --> $DIR/existing_doc_keyword.rs:9:1
    |
 LL | #[doc(keyword = "tadam")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: only existing keywords are allowed in core/std
 note: the lint level is defined here
-  --> $DIR/existing_doc_keyword.rs:8:9
+  --> $DIR/existing_doc_keyword.rs:7:9
    |
 LL | #![deny(rustc::existing_doc_keyword)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/issues/issue-13259-windows-tcb-trash.rs b/tests/ui/issues/issue-13259-windows-tcb-trash.rs
index 803cda091b9..381e3f15259 100644
--- a/tests/ui/issues/issue-13259-windows-tcb-trash.rs
+++ b/tests/ui/issues/issue-13259-windows-tcb-trash.rs
@@ -1,7 +1,4 @@
 //@ run-pass
-#![feature(rustc_private)]
-
-extern crate libc;
 
 #[cfg(windows)]
 mod imp {
diff --git a/tests/ui/issues/issue-22034.rs b/tests/ui/issues/issue-22034.rs
index ed741779f68..3631c2368fe 100644
--- a/tests/ui/issues/issue-22034.rs
+++ b/tests/ui/issues/issue-22034.rs
@@ -1,7 +1,3 @@
-#![feature(rustc_private)]
-
-extern crate libc;
-
 fn main() {
     let ptr: *mut () = core::ptr::null_mut();
     let _: &mut dyn Fn() = unsafe {
diff --git a/tests/ui/issues/issue-22034.stderr b/tests/ui/issues/issue-22034.stderr
index 6d899618d7a..75ddcd47899 100644
--- a/tests/ui/issues/issue-22034.stderr
+++ b/tests/ui/issues/issue-22034.stderr
@@ -1,5 +1,5 @@
 error[E0277]: expected a `Fn()` closure, found `()`
-  --> $DIR/issue-22034.rs:8:16
+  --> $DIR/issue-22034.rs:4:16
    |
 LL |         &mut *(ptr as *mut dyn Fn())
    |                ^^^ expected an `Fn()` closure, found `()`
diff --git a/tests/ui/issues/issue-2214.rs b/tests/ui/issues/issue-2214.rs
index 5d732cd7798..453bb58a622 100644
--- a/tests/ui/issues/issue-2214.rs
+++ b/tests/ui/issues/issue-2214.rs
@@ -1,11 +1,8 @@
 //@ run-pass
 //@ ignore-wasm32 wasi-libc does not have lgamma
 //@ ignore-sgx no libc
-#![feature(rustc_private)]
 
-extern crate libc;
-
-use libc::{c_double, c_int};
+use std::ffi::{c_double, c_int};
 use std::mem;
 
 fn to_c_int(v: &mut isize) -> &mut c_int {
@@ -19,8 +16,7 @@ fn lgamma(n: c_double, value: &mut isize) -> c_double {
 }
 
 mod m {
-    use libc::{c_double, c_int};
-
+    use std::ffi::{c_double, c_int};
     extern "C" {
         #[cfg(all(unix, not(target_os = "vxworks")))]
         #[link_name="lgamma_r"]
diff --git a/tests/ui/issues/issue-3656.rs b/tests/ui/issues/issue-3656.rs
index 1b65129d0c3..975695e497f 100644
--- a/tests/ui/issues/issue-3656.rs
+++ b/tests/ui/issues/issue-3656.rs
@@ -6,10 +6,8 @@
 // the alignment of elements into account.
 
 //@ pretty-expanded FIXME #23616
-#![feature(rustc_private)]
 
-extern crate libc;
-use libc::{c_uint, c_void};
+use std::ffi::{c_uint, c_void};
 
 pub struct KEYGEN {
     hash_algorithm: [c_uint; 2],
diff --git a/tests/ui/lint/lint-ctypes-fn.rs b/tests/ui/lint/lint-ctypes-fn.rs
index 14831e24718..73820c86d1a 100644
--- a/tests/ui/lint/lint-ctypes-fn.rs
+++ b/tests/ui/lint/lint-ctypes-fn.rs
@@ -1,12 +1,9 @@
-#![feature(rustc_private)]
-
 #![allow(private_interfaces)]
 #![deny(improper_ctypes_definitions)]
 
-extern crate libc;
-
 use std::default::Default;
 use std::marker::PhantomData;
+use std::ffi::{c_int, c_uint};
 
 trait Trait {}
 
@@ -165,10 +162,10 @@ pub extern "C" fn good17(p: TransparentCustomZst) { }
 pub extern "C" fn good18(_: &String) { }
 
 #[cfg(not(target_arch = "wasm32"))]
-pub extern "C" fn good1(size: *const libc::c_int) { }
+pub extern "C" fn good1(size: *const c_int) { }
 
 #[cfg(not(target_arch = "wasm32"))]
-pub extern "C" fn good2(size: *const libc::c_uint) { }
+pub extern "C" fn good2(size: *const c_uint) { }
 
 pub extern "C" fn unused_generic1<T>(size: *const Foo) { }
 
diff --git a/tests/ui/lint/lint-ctypes-fn.stderr b/tests/ui/lint/lint-ctypes-fn.stderr
index a05206bf18d..a62533a4be1 100644
--- a/tests/ui/lint/lint-ctypes-fn.stderr
+++ b/tests/ui/lint/lint-ctypes-fn.stderr
@@ -1,5 +1,5 @@
 error: `extern` fn uses type `[u32]`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:73:33
+  --> $DIR/lint-ctypes-fn.rs:70:33
    |
 LL | pub extern "C" fn slice_type(p: &[u32]) { }
    |                                 ^^^^^^ not FFI-safe
@@ -7,13 +7,13 @@ LL | pub extern "C" fn slice_type(p: &[u32]) { }
    = help: consider using a raw pointer instead
    = note: slices have no C equivalent
 note: the lint level is defined here
-  --> $DIR/lint-ctypes-fn.rs:4:9
+  --> $DIR/lint-ctypes-fn.rs:2:9
    |
 LL | #![deny(improper_ctypes_definitions)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `extern` fn uses type `str`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:76:31
+  --> $DIR/lint-ctypes-fn.rs:73:31
    |
 LL | pub extern "C" fn str_type(p: &str) { }
    |                               ^^^^ not FFI-safe
@@ -22,7 +22,7 @@ LL | pub extern "C" fn str_type(p: &str) { }
    = note: string slices have no C equivalent
 
 error: `extern` fn uses type `Box<[u8]>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:83:34
+  --> $DIR/lint-ctypes-fn.rs:80:34
    |
 LL | pub extern "C" fn boxed_slice(p: Box<[u8]>) { }
    |                                  ^^^^^^^^^ not FFI-safe
@@ -30,7 +30,7 @@ LL | pub extern "C" fn boxed_slice(p: Box<[u8]>) { }
    = note: box cannot be represented as a single pointer
 
 error: `extern` fn uses type `Box<str>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:86:35
+  --> $DIR/lint-ctypes-fn.rs:83:35
    |
 LL | pub extern "C" fn boxed_string(p: Box<str>) { }
    |                                   ^^^^^^^^ not FFI-safe
@@ -38,7 +38,7 @@ LL | pub extern "C" fn boxed_string(p: Box<str>) { }
    = note: box cannot be represented as a single pointer
 
 error: `extern` fn uses type `Box<dyn Trait>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:89:34
+  --> $DIR/lint-ctypes-fn.rs:86:34
    |
 LL | pub extern "C" fn boxed_trait(p: Box<dyn Trait>) { }
    |                                  ^^^^^^^^^^^^^^ not FFI-safe
@@ -46,7 +46,7 @@ LL | pub extern "C" fn boxed_trait(p: Box<dyn Trait>) { }
    = note: box cannot be represented as a single pointer
 
 error: `extern` fn uses type `char`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:92:32
+  --> $DIR/lint-ctypes-fn.rs:89:32
    |
 LL | pub extern "C" fn char_type(p: char) { }
    |                                ^^^^ not FFI-safe
@@ -55,7 +55,7 @@ LL | pub extern "C" fn char_type(p: char) { }
    = note: the `char` type has no C equivalent
 
 error: `extern` fn uses type `i128`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:95:32
+  --> $DIR/lint-ctypes-fn.rs:92:32
    |
 LL | pub extern "C" fn i128_type(p: i128) { }
    |                                ^^^^ not FFI-safe
@@ -63,7 +63,7 @@ LL | pub extern "C" fn i128_type(p: i128) { }
    = note: 128-bit integers don't currently have a known stable ABI
 
 error: `extern` fn uses type `u128`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:98:32
+  --> $DIR/lint-ctypes-fn.rs:95:32
    |
 LL | pub extern "C" fn u128_type(p: u128) { }
    |                                ^^^^ not FFI-safe
@@ -71,7 +71,7 @@ LL | pub extern "C" fn u128_type(p: u128) { }
    = note: 128-bit integers don't currently have a known stable ABI
 
 error: `extern` fn uses type `(i32, i32)`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:101:33
+  --> $DIR/lint-ctypes-fn.rs:98:33
    |
 LL | pub extern "C" fn tuple_type(p: (i32, i32)) { }
    |                                 ^^^^^^^^^^ not FFI-safe
@@ -80,7 +80,7 @@ LL | pub extern "C" fn tuple_type(p: (i32, i32)) { }
    = note: tuples have unspecified layout
 
 error: `extern` fn uses type `(i32, i32)`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:104:34
+  --> $DIR/lint-ctypes-fn.rs:101:34
    |
 LL | pub extern "C" fn tuple_type2(p: I32Pair) { }
    |                                  ^^^^^^^ not FFI-safe
@@ -89,7 +89,7 @@ LL | pub extern "C" fn tuple_type2(p: I32Pair) { }
    = note: tuples have unspecified layout
 
 error: `extern` fn uses type `ZeroSize`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:107:32
+  --> $DIR/lint-ctypes-fn.rs:104:32
    |
 LL | pub extern "C" fn zero_size(p: ZeroSize) { }
    |                                ^^^^^^^^ not FFI-safe
@@ -97,26 +97,26 @@ LL | pub extern "C" fn zero_size(p: ZeroSize) { }
    = help: consider adding a member to this struct
    = note: this struct has no fields
 note: the type is defined here
-  --> $DIR/lint-ctypes-fn.rs:28:1
+  --> $DIR/lint-ctypes-fn.rs:25:1
    |
 LL | pub struct ZeroSize;
    | ^^^^^^^^^^^^^^^^^^^
 
 error: `extern` fn uses type `ZeroSizeWithPhantomData`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:110:40
+  --> $DIR/lint-ctypes-fn.rs:107:40
    |
 LL | pub extern "C" fn zero_size_phantom(p: ZeroSizeWithPhantomData) { }
    |                                        ^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
    |
    = note: composed only of `PhantomData`
 note: the type is defined here
-  --> $DIR/lint-ctypes-fn.rs:63:1
+  --> $DIR/lint-ctypes-fn.rs:60:1
    |
 LL | pub struct ZeroSizeWithPhantomData(PhantomData<i32>);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `extern` fn uses type `PhantomData<bool>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:113:51
+  --> $DIR/lint-ctypes-fn.rs:110:51
    |
 LL | pub extern "C" fn zero_size_phantom_toplevel() -> PhantomData<bool> {
    |                                                   ^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -124,7 +124,7 @@ LL | pub extern "C" fn zero_size_phantom_toplevel() -> PhantomData<bool> {
    = note: composed only of `PhantomData`
 
 error: `extern` fn uses type `fn()`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:118:30
+  --> $DIR/lint-ctypes-fn.rs:115:30
    |
 LL | pub extern "C" fn fn_type(p: RustFn) { }
    |                              ^^^^^^ not FFI-safe
@@ -133,7 +133,7 @@ LL | pub extern "C" fn fn_type(p: RustFn) { }
    = note: this function pointer has Rust-specific calling convention
 
 error: `extern` fn uses type `fn()`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:121:31
+  --> $DIR/lint-ctypes-fn.rs:118:31
    |
 LL | pub extern "C" fn fn_type2(p: fn()) { }
    |                               ^^^^ not FFI-safe
@@ -142,7 +142,7 @@ LL | pub extern "C" fn fn_type2(p: fn()) { }
    = note: this function pointer has Rust-specific calling convention
 
 error: `extern` fn uses type `i128`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:126:39
+  --> $DIR/lint-ctypes-fn.rs:123:39
    |
 LL | pub extern "C" fn transparent_i128(p: TransparentI128) { }
    |                                       ^^^^^^^^^^^^^^^ not FFI-safe
@@ -150,7 +150,7 @@ LL | pub extern "C" fn transparent_i128(p: TransparentI128) { }
    = note: 128-bit integers don't currently have a known stable ABI
 
 error: `extern` fn uses type `str`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:129:38
+  --> $DIR/lint-ctypes-fn.rs:126:38
    |
 LL | pub extern "C" fn transparent_str(p: TransparentStr) { }
    |                                      ^^^^^^^^^^^^^^ not FFI-safe
@@ -159,7 +159,7 @@ LL | pub extern "C" fn transparent_str(p: TransparentStr) { }
    = note: string slices have no C equivalent
 
 error: `extern` fn uses type `PhantomData<bool>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:175:43
+  --> $DIR/lint-ctypes-fn.rs:172:43
    |
 LL | pub extern "C" fn unused_generic2<T>() -> PhantomData<bool> {
    |                                           ^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -167,7 +167,7 @@ LL | pub extern "C" fn unused_generic2<T>() -> PhantomData<bool> {
    = note: composed only of `PhantomData`
 
 error: `extern` fn uses type `Vec<T>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:188:39
+  --> $DIR/lint-ctypes-fn.rs:185:39
    |
 LL | pub extern "C" fn used_generic4<T>(x: Vec<T>) { }
    |                                       ^^^^^^ not FFI-safe
@@ -176,7 +176,7 @@ LL | pub extern "C" fn used_generic4<T>(x: Vec<T>) { }
    = note: this struct has unspecified layout
 
 error: `extern` fn uses type `Vec<T>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:191:41
+  --> $DIR/lint-ctypes-fn.rs:188:41
    |
 LL | pub extern "C" fn used_generic5<T>() -> Vec<T> {
    |                                         ^^^^^^ not FFI-safe
diff --git a/tests/ui/lint/lint-ctypes.rs b/tests/ui/lint/lint-ctypes.rs
index 3dd731625f4..dae07930aba 100644
--- a/tests/ui/lint/lint-ctypes.rs
+++ b/tests/ui/lint/lint-ctypes.rs
@@ -3,10 +3,9 @@
 #![allow(private_interfaces)]
 #![deny(improper_ctypes)]
 
-extern crate libc;
-
 use std::cell::UnsafeCell;
 use std::marker::PhantomData;
+use std::ffi::{c_int, c_uint};
 
 trait Bar { }
 trait Mirror { type It: ?Sized; }
@@ -110,8 +109,8 @@ extern "C" {
 
 #[cfg(not(target_arch = "wasm32"))]
 extern "C" {
-    pub fn good1(size: *const libc::c_int);
-    pub fn good2(size: *const libc::c_uint);
+    pub fn good1(size: *const c_int);
+    pub fn good2(size: *const c_uint);
 }
 
 fn main() {
diff --git a/tests/ui/lint/lint-ctypes.stderr b/tests/ui/lint/lint-ctypes.stderr
index 121ad0ce8fa..2c81c7b8e4b 100644
--- a/tests/ui/lint/lint-ctypes.stderr
+++ b/tests/ui/lint/lint-ctypes.stderr
@@ -1,5 +1,5 @@
 error: `extern` block uses type `Foo`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:48:28
+  --> $DIR/lint-ctypes.rs:47:28
    |
 LL |     pub fn ptr_type1(size: *const Foo);
    |                            ^^^^^^^^^^ not FFI-safe
@@ -7,7 +7,7 @@ LL |     pub fn ptr_type1(size: *const Foo);
    = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
    = note: this struct has unspecified layout
 note: the type is defined here
-  --> $DIR/lint-ctypes.rs:26:1
+  --> $DIR/lint-ctypes.rs:25:1
    |
 LL | pub struct Foo;
    | ^^^^^^^^^^^^^^
@@ -18,7 +18,7 @@ LL | #![deny(improper_ctypes)]
    |         ^^^^^^^^^^^^^^^
 
 error: `extern` block uses type `Foo`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:49:28
+  --> $DIR/lint-ctypes.rs:48:28
    |
 LL |     pub fn ptr_type2(size: *const Foo);
    |                            ^^^^^^^^^^ not FFI-safe
@@ -26,13 +26,13 @@ LL |     pub fn ptr_type2(size: *const Foo);
    = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
    = note: this struct has unspecified layout
 note: the type is defined here
-  --> $DIR/lint-ctypes.rs:26:1
+  --> $DIR/lint-ctypes.rs:25:1
    |
 LL | pub struct Foo;
    | ^^^^^^^^^^^^^^
 
 error: `extern` block uses type `((),)`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:51:25
+  --> $DIR/lint-ctypes.rs:50:25
    |
 LL |     pub fn ptr_tuple(p: *const ((),));
    |                         ^^^^^^^^^^^^ not FFI-safe
@@ -41,7 +41,7 @@ LL |     pub fn ptr_tuple(p: *const ((),));
    = note: tuples have unspecified layout
 
 error: `extern` block uses type `[u32]`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:52:26
+  --> $DIR/lint-ctypes.rs:51:26
    |
 LL |     pub fn slice_type(p: &[u32]);
    |                          ^^^^^^ not FFI-safe
@@ -50,7 +50,7 @@ LL |     pub fn slice_type(p: &[u32]);
    = note: slices have no C equivalent
 
 error: `extern` block uses type `str`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:53:24
+  --> $DIR/lint-ctypes.rs:52:24
    |
 LL |     pub fn str_type(p: &str);
    |                        ^^^^ not FFI-safe
@@ -59,7 +59,7 @@ LL |     pub fn str_type(p: &str);
    = note: string slices have no C equivalent
 
 error: `extern` block uses type `Box<u32>`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:54:24
+  --> $DIR/lint-ctypes.rs:53:24
    |
 LL |     pub fn box_type(p: Box<u32>);
    |                        ^^^^^^^^ not FFI-safe
@@ -68,7 +68,7 @@ LL |     pub fn box_type(p: Box<u32>);
    = note: this struct has unspecified layout
 
 error: `extern` block uses type `Option<Box<u32>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:55:28
+  --> $DIR/lint-ctypes.rs:54:28
    |
 LL |     pub fn opt_box_type(p: Option<Box<u32>>);
    |                            ^^^^^^^^^^^^^^^^ not FFI-safe
@@ -77,7 +77,7 @@ LL |     pub fn opt_box_type(p: Option<Box<u32>>);
    = note: enum has no representation hint
 
 error: `extern` block uses type `char`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:57:25
+  --> $DIR/lint-ctypes.rs:56:25
    |
 LL |     pub fn char_type(p: char);
    |                         ^^^^ not FFI-safe
@@ -86,7 +86,7 @@ LL |     pub fn char_type(p: char);
    = note: the `char` type has no C equivalent
 
 error: `extern` block uses type `i128`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:58:25
+  --> $DIR/lint-ctypes.rs:57:25
    |
 LL |     pub fn i128_type(p: i128);
    |                         ^^^^ not FFI-safe
@@ -94,7 +94,7 @@ LL |     pub fn i128_type(p: i128);
    = note: 128-bit integers don't currently have a known stable ABI
 
 error: `extern` block uses type `u128`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:59:25
+  --> $DIR/lint-ctypes.rs:58:25
    |
 LL |     pub fn u128_type(p: u128);
    |                         ^^^^ not FFI-safe
@@ -102,7 +102,7 @@ LL |     pub fn u128_type(p: u128);
    = note: 128-bit integers don't currently have a known stable ABI
 
 error: `extern` block uses type `dyn Bar`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:60:26
+  --> $DIR/lint-ctypes.rs:59:26
    |
 LL |     pub fn trait_type(p: &dyn Bar);
    |                          ^^^^^^^^ not FFI-safe
@@ -110,7 +110,7 @@ LL |     pub fn trait_type(p: &dyn Bar);
    = note: trait objects have no C equivalent
 
 error: `extern` block uses type `(i32, i32)`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:61:26
+  --> $DIR/lint-ctypes.rs:60:26
    |
 LL |     pub fn tuple_type(p: (i32, i32));
    |                          ^^^^^^^^^^ not FFI-safe
@@ -119,7 +119,7 @@ LL |     pub fn tuple_type(p: (i32, i32));
    = note: tuples have unspecified layout
 
 error: `extern` block uses type `(i32, i32)`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:62:27
+  --> $DIR/lint-ctypes.rs:61:27
    |
 LL |     pub fn tuple_type2(p: I32Pair);
    |                           ^^^^^^^ not FFI-safe
@@ -128,7 +128,7 @@ LL |     pub fn tuple_type2(p: I32Pair);
    = note: tuples have unspecified layout
 
 error: `extern` block uses type `ZeroSize`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:63:25
+  --> $DIR/lint-ctypes.rs:62:25
    |
 LL |     pub fn zero_size(p: ZeroSize);
    |                         ^^^^^^^^ not FFI-safe
@@ -136,26 +136,26 @@ LL |     pub fn zero_size(p: ZeroSize);
    = help: consider adding a member to this struct
    = note: this struct has no fields
 note: the type is defined here
-  --> $DIR/lint-ctypes.rs:22:1
+  --> $DIR/lint-ctypes.rs:21:1
    |
 LL | pub struct ZeroSize;
    | ^^^^^^^^^^^^^^^^^^^
 
 error: `extern` block uses type `ZeroSizeWithPhantomData`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:64:33
+  --> $DIR/lint-ctypes.rs:63:33
    |
 LL |     pub fn zero_size_phantom(p: ZeroSizeWithPhantomData);
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
    |
    = note: composed only of `PhantomData`
 note: the type is defined here
-  --> $DIR/lint-ctypes.rs:45:1
+  --> $DIR/lint-ctypes.rs:44:1
    |
 LL | pub struct ZeroSizeWithPhantomData(::std::marker::PhantomData<i32>);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `extern` block uses type `PhantomData<bool>`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:67:12
+  --> $DIR/lint-ctypes.rs:66:12
    |
 LL |         -> ::std::marker::PhantomData<bool>;
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -163,7 +163,7 @@ LL |         -> ::std::marker::PhantomData<bool>;
    = note: composed only of `PhantomData`
 
 error: `extern` block uses type `fn()`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:68:23
+  --> $DIR/lint-ctypes.rs:67:23
    |
 LL |     pub fn fn_type(p: RustFn);
    |                       ^^^^^^ not FFI-safe
@@ -172,7 +172,7 @@ LL |     pub fn fn_type(p: RustFn);
    = note: this function pointer has Rust-specific calling convention
 
 error: `extern` block uses type `fn()`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:69:24
+  --> $DIR/lint-ctypes.rs:68:24
    |
 LL |     pub fn fn_type2(p: fn());
    |                        ^^^^ not FFI-safe
@@ -181,7 +181,7 @@ LL |     pub fn fn_type2(p: fn());
    = note: this function pointer has Rust-specific calling convention
 
 error: `extern` block uses type `Box<u32>`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:70:28
+  --> $DIR/lint-ctypes.rs:69:28
    |
 LL |     pub fn fn_contained(p: RustBadRet);
    |                            ^^^^^^^^^^ not FFI-safe
@@ -190,7 +190,7 @@ LL |     pub fn fn_contained(p: RustBadRet);
    = note: this struct has unspecified layout
 
 error: `extern` block uses type `i128`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:71:32
+  --> $DIR/lint-ctypes.rs:70:32
    |
 LL |     pub fn transparent_i128(p: TransparentI128);
    |                                ^^^^^^^^^^^^^^^ not FFI-safe
@@ -198,7 +198,7 @@ LL |     pub fn transparent_i128(p: TransparentI128);
    = note: 128-bit integers don't currently have a known stable ABI
 
 error: `extern` block uses type `str`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:72:31
+  --> $DIR/lint-ctypes.rs:71:31
    |
 LL |     pub fn transparent_str(p: TransparentStr);
    |                               ^^^^^^^^^^^^^^ not FFI-safe
@@ -207,7 +207,7 @@ LL |     pub fn transparent_str(p: TransparentStr);
    = note: string slices have no C equivalent
 
 error: `extern` block uses type `Box<u32>`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:73:30
+  --> $DIR/lint-ctypes.rs:72:30
    |
 LL |     pub fn transparent_fn(p: TransparentBadFn);
    |                              ^^^^^^^^^^^^^^^^ not FFI-safe
@@ -216,7 +216,7 @@ LL |     pub fn transparent_fn(p: TransparentBadFn);
    = note: this struct has unspecified layout
 
 error: `extern` block uses type `[u8; 8]`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:74:27
+  --> $DIR/lint-ctypes.rs:73:27
    |
 LL |     pub fn raw_array(arr: [u8; 8]);
    |                           ^^^^^^^ not FFI-safe
@@ -225,7 +225,7 @@ LL |     pub fn raw_array(arr: [u8; 8]);
    = note: passing raw arrays by value is not FFI-safe
 
 error: `extern` block uses type `Option<UnsafeCell<extern "C" fn()>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:76:26
+  --> $DIR/lint-ctypes.rs:75:26
    |
 LL |     pub fn no_niche_a(a: Option<UnsafeCell<extern fn()>>);
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -234,7 +234,7 @@ LL |     pub fn no_niche_a(a: Option<UnsafeCell<extern fn()>>);
    = note: enum has no representation hint
 
 error: `extern` block uses type `Option<UnsafeCell<&i32>>`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:78:26
+  --> $DIR/lint-ctypes.rs:77:26
    |
 LL |     pub fn no_niche_b(b: Option<UnsafeCell<&i32>>);
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -243,7 +243,7 @@ LL |     pub fn no_niche_b(b: Option<UnsafeCell<&i32>>);
    = note: enum has no representation hint
 
 error: `extern` block uses type `u128`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:81:34
+  --> $DIR/lint-ctypes.rs:80:34
    |
 LL |     pub static static_u128_type: u128;
    |                                  ^^^^ not FFI-safe
@@ -251,7 +251,7 @@ LL |     pub static static_u128_type: u128;
    = note: 128-bit integers don't currently have a known stable ABI
 
 error: `extern` block uses type `u128`, which is not FFI-safe
-  --> $DIR/lint-ctypes.rs:82:40
+  --> $DIR/lint-ctypes.rs:81:40
    |
 LL |     pub static static_u128_array_type: [u128; 16];
    |                                        ^^^^^^^^^^ not FFI-safe
diff --git a/tests/ui/non-copyable-void.rs b/tests/ui/non-copyable-void.rs
index 58668147801..55bad82bc33 100644
--- a/tests/ui/non-copyable-void.rs
+++ b/tests/ui/non-copyable-void.rs
@@ -1,10 +1,8 @@
-#![feature(rustc_private)]
-
-extern crate libc;
+use std::ffi::c_void;
 
 fn main() {
     let x : *const Vec<isize> = &vec![1,2,3];
-    let y : *const libc::c_void = x as *const libc::c_void;
+    let y : *const c_void = x as *const c_void;
     unsafe {
         let _z = (*y).clone();
         //~^ ERROR no method named `clone` found
diff --git a/tests/ui/non-copyable-void.stderr b/tests/ui/non-copyable-void.stderr
index d25bb8c17ee..373557fa01a 100644
--- a/tests/ui/non-copyable-void.stderr
+++ b/tests/ui/non-copyable-void.stderr
@@ -1,5 +1,5 @@
 error[E0599]: no method named `clone` found for enum `c_void` in the current scope
-  --> $DIR/non-copyable-void.rs:9:23
+  --> $DIR/non-copyable-void.rs:7:23
    |
 LL |         let _z = (*y).clone();
    |                       ^^^^^ method not found in `c_void`
diff --git a/tests/ui/process/core-run-destroy.rs b/tests/ui/process/core-run-destroy.rs
index 338203657bd..3f2ea0e8441 100644
--- a/tests/ui/process/core-run-destroy.rs
+++ b/tests/ui/process/core-run-destroy.rs
@@ -14,10 +14,6 @@
 // memory, which makes for some *confusing* logs. That's why these are here
 // instead of in std.
 
-#![feature(rustc_private, duration)]
-
-extern crate libc;
-
 use std::process::{self, Command, Child, Output, Stdio};
 use std::str;
 use std::sync::mpsc::channel;
diff --git a/tests/ui/process/process-panic-after-fork.rs b/tests/ui/process/process-panic-after-fork.rs
index bae121576bd..afb1b721182 100644
--- a/tests/ui/process/process-panic-after-fork.rs
+++ b/tests/ui/process/process-panic-after-fork.rs
@@ -14,14 +14,13 @@
 extern crate libc;
 
 use std::alloc::{GlobalAlloc, Layout};
+use std::ffi::c_int;
 use std::fmt;
 use std::panic::{self, panic_any};
 use std::os::unix::process::{CommandExt, ExitStatusExt};
 use std::process::{self, Command, ExitStatus};
 use std::sync::atomic::{AtomicU32, Ordering};
 
-use libc::c_int;
-
 /// This stunt allocator allows us to spot heap allocations in the child.
 struct PidChecking<A> {
     parent: A,
diff --git a/tests/ui/ret-non-nil.stderr b/tests/ui/ret-non-nil.stderr
index 17567c6016a..802900e61a3 100644
--- a/tests/ui/ret-non-nil.stderr
+++ b/tests/ui/ret-non-nil.stderr
@@ -5,6 +5,11 @@ LL | fn g() -> isize { return; }
    |           -----   ^^^^^^ return type is not `()`
    |           |
    |           expected `isize` because of this return type
+   |
+help: give the `return` a value of the expected type
+   |
+LL | fn g() -> isize { return 42; }
+   |                          ++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/return/suggest-a-value.rs b/tests/ui/return/suggest-a-value.rs
new file mode 100644
index 00000000000..7d23c0c44b7
--- /dev/null
+++ b/tests/ui/return/suggest-a-value.rs
@@ -0,0 +1,6 @@
+fn test() -> (i32,) {
+    return;
+    //~^ ERROR `return;` in a function whose return type is not `()`
+}
+
+fn main() {}
diff --git a/tests/ui/return/suggest-a-value.stderr b/tests/ui/return/suggest-a-value.stderr
new file mode 100644
index 00000000000..573ade7b712
--- /dev/null
+++ b/tests/ui/return/suggest-a-value.stderr
@@ -0,0 +1,16 @@
+error[E0069]: `return;` in a function whose return type is not `()`
+  --> $DIR/suggest-a-value.rs:2:5
+   |
+LL | fn test() -> (i32,) {
+   |              ------ expected `(i32,)` because of this return type
+LL |     return;
+   |     ^^^^^^ return type is not `()`
+   |
+help: give the `return` a value of the expected type
+   |
+LL |     return (42,);
+   |            +++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0069`.