about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-08-29 22:49:04 +0000
committerbors <bors@rust-lang.org>2022-08-29 22:49:04 +0000
commit9f4d5d2a28849ec0ecb2976ddc9946f65b626fe8 (patch)
tree659d6d0e27f56b1f2ff7e2a386c49e88899895de
parentbc4b39c271bbd36736cbf1c0a1ac23d5df38d365 (diff)
parentbf42ba41a44dc9bd74b0e2abe2954ad0d818d3ed (diff)
downloadrust-9f4d5d2a28849ec0ecb2976ddc9946f65b626fe8.tar.gz
rust-9f4d5d2a28849ec0ecb2976ddc9946f65b626fe8.zip
Auto merge of #101167 - matthiaskrgr:rollup-yt3jdmp, r=matthiaskrgr
Rollup of 7 pull requests

Successful merges:

 - #100898 (Do not report too many expr field candidates)
 - #101056 (Add the syntax of references to their documentation summary.)
 - #101106 (Rustdoc-Json: Retain Stripped Modules when they are imported, not when they have items)
 - #101131 (CTFE: exposing pointers and calling extern fn is just impossible)
 - #101141 (Simplify `get_trait_ref` fn used for `virtual_function_elimination`)
 - #101146 (Various changes to logging of borrowck-related code)
 - #101156 (Remove `Sync` requirement from lint pass objects)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_borrowck/src/constraints/mod.rs4
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs22
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs20
-rw-r--r--compiler/rustc_borrowck/src/lib.rs8
-rw-r--r--compiler/rustc_borrowck/src/places_conflict.rs15
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs24
-rw-r--r--compiler/rustc_borrowck/src/type_check/canonical.rs2
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs1
-rw-r--r--compiler/rustc_codegen_ssa/src/meth.rs18
-rw-r--r--compiler/rustc_const_eval/src/const_eval/error.rs4
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs24
-rw-r--r--compiler/rustc_const_eval/src/interpret/machine.rs1
-rw-r--r--compiler/rustc_infer/src/infer/canonical/canonicalizer.rs2
-rw-r--r--compiler/rustc_infer/src/infer/canonical/query_response.rs6
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs12
-rw-r--r--compiler/rustc_infer/src/infer/outlives/obligations.rs4
-rw-r--r--compiler/rustc_lint/src/passes.rs5
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--compiler/rustc_traits/src/type_op.rs5
-rw-r--r--compiler/rustc_typeck/src/check/expr.rs51
-rw-r--r--compiler/rustc_typeck/src/check/method/suggest.rs88
-rw-r--r--library/core/src/primitive_docs.rs2
-rw-r--r--library/std/src/primitive_docs.rs2
-rw-r--r--src/etc/check_missing_items.py6
-rw-r--r--src/librustdoc/json/conversions.rs8
-rw-r--r--src/librustdoc/json/import_finder.rs38
-rw-r--r--src/librustdoc/json/mod.rs8
-rw-r--r--src/test/rustdoc-json/reexport/glob_collision.rs28
-rw-r--r--src/test/rustdoc-json/reexport/glob_empty_mod.rs8
-rw-r--r--src/test/rustdoc-json/reexport/in_root_and_mod.rs3
-rw-r--r--src/test/rustdoc-json/reexport/mod_not_included.rs14
-rw-r--r--src/test/rustdoc-json/reexport/private_two_names.rs3
-rw-r--r--src/test/rustdoc-json/reexport/rename_private.rs3
-rw-r--r--src/test/rustdoc-json/reexport/simple_private.rs5
-rw-r--r--src/test/rustdoc-json/stripped_modules.rs2
-rw-r--r--src/test/ui/consts/miri_unleashed/ptr_arith.rs5
-rw-r--r--src/test/ui/consts/miri_unleashed/ptr_arith.stderr2
-rw-r--r--src/test/ui/copy-a-resource.stderr4
-rw-r--r--src/test/ui/issues/issue-2823.stderr4
-rw-r--r--src/test/ui/noncopyable-class.stderr8
-rw-r--r--src/test/ui/suggestions/too-many-field-suggestions.rs29
-rw-r--r--src/test/ui/suggestions/too-many-field-suggestions.stderr44
42 files changed, 341 insertions, 202 deletions
diff --git a/compiler/rustc_borrowck/src/constraints/mod.rs b/compiler/rustc_borrowck/src/constraints/mod.rs
index a504d0c9122..c94dfe39b69 100644
--- a/compiler/rustc_borrowck/src/constraints/mod.rs
+++ b/compiler/rustc_borrowck/src/constraints/mod.rs
@@ -105,8 +105,8 @@ impl<'tcx> fmt::Debug for OutlivesConstraint<'tcx> {
     fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(
             formatter,
-            "({:?}: {:?}) due to {:?} ({:?})",
-            self.sup, self.sub, self.locations, self.variance_info
+            "({:?}: {:?}) due to {:?} ({:?}) ({:?})",
+            self.sup, self.sub, self.locations, self.variance_info, self.category,
         )
     }
 }
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 84a0d4ba7ba..5971f7623f2 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -1119,6 +1119,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     /// short a lifetime. (But sometimes it is more useful to report
     /// it as a more direct conflict between the execution of a
     /// `Drop::drop` with an aliasing borrow.)
