diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index 3ddc7fce1b7..e8fca6f04ba 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -1366,7 +1366,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         generics: &Generics,
         itctx: ImplTraitContext<'_, 'hir>,
     ) -> GenericsCtor<'hir> {
-        // Error if `?Trait` bounds in where clauses don't refer directly to type paramters.
+        // Error if `?Trait` bounds in where clauses don't refer directly to type parameters.
         // Note: we used to clone these bounds directly onto the type parameter (and avoid lowering
         // these into hir when we lower thee where clauses), but this makes it quite difficult to
         // keep track of the Span info. Now, `add_implicitly_sized` in `AstConv` checks both param bounds and
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index 3f0ce7dea00..fa9fe905256 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -1992,7 +1992,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             .find_map(|constraint| {
                 if let ConstraintCategory::Predicate(predicate_span) = constraint.category {
                     // We currentl'y doesn't store the `DefId` in the `ConstraintCategory`
-                    // for perforamnce reasons. The error reporting code used by NLL only
+                    // for performances reasons. The error reporting code used by NLL only
                     // uses the span, so this doesn't cause any problems at the moment.
                     Some(ObligationCauseCode::BindingObligation(
                         CRATE_DEF_ID.to_def_id(),
diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs
index 31086a2acf8..8574cfae860 100644
--- a/compiler/rustc_builtin_macros/src/cfg_eval.rs
+++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs
@@ -201,7 +201,7 @@ impl CfgEval<'_, '_> {
 
         // Re-parse the tokens, setting the `capture_cfg` flag to save extra information
         // to the captured `AttrAnnotatedTokenStream` (specifically, we capture
-        // `AttrAnnotatedTokenTree::AttributesData` for all occurences of `#[cfg]` and `#[cfg_attr]`)
+        // `AttrAnnotatedTokenTree::AttributesData` for all occurrences of `#[cfg]` and `#[cfg_attr]`)
         let mut parser =
             rustc_parse::stream_to_parser(&self.cfg.sess.parse_sess, orig_tokens, None);
         parser.capture_cfg = true;
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 587453fd8e8..b36645ad37b 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -989,7 +989,7 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(
 
         // ... and otherwise we're processing a `*.dwp` packed dwarf file.
         //
-        // We cannot rely on the .o paths in the exectuable because they may have been
+        // We cannot rely on the .o paths in the executable because they may have been
         // remapped by --remap-path-prefix and therefore invalid, so we need to provide
         // the .o/.dwo paths explicitly.
         SplitDebuginfo::Packed => link_dwarf_object(sess, codegen_results, out_filename),
diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs
index 3fb56f42b8c..a838787381d 100644
--- a/compiler/rustc_codegen_ssa/src/back/linker.rs
+++ b/compiler/rustc_codegen_ssa/src/back/linker.rs
@@ -1338,7 +1338,7 @@ impl<'a> Linker for WasmLd<'a> {
         }
 
         // LLD will hide these otherwise-internal symbols since it only exports
-        // symbols explicity passed via the `--export` flags above and hides all
+        // symbols explicitly passed via the `--export` flags above and hides all
         // others. Various bits and pieces of tooling use this, so be sure these
         // symbols make their way out of the linker as well.
         self.cmd.arg("--export=__heap_base");
diff --git a/compiler/rustc_data_structures/src/sso/either_iter.rs b/compiler/rustc_data_structures/src/sso/either_iter.rs
index af8ffcf4c13..131eeef4582 100644
--- a/compiler/rustc_data_structures/src/sso/either_iter.rs
+++ b/compiler/rustc_data_structures/src/sso/either_iter.rs
@@ -7,7 +7,7 @@ use std::iter::Iterator;
 /// one of two specific implementations.
 ///
 /// Note: For most methods providing custom
-///       implementation may margianlly
+///       implementation may marginally
 ///       improve performance by avoiding
 ///       doing Left/Right match on every step
 ///       and doing it only once instead.
diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs
index d655f12f5e1..4c93d661fd2 100644
--- a/compiler/rustc_hir/src/definitions.rs
+++ b/compiler/rustc_hir/src/definitions.rs
@@ -50,7 +50,7 @@ impl DefPathTable {
             // Continuing with colliding DefPathHashes can lead to correctness
             // issues. We must abort compilation.
             //
-            // The likelyhood of such a collision is very small, so actually
+            // The likelihood of such a collision is very small, so actually
             // running into one could be indicative of a poor hash function
             // being used.
             //
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs
index bbbb0f79acc..d7e88d02595 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs
@@ -166,59 +166,61 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
             if lifetime_sub.name.is_elided() && lifetime_sup.name.is_elided() {
                 if let Some(anon_reg) = self.tcx().is_suitable_region(sub) {
                     let hir_id = self.tcx().hir().local_def_id_to_hir_id(anon_reg.def_id);
-                    if let hir::Node::Item(&hir::Item {
-                        kind: hir::ItemKind::Fn(_, ref generics, ..),
-                        ..
-                    }) = self.tcx().hir().get(hir_id)
-                    {
-                        let (suggestion_param_name, introduce_new) = generics
-                            .params
-                            .iter()
-                            .find(|p| matches!(p.kind, GenericParamKind::Lifetime { .. }))
-                            .and_then(|p| self.tcx().sess.source_map().span_to_snippet(p.span).ok())
-                            .map(|name| (name, false))
-                            .unwrap_or_else(|| ("'a".to_string(), true));
 
-                        let mut suggestions = vec![
-                            if let hir::LifetimeName::Underscore = lifetime_sub.name {
-                                (lifetime_sub.span, suggestion_param_name.clone())
-                            } else {
-                                (
-                                    lifetime_sub.span.shrink_to_hi(),
-                                    suggestion_param_name.clone() + " ",
-                                )
-                            },
-                            if let hir::LifetimeName::Underscore = lifetime_sup.name {
-                                (lifetime_sup.span, suggestion_param_name.clone())
-                            } else {
-                                (
-                                    lifetime_sup.span.shrink_to_hi(),
-                                    suggestion_param_name.clone() + " ",
-                                )
-                            },
-                        ];
+                    let node = self.tcx().hir().get(hir_id);
+                    let is_impl = matches!(&node, hir::Node::ImplItem(_));
+                    let generics = match node {
+                        hir::Node::Item(&hir::Item {
+                            kind: hir::ItemKind::Fn(_, ref generics, ..),
+                            ..
+                        })
+                        | hir::Node::TraitItem(&hir::TraitItem { ref generics, .. })
+                        | hir::Node::ImplItem(&hir::ImplItem { ref generics, .. }) => generics,
+                        _ => return,
+                    };
 
-                        if introduce_new {
-                            let new_param_suggestion = match &generics.params {
-                                [] => (generics.span, format!("<{}>", suggestion_param_name)),
-                                [first, ..] => (
-                                    first.span.shrink_to_lo(),
-                                    format!("{}, ", suggestion_param_name),
-                                ),
-                            };
+                    let (suggestion_param_name, introduce_new) = generics
+                        .params
+                        .iter()
+                        .find(|p| matches!(p.kind, GenericParamKind::Lifetime { .. }))
+                        .and_then(|p| self.tcx().sess.source_map().span_to_snippet(p.span).ok())
+                        .map(|name| (name, false))
+                        .unwrap_or_else(|| ("'a".to_string(), true));
 
-                            suggestions.push(new_param_suggestion);
-                        }
+                    let mut suggestions = vec![
+                        if let hir::LifetimeName::Underscore = lifetime_sub.name {
+                            (lifetime_sub.span, suggestion_param_name.clone())
+                        } else {
+                            (lifetime_sub.span.shrink_to_hi(), suggestion_param_name.clone() + " ")
+                        },
+                        if let hir::LifetimeName::Underscore = lifetime_sup.name {
+                            (lifetime_sup.span, suggestion_param_name.clone())
+                        } else {
+                            (lifetime_sup.span.shrink_to_hi(), suggestion_param_name.clone() + " ")
+                        },
+                    ];
 
-                        err.multipart_suggestion(
-                            "consider introducing a named lifetime parameter",
-                            suggestions,
-                            Applicability::MaybeIncorrect,
-                        );
-                        err.note(
-                            "each elided lifetime in input position becomes a distinct lifetime",
-                        );
+                    if introduce_new {
+                        let new_param_suggestion = match &generics.params {
+                            [] => (generics.span, format!("<{}>", suggestion_param_name)),
+                            [first, ..] => {
+                                (first.span.shrink_to_lo(), format!("{}, ", suggestion_param_name))
+                            }
+                        };
+
+                        suggestions.push(new_param_suggestion);
                     }
+
+                    let mut sugg = String::from("consider introducing a named lifetime parameter");
+                    if is_impl {
+                        sugg.push_str(" and update trait if needed");
+                    }
+                    err.multipart_suggestion(
+                        sugg.as_str(),
+                        suggestions,
+                        Applicability::MaybeIncorrect,
+                    );
+                    err.note("each elided lifetime in input position becomes a distinct lifetime");
                 }
             }
         }
diff --git a/compiler/rustc_mir_transform/src/const_debuginfo.rs b/compiler/rustc_mir_transform/src/const_debuginfo.rs
index 839d94167fe..ef4b27a15d8 100644
--- a/compiler/rustc_mir_transform/src/const_debuginfo.rs
+++ b/compiler/rustc_mir_transform/src/const_debuginfo.rs
@@ -55,10 +55,8 @@ fn find_optimization_oportunities<'tcx>(body: &Body<'tcx>) -> Vec<(Local, Consta
 
     let mut locals_to_debuginfo = BitSet::new_empty(body.local_decls.len());
     for debuginfo in &body.var_debug_info {
-        if let VarDebugInfoContents::Place(p) = debuginfo.value {
-            if let Some(l) = p.as_local() {
-                locals_to_debuginfo.insert(l);
-            }
+        if let VarDebugInfoContents::Place(p) = debuginfo.value && let Some(l) = p.as_local() {
+            locals_to_debuginfo.insert(l);
         }
     }
 
diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs
index 6075f572a65..c5ef1e10146 100644
--- a/compiler/rustc_mir_transform/src/const_prop.rs
+++ b/compiler/rustc_mir_transform/src/const_prop.rs
@@ -633,24 +633,22 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
     fn propagate_operand(&mut self, operand: &mut Operand<'tcx>) {
         match *operand {
             Operand::Copy(l) | Operand::Move(l) => {
-                if let Some(value) = self.get_const(l) {
-                    if self.should_const_prop(&value) {
-                        // FIXME(felix91gr): this code only handles `Scalar` cases.
-                        // For now, we're not handling `ScalarPair` cases because
-                        // doing so here would require a lot of code duplication.
-                        // We should hopefully generalize `Operand` handling into a fn,
-                        // and use it to do const-prop here and everywhere else
-                        // where it makes sense.
-                        if let interpret::Operand::Immediate(interpret::Immediate::Scalar(
-                            ScalarMaybeUninit::Scalar(scalar),
-                        )) = *value
-                        {
-                            *operand = self.operand_from_scalar(
-                                scalar,
-                                value.layout.ty,
-                                self.source_info.unwrap().span,
-                            );
-                        }
+                if let Some(value) = self.get_const(l) && self.should_const_prop(&value) {
+                    // FIXME(felix91gr): this code only handles `Scalar` cases.
+                    // For now, we're not handling `ScalarPair` cases because
+                    // doing so here would require a lot of code duplication.
+                    // We should hopefully generalize `Operand` handling into a fn,
+                    // and use it to do const-prop here and everywhere else
+                    // where it makes sense.
+                    if let interpret::Operand::Immediate(interpret::Immediate::Scalar(
+                        ScalarMaybeUninit::Scalar(scalar),
+                    )) = *value
+                    {
+                        *operand = self.operand_from_scalar(
+                            scalar,
+                            value.layout.ty,
+                            self.source_info.unwrap().span,
+                        );
                     }
                 }
             }
@@ -1086,15 +1084,13 @@ impl<'tcx> MutVisitor<'tcx> for ConstPropagator<'_, 'tcx> {
                 // This will return None if the above `const_prop` invocation only "wrote" a
                 // type whose creation requires no write. E.g. a generator whose initial state
                 // consists solely of uninitialized memory (so it doesn't capture any locals).
-                if let Some(ref value) = self.get_const(place) {
-                    if self.should_const_prop(value) {
-                        trace!("replacing {:?} with {:?}", rval, value);
-                        self.replace_with_const(rval, value, source_info);
-                        if can_const_prop == ConstPropMode::FullConstProp
-                            || can_const_prop == ConstPropMode::OnlyInsideOwnBlock
-                        {
-                            trace!("propagated into {:?}", place);
-                        }
+                if let Some(ref value) = self.get_const(place) && self.should_const_prop(value) {
+                    trace!("replacing {:?} with {:?}", rval, value);
+                    self.replace_with_const(rval, value, source_info);
+                    if can_const_prop == ConstPropMode::FullConstProp
+                        || can_const_prop == ConstPropMode::OnlyInsideOwnBlock
+                    {
+                        trace!("propagated into {:?}", place);
                     }
                 }
                 match can_const_prop {
diff --git a/compiler/rustc_mir_transform/src/coverage/debug.rs b/compiler/rustc_mir_transform/src/coverage/debug.rs
index 62e060c8e0c..8e28ed2426b 100644
--- a/compiler/rustc_mir_transform/src/coverage/debug.rs
+++ b/compiler/rustc_mir_transform/src/coverage/debug.rs
@@ -357,14 +357,12 @@ impl DebugCounters {
         if let Some(counters) = &self.some_counters {
             if let Some(DebugCounter { counter_kind, some_block_label }) = counters.get(&operand) {
                 if let CoverageKind::Expression { .. } = counter_kind {
-                    if let Some(block_label) = some_block_label {
-                        if debug_options().counter_format.block {
-                            return format!(
-                                "{}:({})",
-                                block_label,
-                                self.format_counter_kind(counter_kind)
-                            );
-                        }
+                    if let Some(label) = some_block_label && debug_options().counter_format.block {
+                        return format!(
+                            "{}:({})",
+                            label,
+                            self.format_counter_kind(counter_kind)
+                        );
                     }
                     return format!("({})", self.format_counter_kind(counter_kind));
                 }
diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs
index 27b9b6c2fa3..a36ba9300e4 100644
--- a/compiler/rustc_mir_transform/src/coverage/spans.rs
+++ b/compiler/rustc_mir_transform/src/coverage/spans.rs
@@ -191,16 +191,13 @@ impl CoverageSpan {
     /// If the span is part of a macro, and the macro is visible (expands directly to the given
     /// body_span), returns the macro name symbol.
     pub fn visible_macro(&self, body_span: Span) -> Option<Symbol> {
-        if let Some(current_macro) = self.current_macro() {
-            if self
-                .expn_span
-                .parent_callsite()
-                .unwrap_or_else(|| bug!("macro must have a parent"))
-                .ctxt()
-                == body_span.ctxt()
-            {
-                return Some(current_macro);
-            }
+        if let Some(current_macro) = self.current_macro() && self
+            .expn_span
+            .parent_callsite()
+            .unwrap_or_else(|| bug!("macro must have a parent"))
+            .ctxt() == body_span.ctxt()
+        {
+            return Some(current_macro);
         }
         None
     }
@@ -584,21 +581,19 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
     /// In either case, no more spans will match the span of `pending_dups`, so
     /// add the `pending_dups` if they don't overlap `curr`, and clear the list.
     fn check_pending_dups(&mut self) {
-        if let Some(dup) = self.pending_dups.last() {
-            if dup.span != self.prev().span {
-                debug!(
-                    "    SAME spans, but pending_dups are NOT THE SAME, so BCBs matched on \
-                    previous iteration, or prev started a new disjoint span"
-                );
-                if dup.span.hi() <= self.curr().span.lo() {
-                    let pending_dups = self.pending_dups.split_off(0);
-                    for dup in pending_dups.into_iter() {
-                        debug!("    ...adding at least one pending={:?}", dup);
-                        self.push_refined_span(dup);
-                    }
-                } else {
-                    self.pending_dups.clear();
+        if let Some(dup) = self.pending_dups.last() && dup.span != self.prev().span {
+            debug!(
+                "    SAME spans, but pending_dups are NOT THE SAME, so BCBs matched on \
+                previous iteration, or prev started a new disjoint span"
+            );
+            if dup.span.hi() <= self.curr().span.lo() {
+                let pending_dups = self.pending_dups.split_off(0);
+                for dup in pending_dups.into_iter() {
+                    debug!("    ...adding at least one pending={:?}", dup);
+                    self.push_refined_span(dup);
                 }
+            } else {
+                self.pending_dups.clear();
             }
         }
     }
diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs
index 7878d6eaab1..5d0b58e9c53 100644
--- a/compiler/rustc_mir_transform/src/dest_prop.rs
+++ b/compiler/rustc_mir_transform/src/dest_prop.rs
@@ -549,14 +549,15 @@ impl<'a> Conflicts<'a> {
                 target: _,
                 unwind: _,
             } => {
-                if let Some(place) = value.place() {
-                    if !place.is_indirect() && !dropped_place.is_indirect() {
-                        self.record_local_conflict(
-                            place.local,
-                            dropped_place.local,
-                            "DropAndReplace operand overlap",
-                        );
-                    }
+                if let Some(place) = value.place()
+                    && !place.is_indirect()
+                    && !dropped_place.is_indirect()
+                {
+                    self.record_local_conflict(
+                        place.local,
+                        dropped_place.local,
+                        "DropAndReplace operand overlap",
+                    );
                 }
             }
             TerminatorKind::Yield { value, resume: _, resume_arg, drop: _ } => {
@@ -614,14 +615,15 @@ impl<'a> Conflicts<'a> {
                             for op in operands {
                                 match op {
                                     InlineAsmOperand::In { reg: _, value } => {
-                                        if let Some(p) = value.place() {
-                                            if !p.is_indirect() && !dest_place.is_indirect() {
-                                                self.record_local_conflict(
-                                                    p.local,
-                                                    dest_place.local,
-                                                    "asm! operand overlap",
-                                                );
-                                            }
+                                        if let Some(p) = value.place()
+                                            && !p.is_indirect()
+                                            && !dest_place.is_indirect()
+                                        {
+                                            self.record_local_conflict(
+                                                p.local,
+                                                dest_place.local,
+                                                "asm! operand overlap",
+                                            );
                                         }
                                     }
                                     InlineAsmOperand::Out {
@@ -643,24 +645,26 @@ impl<'a> Conflicts<'a> {
                                         in_value,
                                         out_place,
                                     } => {
-                                        if let Some(place) = in_value.place() {
-                                            if !place.is_indirect() && !dest_place.is_indirect() {
-                                                self.record_local_conflict(
-                                                    place.local,
-                                                    dest_place.local,
-                                                    "asm! operand overlap",
-                                                );
-                                            }
+                                        if let Some(place) = in_value.place()
+                                            && !place.is_indirect()
+                                            && !dest_place.is_indirect()
+                                        {
+                                            self.record_local_conflict(
+                                                place.local,
+                                                dest_place.local,
+                                                "asm! operand overlap",
+                                            );
                                         }
 
-                                        if let Some(place) = out_place {
-                                            if !place.is_indirect() && !dest_place.is_indirect() {
-                                                self.record_local_conflict(
-                                                    place.local,
-                                                    dest_place.local,
-                                                    "asm! operand overlap",
-                                                );
-                                            }
+                                        if let Some(place) = out_place
+                                            && !place.is_indirect()
+                                            && !dest_place.is_indirect()
+                                        {
+                                            self.record_local_conflict(
+                                                place.local,
+                                                dest_place.local,
+                                                "asm! operand overlap",
+                                            );
                                         }
                                     }
                                     InlineAsmOperand::Out { reg: _, late: _, place: None }
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index cbd7c7964d7..23e5f0b4f30 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -724,12 +724,11 @@ impl<'tcx> Inliner<'tcx> {
         caller_body: &mut Body<'tcx>,
     ) -> Local {
         // Reuse the operand if it is a moved temporary.
-        if let Operand::Move(place) = &arg {
-            if let Some(local) = place.as_local() {
-                if caller_body.local_kind(local) == LocalKind::Temp {
-                    return local;
-                }
-            }
+        if let Operand::Move(place) = &arg
+            && let Some(local) = place.as_local()
+            && caller_body.local_kind(local) == LocalKind::Temp
+        {
+            return local;
         }
 
         // Otherwise, create a temporary for the argument.
diff --git a/compiler/rustc_mir_transform/src/instcombine.rs b/compiler/rustc_mir_transform/src/instcombine.rs
index 792ac68671e..385fcc43496 100644
--- a/compiler/rustc_mir_transform/src/instcombine.rs
+++ b/compiler/rustc_mir_transform/src/instcombine.rs
@@ -77,10 +77,8 @@ impl<'tcx> InstCombineContext<'tcx, '_> {
                     _ => None,
                 };
 
-                if let Some(new) = new {
-                    if self.should_combine(source_info, rvalue) {
-                        *rvalue = new;
-                    }
+                if let Some(new) = new && self.should_combine(source_info, rvalue) {
+                    *rvalue = new;
                 }
             }
 
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index c0c66daffa8..3b2332a6e31 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -1,16 +1,17 @@
+#![allow(rustc::potential_query_instability)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
 #![feature(crate_visibility_modifier)]
+#![feature(let_chains)]
 #![feature(let_else)]
 #![feature(map_try_insert)]
 #![feature(min_specialization)]
-#![feature(option_get_or_insert_default)]
-#![feature(once_cell)]
 #![feature(never_type)]
+#![feature(once_cell)]
+#![feature(option_get_or_insert_default)]
 #![feature(trusted_step)]
 #![feature(try_blocks)]
 #![recursion_limit = "256"]
-#![allow(rustc::potential_query_instability)]
 
 #[macro_use]
 extern crate tracing;
diff --git a/compiler/rustc_mir_transform/src/required_consts.rs b/compiler/rustc_mir_transform/src/required_consts.rs
index 1c48efd8b42..b87220a3aa4 100644
--- a/compiler/rustc_mir_transform/src/required_consts.rs
+++ b/compiler/rustc_mir_transform/src/required_consts.rs
@@ -14,10 +14,9 @@ impl<'a, 'tcx> RequiredConstsVisitor<'a, 'tcx> {
 
 impl<'tcx> Visitor<'tcx> for RequiredConstsVisitor<'_, 'tcx> {
     fn visit_constant(&mut self, constant: &Constant<'tcx>, _: Location) {
-        if let Some(ct) = constant.literal.const_for_ty() {
-            if let ConstKind::Unevaluated(_) = ct.val() {
-                self.required_consts.push(*constant);
-            }
+        let literal = constant.literal;
+        if let Some(ct) = literal.const_for_ty() && let ConstKind::Unevaluated(_) = ct.val() {
+            self.required_consts.push(*constant);
         }
     }
 }
diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs
index 5569334ff3d..7523b844101 100644
--- a/compiler/rustc_trait_selection/src/lib.rs
+++ b/compiler/rustc_trait_selection/src/lib.rs
@@ -10,19 +10,20 @@
 //!
 //! This API is completely unstable and subject to change.
 
+#![allow(rustc::potential_query_instability)]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![feature(bool_to_option)]
 #![feature(box_patterns)]
-#![feature(drain_filter)]
+#![feature(control_flow_enum)]
+#![feature(crate_visibility_modifier)]
 #![feature(derive_default_enum)]
+#![feature(drain_filter)]
 #![feature(hash_drain_filter)]
 #![feature(label_break_value)]
+#![feature(let_chains)]
 #![feature(let_else)]
 #![feature(never_type)]
-#![feature(crate_visibility_modifier)]
-#![feature(control_flow_enum)]
 #![recursion_limit = "512"] // For rustdoc
-#![allow(rustc::potential_query_instability)]
 
 #[macro_use]
 extern crate rustc_macros;
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 82c3f79a4fa..8e42a41c8cf 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -1098,42 +1098,43 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                     );
                 }
             }
-            if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..] {
-                if fields.len() == found_args.len() && is_closure {
-                    let sugg = format!(
-                        "|({}){}|",
-                        found_args
-                            .iter()
-                            .map(|arg| match arg {
-                                ArgKind::Arg(name, _) => name.to_owned(),
-                                _ => "_".to_owned(),
-                            })
-                            .collect::<Vec<String>>()
-                            .join(", "),
-                        // add type annotations if available
-                        if found_args.iter().any(|arg| match arg {
-                            ArgKind::Arg(_, ty) => ty != "_",
-                            _ => false,
-                        }) {
-                            format!(
-                                ": ({})",
-                                fields
-                                    .iter()
-                                    .map(|(_, ty)| ty.to_owned())
-                                    .collect::<Vec<String>>()
-                                    .join(", ")
-                            )
-                        } else {
-                            String::new()
-                        },
-                    );
-                    err.span_suggestion_verbose(
-                        found_span,
-                        "change the closure to accept a tuple instead of individual arguments",
-                        sugg,
-                        Applicability::MachineApplicable,
-                    );
-                }
+            if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..]
+                && fields.len() == found_args.len()
+                && is_closure
+            {
+                let sugg = format!(
+                    "|({}){}|",
+                    found_args
+                        .iter()
+                        .map(|arg| match arg {
+                            ArgKind::Arg(name, _) => name.to_owned(),
+                            _ => "_".to_owned(),
+                        })
+                        .collect::<Vec<String>>()
+                        .join(", "),
+                    // add type annotations if available
+                    if found_args.iter().any(|arg| match arg {
+                        ArgKind::Arg(_, ty) => ty != "_",
+                        _ => false,
+                    }) {
+                        format!(
+                            ": ({})",
+                            fields
+                                .iter()
+                                .map(|(_, ty)| ty.to_owned())
+                                .collect::<Vec<String>>()
+                                .join(", ")
+                        )
+                    } else {
+                        String::new()
+                    },
+                );
+                err.span_suggestion_verbose(
+                    found_span,
+                    "change the closure to accept a tuple instead of individual arguments",
+                    sugg,
+                    Applicability::MachineApplicable,
+                );
             }
         }
 
@@ -2231,16 +2232,13 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
             if obligated_types.iter().any(|ot| ot == &self_ty) {
                 return true;
             }
-            if let ty::Adt(def, substs) = self_ty.kind() {
-                if let [arg] = &substs[..] {
-                    if let ty::subst::GenericArgKind::Type(ty) = arg.unpack() {
-                        if let ty::Adt(inner_def, _) = ty.kind() {
-                            if inner_def == def {
-                                return true;
-                            }
-                        }
-                    }
-                }
+            if let ty::Adt(def, substs) = self_ty.kind()
+                && let [arg] = &substs[..]
+                && let ty::subst::GenericArgKind::Type(ty) = arg.unpack()
+                && let ty::Adt(inner_def, _) = ty.kind()
+                && inner_def == def
+            {
+                return true;
             }
         }
         false
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 45bfb2b1e94..7af2ba8b30f 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -891,23 +891,20 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                         }
                         if let Some(typeck_results) =
                             self.in_progress_typeck_results.map(|t| t.borrow())
+                            && let ty = typeck_results.expr_ty_adjusted(base)
+                            && let ty::FnDef(def_id, _substs) = ty.kind()
+                            && let Some(hir::Node::Item(hir::Item { span, ident, .. })) =
+                                hir.get_if_local(*def_id)
                         {
-                            let ty = typeck_results.expr_ty_adjusted(base);
-                            if let ty::FnDef(def_id, _substs) = ty.kind() {
-                                if let Some(hir::Node::Item(hir::Item { span, ident, .. })) =
-                                    hir.get_if_local(*def_id)
-                                {
-                                    err.span_suggestion_verbose(
-                                        span.shrink_to_lo(),
-                                        &format!(
-                                            "alternatively, consider making `fn {}` asynchronous",
-                                            ident
-                                        ),
-                                        "async ".to_string(),
-                                        Applicability::MaybeIncorrect,
-                                    );
-                                }
-                            }
+                            err.span_suggestion_verbose(
+                                span.shrink_to_lo(),
+                                &format!(
+                                    "alternatively, consider making `fn {}` asynchronous",
+                                    ident
+                                ),
+                                "async ".to_string(),
+                                Applicability::MaybeIncorrect,
+                            );
                         }
                     }
                 }
@@ -1000,34 +997,24 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
         span: Span,
         trait_pred: ty::PolyTraitPredicate<'tcx>,
     ) {
-        let is_empty_tuple =
-            |ty: ty::Binder<'tcx, Ty<'_>>| *ty.skip_binder().kind() == ty::Tuple(ty::List::empty());
-
         let hir = self.tcx.hir();
         let parent_node = hir.get_parent_node(obligation.cause.body_id);
         let node = hir.find(parent_node);
-        if let Some(hir::Node::Item(hir::Item {
-            kind: hir::ItemKind::Fn(sig, _, body_id), ..
-        })) = node
+        if let Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. })) = node
+            && let body = hir.body(*body_id)
+            && let hir::ExprKind::Block(blk, _) = &body.value.kind
+            && sig.decl.output.span().overlaps(span)
+            && blk.expr.is_none()
+            && *trait_pred.self_ty().skip_binder().kind() == ty::Tuple(ty::List::empty())
+            // FIXME(estebank): When encountering a method with a trait
+            // bound not satisfied in the return type with a body that has
+            // no return, suggest removal of semicolon on last statement.
+            // Once that is added, close #54771.
+            && let Some(stmt) = blk.stmts.last()
+            && let hir::StmtKind::Semi(_) = stmt.kind
         {
-            let body = hir.body(*body_id);
-            if let hir::ExprKind::Block(blk, _) = &body.value.kind {
-                if sig.decl.output.span().overlaps(span)
-                    && blk.expr.is_none()
-                    && is_empty_tuple(trait_pred.self_ty())
-                {
-                    // FIXME(estebank): When encountering a method with a trait
-                    // bound not satisfied in the return type with a body that has
-                    // no return, suggest removal of semicolon on last statement.
-                    // Once that is added, close #54771.
-                    if let Some(ref stmt) = blk.stmts.last() {
-                        if let hir::StmtKind::Semi(_) = stmt.kind {
-                            let sp = self.tcx.sess.source_map().end_point(stmt.span);
-                            err.span_label(sp, "consider removing this semicolon");
-                        }
-                    }
-                }
-            }
+            let sp = self.tcx.sess.source_map().end_point(stmt.span);
+            err.span_label(sp, "consider removing this semicolon");
         }
     }
 
@@ -2481,17 +2468,15 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                 debug!("suggest_await_before_try: try_trait_obligation {:?}", try_obligation);
                 if self.predicate_may_hold(&try_obligation)
                     && impls_future.must_apply_modulo_regions()
+                    && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
+                    && snippet.ends_with('?')
                 {
-                    if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
-                        if snippet.ends_with('?') {
-                            err.span_suggestion_verbose(
-                                span.with_hi(span.hi() - BytePos(1)).shrink_to_hi(),
-                                "consider `await`ing on the `Future`",
-                                ".await".to_string(),
-                                Applicability::MaybeIncorrect,
-                            );
-                        }
-                    }
+                    err.span_suggestion_verbose(
+                        span.with_hi(span.hi() - BytePos(1)).shrink_to_hi(),
+                        "consider `await`ing on the `Future`",
+                        ".await".to_string(),
+                        Applicability::MaybeIncorrect,
+                    );
                 }
             }
         }
diff --git a/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs
index b05dbbe898a..7fbdd3689a7 100644
--- a/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs
+++ b/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs
@@ -91,10 +91,8 @@ impl<'tcx> OnUnimplementedDirective {
                     )
                 })?;
             attr::eval_condition(cond, &tcx.sess.parse_sess, Some(tcx.features()), &mut |item| {
-                if let Some(symbol) = item.value_str() {
-                    if parse_value(symbol).is_err() {
-                        errored = true;
-                    }
+                if let Some(symbol) = item.value_str() && parse_value(symbol).is_err() {
+                    errored = true;
                 }
                 true
             });
@@ -232,24 +230,22 @@ impl<'tcx> OnUnimplementedDirective {
             options.iter().filter_map(|(k, v)| v.as_ref().map(|v| (*k, v.to_owned()))).collect();
 
         for command in self.subcommands.iter().chain(Some(self)).rev() {
-            if let Some(ref condition) = command.condition {
-                if !attr::eval_condition(
-                    condition,
-                    &tcx.sess.parse_sess,
-                    Some(tcx.features()),
-                    &mut |c| {
-                        c.ident().map_or(false, |ident| {
-                            let value = c.value_str().map(|s| {
-                                OnUnimplementedFormatString(s).format(tcx, trait_ref, &options_map)
-                            });
+            if let Some(ref condition) = command.condition && !attr::eval_condition(
+                condition,
+                &tcx.sess.parse_sess,
+                Some(tcx.features()),
+                &mut |c| {
+                    c.ident().map_or(false, |ident| {
+                        let value = c.value_str().map(|s| {
+                            OnUnimplementedFormatString(s).format(tcx, trait_ref, &options_map)
+                        });
 
-                            options.contains(&(ident.name, value))
-                        })
-                    },
-                ) {
-                    debug!("evaluate: skipping {:?} due to condition", command);
-                    continue;
-                }
+                        options.contains(&(ident.name, value))
+                    })
+                },
+            ) {
+                debug!("evaluate: skipping {:?} due to condition", command);
+                continue;
             }
             debug!("evaluate: {:?} succeeded", command);
             if let Some(ref message_) = command.message {
diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
index 066f3ffada5..435d709d37e 100644
--- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
@@ -43,21 +43,19 @@ impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> {
         let c_ty = self.infcx.canonicalize_query(self.param_env.and(ty), &mut orig_values);
         let span = self.cause.span;
         debug!("c_ty = {:?}", c_ty);
-        if let Ok(result) = tcx.dropck_outlives(c_ty) {
-            if result.is_proven() {
-                if let Ok(InferOk { value, obligations }) =
-                    self.infcx.instantiate_query_response_and_region_obligations(
-                        self.cause,
-                        self.param_env,
-                        &orig_values,
-                        result,
-                    )
-                {
-                    let ty = self.infcx.resolve_vars_if_possible(ty);
-                    let kinds = value.into_kinds_reporting_overflows(tcx, span, ty);
-                    return InferOk { value: kinds, obligations };
-                }
-            }
+        if let Ok(result) = tcx.dropck_outlives(c_ty)
+            && result.is_proven()
+            && let Ok(InferOk { value, obligations }) =
+                self.infcx.instantiate_query_response_and_region_obligations(
+                    self.cause,
+                    self.param_env,
+                    &orig_values,
+                    result,
+                )
+        {
+            let ty = self.infcx.resolve_vars_if_possible(ty);
+            let kinds = value.into_kinds_reporting_overflows(tcx, span, ty);
+            return InferOk { value: kinds, obligations };
         }
 
         // Errors and ambiuity in dropck occur in two cases:
diff --git a/compiler/rustc_trait_selection/src/traits/relationships.rs b/compiler/rustc_trait_selection/src/traits/relationships.rs
index aea44841b8f..b13646ba1a0 100644
--- a/compiler/rustc_trait_selection/src/traits/relationships.rs
+++ b/compiler/rustc_trait_selection/src/traits/relationships.rs
@@ -12,50 +12,38 @@ pub(crate) fn update<'tcx, T>(
     T: TraitEngine<'tcx>,
 {
     // (*) binder skipped
-    if let ty::PredicateKind::Trait(predicate) = obligation.predicate.kind().skip_binder() {
-        if let Some(ty) =
-            infcx.shallow_resolve(predicate.self_ty()).ty_vid().map(|t| infcx.root_var(t))
-        {
-            if infcx
-                .tcx
-                .lang_items()
-                .sized_trait()
-                .map_or(false, |st| st != predicate.trait_ref.def_id)
-            {
-                let new_self_ty = infcx.tcx.types.unit;
+    if let ty::PredicateKind::Trait(tpred) = obligation.predicate.kind().skip_binder()
+        && let Some(ty) = infcx.shallow_resolve(tpred.self_ty()).ty_vid().map(|t| infcx.root_var(t))
+        && infcx.tcx.lang_items().sized_trait().map_or(false, |st| st != tpred.trait_ref.def_id)
+    {
+        let new_self_ty = infcx.tcx.types.unit;
 
-                let trait_ref = ty::TraitRef {
-                    substs: infcx
-                        .tcx
-                        .mk_substs_trait(new_self_ty, &predicate.trait_ref.substs[1..]),
-                    ..predicate.trait_ref
-                };
+        let trait_ref = ty::TraitRef {
+            substs: infcx.tcx.mk_substs_trait(new_self_ty, &tpred.trait_ref.substs[1..]),
+            ..tpred.trait_ref
+        };
 
-                // Then contstruct a new obligation with Self = () added
-                // to the ParamEnv, and see if it holds.
-                let o = rustc_infer::traits::Obligation::new(
-                    ObligationCause::dummy(),
-                    obligation.param_env,
-                    obligation
-                        .predicate
-                        .kind()
-                        .map_bound(|_| {
-                            // (*) binder moved here
-                            ty::PredicateKind::Trait(ty::TraitPredicate {
-                                trait_ref,
-                                constness: predicate.constness,
-                                polarity: predicate.polarity,
-                            })
-                        })
-                        .to_predicate(infcx.tcx),
-                );
-                // Don't report overflow errors. Otherwise equivalent to may_hold.
-                if let Ok(result) = infcx.probe(|_| infcx.evaluate_obligation(&o)) {
-                    if result.may_apply() {
-                        engine.relationships().entry(ty).or_default().self_in_trait = true;
-                    }
-                }
-            }
+        // Then contstruct a new obligation with Self = () added
+        // to the ParamEnv, and see if it holds.
+        let o = rustc_infer::traits::Obligation::new(
+            ObligationCause::dummy(),
+            obligation.param_env,
+            obligation
+                .predicate
+                .kind()
+                .map_bound(|_| {
+                    // (*) binder moved here
+                    ty::PredicateKind::Trait(ty::TraitPredicate {
+                        trait_ref,
+                        constness: tpred.constness,
+                        polarity: tpred.polarity,
+                    })
+                })
+                .to_predicate(infcx.tcx),
+        );
+        // Don't report overflow errors. Otherwise equivalent to may_hold.
+        if let Ok(result) = infcx.probe(|_| infcx.evaluate_obligation(&o)) && result.may_apply() {
+            engine.relationships().entry(ty).or_default().self_in_trait = true;
         }
     }
 
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 8bcb1ccb584..f3c7642f7a3 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -579,24 +579,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                                     previous_stack,
                                     subobligations,
                                 );
-                                if let Ok(res) = res {
-                                    if res == EvaluatedToOk || res == EvaluatedToOkModuloRegions {
-                                        if let Some(key) =
-                                            ProjectionCacheKey::from_poly_projection_predicate(
-                                                self, data,
-                                            )
-                                        {
-                                            // If the result is something that we can cache, then mark this
-                                            // entry as 'complete'. This will allow us to skip evaluating the
-                                            // suboligations at all the next time we evaluate the projection
-                                            // predicate.
-                                            self.infcx
-                                                .inner
-                                                .borrow_mut()
-                                                .projection_cache()
-                                                .complete(key, res);
-                                        }
-                                    }
+                                if let Ok(eval_rslt) = res
+                                    && (eval_rslt == EvaluatedToOk || eval_rslt == EvaluatedToOkModuloRegions)
+                                    && let Some(key) =
+                                        ProjectionCacheKey::from_poly_projection_predicate(
+                                            self, data,
+                                        )
+                                {
+                                    // If the result is something that we can cache, then mark this
+                                    // entry as 'complete'. This will allow us to skip evaluating the
+                                    // suboligations at all the next time we evaluate the projection
+                                    // predicate.
+                                    self.infcx
+                                        .inner
+                                        .borrow_mut()
+                                        .projection_cache()
+                                        .complete(key, eval_rslt);
                                 }
                                 res
                             }
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index 7da5c50d230..943f36efc15 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -224,36 +224,30 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>(
             // projection coming from another associated type. See
             // `src/test/ui/associated-types/point-at-type-on-obligation-failure.rs` and
             // `traits-assoc-type-in-supertrait-bad.rs`.
-            if let Some(ty::Projection(projection_ty)) = proj.term.ty().map(|ty| ty.kind()) {
-                if let Some(&impl_item_id) =
+            if let Some(ty::Projection(projection_ty)) = proj.term.ty().map(|ty| ty.kind())
+                && let Some(&impl_item_id) =
                     tcx.impl_item_implementor_ids(impl_def_id).get(&projection_ty.item_def_id)
-                {
-                    if let Some(impl_item_span) = items
-                        .iter()
-                        .find(|item| item.id.def_id.to_def_id() == impl_item_id)
-                        .map(fix_span)
-                    {
-                        cause.span = impl_item_span;
-                    }
-                }
+                && let Some(impl_item_span) = items
+                    .iter()
+                    .find(|item| item.id.def_id.to_def_id() == impl_item_id)
+                    .map(fix_span)
+            {
+                cause.span = impl_item_span;
             }
         }
         ty::PredicateKind::Trait(pred) => {
             // An associated item obligation born out of the `trait` failed to be met. An example
             // can be seen in `ui/associated-types/point-at-type-on-obligation-failure-2.rs`.
             debug!("extended_cause_with_original_assoc_item_obligation trait proj {:?}", pred);
-            if let ty::Projection(ty::ProjectionTy { item_def_id, .. }) = *pred.self_ty().kind() {
-                if let Some(&impl_item_id) =
+            if let ty::Projection(ty::ProjectionTy { item_def_id, .. }) = *pred.self_ty().kind()
+                && let Some(&impl_item_id) =
                     tcx.impl_item_implementor_ids(impl_def_id).get(&item_def_id)
-                {
-                    if let Some(impl_item_span) = items
-                        .iter()
-                        .find(|item| item.id.def_id.to_def_id() == impl_item_id)
-                        .map(fix_span)
-                    {
-                        cause.span = impl_item_span;
-                    }
-                }
+                && let Some(impl_item_span) = items
+                    .iter()
+                    .find(|item| item.id.def_id.to_def_id() == impl_item_id)
+                    .map(fix_span)
+            {
+                cause.span = impl_item_span;
             }
         }
         _ => {}
diff --git a/library/std/src/os/raw/char.md b/library/core/src/ffi/c_char.md
similarity index 91%
rename from library/std/src/os/raw/char.md
rename to library/core/src/ffi/c_char.md
index 375d070516e..b262a3663b3 100644
--- a/library/std/src/os/raw/char.md
+++ b/library/core/src/ffi/c_char.md
@@ -2,8 +2,7 @@ Equivalent to C's `char` type.
 
 [C's `char` type] is completely unlike [Rust's `char` type]; while Rust's type represents a unicode scalar value, C's `char` type is just an ordinary integer. On modern architectures this type will always be either [`i8`] or [`u8`], as they use byte-addresses memory with 8-bit bytes.
 
-C chars are most commonly used to make C strings. Unlike Rust, where the length of a string is included alongside the string, C strings mark the end of a string with the character `'\0'`. See [`CStr`] for more information.
+C chars are most commonly used to make C strings. Unlike Rust, where the length of a string is included alongside the string, C strings mark the end of a string with the character `'\0'`. See `CStr` for more information.
 
 [C's `char` type]: https://en.wikipedia.org/wiki/C_data_types#Basic_types
 [Rust's `char` type]: char
-[`CStr`]: crate::ffi::CStr
diff --git a/library/std/src/os/raw/double.md b/library/core/src/ffi/c_double.md
similarity index 100%
rename from library/std/src/os/raw/double.md
rename to library/core/src/ffi/c_double.md
diff --git a/library/std/src/os/raw/float.md b/library/core/src/ffi/c_float.md
similarity index 100%
rename from library/std/src/os/raw/float.md
rename to library/core/src/ffi/c_float.md
diff --git a/library/std/src/os/raw/int.md b/library/core/src/ffi/c_int.md
similarity index 100%
rename from library/std/src/os/raw/int.md
rename to library/core/src/ffi/c_int.md
diff --git a/library/std/src/os/raw/long.md b/library/core/src/ffi/c_long.md
similarity index 100%
rename from library/std/src/os/raw/long.md
rename to library/core/src/ffi/c_long.md
diff --git a/library/std/src/os/raw/longlong.md b/library/core/src/ffi/c_longlong.md
similarity index 100%
rename from library/std/src/os/raw/longlong.md
rename to library/core/src/ffi/c_longlong.md
diff --git a/library/std/src/os/raw/schar.md b/library/core/src/ffi/c_schar.md
similarity index 100%
rename from library/std/src/os/raw/schar.md
rename to library/core/src/ffi/c_schar.md
diff --git a/library/std/src/os/raw/short.md b/library/core/src/ffi/c_short.md
similarity index 100%
rename from library/std/src/os/raw/short.md
rename to library/core/src/ffi/c_short.md
diff --git a/library/std/src/os/raw/uchar.md b/library/core/src/ffi/c_uchar.md
similarity index 100%
rename from library/std/src/os/raw/uchar.md
rename to library/core/src/ffi/c_uchar.md
diff --git a/library/std/src/os/raw/uint.md b/library/core/src/ffi/c_uint.md
similarity index 100%
rename from library/std/src/os/raw/uint.md
rename to library/core/src/ffi/c_uint.md
diff --git a/library/std/src/os/raw/ulong.md b/library/core/src/ffi/c_ulong.md
similarity index 100%
rename from library/std/src/os/raw/ulong.md
rename to library/core/src/ffi/c_ulong.md
diff --git a/library/std/src/os/raw/ulonglong.md b/library/core/src/ffi/c_ulonglong.md
similarity index 100%
rename from library/std/src/os/raw/ulonglong.md
rename to library/core/src/ffi/c_ulonglong.md
diff --git a/library/std/src/os/raw/ushort.md b/library/core/src/ffi/c_ushort.md
similarity index 100%
rename from library/std/src/os/raw/ushort.md
rename to library/core/src/ffi/c_ushort.md
diff --git a/library/core/src/ffi/c_void.md b/library/core/src/ffi/c_void.md
new file mode 100644
index 00000000000..ee7403aa040
--- /dev/null
+++ b/library/core/src/ffi/c_void.md
@@ -0,0 +1,16 @@
+Equivalent to C's `void` type when used as a [pointer].
+
+In essence, `*const c_void` is equivalent to C's `const void*`
+and `*mut c_void` is equivalent to C's `void*`. That said, this is
+*not* the same as C's `void` return type, which is Rust's `()` type.
+
+To model pointers to opaque types in FFI, until `extern type` is
+stabilized, it is recommended to use a newtype wrapper around an empty
+byte array. See the [Nomicon] for details.
+
+One could use `std::os::raw::c_void` if they want to support old Rust
+compiler down to 1.1.0. After Rust 1.30.0, it was re-exported by
+this definition. For more information, please read [RFC 2521].
+
+[Nomicon]: https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs
+[RFC 2521]: https://github.com/rust-lang/rfcs/blob/master/text/2521-c_void-reunification.md
diff --git a/library/core/src/ffi.rs b/library/core/src/ffi/mod.rs
similarity index 67%
rename from library/core/src/ffi.rs
rename to library/core/src/ffi/mod.rs
index 9c4cf89b6bc..e5255686ff9 100644
--- a/library/core/src/ffi.rs
+++ b/library/core/src/ffi/mod.rs
@@ -1,28 +1,157 @@
+//! Platform-specific types, as defined by C.
+//!
+//! Code that interacts via FFI will almost certainly be using the
+//! base types provided by C, which aren't nearly as nicely defined
+//! as Rust's primitive types. This module provides types which will
+//! match those defined by C, so that code that interacts with C will
+//! refer to the correct types.
+
 #![stable(feature = "", since = "1.30.0")]
 #![allow(non_camel_case_types)]
 
-//! Utilities related to foreign function interface (FFI) bindings.
-
 use crate::fmt;
 use crate::marker::PhantomData;
+use crate::num::*;
 use crate::ops::{Deref, DerefMut};
 
-/// Equivalent to C's `void` type when used as a [pointer].
+macro_rules! type_alias_no_nz {
+    {
+      $Docfile:tt, $Alias:ident = $Real:ty;
+      $( $Cfg:tt )*
+    } => {
+        #[doc = include_str!($Docfile)]
+        $( $Cfg )*
+        #[unstable(feature = "core_ffi_c", issue = "94501")]
+        pub type $Alias = $Real;
+    }
+}
+
+// To verify that the NonZero types in this file's macro invocations correspond
+//
+//  perl -n < library/std/src/os/raw/mod.rs -e 'next unless m/type_alias\!/; die "$_ ?" unless m/, (c_\w+) = (\w+), NonZero_(\w+) = NonZero(\w+)/; die "$_ ?" unless $3 eq $1 and $4 eq ucfirst $2'
+//
+// NB this does not check that the main c_* types are right.
+
+macro_rules! type_alias {
+    {
+      $Docfile:tt, $Alias:ident = $Real:ty, $NZAlias:ident = $NZReal:ty;
+      $( $Cfg:tt )*
+    } => {
+        type_alias_no_nz! { $Docfile, $Alias = $Real; $( $Cfg )* }
+
+        #[doc = concat!("Type alias for `NonZero` version of [`", stringify!($Alias), "`]")]
+        #[unstable(feature = "raw_os_nonzero", issue = "82363")]
+        $( $Cfg )*
+        pub type $NZAlias = $NZReal;
+    }
+}
+
+type_alias! { "c_char.md", c_char = c_char_definition::c_char, NonZero_c_char = c_char_definition::NonZero_c_char;
+// Make this type alias appear cfg-dependent so that Clippy does not suggest
+// replacing `0 as c_char` with `0_i8`/`0_u8`. This #[cfg(all())] can be removed
+// after the false positive in https://github.com/rust-lang/rust-clippy/issues/8093
+// is fixed.
+#[cfg(all())]
+#[doc(cfg(all()))] }
+type_alias! { "c_schar.md", c_schar = i8, NonZero_c_schar = NonZeroI8; }
+type_alias! { "c_uchar.md", c_uchar = u8, NonZero_c_uchar = NonZeroU8; }
+type_alias! { "c_short.md", c_short = i16, NonZero_c_short = NonZeroI16; }
+type_alias! { "c_ushort.md", c_ushort = u16, NonZero_c_ushort = NonZeroU16; }
+type_alias! { "c_int.md", c_int = i32, NonZero_c_int = NonZeroI32; }
+type_alias! { "c_uint.md", c_uint = u32, NonZero_c_uint = NonZeroU32; }
+type_alias! { "c_long.md", c_long = i32, NonZero_c_long = NonZeroI32;
+#[doc(cfg(all()))]
+#[cfg(any(target_pointer_width = "32", windows))] }
+type_alias! { "c_ulong.md", c_ulong = u32, NonZero_c_ulong = NonZeroU32;
+#[doc(cfg(all()))]
+#[cfg(any(target_pointer_width = "32", windows))] }
+type_alias! { "c_long.md", c_long = i64, NonZero_c_long = NonZeroI64;
+#[doc(cfg(all()))]
+#[cfg(all(target_pointer_width = "64", not(windows)))] }
+type_alias! { "c_ulong.md", c_ulong = u64, NonZero_c_ulong = NonZeroU64;
+#[doc(cfg(all()))]
+#[cfg(all(target_pointer_width = "64", not(windows)))] }
+type_alias! { "c_longlong.md", c_longlong = i64, NonZero_c_longlong = NonZeroI64; }
+type_alias! { "c_ulonglong.md", c_ulonglong = u64, NonZero_c_ulonglong = NonZeroU64; }
+type_alias_no_nz! { "c_float.md", c_float = f32; }
+type_alias_no_nz! { "c_double.md", c_double = f64; }
+
+/// Equivalent to C's `size_t` type, from `stddef.h` (or `cstddef` for C++).
 ///
-/// In essence, `*const c_void` is equivalent to C's `const void*`
-/// and `*mut c_void` is equivalent to C's `void*`. That said, this is
-/// *not* the same as C's `void` return type, which is Rust's `()` type.
+/// This type is currently always [`usize`], however in the future there may be
+/// platforms where this is not the case.
+#[unstable(feature = "c_size_t", issue = "88345")]
+pub type c_size_t = usize;
+
+/// Equivalent to C's `ptrdiff_t` type, from `stddef.h` (or `cstddef` for C++).
 ///
-/// To model pointers to opaque types in FFI, until `extern type` is
-/// stabilized, it is recommended to use a newtype wrapper around an empty
-/// byte array. See the [Nomicon] for details.
+/// This type is currently always [`isize`], however in the future there may be
+/// platforms where this is not the case.
+#[unstable(feature = "c_size_t", issue = "88345")]
+pub type c_ptrdiff_t = isize;
+
+/// Equivalent to C's `ssize_t` (on POSIX) or `SSIZE_T` (on Windows) type.
 ///
-/// One could use `std::os::raw::c_void` if they want to support old Rust
-/// compiler down to 1.1.0. After Rust 1.30.0, it was re-exported by
-/// this definition. For more information, please read [RFC 2521].
-///
-/// [Nomicon]: https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs
-/// [RFC 2521]: https://github.com/rust-lang/rfcs/blob/master/text/2521-c_void-reunification.md
+/// This type is currently always [`isize`], however in the future there may be
+/// platforms where this is not the case.
+#[unstable(feature = "c_size_t", issue = "88345")]
+pub type c_ssize_t = isize;
+
+mod c_char_definition {
+    cfg_if! {
+        // These are the targets on which c_char is unsigned.
+        if #[cfg(any(
+            all(
+                target_os = "linux",
+                any(
+                    target_arch = "aarch64",
+                    target_arch = "arm",
+                    target_arch = "hexagon",
+                    target_arch = "powerpc",
+                    target_arch = "powerpc64",
+                    target_arch = "s390x",
+                    target_arch = "riscv64",
+                    target_arch = "riscv32"
+                )
+            ),
+            all(target_os = "android", any(target_arch = "aarch64", target_arch = "arm")),
+            all(target_os = "l4re", target_arch = "x86_64"),
+            all(
+                target_os = "freebsd",
+                any(
+                    target_arch = "aarch64",
+                    target_arch = "arm",
+                    target_arch = "powerpc",
+                    target_arch = "powerpc64",
+                    target_arch = "riscv64"
+                )
+            ),
+            all(
+                target_os = "netbsd",
+                any(target_arch = "aarch64", target_arch = "arm", target_arch = "powerpc")
+            ),
+            all(target_os = "openbsd", target_arch = "aarch64"),
+            all(
+                target_os = "vxworks",
+                any(
+                    target_arch = "aarch64",
+                    target_arch = "arm",
+                    target_arch = "powerpc64",
+                    target_arch = "powerpc"
+                )
+            ),
+            all(target_os = "fuchsia", target_arch = "aarch64")
+        ))] {
+            pub type c_char = u8;
+            pub type NonZero_c_char = crate::num::NonZeroU8;
+        } else {
+            // On every other target, c_char is signed.
+            pub type c_char = i8;
+            pub type NonZero_c_char = crate::num::NonZeroI8;
+        }
+    }
+}
+
 // N.B., for LLVM to recognize the void pointer type and by extension
 //     functions like malloc(), we need to have it represented as i8* in
 //     LLVM bitcode. The enum used here ensures this and prevents misuse
@@ -31,6 +160,7 @@ use crate::ops::{Deref, DerefMut};
 //     otherwise and we need at least one variant as otherwise the enum
 //     would be uninhabited and at least dereferencing such pointers would
 //     be UB.
+#[doc = include_str!("c_void.md")]
 #[repr(u8)]
 #[stable(feature = "core_c_void", since = "1.30.0")]
 pub enum c_void {
diff --git a/library/core/src/internal_macros.rs b/library/core/src/internal_macros.rs
index 9c6acfb1e8c..417ed51c6b6 100644
--- a/library/core/src/internal_macros.rs
+++ b/library/core/src/internal_macros.rs
@@ -187,3 +187,96 @@ macro_rules! impl_fn_for_zst {
         )+
     }
 }
+
+/// A macro for defining `#[cfg]` if-else statements.
+///
+/// `cfg_if` is similar to the `if/elif` C preprocessor macro by allowing definition of a cascade
+/// of `#[cfg]` cases, emitting the implementation which matches first.
+///
+/// This allows you to conveniently provide a long list `#[cfg]`'d blocks of code without having to
+/// rewrite each clause multiple times.
+///
+/// # Example
+///
+/// ```
+/// cfg_if! {
+///     if #[cfg(unix)] {
+///         fn foo() { /* unix specific functionality */ }
+///     } else if #[cfg(target_pointer_width = "32")] {
+///         fn foo() { /* non-unix, 32-bit functionality */ }
+///     } else {
+///         fn foo() { /* fallback implementation */ }
+///     }
+/// }
+///
+/// # fn main() {}
+/// ```
+// This is a copy of `cfg_if!` from the `cfg_if` crate.
+// The recursive invocations should use $crate if this is ever exported.
+macro_rules! cfg_if {
+    // match if/else chains with a final `else`
+    (
+        $(
+            if #[cfg( $i_meta:meta )] { $( $i_tokens:tt )* }
+        ) else+
+        else { $( $e_tokens:tt )* }
+    ) => {
+        cfg_if! {
+            @__items () ;
+            $(
+                (( $i_meta ) ( $( $i_tokens )* )) ,
+            )+
+            (() ( $( $e_tokens )* )) ,
+        }
+    };
+
+    // match if/else chains lacking a final `else`
+    (
+        if #[cfg( $i_meta:meta )] { $( $i_tokens:tt )* }
+        $(
+            else if #[cfg( $e_meta:meta )] { $( $e_tokens:tt )* }
+        )*
+    ) => {
+        cfg_if! {
+            @__items () ;
+            (( $i_meta ) ( $( $i_tokens )* )) ,
+            $(
+                (( $e_meta ) ( $( $e_tokens )* )) ,
+            )*
+        }
+    };
+
+    // Internal and recursive macro to emit all the items
+    //
+    // Collects all the previous cfgs in a list at the beginning, so they can be
+    // negated. After the semicolon is all the remaining items.
+    (@__items ( $( $_:meta , )* ) ; ) => {};
+    (
+        @__items ( $( $no:meta , )* ) ;
+        (( $( $yes:meta )? ) ( $( $tokens:tt )* )) ,
+        $( $rest:tt , )*
+    ) => {
+        // Emit all items within one block, applying an appropriate #[cfg]. The
+        // #[cfg] will require all `$yes` matchers specified and must also negate
+        // all previous matchers.
+        #[cfg(all(
+            $( $yes , )?
+            not(any( $( $no ),* ))
+        ))]
+        cfg_if! { @__identity $( $tokens )* }
+
+        // Recurse to emit all other items in `$rest`, and when we do so add all
+        // our `$yes` matchers to the list of `$no` matchers as future emissions
+        // will have to negate everything we just matched as well.
+        cfg_if! {
+            @__items ( $( $no , )* $( $yes , )? ) ;
+            $( $rest , )*
+        }
+    };
+
+    // Internal macro to make __apply work out right for different match types,
+    // because of how macros match/expand stuff.
+    (@__identity $( $tokens:tt )* ) => {
+        $( $tokens )*
+    };
+}
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 1e0d9b79b9f..4603b5aae20 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -261,6 +261,7 @@
 #![feature(const_socketaddr)]
 #![feature(const_trait_impl)]
 #![feature(container_error_extra)]
+#![feature(core_ffi_c)]
 #![feature(core_intrinsics)]
 #![feature(core_panic)]
 #![feature(custom_test_frameworks)]
@@ -315,6 +316,7 @@
 #![feature(prelude_import)]
 #![feature(ptr_as_uninit)]
 #![feature(ptr_internals)]
+#![feature(raw_os_nonzero)]
 #![feature(rustc_attrs)]
 #![feature(rustc_private)]
 #![feature(saturating_int_impl)]
diff --git a/library/std/src/os/raw/mod.rs b/library/std/src/os/raw/mod.rs
index b6d5199341c..19d0ffb2e39 100644
--- a/library/std/src/os/raw/mod.rs
+++ b/library/std/src/os/raw/mod.rs
@@ -1,156 +1,31 @@
-//! Platform-specific types, as defined by C.
-//!
-//! Code that interacts via FFI will almost certainly be using the
-//! base types provided by C, which aren't nearly as nicely defined
-//! as Rust's primitive types. This module provides types which will
-//! match those defined by C, so that code that interacts with C will
-//! refer to the correct types.
+//! Compatibility module for C platform-specific types. Use [`core::ffi`] instead.
 
 #![stable(feature = "raw_os", since = "1.1.0")]
 
 #[cfg(test)]
 mod tests;
 
-use core::num::*;
-
-macro_rules! type_alias_no_nz {
-    {
-      $Docfile:tt, $Alias:ident = $Real:ty;
-      $( $Cfg:tt )*
-    } => {
-        #[doc = include_str!($Docfile)]
-        $( $Cfg )*
+macro_rules! alias_core_ffi {
+    ($($t:ident)*) => {$(
         #[stable(feature = "raw_os", since = "1.1.0")]
-        pub type $Alias = $Real;
-    }
+        #[doc = include_str!(concat!("../../../../core/src/ffi/", stringify!($t), ".md"))]
+        // Make this type alias appear cfg-dependent so that Clippy does not suggest
+        // replacing expressions like `0 as c_char` with `0_i8`/`0_u8`. This #[cfg(all())] can be
+        // removed after the false positive in https://github.com/rust-lang/rust-clippy/issues/8093
+        // is fixed.
+        #[cfg(all())]
+        #[doc(cfg(all()))]
+        pub type $t = core::ffi::$t;
+    )*}
 }
 
-// To verify that the NonZero types in this file's macro invocations correspond
-//
-//  perl -n < library/std/src/os/raw/mod.rs -e 'next unless m/type_alias\!/; die "$_ ?" unless m/, (c_\w+) = (\w+), NonZero_(\w+) = NonZero(\w+)/; die "$_ ?" unless $3 eq $1 and $4 eq ucfirst $2'
-//
-// NB this does not check that the main c_* types are right.
-
-macro_rules! type_alias {
-    {
-      $Docfile:tt, $Alias:ident = $Real:ty, $NZAlias:ident = $NZReal:ty;
-      $( $Cfg:tt )*
-    } => {
-        type_alias_no_nz! { $Docfile, $Alias = $Real; $( $Cfg )* }
-
-        #[doc = concat!("Type alias for `NonZero` version of [`", stringify!($Alias), "`]")]
-        #[unstable(feature = "raw_os_nonzero", issue = "82363")]
-        $( $Cfg )*
-        pub type $NZAlias = $NZReal;
-    }
-}
-
-type_alias! { "char.md", c_char = c_char_definition::c_char, NonZero_c_char = c_char_definition::NonZero_c_char;
-// Make this type alias appear cfg-dependent so that Clippy does not suggest
-// replacing `0 as c_char` with `0_i8`/`0_u8`. This #[cfg(all())] can be removed
-// after the false positive in https://github.com/rust-lang/rust-clippy/issues/8093
-// is fixed.
-#[cfg(all())]
-#[doc(cfg(all()))] }
-type_alias! { "schar.md", c_schar = i8, NonZero_c_schar = NonZeroI8; }
-type_alias! { "uchar.md", c_uchar = u8, NonZero_c_uchar = NonZeroU8; }
-type_alias! { "short.md", c_short = i16, NonZero_c_short = NonZeroI16; }
-type_alias! { "ushort.md", c_ushort = u16, NonZero_c_ushort = NonZeroU16; }
-type_alias! { "int.md", c_int = i32, NonZero_c_int = NonZeroI32; }
-type_alias! { "uint.md", c_uint = u32, NonZero_c_uint = NonZeroU32; }
-type_alias! { "long.md", c_long = i32, NonZero_c_long = NonZeroI32;
-#[doc(cfg(all()))]
-#[cfg(any(target_pointer_width = "32", windows))] }
-type_alias! { "ulong.md", c_ulong = u32, NonZero_c_ulong = NonZeroU32;
-#[doc(cfg(all()))]
-#[cfg(any(target_pointer_width = "32", windows))] }
-type_alias! { "long.md", c_long = i64, NonZero_c_long = NonZeroI64;
-#[doc(cfg(all()))]
-#[cfg(all(target_pointer_width = "64", not(windows)))] }
-type_alias! { "ulong.md", c_ulong = u64, NonZero_c_ulong = NonZeroU64;
-#[doc(cfg(all()))]
-#[cfg(all(target_pointer_width = "64", not(windows)))] }
-type_alias! { "longlong.md", c_longlong = i64, NonZero_c_longlong = NonZeroI64; }
-type_alias! { "ulonglong.md", c_ulonglong = u64, NonZero_c_ulonglong = NonZeroU64; }
-type_alias_no_nz! { "float.md", c_float = f32; }
-type_alias_no_nz! { "double.md", c_double = f64; }
-
-#[stable(feature = "raw_os", since = "1.1.0")]
-#[doc(no_inline)]
-pub use core::ffi::c_void;
-
-/// Equivalent to C's `size_t` type, from `stddef.h` (or `cstddef` for C++).
-///
-/// This type is currently always [`usize`], however in the future there may be
-/// platforms where this is not the case.
-#[unstable(feature = "c_size_t", issue = "88345")]
-pub type c_size_t = usize;
-
-/// Equivalent to C's `ptrdiff_t` type, from `stddef.h` (or `cstddef` for C++).
-///
-/// This type is currently always [`isize`], however in the future there may be
-/// platforms where this is not the case.
-#[unstable(feature = "c_size_t", issue = "88345")]
-pub type c_ptrdiff_t = isize;
-
-/// Equivalent to C's `ssize_t` (on POSIX) or `SSIZE_T` (on Windows) type.
-///
-/// This type is currently always [`isize`], however in the future there may be
-/// platforms where this is not the case.
-#[unstable(feature = "c_size_t", issue = "88345")]
-pub type c_ssize_t = isize;
-
-mod c_char_definition {
-    cfg_if::cfg_if! {
-        // These are the targets on which c_char is unsigned.
-        if #[cfg(any(
-            all(
-                target_os = "linux",
-                any(
-                    target_arch = "aarch64",
-                    target_arch = "arm",
-                    target_arch = "hexagon",
-                    target_arch = "powerpc",
-                    target_arch = "powerpc64",
-                    target_arch = "s390x",
-                    target_arch = "riscv64",
-                    target_arch = "riscv32"
-                )
-            ),
-            all(target_os = "android", any(target_arch = "aarch64", target_arch = "arm")),
-            all(target_os = "l4re", target_arch = "x86_64"),
-            all(
-                target_os = "freebsd",
-                any(
-                    target_arch = "aarch64",
-                    target_arch = "arm",
-                    target_arch = "powerpc",
-                    target_arch = "powerpc64",
-                    target_arch = "riscv64"
-                )
-            ),
-            all(
-                target_os = "netbsd",
-                any(target_arch = "aarch64", target_arch = "arm", target_arch = "powerpc")
-            ),
-            all(target_os = "openbsd", target_arch = "aarch64"),
-            all(
-                target_os = "vxworks",
-                any(
-                    target_arch = "aarch64",
-                    target_arch = "arm",
-                    target_arch = "powerpc64",
-                    target_arch = "powerpc"
-                )
-            ),
-            all(target_os = "fuchsia", target_arch = "aarch64")
-        ))] {
-            pub type c_char = u8;
-            pub type NonZero_c_char = core::num::NonZeroU8;
-        } else {
-            // On every other target, c_char is signed.
-            pub type c_char = i8;
-            pub type NonZero_c_char = core::num::NonZeroI8;
-        }
-    }
+alias_core_ffi! {
+    c_char c_schar c_uchar
+    c_short c_ushort
+    c_int c_uint
+    c_long c_ulong
+    c_longlong c_ulonglong
+    c_float
+    c_double
+    c_void
 }
diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs
index 9fc2d9fce4d..07a0339c066 100644
--- a/library/std/src/sys/unix/process/process_unix.rs
+++ b/library/std/src/sys/unix/process/process_unix.rs
@@ -3,11 +3,11 @@ use crate::fmt;
 use crate::io::{self, Error, ErrorKind};
 use crate::mem;
 use crate::num::NonZeroI32;
-use crate::os::raw::NonZero_c_int;
 use crate::ptr;
 use crate::sys;
 use crate::sys::cvt;
 use crate::sys::process::process_common::*;
+use core::ffi::NonZero_c_int;
 
 #[cfg(target_os = "linux")]
 use crate::os::linux::process::PidFd;
diff --git a/library/std/src/sys/unix/process/process_unsupported.rs b/library/std/src/sys/unix/process/process_unsupported.rs
index 7d549d060fd..bbabdf787d9 100644
--- a/library/std/src/sys/unix/process/process_unsupported.rs
+++ b/library/std/src/sys/unix/process/process_unsupported.rs
@@ -3,12 +3,12 @@ use crate::fmt;
 use crate::io;
 use crate::io::ErrorKind;
 use crate::num::NonZeroI32;
-use crate::os::raw::NonZero_c_int;
 use crate::sys;
 use crate::sys::cvt;
 use crate::sys::pipe::AnonPipe;
 use crate::sys::process::process_common::*;
 use crate::sys::unix::unsupported::*;
+use core::ffi::NonZero_c_int;
 
 use libc::{c_int, pid_t};
 
diff --git a/library/std/src/sys/unix/process/process_vxworks.rs b/library/std/src/sys/unix/process/process_vxworks.rs
index c6714d3aae2..56ed6cfeb6a 100644
--- a/library/std/src/sys/unix/process/process_vxworks.rs
+++ b/library/std/src/sys/unix/process/process_vxworks.rs
@@ -2,11 +2,11 @@ use crate::convert::{TryFrom, TryInto};
 use crate::fmt;
 use crate::io::{self, Error, ErrorKind};
 use crate::num::NonZeroI32;
-use crate::os::raw::NonZero_c_int;
 use crate::sys;
 use crate::sys::cvt;
 use crate::sys::process::process_common::*;
 use crate::sys_common::thread;
+use core::ffi::NonZero_c_int;
 use libc::RTP_ID;
 use libc::{self, c_char, c_int};
 
diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs
index c7b6290693e..2affd7e75b0 100644
--- a/library/std/src/sys/windows/c.rs
+++ b/library/std/src/sys/windows/c.rs
@@ -5,9 +5,9 @@
 #![unstable(issue = "none", feature = "windows_c")]
 
 use crate::mem;
-use crate::os::raw::NonZero_c_ulong;
 use crate::os::raw::{c_char, c_int, c_long, c_longlong, c_uint, c_ulong, c_ushort};
 use crate::ptr;
+use core::ffi::NonZero_c_ulong;
 
 use libc::{c_void, size_t, wchar_t};
 
diff --git a/src/doc/book b/src/doc/book
index 67b768c0b66..3f255ed40b8 160000
--- a/src/doc/book
+++ b/src/doc/book
@@ -1 +1 @@
-Subproject commit 67b768c0b660a069a45f0e5d8ae2f679df1022ab
+Subproject commit 3f255ed40b8c82a0434088568fbed270dc31bf00
diff --git a/src/doc/edition-guide b/src/doc/edition-guide
index beea0a3cdc3..c55611dd6c5 160000
--- a/src/doc/edition-guide
+++ b/src/doc/edition-guide
@@ -1 +1 @@
-Subproject commit beea0a3cdc3885375342fd010f9ad658e6a5e09a
+Subproject commit c55611dd6c58bdeb52423b5c52fd0f3c93615ba8
diff --git a/src/doc/nomicon b/src/doc/nomicon
index 90993eeac93..f6d6126fc96 160000
--- a/src/doc/nomicon
+++ b/src/doc/nomicon
@@ -1 +1 @@
-Subproject commit 90993eeac93dbf9388992de92965f99cf6f29a03
+Subproject commit f6d6126fc96ecf4a7f7d22da330df9506293b0d0
diff --git a/src/doc/reference b/src/doc/reference
index 70fc73a6b90..9d289c05fce 160000
--- a/src/doc/reference
+++ b/src/doc/reference
@@ -1 +1 @@
-Subproject commit 70fc73a6b908e08e66aa0306856c5211312f6c05
+Subproject commit 9d289c05fce7254b99c6a0d354d84abb7fd7a032
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
index 18c0055b8ae..2a928483a20 160000
--- a/src/doc/rust-by-example
+++ b/src/doc/rust-by-example
@@ -1 +1 @@
-Subproject commit 18c0055b8aea49391e8f758a4400097999c9cf1e
+Subproject commit 2a928483a20bb306a7399c0468234db90d89afb5
diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide
index 62f58394ba7..32f2a5b4e75 160000
--- a/src/doc/rustc-dev-guide
+++ b/src/doc/rustc-dev-guide
@@ -1 +1 @@
-Subproject commit 62f58394ba7b203f55ac35ddcc4c0b79578f5706
+Subproject commit 32f2a5b4e7545318846185198542230170dd8a42
diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs
index 2c2bf2b8c0f..5db2d0747c8 100644
--- a/src/librustdoc/passes/mod.rs
+++ b/src/librustdoc/passes/mod.rs
@@ -178,7 +178,7 @@ crate fn source_span_for_markdown_range(
 
     'outer: for (line_no, md_line) in md_lines.enumerate() {
         loop {
-            let source_line = src_lines.next().expect("could not find markdown in source");
+            let source_line = src_lines.next()?;
             match source_line.find(md_line) {
                 Some(offset) => {
                     if line_no == starting_line {
diff --git a/src/test/codegen/dst-vtable-align-nonzero.rs b/src/test/codegen/dst-vtable-align-nonzero.rs
index 021c7b19f89..14c4c3f30f9 100644
--- a/src/test/codegen/dst-vtable-align-nonzero.rs
+++ b/src/test/codegen/dst-vtable-align-nonzero.rs
@@ -24,6 +24,7 @@ pub fn eliminates_runtime_check_when_align_1(
     x: &Struct<WrapperWithAlign1<dyn Trait>>
 ) -> &WrapperWithAlign1<dyn Trait> {
     // CHECK: load [[USIZE:i[0-9]+]], {{.+}} !range [[RANGE_META:![0-9]+]]
+    // CHECK-NOT: llvm.umax
     // CHECK-NOT: icmp
     // CHECK-NOT: select
     // CHECK: ret
@@ -36,8 +37,7 @@ pub fn does_not_eliminate_runtime_check_when_align_2(
     x: &Struct<WrapperWithAlign2<dyn Trait>>
 ) -> &WrapperWithAlign2<dyn Trait> {
     // CHECK: [[X0:%[0-9]+]] = load [[USIZE]], {{.+}} !range [[RANGE_META]]
-    // CHECK: [[X1:%[0-9]+]] = icmp {{.+}} [[X0]]
-    // CHECK: [[X2:%[0-9]+]] = select {{.+}} [[X1]]
+    // CHECK: {{icmp|llvm.umax}}
     // CHECK: ret
     &x.dst
 }
diff --git a/src/test/rustdoc-ui/auxiliary/module_macro_doc.rs b/src/test/rustdoc-ui/auxiliary/module_macro_doc.rs
new file mode 100644
index 00000000000..9d6b52b95a7
--- /dev/null
+++ b/src/test/rustdoc-ui/auxiliary/module_macro_doc.rs
@@ -0,0 +1 @@
+//! [`long_cat`] is really long
diff --git a/src/test/rustdoc-ui/macro-docs.rs b/src/test/rustdoc-ui/macro-docs.rs
new file mode 100644
index 00000000000..0e8472eb242
--- /dev/null
+++ b/src/test/rustdoc-ui/macro-docs.rs
@@ -0,0 +1,12 @@
+// check-pass
+
+macro_rules! m {
+    () => {
+        /// A
+        //~^ WARNING
+        #[path = "auxiliary/module_macro_doc.rs"]
+        pub mod mymodule;
+    }
+}
+
+m!();
diff --git a/src/test/rustdoc-ui/macro-docs.stderr b/src/test/rustdoc-ui/macro-docs.stderr
new file mode 100644
index 00000000000..e3cc1731146
--- /dev/null
+++ b/src/test/rustdoc-ui/macro-docs.stderr
@@ -0,0 +1,20 @@
+warning: unresolved link to `long_cat`
+  --> $DIR/macro-docs.rs:5:9
+   |
+LL |         /// A
+   |         ^^^^^
+...
+LL | m!();
+   | ---- in this macro invocation
+   |
+   = note: `#[warn(rustdoc::broken_intra_doc_links)]` on by default
+   = note: the link appears in this line:
+           
+           [`long_cat`] is really long
+            ^^^^^^^^^^
+   = note: no item named `long_cat` in scope
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+   = note: this warning originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+warning: 1 warning emitted
+
diff --git a/src/test/rustdoc-ui/macro-docs.stdout b/src/test/rustdoc-ui/macro-docs.stdout
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/src/test/ui/issues/issue-17728.stderr b/src/test/ui/issues/issue-17728.stderr
index 50e3b853fcb..943c63667e0 100644
--- a/src/test/ui/issues/issue-17728.stderr
+++ b/src/test/ui/issues/issue-17728.stderr
@@ -8,6 +8,12 @@ LL |     fn attemptTraverse(&self, room: &Room, directionStr: &str) -> Result<&R
 ...
 LL |             Some(entry) => Ok(entry),
    |                            ^^^^^^^^^ ...but data from `room` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter
+   |
+LL |     fn attemptTraverse<'a>(&'a self, room: &'a Room, directionStr: &str) -> Result<&Room, &str> {
+   |                       ++++  ++              ++
 
 error[E0308]: `match` arms have incompatible types
   --> $DIR/issue-17728.rs:109:14
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.stderr
index 199f880b3c4..636904aefb4 100644
--- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.stderr
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.stderr
@@ -7,6 +7,12 @@ LL |   fn foo<'a>(&self, x: &i32) -> &i32 {
    |                        this parameter and the return type are declared with different lifetimes...
 LL |     x
    |     ^ ...but data from `x` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |   fn foo<'a>(&'a self, x: &'a i32) -> &i32 {
+   |               ++           ++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-self-is-anon.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-self-is-anon.stderr
index 838f43b3774..474eadb7f92 100644
--- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-self-is-anon.stderr
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-self-is-anon.stderr
@@ -7,6 +7,12 @@ LL |     fn foo<'a>(&self, x: &Foo) -> &Foo {
    |                          this parameter and the return type are declared with different lifetimes...
 LL |         if true { x } else { self }
    |                   ^ ...but data from `x` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn foo<'a>(&'a self, x: &'a Foo) -> &Foo {
+   |                 ++           ++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-impl-items.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-impl-items.stderr
index e8b0208f092..68893781dc2 100644
--- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-impl-items.stderr
+++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-impl-items.stderr
@@ -5,6 +5,12 @@ LL |     fn foo(x: &mut Vec<&u8>, y: &u8) {
    |                        ---      --- these two types are declared with different lifetimes...
 LL |         x.push(y);
    |                ^ ...but data from `y` flows into `x` here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) {
+   |           ++++              ++          ++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.stderr
index 6bb7ad7cdc7..64a57469510 100644
--- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.stderr
+++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.stderr
@@ -5,6 +5,12 @@ LL |     fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f }
    |                              ----     ----   ^ ...but data from `f` is returned here
    |                              |
    |                              this parameter and the return type are declared with different lifetimes...
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn a<'a>(self: Pin<&'a Foo>, f: &'a Foo) -> &Foo { f }
+   |         ++++            ++           ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:8:76
@@ -13,6 +19,12 @@ LL |     fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self,
    |                               ----              -----------------          ^ ...but data from `f` is returned here
    |                               |
    |                               this parameter and the return type are declared with different lifetimes...
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn c<'a>(self: Pin<&'a Self>, f: &'a Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
+   |         ++++            ++            ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:13:58
diff --git a/src/test/ui/self/elision/lt-ref-self.stderr b/src/test/ui/self/elision/lt-ref-self.stderr
index f392580d422..5764ab03c55 100644
--- a/src/test/ui/self/elision/lt-ref-self.stderr
+++ b/src/test/ui/self/elision/lt-ref-self.stderr
@@ -7,6 +7,12 @@ LL |     fn ref_self(&self, f: &u32) -> &u32 {
    |                           this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn ref_self<'a>(&'a self, f: &'a u32) -> &u32 {
+   |                ++++  ++           ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/lt-ref-self.rs:17:9
@@ -17,6 +23,12 @@ LL |     fn ref_Self(self: &Self, f: &u32) -> &u32 {
    |                                 this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn ref_Self<'a>(self: &'a Self, f: &'a u32) -> &u32 {
+   |                ++++        ++           ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/lt-ref-self.rs:21:9
@@ -27,6 +39,12 @@ LL |     fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
    |                                          this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn box_ref_Self<'a>(self: Box<&'a Self>, f: &'a u32) -> &u32 {
+   |                    ++++            ++            ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/lt-ref-self.rs:25:9
@@ -37,6 +55,12 @@ LL |     fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
    |                                          this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn pin_ref_Self<'a>(self: Pin<&'a Self>, f: &'a u32) -> &u32 {
+   |                    ++++            ++            ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/lt-ref-self.rs:29:9
@@ -47,6 +71,12 @@ LL |     fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
    |                                                   this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn box_box_ref_Self<'a>(self: Box<Box<&'a Self>>, f: &'a u32) -> &u32 {
+   |                        ++++                ++             ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/lt-ref-self.rs:33:9
@@ -57,6 +87,12 @@ LL |     fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
    |                                               this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn box_pin_Self<'a>(self: Box<Pin<&'a Self>>, f: &'a u32) -> &u32 {
+   |                    ++++                ++             ++
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/self/elision/ref-mut-self.stderr b/src/test/ui/self/elision/ref-mut-self.stderr
index 46d849741eb..416719a08e0 100644
--- a/src/test/ui/self/elision/ref-mut-self.stderr
+++ b/src/test/ui/self/elision/ref-mut-self.stderr
@@ -7,6 +7,12 @@ LL |     fn ref_self(&mut self, f: &u32) -> &u32 {
    |                               this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn ref_self<'a>(&'a mut self, f: &'a u32) -> &u32 {
+   |                ++++  ++               ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-mut-self.rs:17:9
@@ -17,6 +23,12 @@ LL |     fn ref_Self(self: &mut Self, f: &u32) -> &u32 {
    |                                     this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn ref_Self<'a>(self: &'a mut Self, f: &'a u32) -> &u32 {
+   |                ++++        ++               ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-mut-self.rs:21:9
@@ -27,6 +39,12 @@ LL |     fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 {
    |                                              this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn box_ref_Self<'a>(self: Box<&'a mut Self>, f: &'a u32) -> &u32 {
+   |                    ++++            ++                ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-mut-self.rs:25:9
@@ -37,6 +55,12 @@ LL |     fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 {
    |                                              this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn pin_ref_Self<'a>(self: Pin<&'a mut Self>, f: &'a u32) -> &u32 {
+   |                    ++++            ++                ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-mut-self.rs:29:9
@@ -47,6 +71,12 @@ LL |     fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 {
    |                                                       this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn box_box_ref_Self<'a>(self: Box<Box<&'a mut Self>>, f: &'a u32) -> &u32 {
+   |                        ++++                ++                 ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-mut-self.rs:33:9
@@ -57,6 +87,12 @@ LL |     fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 {
    |                                                       this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn box_pin_ref_Self<'a>(self: Box<Pin<&'a mut Self>>, f: &'a u32) -> &u32 {
+   |                        ++++                ++                 ++
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/self/elision/ref-mut-struct.stderr b/src/test/ui/self/elision/ref-mut-struct.stderr
index c824f2cac98..6ca9ab1b2c7 100644
--- a/src/test/ui/self/elision/ref-mut-struct.stderr
+++ b/src/test/ui/self/elision/ref-mut-struct.stderr
@@ -7,6 +7,12 @@ LL |     fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 {
    |                                         this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn ref_Struct<'a>(self: &'a mut Struct, f: &'a u32) -> &u32 {
+   |                  ++++        ++                 ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-mut-struct.rs:15:9
@@ -17,6 +23,12 @@ LL |     fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 {
    |                                                  this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn box_ref_Struct<'a>(self: Box<&'a mut Struct>, f: &'a u32) -> &u32 {
+   |                      ++++            ++                  ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-mut-struct.rs:19:9
@@ -27,6 +39,12 @@ LL |     fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 {
    |                                                  this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn pin_ref_Struct<'a>(self: Pin<&'a mut Struct>, f: &'a u32) -> &u32 {
+   |                      ++++            ++                  ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-mut-struct.rs:23:9
@@ -37,6 +55,12 @@ LL |     fn box_box_ref_Struct(self: Box<Box<&mut Struct>>, f: &u32) -> &u32 {
    |                                                           this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn box_box_ref_Struct<'a>(self: Box<Box<&'a mut Struct>>, f: &'a u32) -> &u32 {
+   |                          ++++                ++                   ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-mut-struct.rs:27:9
@@ -47,6 +71,12 @@ LL |     fn box_pin_ref_Struct(self: Box<Pin<&mut Struct>>, f: &u32) -> &u32 {
    |                                                           this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn box_pin_ref_Struct<'a>(self: Box<Pin<&'a mut Struct>>, f: &'a u32) -> &u32 {
+   |                          ++++                ++                   ++
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/self/elision/ref-self.stderr b/src/test/ui/self/elision/ref-self.stderr
index 8343c8d349e..955222f7655 100644
--- a/src/test/ui/self/elision/ref-self.stderr
+++ b/src/test/ui/self/elision/ref-self.stderr
@@ -7,6 +7,12 @@ LL |     fn ref_self(&self, f: &u32) -> &u32 {
    |                           this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn ref_self<'a>(&'a self, f: &'a u32) -> &u32 {
+   |                ++++  ++           ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-self.rs:27:9
@@ -17,6 +23,12 @@ LL |     fn ref_Self(self: &Self, f: &u32) -> &u32 {
    |                                 this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn ref_Self<'a>(self: &'a Self, f: &'a u32) -> &u32 {
+   |                ++++        ++           ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-self.rs:31:9
@@ -27,6 +39,12 @@ LL |     fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
    |                                          this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn box_ref_Self<'a>(self: Box<&'a Self>, f: &'a u32) -> &u32 {
+   |                    ++++            ++            ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-self.rs:35:9
@@ -37,6 +55,12 @@ LL |     fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
    |                                          this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn pin_ref_Self<'a>(self: Pin<&'a Self>, f: &'a u32) -> &u32 {
+   |                    ++++            ++            ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-self.rs:39:9
@@ -47,6 +71,12 @@ LL |     fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
    |                                                   this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn box_box_ref_Self<'a>(self: Box<Box<&'a Self>>, f: &'a u32) -> &u32 {
+   |                        ++++                ++             ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-self.rs:43:9
@@ -57,6 +87,12 @@ LL |     fn box_pin_ref_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
    |                                                   this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn box_pin_ref_Self<'a>(self: Box<Pin<&'a Self>>, f: &'a u32) -> &u32 {
+   |                        ++++                ++             ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-self.rs:47:9
@@ -67,6 +103,12 @@ LL |     fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 {
    |                                                       this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn wrap_ref_Self_Self<'a>(self: Wrap<&'a Self, Self>, f: &'a u8) -> &u8 {
+   |                          ++++             ++                  ++
 
 error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/self/elision/ref-struct.stderr b/src/test/ui/self/elision/ref-struct.stderr
index a6967309143..c80993fe8c4 100644
--- a/src/test/ui/self/elision/ref-struct.stderr
+++ b/src/test/ui/self/elision/ref-struct.stderr
@@ -7,6 +7,12 @@ LL |     fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
    |                                     this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn ref_Struct<'a>(self: &'a Struct, f: &'a u32) -> &u32 {
+   |                  ++++        ++             ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-struct.rs:15:9
@@ -17,6 +23,12 @@ LL |     fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 {
    |                                              this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn box_ref_Struct<'a>(self: Box<&'a Struct>, f: &'a u32) -> &u32 {
+   |                      ++++            ++              ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-struct.rs:19:9
@@ -27,6 +39,12 @@ LL |     fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 {
    |                                              this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn pin_ref_Struct<'a>(self: Pin<&'a Struct>, f: &'a u32) -> &u32 {
+   |                      ++++            ++              ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-struct.rs:23:9
@@ -37,6 +55,12 @@ LL |     fn box_box_ref_Struct(self: Box<Box<&Struct>>, f: &u32) -> &u32 {
    |                                                       this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn box_box_ref_Struct<'a>(self: Box<Box<&'a Struct>>, f: &'a u32) -> &u32 {
+   |                          ++++                ++               ++
 
 error[E0623]: lifetime mismatch
   --> $DIR/ref-struct.rs:27:9
@@ -47,6 +71,12 @@ LL |     fn box_pin_Struct(self: Box<Pin<&Struct>>, f: &u32) -> &u32 {
    |                                                   this parameter and the return type are declared with different lifetimes...
 LL |         f
    |         ^ ...but data from `f` is returned here
+   |
+   = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter and update trait if needed
+   |
+LL |     fn box_pin_Struct<'a>(self: Box<Pin<&'a Struct>>, f: &'a u32) -> &u32 {
+   |                      ++++                ++               ++
 
 error: aborting due to 5 previous errors
 
diff --git a/src/tools/miri b/src/tools/miri
index e05a543f74d..c6b3f687d5d 160000
--- a/src/tools/miri
+++ b/src/tools/miri
@@ -1 +1 @@
-Subproject commit e05a543f74dbdd0580b2bd35ddb7f8e144d9edda
+Subproject commit c6b3f687d5d9917b626f80a730552a185052ff28
diff --git a/src/tools/tidy/src/pal.rs b/src/tools/tidy/src/pal.rs
index cb6d56a167d..f5ff3860afe 100644
--- a/src/tools/tidy/src/pal.rs
+++ b/src/tools/tidy/src/pal.rs
@@ -46,7 +46,7 @@ const EXCEPTION_PATHS: &[&str] = &[
     // pointer regardless of the target architecture. As a result,
     // we must use `#[cfg(windows)]` to conditionally compile the
     // correct `VaList` structure for windows.
-    "library/core/src/ffi.rs",
+    "library/core/src/ffi/mod.rs",
     "library/std/src/sys/", // Platform-specific code for std lives here.
     "library/std/src/os",   // Platform-specific public interfaces
     // Temporary `std` exceptions