about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-05-16 18:43:04 +0000
committerbors <bors@rust-lang.org>2023-05-16 18:43:04 +0000
commite77366b57b799dfa3ce1fcb850c068723a3213ee (patch)
treeede7c5b5c1272a50cf067778a62eafc957629416
parentb652d9a0fd5c5a7eeacd1ae8299166941c221230 (diff)
parent54a49769fa106b0732dcc15f68e59f4a07ffa909 (diff)
downloadrust-e77366b57b799dfa3ce1fcb850c068723a3213ee.tar.gz
rust-e77366b57b799dfa3ce1fcb850c068723a3213ee.zip
Auto merge of #111650 - matthiaskrgr:rollup-n7w17v4, r=matthiaskrgr
Rollup of 7 pull requests

Successful merges:

 - #107680 (Hide repr attribute from doc of types without guaranteed repr)
 - #111488 (Use error term in projection if missing associated item in new solver)
 - #111533 (Handle error body in generator layout)
 - #111573 (Erase `ReError` properly)
 - #111592 (Change Vec examples to not assert exact capacity except where it is guaranteed)
 - #111610 (fix(diagnostic): wrap parens for ref impl trait param)
 - #111642 ([rustdoc] Only keep impl blocks from bodies)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs77
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs7
-rw-r--r--compiler/rustc_middle/src/query/mod.rs2
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs4
-rw-r--r--compiler/rustc_middle/src/ty/util.rs6
-rw-r--r--compiler/rustc_mir_transform/src/generator.rs5
-rw-r--r--compiler/rustc_trait_selection/src/solve/project_goals.rs16
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs3
-rw-r--r--library/alloc/src/vec/mod.rs12
-rw-r--r--library/core/src/any.rs2
-rw-r--r--library/core/src/ffi/mod.rs14
-rw-r--r--library/core/src/task/wake.rs2
-rw-r--r--library/portable-simd/crates/core_simd/src/masks.rs2
-rw-r--r--src/librustdoc/visit_ast.rs30
-rw-r--r--tests/rustdoc/nested-items-issue-111415.rs36
-rw-r--r--tests/ui/borrowck/erase-error-in-mir-drop-tracking.rs23
-rw-r--r--tests/ui/borrowck/erase-error-in-mir-drop-tracking.stderr24
-rw-r--r--tests/ui/generator/drop-tracking-error-body.rs18
-rw-r--r--tests/ui/generator/drop-tracking-error-body.stderr17
-rw-r--r--tests/ui/impl-trait/issue-103181-1.current.stderr (renamed from tests/ui/impl-trait/issue-103181-1.stderr)2
-rw-r--r--tests/ui/impl-trait/issue-103181-1.next.stderr12
-rw-r--r--tests/ui/impl-trait/issue-103181-1.rs2
-rw-r--r--tests/ui/suggestions/issue-99597.rs15
-rw-r--r--tests/ui/suggestions/issue-99597.stderr15
25 files changed, 286 insertions, 62 deletions
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 78ffe59679a..d3495d3dbd7 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -1514,8 +1514,8 @@ fn opaque_type_cycle_error(
                     }
                     if tcx.sess.opts.unstable_opts.drop_tracking_mir
                         && let DefKind::Generator = tcx.def_kind(closure_def_id)
+                        && let Some(generator_layout) = tcx.mir_generator_witnesses(closure_def_id)
                     {
-                        let generator_layout = tcx.mir_generator_witnesses(closure_def_id);
                         for interior_ty in &generator_layout.field_tys {
                             label_match(interior_ty.ty, interior_ty.source_info.span);
                         }
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 486c217707e..550a87e6102 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -2633,47 +2633,62 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                 Nothing,
                             }
                             let ast_generics = hir.get_generics(id.owner.def_id).unwrap();