+    #[instrument(level = "debug", skip(self))]
     pub(crate) fn report_borrowed_value_does_not_live_long_enough(
         &mut self,
         location: Location,
@@ -1126,13 +1127,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         place_span: (Place<'tcx>, Span),
         kind: Option<WriteKind>,
     ) {
-        debug!(
-            "report_borrowed_value_does_not_live_long_enough(\
-             {:?}, {:?}, {:?}, {:?}\
-             )",
-            location, borrow, place_span, kind
-        );
-
         let drop_span = place_span.1;
         let root_place =
             self.prefixes(borrow.borrowed_place.as_ref(), PrefixSet::All).last().unwrap();
@@ -1189,10 +1183,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         let kind_place = kind.filter(|_| place_desc.is_some()).map(|k| (k, place_span.0));
         let explanation = self.explain_why_borrow_contains_point(location, &borrow, kind_place);
 
-        debug!(
-            "report_borrowed_value_does_not_live_long_enough(place_desc: {:?}, explanation: {:?})",
-            place_desc, explanation
-        );
+        debug!(?place_desc, ?explanation);
+
         let err = match (place_desc, explanation) {
             // If the outlives constraint comes from inside the closure,
             // for example:
@@ -1464,6 +1456,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         err
     }
 
+    #[instrument(level = "debug", skip(self))]
     fn report_temporary_value_does_not_live_long_enough(
         &mut self,
         location: Location,
@@ -1473,13 +1466,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         proper_span: Span,
         explanation: BorrowExplanation<'tcx>,
     ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
-        debug!(
-            "report_temporary_value_does_not_live_long_enough(\
-             {:?}, {:?}, {:?}, {:?}\
-             )",
-            location, borrow, drop_span, proper_span
-        );
-
         if let BorrowExplanation::MustBeValidFor { category, span, from_closure: false, .. } =
             explanation
         {
diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
index a6b8c6057e0..2f61849c383 100644
--- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
@@ -336,26 +336,22 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     ///   - second half is the place being accessed
     ///
     /// [d]: https://rust-lang.github.io/rfcs/2094-nll.html#leveraging-intuition-framing-errors-in-terms-of-points
+    #[instrument(level = "debug", skip(self))]
     pub(crate) fn explain_why_borrow_contains_point(
         &self,
         location: Location,
         borrow: &BorrowData<'tcx>,
         kind_place: Option<(WriteKind, Place<'tcx>)>,
     ) -> BorrowExplanation<'tcx> {
-        debug!(
-            "explain_why_borrow_contains_point(location={:?}, borrow={:?}, kind_place={:?})",
-            location, borrow, kind_place
-        );
-
         let regioncx = &self.regioncx;
         let body: &Body<'_> = &self.body;
         let tcx = self.infcx.tcx;
 
         let borrow_region_vid = borrow.region;
-        debug!("explain_why_borrow_contains_point: borrow_region_vid={:?}", borrow_region_vid);
+        debug!(?borrow_region_vid);
 
         let region_sub = self.regioncx.find_sub_region_live_at(borrow_region_vid, location);
-        debug!("explain_why_borrow_contains_point: region_sub={:?}", region_sub);
+        debug!(?region_sub);
 
         match find_use::find(body, regioncx, tcx, region_sub, location) {
             Some(Cause::LiveVar(local, location)) => {
@@ -408,17 +404,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                             opt_place_desc,
                         }
                     } else {
-                        debug!(
-                            "explain_why_borrow_contains_point: \
-                             Could not generate a region name"
-                        );
+                        debug!("Could not generate a region name");
                         BorrowExplanation::Unexplained
                     }
                 } else {
-                    debug!(
-                        "explain_why_borrow_contains_point: \
-                         Could not generate an error region vid"
-                    );
+                    debug!("Could not generate an error region vid");
                     BorrowExplanation::Unexplained
                 }
             }
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 0f8afb038f4..362c45ecd7e 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -975,6 +975,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         }
     }
 
+    #[instrument(level = "debug", skip(self, flow_state))]
     fn check_access_for_conflict(
         &mut self,
         location: Location,
@@ -983,11 +984,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         rw: ReadOrWrite,
         flow_state: &Flows<'cx, 'tcx>,
     ) -> bool {
-        debug!(
-            "check_access_for_conflict(location={:?}, place_span={:?}, sd={:?}, rw={:?})",
-            location, place_span, sd, rw,
-        );
-
         let mut error_reported = false;
         let tcx = self.infcx.tcx;
         let body = self.body;
@@ -1451,13 +1447,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
 
     /// Checks whether a borrow of this place is invalidated when the function
     /// exits
+    #[instrument(level = "debug", skip(self))]
     fn check_for_invalidation_at_exit(
         &mut self,
         location: Location,
         borrow: &BorrowData<'tcx>,
         span: Span,
     ) {
-        debug!("check_for_invalidation_at_exit({:?})", borrow);
         let place = borrow.borrowed_place;
         let mut root_place = PlaceRef { local: place.local, projection: &[] };
 
diff --git a/compiler/rustc_borrowck/src/places_conflict.rs b/compiler/rustc_borrowck/src/places_conflict.rs
index 97335fd0dff..6e5a96bee97 100644
--- a/compiler/rustc_borrowck/src/places_conflict.rs
+++ b/compiler/rustc_borrowck/src/places_conflict.rs
@@ -44,6 +44,7 @@ pub(crate) fn places_conflict<'tcx>(
 /// access depth. The `bias` parameter is used to determine how the unknowable (comparing runtime
 /// array indices, for example) should be interpreted - this depends on what the caller wants in
 /// order to make the conservative choice and preserve soundness.
+#[instrument(level = "debug", skip(tcx, body))]
 pub(super) fn borrow_conflicts_with_place<'tcx>(
     tcx: TyCtxt<'tcx>,
     body: &Body<'tcx>,
@@ -53,11 +54,6 @@ pub(super) fn borrow_conflicts_with_place<'tcx>(
     access: AccessDepth,
     bias: PlaceConflictBias,
 ) -> bool {
-    debug!(
-        "borrow_conflicts_with_place({:?}, {:?}, {:?}, {:?})",
-        borrow_place, access_place, access, bias,
-    );
-
     // This Local/Local case is handled by the more general code below, but
     // it's so common that it's a speed win to check for it first.
     if let Some(l1) = borrow_place.as_local() && let Some(l2) = access_place.as_local() {
@@ -140,10 +136,9 @@ fn place_components_conflict<'tcx>(
     for (i, (borrow_c, &access_c)) in
         iter::zip(borrow_place.projection, access_place.projection).enumerate()
     {
-        debug!("borrow_conflicts_with_place: borrow_c = {:?}", borrow_c);
-        let borrow_proj_base = &borrow_place.projection[..i];
+        debug!(?borrow_c, ?access_c);
 
-        debug!("borrow_conflicts_with_place: access_c = {:?}", access_c);
+        let borrow_proj_base = &borrow_place.projection[..i];
 
         // Borrow and access path both have more components.
         //
@@ -180,7 +175,7 @@ fn place_components_conflict<'tcx>(
                 // idea, at least for now, so just give up and
                 // report a conflict. This is unsafe code anyway so
                 // the user could always use raw pointers.
-                debug!("borrow_conflicts_with_place: arbitrary -> conflict");
+                debug!("arbitrary -> conflict");
                 return true;
             }
             Overlap::EqualOrDisjoint => {
@@ -189,7 +184,7 @@ fn place_components_conflict<'tcx>(
             Overlap::Disjoint => {
                 // We have proven the borrow disjoint - further
                 // projections will remain disjoint.
-                debug!("borrow_conflicts_with_place: disjoint");
+                debug!("disjoint");
                 return false;
             }
         }
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index 2894c6d29ec..f5bd5cd3bea 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -1167,8 +1167,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// Therefore, this method should only be used in diagnostic code,
     /// where displaying *some* named universal region is better than
     /// falling back to 'static.
+    #[instrument(level = "debug", skip(self))]
     pub(crate) fn approx_universal_upper_bound(&self, r: RegionVid) -> RegionVid {
-        debug!("approx_universal_upper_bound(r={:?}={})", r, self.region_value_str(r));
+        debug!("{}", self.region_value_str(r));
 
         // Find the smallest universal region that contains all other
         // universal regions within `region`.
@@ -1177,7 +1178,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         let static_r = self.universal_regions.fr_static;
         for ur in self.scc_values.universal_regions_outlived_by(r_scc) {
             let new_lub = self.universal_region_relations.postdom_upper_bound(lub, ur);
-            debug!("approx_universal_upper_bound: ur={:?} lub={:?} new_lub={:?}", ur, lub, new_lub);
+            debug!(?ur, ?lub, ?new_lub);
             // The upper bound of two non-static regions is static: this
             // means we know nothing about the relationship between these
             // two regions. Pick a 'better' one to use when constructing
@@ -1201,7 +1202,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             }
         }
 
-        debug!("approx_universal_upper_bound: r={:?} lub={:?}", r, lub);
+        debug!(?r, ?lub);
 
         lub
     }
@@ -2048,6 +2049,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// creating a constraint path that forces `R` to outlive
     /// `from_region`, and then finding the best choices within that
     /// path to blame.
+    #[instrument(level = "debug", skip(self, target_test))]
     pub(crate) fn best_blame_constraint(
         &self,
         body: &Body<'tcx>,
@@ -2055,16 +2057,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         from_region_origin: NllRegionVariableOrigin,
         target_test: impl Fn(RegionVid) -> bool,
     ) -> BlameConstraint<'tcx> {
-        debug!(
-            "best_blame_constraint(from_region={:?}, from_region_origin={:?})",
-            from_region, from_region_origin
-        );
-
         // Find all paths
         let (path, target_region) =
             self.find_constraint_paths_between_regions(from_region, target_test).unwrap();
         debug!(
-            "best_blame_constraint: path={:#?}",
+            "path={:#?}",
             path.iter()
                 .map(|c| format!(
                     "{:?} ({:?}: {:?})",
@@ -2116,7 +2113,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 }
             })
             .collect();
-        debug!("best_blame_constraint: categorized_path={:#?}", categorized_path);
+        debug!("categorized_path={:#?}", categorized_path);
 
         // To find the best span to cite, we first try to look for the
         // final constraint that is interesting and where the `sup` is
@@ -2214,10 +2211,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         let best_choice =
             if blame_source { range.rev().find(find_region) } else { range.find(find_region) };
 
-        debug!(
-            "best_blame_constraint: best_choice={:?} blame_source={}",
-            best_choice, blame_source
-        );
+        debug!(?best_choice, ?blame_source);
 
         if let Some(i) = best_choice {
             if let Some(next) = categorized_path.get(i + 1) {
@@ -2254,7 +2248,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         // appears to be the most interesting point to report to the
         // user via an even more ad-hoc guess.
         categorized_path.sort_by(|p0, p1| p0.category.cmp(&p1.category));
-        debug!("best_blame_constraint: sorted_path={:#?}", categorized_path);
+        debug!("sorted_path={:#?}", categorized_path);
 
         categorized_path.remove(0)
     }
diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs
index 451b82c5c18..29195b3922f 100644
--- a/compiler/rustc_borrowck/src/type_check/canonical.rs
+++ b/compiler/rustc_borrowck/src/type_check/canonical.rs
@@ -24,7 +24,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
     /// **Any `rustc_infer::infer` operations that might generate region
     /// constraints should occur within this method so that those
     /// constraints can be properly localized!**
-    #[instrument(skip(self, category, op), level = "trace")]
+    #[instrument(skip(self, op), level = "trace")]
     pub(super) fn fully_perform_op<R, Op>(
         &mut self,
         locations: Locations,
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index c1812aa4bba..a620c987052 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -1043,6 +1043,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             let CanonicalUserTypeAnnotation { span, ref user_ty, inferred_ty } = *user_annotation;
             let inferred_ty = self.normalize(inferred_ty, Locations::All(span));
             let annotation = self.instantiate_canonical_with_fresh_inference_vars(span, user_ty);
+            debug!(?annotation);
             match annotation {
                 UserType::Ty(mut ty) => {
                     ty = self.normalize(ty, Locations::All(span));
diff --git a/compiler/rustc_codegen_ssa/src/meth.rs b/compiler/rustc_codegen_ssa/src/meth.rs
index 27d791d90a5..f8e982b7751 100644
--- a/compiler/rustc_codegen_ssa/src/meth.rs
+++ b/compiler/rustc_codegen_ssa/src/meth.rs
@@ -1,6 +1,6 @@
 use crate::traits::*;
 
-use rustc_middle::ty::{self, subst::GenericArgKind, ExistentialPredicate, Ty, TyCtxt};
+use rustc_middle::ty::{self, subst::GenericArgKind, Ty};
 use rustc_session::config::Lto;
 use rustc_symbol_mangling::typeid_for_trait_ref;
 use rustc_target::abi::call::FnAbi;
@@ -29,7 +29,7 @@ impl<'a, 'tcx> VirtualIndex {
             && bx.cx().sess().lto() == Lto::Fat
         {
             let typeid =
-                bx.typeid_metadata(typeid_for_trait_ref(bx.tcx(), get_trait_ref(bx.tcx(), ty)));
+                bx.typeid_metadata(typeid_for_trait_ref(bx.tcx(), expect_dyn_trait_in_self(ty)));
             let vtable_byte_offset = self.0 * bx.data_layout().pointer_size.bytes();
             let type_checked_load = bx.type_checked_load(llvtable, vtable_byte_offset, typeid);
             let func = bx.extract_value(type_checked_load, 0);
@@ -64,17 +64,13 @@ impl<'a, 'tcx> VirtualIndex {
     }
 }
 
-fn get_trait_ref<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ty::PolyExistentialTraitRef<'tcx> {
+/// This takes a valid `self` receiver type and extracts the principal trait
+/// ref of the type.
+fn expect_dyn_trait_in_self<'tcx>(ty: Ty<'tcx>) -> ty::PolyExistentialTraitRef<'tcx> {
     for arg in ty.peel_refs().walk() {
         if let GenericArgKind::Type(ty) = arg.unpack() {
-            if let ty::Dynamic(trait_refs, _) = ty.kind() {
-                return trait_refs[0].map_bound(|trait_ref| match trait_ref {
-                    ExistentialPredicate::Trait(tr) => tr,
-                    ExistentialPredicate::Projection(proj) => proj.trait_ref(tcx),
-                    ExistentialPredicate::AutoTrait(_) => {
-                        bug!("auto traits don't have functions")
-                    }
-                });
+            if let ty::Dynamic(data, _) = ty.kind() {
+                return data.principal().expect("expected principal trait object");
             }
         }
     }
diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs
index eb81f43c3fe..bba4b1815b4 100644
--- a/compiler/rustc_const_eval/src/const_eval/error.rs
+++ b/compiler/rustc_const_eval/src/const_eval/error.rs
@@ -15,7 +15,6 @@ use crate::interpret::{
 /// The CTFE machine has some custom error kinds.
 #[derive(Clone, Debug)]
 pub enum ConstEvalErrKind {
-    NeedsRfc(String),
     ConstAccessesStatic,
     ModifiedGlobal,
     AssertFailure(AssertKind<ConstInt>),
@@ -42,9 +41,6 @@ impl fmt::Display for ConstEvalErrKind {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         use self::ConstEvalErrKind::*;
         match *self {
-            NeedsRfc(ref msg) => {
-                write!(f, "\"{}\" needs an rfc before being allowed inside constants", msg)
-            }
             ConstAccessesStatic => write!(f, "constant accesses static"),
             ModifiedGlobal => {
                 write!(f, "modifying a static's initial value from another static's initializer")
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index 6c1e61fccca..9ea9fbe0e0e 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -269,9 +269,10 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
                     );
                     throw_inval!(AlreadyReported(guar));
                 } else {
+                    // `find_mir_or_eval_fn` checks that this is a const fn before even calling us,
+                    // so this should be unreachable.
                     let path = ecx.tcx.def_path_str(def.did);
-                    Err(ConstEvalErrKind::NeedsRfc(format!("calling extern function `{}`", path))
-                        .into())
+                    bug!("trying to call extern function `{path}` at compile-time");
                 }
             }
             _ => Ok(ecx.tcx.instance_mir(instance)),
@@ -339,11 +340,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
 
         // CTFE-specific intrinsics.
         let Some(ret) = target else {
-            return Err(ConstEvalErrKind::NeedsRfc(format!(
-                "calling intrinsic `{}`",
-                intrinsic_name
-            ))
-            .into());
+            throw_unsup_format!("intrinsic `{intrinsic_name}` is not supported at compile-time");
         };
         match intrinsic_name {
             sym::ptr_guaranteed_eq | sym::ptr_guaranteed_ne => {
@@ -400,11 +397,9 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
                 }
             }
             _ => {
-                return Err(ConstEvalErrKind::NeedsRfc(format!(
-                    "calling intrinsic `{}`",
-                    intrinsic_name
-                ))
-                .into());
+                throw_unsup_format!(
+                    "intrinsic `{intrinsic_name}` is not supported at compile-time"
+                );
             }
         }
 
@@ -447,7 +442,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
         _left: &ImmTy<'tcx>,
         _right: &ImmTy<'tcx>,
     ) -> InterpResult<'tcx, (Scalar, bool, Ty<'tcx>)> {
-        Err(ConstEvalErrKind::NeedsRfc("pointer arithmetic or comparison".to_string()).into())
+        throw_unsup_format!("pointer arithmetic or comparison is not supported at compile-time");
     }
 
     fn before_terminator(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
@@ -469,7 +464,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
         _ecx: &mut InterpCx<'mir, 'tcx, Self>,
         _ptr: Pointer<AllocId>,
     ) -> InterpResult<'tcx> {
-        Err(ConstEvalErrKind::NeedsRfc("exposing pointers".to_string()).into())
+        // This is only reachable with -Zunleash-the-miri-inside-of-you.
+        throw_unsup_format!("exposing pointers is not possible at compile-time")
     }
 
     #[inline(always)]
diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs
index b151d03681f..6ca98371497 100644
--- a/compiler/rustc_const_eval/src/interpret/machine.rs
+++ b/compiler/rustc_const_eval/src/interpret/machine.rs
@@ -479,6 +479,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
     ) -> InterpResult<$tcx, Pointer<Option<AllocId>>> {
         // Allow these casts, but make the pointer not dereferenceable.
         // (I.e., they behave like transmutation.)
+        // This is correct because no pointers can ever be exposed in compile-time evaluation.
         Ok(Pointer::from_addr(addr))
     }
 
diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
index ca7862c9dc4..46f8c0e8d8b 100644
--- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
+++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
@@ -372,7 +372,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> {
                 debug!(
                     "canonical: region var found with vid {:?}, \
                      opportunistically resolved to {:?}",
-                    vid, r
+                    vid, resolved_vid
                 );
                 let r = self.tcx.reuse_or_mk_region(r, ty::ReVar(resolved_vid));
                 self.canonicalize_mode.canonicalize_free_region(self, r)
diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs
index 8dc20544f1b..64c759f73d4 100644
--- a/compiler/rustc_infer/src/infer/canonical/query_response.rs
+++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs
@@ -63,8 +63,8 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
         Canonical<'tcx, QueryResponse<'tcx, T>>: ArenaAllocatable<'tcx>,
     {
         let query_response = self.make_query_response(inference_vars, answer, fulfill_cx)?;
+        debug!("query_response = {:#?}", query_response);
         let canonical_result = self.canonicalize_response(query_response);
-
         debug!("canonical_result = {:#?}", canonical_result);
 
         Ok(self.tcx.arena.alloc(canonical_result))
@@ -125,6 +125,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
         debug!("ambig_errors = {:#?}", ambig_errors);
 
         let region_obligations = self.take_registered_region_obligations();
+        debug!(?region_obligations);
         let region_constraints = self.with_region_constraints(|region_constraints| {
             make_query_region_constraints(
                 tcx,
@@ -132,6 +133,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
                 region_constraints,
             )
         });
+        debug!(?region_constraints);
 
         let certainty =
             if ambig_errors.is_empty() { Certainty::Proven } else { Certainty::Ambiguous };
@@ -632,6 +634,8 @@ pub fn make_query_region_constraints<'tcx>(
     assert!(verifys.is_empty());
     assert!(givens.is_empty());
 
+    debug!(?constraints);
+
     let outlives: Vec<_> = constraints
         .iter()
         .map(|(k, _)| match *k {
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index c95738e0018..4689ebb6cee 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -504,7 +504,7 @@ pub enum FixupError<'tcx> {
 }
 
 /// See the `region_obligations` field for more information.
-#[derive(Clone)]
+#[derive(Clone, Debug)]
 pub struct RegionObligation<'tcx> {
     pub sub_region: ty::Region<'tcx>,
     pub sup_type: Ty<'tcx>,
@@ -2027,16 +2027,6 @@ impl RegionVariableOrigin {
     }
 }
 
-impl<'tcx> fmt::Debug for RegionObligation<'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(
-            f,
-            "RegionObligation(sub_region={:?}, sup_type={:?})",
-            self.sub_region, self.sup_type
-        )
-    }
-}
-
 /// Replaces substs that reference param or infer variables with suitable
 /// placeholders. This function is meant to remove these param and infer
 /// substs when they're not actually needed to evaluate a constant.
diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs
index dded0a0a6b1..fe78890ff6e 100644
--- a/compiler/rustc_infer/src/infer/outlives/obligations.rs
+++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs
@@ -92,6 +92,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
         sub_region: Region<'tcx>,
         cause: &ObligationCause<'tcx>,
     ) {
+        debug!(?sup_type, ?sub_region, ?cause);
         let origin = SubregionOrigin::from_obligation_cause(cause, || {
             infer::RelateParamBound(
                 cause.span,
@@ -248,14 +249,13 @@ where
     /// - `origin`, the reason we need this constraint
     /// - `ty`, the type `T`
     /// - `region`, the region `'a`
+    #[instrument(level = "debug", skip(self))]
     pub fn type_must_outlive(
         &mut self,
         origin: infer::SubregionOrigin<'tcx>,
         ty: Ty<'tcx>,
         region: ty::Region<'tcx>,
     ) {
-        debug!("type_must_outlive(ty={:?}, region={:?}, origin={:?})", ty, region, origin);
-
         assert!(!ty.has_escaping_bound_vars());
 
         let mut components = smallvec![];
diff --git a/compiler/rustc_lint/src/passes.rs b/compiler/rustc_lint/src/passes.rs
index 413f06a97a2..90c554c2e04 100644
--- a/compiler/rustc_lint/src/passes.rs
+++ b/compiler/rustc_lint/src/passes.rs
@@ -243,6 +243,5 @@ macro_rules! declare_combined_early_lint_pass {
 }
 
 /// A lint pass boxed up as a trait object.
-pub type EarlyLintPassObject = Box<dyn EarlyLintPass + sync::Send + sync::Sync + 'static>;
-pub type LateLintPassObject =
-    Box<dyn for<'tcx> LateLintPass<'tcx> + sync::Send + sync::Sync + 'static>;
+pub type EarlyLintPassObject = Box<dyn EarlyLintPass + sync::Send + 'static>;
+pub type LateLintPassObject = Box<dyn for<'tcx> LateLintPass<'tcx> + sync::Send + 'static>;
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 1b47d11f6f8..6eca7dc52b2 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -157,6 +157,7 @@ symbols! {
         BTreeSet,
         BinaryHeap,
         Borrow,
+        BorrowMut,
         Break,
         C,
         CStr,
diff --git a/compiler/rustc_traits/src/type_op.rs b/compiler/rustc_traits/src/type_op.rs
index d895b647db0..60e9b88107d 100644
--- a/compiler/rustc_traits/src/type_op.rs
+++ b/compiler/rustc_traits/src/type_op.rs
@@ -120,6 +120,7 @@ impl<'me, 'tcx> AscribeUserTypeCx<'me, 'tcx> {
         EarlyBinder(value).subst(self.tcx(), substs)
     }
 
+    #[instrument(level = "debug", skip(self))]
     fn relate_mir_and_user_ty(
         &mut self,
         mir_ty: Ty<'tcx>,
@@ -132,8 +133,8 @@ impl<'me, 'tcx> AscribeUserTypeCx<'me, 'tcx> {
 
         let ty = tcx.type_of(def_id);
         let ty = self.subst(ty, substs);
-        debug!("relate_type_and_user_type: ty of def-id is {:?}", ty);
         let ty = self.normalize(ty);
+        debug!("relate_type_and_user_type: ty of def-id is {:?}", ty);
 
         self.relate(mir_ty, Variance::Invariant, ty)?;
 
@@ -144,7 +145,7 @@ impl<'me, 'tcx> AscribeUserTypeCx<'me, 'tcx> {
         // outlives" error messages.
         let instantiated_predicates =
             self.tcx().predicates_of(def_id).instantiate(self.tcx(), substs);
-        debug!(?instantiated_predicates.predicates);
+        debug!(?instantiated_predicates);
         for instantiated_predicate in instantiated_predicates.predicates {
             let instantiated_predicate = self.normalize(instantiated_predicate);
             self.prove_predicate(instantiated_predicate, span);
diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs
index 71ae54bedce..33d74249e7b 100644
--- a/compiler/rustc_typeck/src/check/expr.rs
+++ b/compiler/rustc_typeck/src/check/expr.rs
@@ -2605,32 +2605,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         if let Some((fields, substs)) =
             self.get_field_candidates_considering_privacy(span, expr_t, mod_id)
         {
-            for candidate_field in fields {
-                if let Some(mut field_path) = self.check_for_nested_field_satisfying(
-                    span,
-                    &|candidate_field, _| candidate_field.ident(self.tcx()) == field,
-                    candidate_field,
-                    substs,
-                    vec![],
-                    mod_id,
-                ) {
-                    // field_path includes `field` that we're looking for, so pop it.
+            let candidate_fields: Vec<_> = fields
+                .filter_map(|candidate_field| {
+                    self.check_for_nested_field_satisfying(
+                        span,
+                        &|candidate_field, _| candidate_field.ident(self.tcx()) == field,
+                        candidate_field,
+                        substs,
+                        vec![],
+                        mod_id,
+                    )
+                })
+                .map(|mut field_path| {
                     field_path.pop();
-
-                    let field_path_str = field_path
+                    field_path
                         .iter()
                         .map(|id| id.name.to_ident_string())
                         .collect::<Vec<String>>()
-                        .join(".");
-                    debug!("field_path_str: {:?}", field_path_str);
-
-                    err.span_suggestion_verbose(
-                        field.span.shrink_to_lo(),
-                        "one of the expressions' fields has a field of the same name",
-                        format!("{field_path_str}."),
-                        Applicability::MaybeIncorrect,
-                    );
-                }
+                        .join(".")
+                })
+                .collect::<Vec<_>>();
+
+            let len = candidate_fields.len();
+            if len > 0 {
+                err.span_suggestions(
+                    field.span.shrink_to_lo(),
+                    format!(
+                        "{} of the expressions' fields {} a field of the same name",
+                        if len > 1 { "some" } else { "one" },
+                        if len > 1 { "have" } else { "has" },
+                    ),
+                    candidate_fields.iter().map(|path| format!("{path}.")),
+                    Applicability::MaybeIncorrect,
+                );
             }
         }
         err
diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs
index 8bb8c7ac515..e532f392157 100644
--- a/compiler/rustc_typeck/src/check/method/suggest.rs
+++ b/compiler/rustc_typeck/src/check/method/suggest.rs
@@ -1350,42 +1350,68 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         item_name: Ident,
     ) {
         if let SelfSource::MethodCall(expr) = source
-            && let mod_id = self.tcx.parent_module(expr.hir_id).to_def_id()
-            && let Some((fields, substs)) = self.get_field_candidates_considering_privacy(span, actual, mod_id)
+        && let mod_id = self.tcx.parent_module(expr.hir_id).to_def_id()
+        && let Some((fields, substs)) =
+            self.get_field_candidates_considering_privacy(span, actual, mod_id)
         {
             let call_expr = self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
-            for candidate_field in fields {
-                if let Some(field_path) = self.check_for_nested_field_satisfying(
-                    span,
-                    &|_, field_ty| {
-                        self.lookup_probe(
-                            span,
-                            item_name,
-                            field_ty,
-                            call_expr,
-                            ProbeScope::AllTraits,
-                        )
-                        .is_ok()
-                    },
-                    candidate_field,
-                    substs,
-                    vec![],
-                    mod_id,
-                ) {
-                    let field_path_str = field_path
+
+            let lang_items = self.tcx.lang_items();
+            let never_mention_traits = [
+                lang_items.clone_trait(),
+                lang_items.deref_trait(),
+                lang_items.deref_mut_trait(),
+                self.tcx.get_diagnostic_item(sym::AsRef),
+                self.tcx.get_diagnostic_item(sym::AsMut),
+                self.tcx.get_diagnostic_item(sym::Borrow),
+                self.tcx.get_diagnostic_item(sym::BorrowMut),
+            ];
+            let candidate_fields: Vec<_> = fields
+                .filter_map(|candidate_field| {
+                    self.check_for_nested_field_satisfying(
+                        span,
+                        &|_, field_ty| {
+                            self.lookup_probe(
+                                span,
+                                item_name,
+                                field_ty,
+                                call_expr,
+                                ProbeScope::TraitsInScope,
+                            )
+                            .map_or(false, |pick| {
+                                !never_mention_traits
+                                    .iter()
+                                    .flatten()
+                                    .any(|def_id| self.tcx.parent(pick.item.def_id) == *def_id)
+                            })
+                        },
+                        candidate_field,
+                        substs,
+                        vec![],
+                        mod_id,
+                    )
+                })
+                .map(|field_path| {
+                    field_path
                         .iter()
                         .map(|id| id.name.to_ident_string())
                         .collect::<Vec<String>>()
-                        .join(".");
-                    debug!("field_path_str: {:?}", field_path_str);
-
-                    err.span_suggestion_verbose(
-                        item_name.span.shrink_to_lo(),
-                        "one of the expressions' fields has a method of the same name",
-                        format!("{field_path_str}."),
-                        Applicability::MaybeIncorrect,
-                    );
-                }
+                        .join(".")
+                })
+                .collect();
+
+            let len = candidate_fields.len();
+            if len > 0 {
+                err.span_suggestions(
+                    item_name.span.shrink_to_lo(),
+                    format!(
+                        "{} of the expressions' fields {} a method of the same name",
+                        if len > 1 { "some" } else { "one" },
+                        if len > 1 { "have" } else { "has" },
+                    ),
+                    candidate_fields.iter().map(|path| format!("{path}.")),
+                    Applicability::MaybeIncorrect,
+                );
             }
         }
     }
diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs
index 2b2ef64fdb1..242f44ade8a 100644
--- a/library/core/src/primitive_docs.rs
+++ b/library/core/src/primitive_docs.rs
@@ -1223,7 +1223,7 @@ mod prim_usize {}
 #[doc(alias = "&")]
 #[doc(alias = "&mut")]
 //
-/// References, both shared and mutable.
+/// References, `&T` and `&mut T`.
 ///
 /// A reference represents a borrow of some owned value. You can get one by using the `&` or `&mut`
 /// operators on a value, or by using a [`ref`](../std/keyword.ref.html) or
diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs
index 2b2ef64fdb1..242f44ade8a 100644
--- a/library/std/src/primitive_docs.rs
+++ b/library/std/src/primitive_docs.rs
@@ -1223,7 +1223,7 @@ mod prim_usize {}
 #[doc(alias = "&")]
 #[doc(alias = "&mut")]
 //
-/// References, both shared and mutable.
+/// References, `&T` and `&mut T`.
 ///
 /// A reference represents a borrow of some owned value. You can get one by using the `&` or `&mut`
 /// operators on a value, or by using a [`ref`](../std/keyword.ref.html) or
diff --git a/src/etc/check_missing_items.py b/src/etc/check_missing_items.py
index ce06a79a21c..025f320e3a1 100644
--- a/src/etc/check_missing_items.py
+++ b/src/etc/check_missing_items.py
@@ -187,3 +187,9 @@ while work_list:
             check_generic_bound(bound)
         if item["inner"]["default"]:
             check_type(item["inner"]["default"])
+    elif item["kind"] == "import":
+        if item["inner"]["id"]:
+            inner_id = item["inner"]["id"]
+            assert valid_id(inner_id)
+            if inner_id in crate["index"] and inner_id not in visited:
+                work_list.add(inner_id)
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index c4e8b6f5f84..20b9eb1c27e 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -46,10 +46,14 @@ impl JsonRenderer<'_> {
             clean::KeywordItem => return None,
             clean::StrippedItem(ref inner) => {
                 match &**inner {
-                    // We document non-empty stripped modules as with `Module::is_stripped` set to
+                    // We document stripped modules as with `Module::is_stripped` set to
                     // `true`, to prevent contained items from being orphaned for downstream users,
                     // as JSON does no inlining.
-                    clean::ModuleItem(m) if !m.items.is_empty() => from_clean_item(item, self.tcx),
+                    clean::ModuleItem(_)
+                        if self.imported_items.contains(&item_id.expect_def_id()) =>
+                    {
+                        from_clean_item(item, self.tcx)
+                    }
                     _ => return None,
                 }
             }
diff --git a/src/librustdoc/json/import_finder.rs b/src/librustdoc/json/import_finder.rs
new file mode 100644
index 00000000000..c5c687df74f
--- /dev/null
+++ b/src/librustdoc/json/import_finder.rs
@@ -0,0 +1,38 @@
+use rustc_data_structures::fx::FxHashSet;
+use rustc_hir::def_id::DefId;
+
+use crate::{
+    clean::{self, Import, ImportSource, Item},
+    fold::DocFolder,
+};
+
+/// Get the id's of all items that are `pub use`d in the crate.
+///
+/// We need this to know if a stripped module is `pub use mod::*`, to decide
+/// if it needs to be kept in the index, despite being stripped.
+///
+/// See [#100973](https://github.com/rust-lang/rust/issues/100973) and
+/// [#101103](https://github.com/rust-lang/rust/issues/101103) for times when
+/// this information is needed.
+pub(crate) fn get_imports(krate: clean::Crate) -> (clean::Crate, FxHashSet<DefId>) {
+    let mut finder = ImportFinder { imported: FxHashSet::default() };
+    let krate = finder.fold_crate(krate);
+    (krate, finder.imported)
+}
+
+struct ImportFinder {
+    imported: FxHashSet<DefId>,
+}
+
+impl DocFolder for ImportFinder {
+    fn fold_item(&mut self, i: Item) -> Option<Item> {
+        match *i.kind {
+            clean::ImportItem(Import { source: ImportSource { did: Some(did), .. }, .. }) => {
+                self.imported.insert(did);
+                Some(i)
+            }
+
+            _ => Some(self.fold_item_recur(i)),
+        }
+    }
+}
diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs
index b78f8f2b4f1..6a1409c7394 100644
--- a/src/librustdoc/json/mod.rs
+++ b/src/librustdoc/json/mod.rs
@@ -5,6 +5,7 @@
 //! docs for usage and details.
 
 mod conversions;
+mod import_finder;
 
 use std::cell::RefCell;
 use std::fs::{create_dir_all, File};
@@ -12,7 +13,7 @@ use std::io::{BufWriter, Write};
 use std::path::PathBuf;
 use std::rc::Rc;
 
-use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir::def_id::DefId;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::Session;
@@ -39,6 +40,7 @@ pub(crate) struct JsonRenderer<'tcx> {
     /// The directory where the blob will be written to.
     out_path: PathBuf,
     cache: Rc<Cache>,
+    imported_items: FxHashSet<DefId>,
 }
 
 impl<'tcx> JsonRenderer<'tcx> {
@@ -159,12 +161,16 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
         tcx: TyCtxt<'tcx>,
     ) -> Result<(Self, clean::Crate), Error> {
         debug!("Initializing json renderer");
+
+        let (krate, imported_items) = import_finder::get_imports(krate);
+
         Ok((
             JsonRenderer {
                 tcx,
                 index: Rc::new(RefCell::new(FxHashMap::default())),
                 out_path: options.output,
                 cache: Rc::new(cache),
+                imported_items,
             },
             krate,
         ))
diff --git a/src/test/rustdoc-json/reexport/glob_collision.rs b/src/test/rustdoc-json/reexport/glob_collision.rs
new file mode 100644
index 00000000000..f91144dbfad
--- /dev/null
+++ b/src/test/rustdoc-json/reexport/glob_collision.rs
@@ -0,0 +1,28 @@
+// Regression test for https://github.com/rust-lang/rust/issues/100973
+
+#![feature(no_core)]
+#![no_core]
+
+// @set m1 = "$.index[*][?(@.name == 'm1' && @.kind == 'module')].id"
+// @is "$.index[*][?(@.name == 'm1' && @.kind == 'module')].inner.items" []
+// @is "$.index[*][?(@.name == 'm1' && @.kind == 'module')].inner.is_stripped" true
+mod m1 {
+    pub fn f() {}
+}
+// @set m2 = "$.index[*][?(@.name == 'm2' && @.kind == 'module')].id"
+// @is "$.index[*][?(@.name == 'm2' && @.kind == 'module')].inner.items" []
+// @is "$.index[*][?(@.name == 'm2' && @.kind == 'module')].inner.is_stripped" true
+mod m2 {
+    pub fn f(_: u8) {}
+}
+
+// @set m1_use = "$.index[*][?(@.inner.name=='m1')].id"
+// @is "$.index[*][?(@.inner.name=='m1')].inner.id" $m1
+// @is "$.index[*][?(@.inner.name=='m1')].inner.glob" true
+pub use m1::*;
+// @set m2_use = "$.index[*][?(@.inner.name=='m2')].id"
+// @is "$.index[*][?(@.inner.name=='m2')].inner.id" $m2
+// @is "$.index[*][?(@.inner.name=='m2')].inner.glob" true
+pub use m2::*;
+
+// @ismany "$.index[*][?(@.inner.is_crate==true)].inner.items[*]" $m1_use $m2_use
diff --git a/src/test/rustdoc-json/reexport/glob_empty_mod.rs b/src/test/rustdoc-json/reexport/glob_empty_mod.rs
new file mode 100644
index 00000000000..da68228352c
--- /dev/null
+++ b/src/test/rustdoc-json/reexport/glob_empty_mod.rs
@@ -0,0 +1,8 @@
+// Regression test for https://github.com/rust-lang/rust/issues/100973
+
+// @is "$.index[*][?(@.name=='m1' && @.kind == 'module')].inner.is_stripped" true
+// @set m1 = "$.index[*][?(@.name=='m1')].id"
+mod m1 {}
+
+// @is "$.index[*][?(@.inner.name=='m1' && @.kind=='import')].inner.id" $m1
+pub use m1::*;
diff --git a/src/test/rustdoc-json/reexport/in_root_and_mod.rs b/src/test/rustdoc-json/reexport/in_root_and_mod.rs
index 68cb694f499..7b97ebf2129 100644
--- a/src/test/rustdoc-json/reexport/in_root_and_mod.rs
+++ b/src/test/rustdoc-json/reexport/in_root_and_mod.rs
@@ -1,8 +1,7 @@
 #![feature(no_core)]
 #![no_core]
 
-// @is "$.index[*][?(@.name=='foo')].kind" \"module\"
-// @is "$.index[*][?(@.name=='foo')].inner.is_stripped" "true"
+// @!has "$.index[*][?(@.name=='foo')]"
 mod foo {
     // @has "$.index[*][?(@.name=='Foo')]"
     pub struct Foo;
diff --git a/src/test/rustdoc-json/reexport/mod_not_included.rs b/src/test/rustdoc-json/reexport/mod_not_included.rs
new file mode 100644
index 00000000000..7b7600ef20f
--- /dev/null
+++ b/src/test/rustdoc-json/reexport/mod_not_included.rs
@@ -0,0 +1,14 @@
+// Regression test for https://github.com/rust-lang/rust/issues/101103
+
+#![feature(no_core)]
+#![no_core]
+
+mod m1 {
+    pub fn x() {}
+}
+
+pub use m1::x;
+
+// @has "$.index[*][?(@.name=='x' && @.kind=='function')]"
+// @has "$.index[*][?(@.kind=='import' && @.inner.name=='x')].inner.source" '"m1::x"'
+// @!has "$.index[*][?(@.name=='m1')]"
diff --git a/src/test/rustdoc-json/reexport/private_two_names.rs b/src/test/rustdoc-json/reexport/private_two_names.rs
index ec78b06d09a..9858538a9d0 100644
--- a/src/test/rustdoc-json/reexport/private_two_names.rs
+++ b/src/test/rustdoc-json/reexport/private_two_names.rs
@@ -6,8 +6,7 @@
 #![no_core]
 #![feature(no_core)]
 
-// @is "$.index[*][?(@.name=='style')].kind" \"module\"
-// @is "$.index[*][?(@.name=='style')].inner.is_stripped" "true"
+// @!has "$.index[*][?(@.name=='style')]"
 mod style {
     // @set color_struct_id = "$.index[*][?(@.kind=='struct' && @.name=='Color')].id"
     pub struct Color;
diff --git a/src/test/rustdoc-json/reexport/rename_private.rs b/src/test/rustdoc-json/reexport/rename_private.rs
index 1537f834481..8fd850f9b13 100644
--- a/src/test/rustdoc-json/reexport/rename_private.rs
+++ b/src/test/rustdoc-json/reexport/rename_private.rs
@@ -3,8 +3,7 @@
 #![no_core]
 #![feature(no_core)]
 
-// @is "$.index[*][?(@.name=='inner')].kind" \"module\"
-// @is "$.index[*][?(@.name=='inner')].inner.is_stripped" "true"
+// @!has "$.index[*][?(@.kind=='inner')]"
 mod inner {
     // @has "$.index[*][?(@.name=='Public')]"
     pub struct Public;
diff --git a/src/test/rustdoc-json/reexport/simple_private.rs b/src/test/rustdoc-json/reexport/simple_private.rs
index 82348b383c3..d058ce0598d 100644
--- a/src/test/rustdoc-json/reexport/simple_private.rs
+++ b/src/test/rustdoc-json/reexport/simple_private.rs
@@ -2,16 +2,15 @@
 #![no_core]
 #![feature(no_core)]
 
-// @is "$.index[*][?(@.name=='inner')].kind" \"module\"
-// @is "$.index[*][?(@.name=='inner')].inner.is_stripped" "true"
+// @!has "$.index[*][?(@.name=='inner')]"
 mod inner {
     // @set pub_id = "$.index[*][?(@.name=='Public')].id"
     pub struct Public;
 }
 
 // @is "$.index[*][?(@.kind=='import')].inner.name" \"Public\"
+// @is "$.index[*][?(@.kind=='import')].inner.id" $pub_id
 // @set use_id = "$.index[*][?(@.kind=='import')].id"
 pub use inner::Public;
 
-// @ismany "$.index[*][?(@.name=='inner')].inner.items[*]" $pub_id
 // @ismany "$.index[*][?(@.name=='simple_private')].inner.items[*]" $use_id
diff --git a/src/test/rustdoc-json/stripped_modules.rs b/src/test/rustdoc-json/stripped_modules.rs
index 33e95ce69d0..d2664b49e9c 100644
--- a/src/test/rustdoc-json/stripped_modules.rs
+++ b/src/test/rustdoc-json/stripped_modules.rs
@@ -12,7 +12,7 @@ mod pub_inner_unreachable {
     pub fn pub_inner_1() {}
 }
 
-// @has "$.index[*][?(@.name=='pub_inner_reachable')]"
+// @!has "$.index[*][?(@.name=='pub_inner_reachable')]"
 mod pub_inner_reachable {
     // @has "$.index[*][?(@.name=='pub_inner_2')]"
     pub fn pub_inner_2() {}
diff --git a/src/test/ui/consts/miri_unleashed/ptr_arith.rs b/src/test/ui/consts/miri_unleashed/ptr_arith.rs
index 13e6af36e02..6a19b294585 100644
--- a/src/test/ui/consts/miri_unleashed/ptr_arith.rs
+++ b/src/test/ui/consts/miri_unleashed/ptr_arith.rs
@@ -8,7 +8,7 @@
 static PTR_INT_CAST: () = {
     let x = &0 as *const _ as usize;
     //~^ ERROR could not evaluate static initializer
-    //~| "exposing pointers" needs an rfc before being allowed inside constants
+    //~| exposing pointers
     let _v = x == x;
 };
 
@@ -19,4 +19,7 @@ static PTR_INT_TRANSMUTE: () = unsafe {
     //~| unable to turn pointer into raw bytes
 };
 
+// I'd love to test pointer comparison, but that is not possible since
+// their `PartialEq` impl is non-`const`.
+
 fn main() {}
diff --git a/src/test/ui/consts/miri_unleashed/ptr_arith.stderr b/src/test/ui/consts/miri_unleashed/ptr_arith.stderr
index 00cff23fb3f..f5c5ee2b8eb 100644
--- a/src/test/ui/consts/miri_unleashed/ptr_arith.stderr
+++ b/src/test/ui/consts/miri_unleashed/ptr_arith.stderr
@@ -2,7 +2,7 @@ error[E0080]: could not evaluate static initializer
   --> $DIR/ptr_arith.rs:9:13
    |
 LL |     let x = &0 as *const _ as usize;
-   |             ^^^^^^^^^^^^^^^^^^^^^^^ "exposing pointers" needs an rfc before being allowed inside constants
+   |             ^^^^^^^^^^^^^^^^^^^^^^^ exposing pointers is not possible at compile-time
 
 error[E0080]: could not evaluate static initializer
   --> $DIR/ptr_arith.rs:17:14
diff --git a/src/test/ui/copy-a-resource.stderr b/src/test/ui/copy-a-resource.stderr
index b92449c6e0a..128087f1e37 100644
--- a/src/test/ui/copy-a-resource.stderr
+++ b/src/test/ui/copy-a-resource.stderr
@@ -10,10 +10,6 @@ LL |     let _y = x.clone();
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `clone`, perhaps you need to implement it:
            candidate #1: `Clone`
-help: one of the expressions' fields has a method of the same name
-   |
-LL |     let _y = x.i.clone();
-   |                ++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-2823.stderr b/src/test/ui/issues/issue-2823.stderr
index 208b340d064..b5a2b2f55a6 100644
--- a/src/test/ui/issues/issue-2823.stderr
+++ b/src/test/ui/issues/issue-2823.stderr
@@ -10,10 +10,6 @@ LL |     let _d = c.clone();
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `clone`, perhaps you need to implement it:
            candidate #1: `Clone`
-help: one of the expressions' fields has a method of the same name
-   |
-LL |     let _d = c.x.clone();
-   |                ++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/noncopyable-class.stderr b/src/test/ui/noncopyable-class.stderr
index 15e22e946da..0c696163a26 100644
--- a/src/test/ui/noncopyable-class.stderr
+++ b/src/test/ui/noncopyable-class.stderr
@@ -10,14 +10,6 @@ LL |     let _y = x.clone();
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `clone`, perhaps you need to implement it:
            candidate #1: `Clone`
-help: one of the expressions' fields has a method of the same name
-   |
-LL |     let _y = x.i.clone();
-   |                ++
-help: one of the expressions' fields has a method of the same name
-   |
-LL |     let _y = x.j.x.clone();
-   |                ++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/suggestions/too-many-field-suggestions.rs b/src/test/ui/suggestions/too-many-field-suggestions.rs
new file mode 100644
index 00000000000..905f9502cf5
--- /dev/null
+++ b/src/test/ui/suggestions/too-many-field-suggestions.rs
@@ -0,0 +1,29 @@
+struct Thing {
+    a0: Foo,
+    a1: Foo,
+    a2: Foo,
+    a3: Foo,
+    a4: Foo,
+    a5: Foo,
+    a6: Foo,
+    a7: Foo,
+    a8: Foo,
+    a9: Foo,
+}
+
+struct Foo {
+    field: Field,
+}
+
+struct Field;
+
+impl Foo {
+    fn bar(&self) {}
+}
+
+fn bar(t: Thing) {
+    t.bar(); //~ ERROR no method named `bar` found for struct `Thing`
+    t.field; //~ ERROR no field `field` on type `Thing`
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/too-many-field-suggestions.stderr b/src/test/ui/suggestions/too-many-field-suggestions.stderr
new file mode 100644
index 00000000000..63ad6fdb169
--- /dev/null
+++ b/src/test/ui/suggestions/too-many-field-suggestions.stderr
@@ -0,0 +1,44 @@
+error[E0599]: no method named `bar` found for struct `Thing` in the current scope
+  --> $DIR/too-many-field-suggestions.rs:25:7
+   |
+LL | struct Thing {
+   | ------------ method `bar` not found for this struct
+...
+LL |     t.bar();
+   |       ^^^ method not found in `Thing`
+   |
+help: some of the expressions' fields have a method of the same name
+   |
+LL |     t.a0.bar();
+   |       +++
+LL |     t.a1.bar();
+   |       +++
+LL |     t.a2.bar();
+   |       +++
+LL |     t.a3.bar();
+   |       +++
+     and 6 other candidates
+
+error[E0609]: no field `field` on type `Thing`
+  --> $DIR/too-many-field-suggestions.rs:26:7
+   |
+LL |     t.field;
+   |       ^^^^^ unknown field
+   |
+   = note: available fields are: `a0`, `a1`, `a2`, `a3`, `a4` ... and 5 others
+help: some of the expressions' fields have a field of the same name
+   |
+LL |     t.a0.field;
+   |       +++
+LL |     t.a1.field;
+   |       +++
+LL |     t.a2.field;
+   |       +++
+LL |     t.a3.field;
+   |       +++
+     and 6 other candidates
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0599, E0609.
+For more information about an error, try `rustc --explain E0599`.