-                            let (sp, mut introducer) = if let Some(span) =
-                                ast_generics.bounds_span_for_suggestions(def_id)
-                            {
-                                (span, Introducer::Plus)
-                            } else if let Some(colon_span) = param.colon_span {
-                                (colon_span.shrink_to_hi(), Introducer::Nothing)
-                            } else {
-                                (param.span.shrink_to_hi(), Introducer::Colon)
-                            };
-                            if matches!(
-                                param.kind,
-                                hir::GenericParamKind::Type { synthetic: true, .. },
-                            ) {
-                                introducer = Introducer::Plus
-                            }
                             let trait_def_ids: FxHashSet<DefId> = ast_generics
                                 .bounds_for_param(def_id)
                                 .flat_map(|bp| bp.bounds.iter())
                                 .filter_map(|bound| bound.trait_ref()?.trait_def_id())
                                 .collect();
-                            if !candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) {
-                                err.span_suggestions(
-                                    sp,
-                                    message(format!(
-                                        "restrict type parameter `{}` with",
-                                        param.name.ident(),
-                                    )),
+                            if candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) {
+                                return;
+                            }
+                            let msg = message(format!(
+                                "restrict type parameter `{}` with",
+                                param.name.ident(),
+                            ));
+                            let bounds_span = ast_generics.bounds_span_for_suggestions(def_id);
+                            if rcvr_ty.is_ref() && param.is_impl_trait() && bounds_span.is_some() {
+                                err.multipart_suggestions(
+                                    msg,
                                     candidates.iter().map(|t| {
-                                        format!(
-                                            "{} {}",
-                                            match introducer {
-                                                Introducer::Plus => " +",
-                                                Introducer::Colon => ":",
-                                                Introducer::Nothing => "",
-                                            },
-                                            self.tcx.def_path_str(t.def_id),
-                                        )
+                                        vec![
+                                            (param.span.shrink_to_lo(), "(".to_string()),
+                                            (
+                                                bounds_span.unwrap(),
+                                                format!(" + {})", self.tcx.def_path_str(t.def_id)),
+                                            ),
+                                        ]
                                     }),
                                     Applicability::MaybeIncorrect,
                                 );
+                                return;
                             }
+
+                            let (sp, introducer) = if let Some(span) = bounds_span {
+                                (span, Introducer::Plus)
+                            } else if let Some(colon_span) = param.colon_span {
+                                (colon_span.shrink_to_hi(), Introducer::Nothing)
+                            } else if param.is_impl_trait() {
+                                (param.span.shrink_to_hi(), Introducer::Plus)
+                            } else {
+                                (param.span.shrink_to_hi(), Introducer::Colon)
+                            };
+
+                            err.span_suggestions(
+                                sp,
+                                msg,
+                                candidates.iter().map(|t| {
+                                    format!(
+                                        "{} {}",
+                                        match introducer {
+                                            Introducer::Plus => " +",
+                                            Introducer::Colon => ":",
+                                            Introducer::Nothing => "",
+                                        },
+                                        self.tcx.def_path_str(t.def_id)
+                                    )
+                                }),
+                                Applicability::MaybeIncorrect,
+                            );
                             return;
                         }
                         Node::Item(hir::Item {
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index c1815ae3851..79eb48a1a31 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -1516,8 +1516,11 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             if encode_opt {
                 record!(self.tables.optimized_mir[def_id.to_def_id()] <- tcx.optimized_mir(def_id));
 
-                if tcx.sess.opts.unstable_opts.drop_tracking_mir && let DefKind::Generator = self.tcx.def_kind(def_id) {
-                    record!(self.tables.mir_generator_witnesses[def_id.to_def_id()] <- tcx.mir_generator_witnesses(def_id));
+                if tcx.sess.opts.unstable_opts.drop_tracking_mir
+                    && let DefKind::Generator = self.tcx.def_kind(def_id)
+                    && let Some(witnesses) = tcx.mir_generator_witnesses(def_id)
+                {
+                    record!(self.tables.mir_generator_witnesses[def_id.to_def_id()] <- witnesses);
                 }
             }
             if encode_const {
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index ef13a277207..f564f5e99e8 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -527,7 +527,7 @@ rustc_queries! {
         }
     }
 
-    query mir_generator_witnesses(key: DefId) -> &'tcx mir::GeneratorLayout<'tcx> {
+    query mir_generator_witnesses(key: DefId) -> &'tcx Option<mir::GeneratorLayout<'tcx>> {
         arena_cache
         desc { |tcx| "generator witness types for `{}`", tcx.def_path_str(key) }
         cache_on_disk_if { key.is_local() }
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index d175cf72d67..e6d51c4ec97 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -1708,7 +1708,9 @@ impl<'tcx> Region<'tcx> {
             ty::ReErased => {
                 flags = flags | TypeFlags::HAS_RE_ERASED;
             }
-            ty::ReError(_) => {}
+            ty::ReError(_) => {
+                flags = flags | TypeFlags::HAS_FREE_REGIONS;
+            }
         }
 
         debug!("type_flags({:?}) = {:?}", self, flags);
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index c32ba3edd5c..eb903ebfd99 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -668,10 +668,10 @@ impl<'tcx> TyCtxt<'tcx> {
         self,
         def_id: DefId,
     ) -> impl Iterator<Item = ty::EarlyBinder<Ty<'tcx>>> {
-        let generator_layout = &self.mir_generator_witnesses(def_id);
+        let generator_layout = self.mir_generator_witnesses(def_id);
         generator_layout
-            .field_tys
-            .iter()
+            .as_ref()
+            .map_or_else(|| [].iter(), |l| l.field_tys.iter())
             .filter(|decl| !decl.ignore_for_traits)
             .map(|decl| ty::EarlyBinder(decl.ty))
     }
diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs
index c9144729145..891e446942e 100644
--- a/compiler/rustc_mir_transform/src/generator.rs
+++ b/compiler/rustc_mir_transform/src/generator.rs
@@ -1397,7 +1397,7 @@ fn create_cases<'tcx>(
 pub(crate) fn mir_generator_witnesses<'tcx>(
     tcx: TyCtxt<'tcx>,
     def_id: LocalDefId,
-) -> GeneratorLayout<'tcx> {
+) -> Option<GeneratorLayout<'tcx>> {
     assert!(tcx.sess.opts.unstable_opts.drop_tracking_mir);
 
     let (body, _) = tcx.mir_promoted(def_id);
@@ -1410,6 +1410,7 @@ pub(crate) fn mir_generator_witnesses<'tcx>(
     // Get the interior types and substs which typeck computed
     let movable = match *gen_ty.kind() {
         ty::Generator(_, _, movability) => movability == hir::Movability::Movable,
+        ty::Error(_) => return None,
         _ => span_bug!(body.span, "unexpected generator type {}", gen_ty),
     };
 
@@ -1425,7 +1426,7 @@ pub(crate) fn mir_generator_witnesses<'tcx>(
 
     check_suspend_tys(tcx, &generator_layout, &body);
 
-    generator_layout
+    Some(generator_layout)
 }
 
 impl<'tcx> MirPass<'tcx> for StateTransform {
diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs
index 20ce2d9416e..d3228074421 100644
--- a/compiler/rustc_trait_selection/src/solve/project_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs
@@ -124,10 +124,24 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
             };
 
             if !assoc_def.item.defaultness(tcx).has_value() {
-                tcx.sess.delay_span_bug(
+                let guar = tcx.sess.delay_span_bug(
                     tcx.def_span(assoc_def.item.def_id),
                     "missing value for assoc item in impl",
                 );
+                let error_term = match assoc_def.item.kind {
+                    ty::AssocKind::Const => tcx
+                        .const_error(
+                            tcx.type_of(goal.predicate.def_id())
+                                .subst(tcx, goal.predicate.projection_ty.substs),
+                            guar,
+                        )
+                        .into(),
+                    ty::AssocKind::Type => tcx.ty_error(guar).into(),
+                    ty::AssocKind::Fn => unreachable!(),
+                };
+                ecx.eq(goal.param_env, goal.predicate.term, error_term)
+                    .expect("expected goal term to be fully unconstrained");
+                return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
             }
 
             // Getting the right substitutions here is complex, e.g. given:
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 49b309abcda..ea17f23434b 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -2447,10 +2447,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             && generator_did.is_local()
             // Try to avoid cycles.
             && !generator_within_in_progress_typeck
+            && let Some(generator_info) = self.tcx.mir_generator_witnesses(generator_did)
         {
-            let generator_info = &self.tcx.mir_generator_witnesses(generator_did);
             debug!(?generator_info);
-
             'find_source: for (variant, source_info) in
                 generator_info.variant_fields.iter().zip(&generator_info.variant_source_info)
             {
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index 97da6f06b70..82f30a26d41 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -646,14 +646,14 @@ impl<T, A: Allocator> Vec<T, A> {
     ///
     /// // The vector contains no items, even though it has capacity for more
     /// assert_eq!(vec.len(), 0);
-    /// assert_eq!(vec.capacity(), 10);
+    /// assert!(vec.capacity() >= 10);
     ///
     /// // These are all done without reallocating...
     /// for i in 0..10 {
     ///     vec.push(i);
     /// }
     /// assert_eq!(vec.len(), 10);
-    /// assert_eq!(vec.capacity(), 10);
+    /// assert!(vec.capacity() >= 10);
     ///
     /// // ...but this may make the vector reallocate
     /// vec.push(11);
@@ -877,7 +877,7 @@ impl<T, A: Allocator> Vec<T, A> {
     /// ```
     /// let mut vec: Vec<i32> = Vec::with_capacity(10);
     /// vec.push(42);
-    /// assert_eq!(vec.capacity(), 10);
+    /// assert!(vec.capacity() >= 10);
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -1028,7 +1028,7 @@ impl<T, A: Allocator> Vec<T, A> {
     /// ```
     /// let mut vec = Vec::with_capacity(10);
     /// vec.extend([1, 2, 3]);
-    /// assert_eq!(vec.capacity(), 10);
+    /// assert!(vec.capacity() >= 10);
     /// vec.shrink_to_fit();
     /// assert!(vec.capacity() >= 3);
     /// ```
@@ -1055,7 +1055,7 @@ impl<T, A: Allocator> Vec<T, A> {
     /// ```
     /// let mut vec = Vec::with_capacity(10);
     /// vec.extend([1, 2, 3]);
-    /// assert_eq!(vec.capacity(), 10);
+    /// assert!(vec.capacity() >= 10);
     /// vec.shrink_to(4);
     /// assert!(vec.capacity() >= 4);
     /// vec.shrink_to(0);
@@ -1090,7 +1090,7 @@ impl<T, A: Allocator> Vec<T, A> {
     /// let mut vec = Vec::with_capacity(10);
     /// vec.extend([1, 2, 3]);
     ///
-    /// assert_eq!(vec.capacity(), 10);
+    /// assert!(vec.capacity() >= 10);
     /// let slice = vec.into_boxed_slice();
     /// assert_eq!(slice.into_vec().capacity(), 3);
     /// ```
diff --git a/library/core/src/any.rs b/library/core/src/any.rs
index bb93ea509d8..d1c1ae6526b 100644
--- a/library/core/src/any.rs
+++ b/library/core/src/any.rs
@@ -866,7 +866,7 @@ where
 ///
 /// A data provider provides values by calling this type's provide methods.
 #[unstable(feature = "provide_any", issue = "96024")]
-#[repr(transparent)]
+#[cfg_attr(not(doc), repr(transparent))] // work around https://github.com/rust-lang/rust/issues/90435
 pub struct Demand<'a>(dyn Erased<'a> + 'a);
 
 impl<'a> Demand<'a> {
diff --git a/library/core/src/ffi/mod.rs b/library/core/src/ffi/mod.rs
index b85894259f1..b73abbbaca7 100644
--- a/library/core/src/ffi/mod.rs
+++ b/library/core/src/ffi/mod.rs
@@ -203,7 +203,7 @@ mod c_long_definition {
 //     be UB.
 #[doc = include_str!("c_void.md")]
 #[cfg_attr(not(bootstrap), lang = "c_void")]
-#[repr(u8)]
+#[cfg_attr(not(doc), repr(u8))] // work around https://github.com/rust-lang/rust/issues/90435
 #[stable(feature = "core_c_void", since = "1.30.0")]
 pub enum c_void {
     #[unstable(
@@ -244,7 +244,7 @@ impl fmt::Debug for c_void {
     target_os = "uefi",
     windows,
 ))]
-#[repr(transparent)]
+#[cfg_attr(not(doc), repr(transparent))] // work around https://github.com/rust-lang/rust/issues/90435
 #[unstable(
     feature = "c_variadic",
     reason = "the `c_variadic` feature has not been properly tested on \
@@ -296,7 +296,7 @@ impl<'f> fmt::Debug for VaListImpl<'f> {
     not(target_os = "uefi"),
     not(windows),
 ))]
-#[repr(C)]
+#[cfg_attr(not(doc), repr(C))] // work around https://github.com/rust-lang/rust/issues/66401
 #[derive(Debug)]
 #[unstable(
     feature = "c_variadic",
@@ -316,7 +316,7 @@ pub struct VaListImpl<'f> {
 
 /// PowerPC ABI implementation of a `va_list`.
 #[cfg(all(target_arch = "powerpc", not(target_os = "uefi"), not(windows)))]
-#[repr(C)]
+#[cfg_attr(not(doc), repr(C))] // work around https://github.com/rust-lang/rust/issues/66401
 #[derive(Debug)]
 #[unstable(
     feature = "c_variadic",
@@ -336,7 +336,7 @@ pub struct VaListImpl<'f> {
 
 /// s390x ABI implementation of a `va_list`.
 #[cfg(target_arch = "s390x")]
-#[repr(C)]
+#[cfg_attr(not(doc), repr(C))] // work around https://github.com/rust-lang/rust/issues/66401
 #[derive(Debug)]
 #[unstable(
     feature = "c_variadic",
@@ -355,7 +355,7 @@ pub struct VaListImpl<'f> {
 
 /// x86_64 ABI implementation of a `va_list`.
 #[cfg(all(target_arch = "x86_64", not(target_os = "uefi"), not(windows)))]
-#[repr(C)]
+#[cfg_attr(not(doc), repr(C))] // work around https://github.com/rust-lang/rust/issues/66401
 #[derive(Debug)]
 #[unstable(
     feature = "c_variadic",
@@ -373,7 +373,7 @@ pub struct VaListImpl<'f> {
 }
 
 /// A wrapper for a `va_list`
-#[repr(transparent)]
+#[cfg_attr(not(doc), repr(transparent))] // work around https://github.com/rust-lang/rust/issues/90435
 #[derive(Debug)]
 #[unstable(
     feature = "c_variadic",
diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs
index 808825326ae..7043ab5ff2b 100644
--- a/library/core/src/task/wake.rs
+++ b/library/core/src/task/wake.rs
@@ -232,7 +232,7 @@ impl fmt::Debug for Context<'_> {
 ///
 /// [`Future::poll()`]: core::future::Future::poll
 /// [`Poll::Pending`]: core::task::Poll::Pending
-#[repr(transparent)]
+#[cfg_attr(not(doc), repr(transparent))] // work around https://github.com/rust-lang/rust/issues/66401
 #[stable(feature = "futures_api", since = "1.36.0")]
 pub struct Waker {
     waker: RawWaker,
diff --git a/library/portable-simd/crates/core_simd/src/masks.rs b/library/portable-simd/crates/core_simd/src/masks.rs
index e58df80fca8..e0f3c7beef6 100644
--- a/library/portable-simd/crates/core_simd/src/masks.rs
+++ b/library/portable-simd/crates/core_simd/src/masks.rs
@@ -88,7 +88,7 @@ impl_element! { isize }
 /// The layout of this type is unspecified, and may change between platforms
 /// and/or Rust versions, and code should not assume that it is equivalent to
 /// `[T; LANES]`.
-#[repr(transparent)]
+#[cfg_attr(not(doc), repr(transparent))] // work around https://github.com/rust-lang/rust/issues/90435
 pub struct Mask<T, const LANES: usize>(mask_impl::Mask<T, LANES>)
 where
     T: MaskElement,
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index ff13daa6db4..8f8dc6b7090 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -5,7 +5,7 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, LocalDefIdSet};
-use rustc_hir::intravisit::{walk_item, Visitor};
+use rustc_hir::intravisit::{walk_body, walk_item, Visitor};
 use rustc_hir::{Node, CRATE_HIR_ID};
 use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::TyCtxt;
@@ -106,6 +106,7 @@ pub(crate) struct RustdocVisitor<'a, 'tcx> {
     exact_paths: DefIdMap<Vec<Symbol>>,
     modules: Vec<Module<'tcx>>,
     is_importable_from_parent: bool,
+    inside_body: bool,
 }
 
 impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
@@ -129,6 +130,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
             exact_paths: Default::default(),
             modules: vec![om],
             is_importable_from_parent: true,
+            inside_body: false,
         }
     }
 
@@ -368,6 +370,26 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         import_id: Option<LocalDefId>,
     ) {
         debug!("visiting item {:?}", item);
+        if self.inside_body {
+            // Only impls can be "seen" outside a body. For example:
+            //
+            // ```
+            // struct Bar;
+            //
+            // fn foo() {
+            //     impl Bar { fn bar() {} }
+            // }
+            // Bar::bar();
+            // ```
+            if let hir::ItemKind::Impl(impl_) = item.kind &&
+                // Don't duplicate impls when inlining or if it's implementing a trait, we'll pick
+                // them up regardless of where they're located.
+                impl_.of_trait.is_none()
+            {
+                self.add_to_current_mod(item, None, None);
+            }
+            return;
+        }
         let name = renamed.unwrap_or(item.ident.name);
         let tcx = self.cx.tcx;
 
@@ -564,4 +586,10 @@ impl<'a, 'tcx> Visitor<'tcx> for RustdocVisitor<'a, 'tcx> {
     fn visit_lifetime(&mut self, _: &hir::Lifetime) {
         // Unneeded.
     }
+
+    fn visit_body(&mut self, b: &'tcx hir::Body<'tcx>) {
+        let prev = mem::replace(&mut self.inside_body, true);
+        walk_body(self, b);
+        self.inside_body = prev;
+    }
 }
diff --git a/tests/rustdoc/nested-items-issue-111415.rs b/tests/rustdoc/nested-items-issue-111415.rs
new file mode 100644
index 00000000000..9b7688c332c
--- /dev/null
+++ b/tests/rustdoc/nested-items-issue-111415.rs
@@ -0,0 +1,36 @@
+// Regression test for <https://github.com/rust-lang/rust/issues/111415>.
+// This test ensures that only impl blocks are documented in bodies.
+
+#![crate_name = "foo"]
+
+// @has 'foo/index.html'
+// Checking there are only three sections.
+// @count - '//*[@id="main-content"]/*[@class="small-section-header"]' 3
+// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Structs'
+// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Functions'
+// @has - '//*[@id="main-content"]/*[@class="small-section-header"]' 'Traits'
+// Checking that there are only three items.
+// @count - '//*[@id="main-content"]//*[@class="item-name"]' 3
+// @has - '//*[@id="main-content"]//a[@href="struct.Bar.html"]' 'Bar'
+// @has - '//*[@id="main-content"]//a[@href="fn.foo.html"]' 'foo'
+// @has - '//*[@id="main-content"]//a[@href="trait.Foo.html"]' 'Foo'
+
+// Now checking that the `foo` method is visible in `Bar` page.
+// @has 'foo/struct.Bar.html'
+// @has - '//*[@id="method.foo"]/*[@class="code-header"]' 'pub fn foo()'
+// @has - '//*[@id="method.bar"]/*[@class="code-header"]' 'fn bar()'
+pub struct Bar;
+
+pub trait Foo {
+    fn bar() {}
+}
+
+pub fn foo() {
+    pub mod inaccessible {}
+    pub fn inner() {}
+    pub const BAR: u32 = 0;
+    impl Bar {
+        pub fn foo() {}
+    }
+    impl Foo for Bar {}
+}
diff --git a/tests/ui/borrowck/erase-error-in-mir-drop-tracking.rs b/tests/ui/borrowck/erase-error-in-mir-drop-tracking.rs
new file mode 100644
index 00000000000..addbe5d658a
--- /dev/null
+++ b/tests/ui/borrowck/erase-error-in-mir-drop-tracking.rs
@@ -0,0 +1,23 @@
+// compile-flags: -Zdrop-tracking-mir
+// edition:2021
+
+use std::future::Future;
+
+trait Client {
+    type Connecting<'a>: Future + Send
+    where
+        Self: 'a;
+
+    fn connect(&'_ self) -> Self::Connecting<'a>;
+    //~^ ERROR use of undeclared lifetime name `'a`
+}
+
+fn call_connect<C>(c: &'_ C) -> impl '_ + Future + Send
+where
+    C: Client + Send + Sync,
+{
+    async move { c.connect().await }
+    //~^ ERROR `C` does not live long enough
+}
+
+fn main() {}
diff --git a/tests/ui/borrowck/erase-error-in-mir-drop-tracking.stderr b/tests/ui/borrowck/erase-error-in-mir-drop-tracking.stderr
new file mode 100644
index 00000000000..53abe3dc952
--- /dev/null
+++ b/tests/ui/borrowck/erase-error-in-mir-drop-tracking.stderr
@@ -0,0 +1,24 @@
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/erase-error-in-mir-drop-tracking.rs:11:46
+   |
+LL |     fn connect(&'_ self) -> Self::Connecting<'a>;
+   |                                              ^^ undeclared lifetime
+   |
+help: consider introducing lifetime `'a` here
+   |
+LL |     fn connect<'a>(&'_ self) -> Self::Connecting<'a>;
+   |               ++++
+help: consider introducing lifetime `'a` here
+   |
+LL | trait Client<'a> {
+   |             ++++
+
+error: `C` does not live long enough
+  --> $DIR/erase-error-in-mir-drop-tracking.rs:19:5
+   |
+LL |     async move { c.connect().await }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0261`.
diff --git a/tests/ui/generator/drop-tracking-error-body.rs b/tests/ui/generator/drop-tracking-error-body.rs
new file mode 100644
index 00000000000..f99d9ab6bf8
--- /dev/null
+++ b/tests/ui/generator/drop-tracking-error-body.rs
@@ -0,0 +1,18 @@
+// compile-flags: -Zdrop-tracking-mir --edition=2021
+
+#![feature(generators)]
+
+pub async fn async_bad_body() {
+    match true {} //~ ERROR non-exhaustive patterns: type `bool` is non-empty
+}
+
+pub fn generator_bad_body() {
+    || {
+        // 'non-exhaustive pattern' only seems to be reported once, so this annotation doesn't work
+        // keep the function around so we can make sure it doesn't ICE
+        match true {}; // ERROR non-exhaustive patterns: type `bool` is non-empty
+        yield ();
+    };
+}
+
+fn main() {}
diff --git a/tests/ui/generator/drop-tracking-error-body.stderr b/tests/ui/generator/drop-tracking-error-body.stderr
new file mode 100644
index 00000000000..28a6892336f
--- /dev/null
+++ b/tests/ui/generator/drop-tracking-error-body.stderr
@@ -0,0 +1,17 @@
+error[E0004]: non-exhaustive patterns: type `bool` is non-empty
+  --> $DIR/drop-tracking-error-body.rs:6:11
+   |
+LL |     match true {}
+   |           ^^^^
+   |
+   = note: the matched value is of type `bool`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match true {
+LL +         _ => todo!(),
+LL ~     }
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/impl-trait/issue-103181-1.stderr b/tests/ui/impl-trait/issue-103181-1.current.stderr
index cd026607d52..e87a9d28ae1 100644
--- a/tests/ui/impl-trait/issue-103181-1.stderr
+++ b/tests/ui/impl-trait/issue-103181-1.current.stderr
@@ -1,5 +1,5 @@
 error[E0046]: not all trait items implemented, missing: `Error`
-  --> $DIR/issue-103181-1.rs:9:5
+  --> $DIR/issue-103181-1.rs:11:5
    |
 LL |         type Error;
    |         ---------- `Error` from trait
diff --git a/tests/ui/impl-trait/issue-103181-1.next.stderr b/tests/ui/impl-trait/issue-103181-1.next.stderr
new file mode 100644
index 00000000000..e87a9d28ae1
--- /dev/null
+++ b/tests/ui/impl-trait/issue-103181-1.next.stderr
@@ -0,0 +1,12 @@
+error[E0046]: not all trait items implemented, missing: `Error`
+  --> $DIR/issue-103181-1.rs:11:5
+   |
+LL |         type Error;
+   |         ---------- `Error` from trait
+LL |     }
+LL |     impl HttpBody for () {
+   |     ^^^^^^^^^^^^^^^^^^^^ missing `Error` in implementation
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0046`.
diff --git a/tests/ui/impl-trait/issue-103181-1.rs b/tests/ui/impl-trait/issue-103181-1.rs
index 197aedf9d98..5154abcd690 100644
--- a/tests/ui/impl-trait/issue-103181-1.rs
+++ b/tests/ui/impl-trait/issue-103181-1.rs
@@ -1,3 +1,5 @@
+// revisions: current next
+//[next] compile-flags: -Ztrait-solver=next
 // edition:2021
 
 mod hyper {
diff --git a/tests/ui/suggestions/issue-99597.rs b/tests/ui/suggestions/issue-99597.rs
new file mode 100644
index 00000000000..8ba9e1fdd62
--- /dev/null
+++ b/tests/ui/suggestions/issue-99597.rs
@@ -0,0 +1,15 @@
+#![allow(dead_code)]
+
+trait T1 { }
+
+trait T2 {
+    fn test(&self) { }
+}
+
+fn go(s: &impl T1) {
+    //~^ SUGGESTION (
+    s.test();
+    //~^ ERROR no method named `test`
+}
+
+fn main() { }
diff --git a/tests/ui/suggestions/issue-99597.stderr b/tests/ui/suggestions/issue-99597.stderr
new file mode 100644
index 00000000000..bdf2a07c143
--- /dev/null
+++ b/tests/ui/suggestions/issue-99597.stderr
@@ -0,0 +1,15 @@
+error[E0599]: no method named `test` found for reference `&impl T1` in the current scope
+  --> $DIR/issue-99597.rs:11:7
+   |
+LL |     s.test();
+   |       ^^^^ method not found in `&impl T1`
+   |
+   = help: items from traits can only be used if the type parameter is bounded by the trait
+help: the following trait defines an item `test`, perhaps you need to restrict type parameter `impl T1` with it:
+   |
+LL | fn go(s: &(impl T1 + T2)) {
+   |           +        +++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.