about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-09-10 14:48:34 +0000
committerbors <bors@rust-lang.org>2022-09-10 14:48:34 +0000
commit14636887008d9ee67a12b4f05f1e404ed1d64579 (patch)
tree7c8889fb012b18c3636ed35e7f7f421c6e64da5d
parent2e44c17c12cec45b6a682b1e53a04ac5b5fcc9d2 (diff)
parent783561029c071cc42f00435e1b1610873c1f9352 (diff)
downloadrust-14636887008d9ee67a12b4f05f1e404ed1d64579.tar.gz
rust-14636887008d9ee67a12b4f05f1e404ed1d64579.zip
Auto merge of #101652 - Dylan-DPC:rollup-f4atky0, r=Dylan-DPC
Rollup of 6 pull requests

Successful merges:

 - #101578 (remove bound var hack in `resolve`)
 - #101606 (doc: fix minor typo)
 - #101614 (Equate fn outputs when inferring RPITIT hidden types)
 - #101631 (rustdoc: avoid cleaning modules with duplicate names)
 - #101635 (Move `Queries::new` out of the macro)
 - #101641 (Update browser-ui-test version to 0.9.8)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_data_structures/src/sync.rs2
-rw-r--r--compiler/rustc_middle/src/query/mod.rs7
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs2
-rw-r--r--compiler/rustc_monomorphize/src/lib.rs2
-rw-r--r--compiler/rustc_query_impl/src/plumbing.rs35
-rw-r--r--compiler/rustc_trait_selection/src/traits/codegen.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs2
-rw-r--r--compiler/rustc_ty_utils/src/instance.rs113
-rw-r--r--compiler/rustc_typeck/src/check/compare_method.rs19
-rw-r--r--library/std/src/thread/mod.rs2
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version2
-rw-r--r--src/librustdoc/clean/mod.rs19
-rw-r--r--src/librustdoc/visit_ast.rs12
-rw-r--r--src/test/rustdoc/glob-shadowing-const.rs20
-rw-r--r--src/test/rustdoc/glob-shadowing.rs86
-rw-r--r--src/test/rustdoc/issue-83375-multiple-mods-w-same-name-doc-inline-last-item.rs16
-rw-r--r--src/test/rustdoc/issue-83375-multiple-mods-w-same-name-doc-inline.rs16
-rw-r--r--src/test/ui/const-generics/issues/issue-83765.stderr4
18 files changed, 215 insertions, 146 deletions
diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs
index 258780ecaea..9c0fb8265cf 100644
--- a/compiler/rustc_data_structures/src/sync.rs
+++ b/compiler/rustc_data_structures/src/sync.rs
@@ -48,7 +48,7 @@ cfg_if! {
         /// the native atomic types.
         /// You should use this type through the `AtomicU64`, `AtomicUsize`, etc, type aliases
         /// as it's not intended to be used separately.
-        #[derive(Debug)]
+        #[derive(Debug, Default)]
         pub struct Atomic<T: Copy>(Cell<T>);
 
         impl<T: Copy> Atomic<T> {
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index adf479c4236..f72e7389fc6 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -1202,14 +1202,11 @@ rustc_queries! {
         }
     }
 
-    query codegen_fulfill_obligation(
+    query codegen_select_candidate(
         key: (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>)
     ) -> Result<&'tcx ImplSource<'tcx, ()>, traits::CodegenObligationError> {
         cache_on_disk_if { true }
-        desc { |tcx|
-            "checking if `{}` fulfills its obligations",
-            tcx.def_path_str(key.1.def_id())
-        }
+        desc { |tcx| "computing candidate for `{}`", key.1 }
     }
 
     /// Return all `impl` blocks in the current crate.
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index a56fac7c4dd..755d9f8f696 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -1024,7 +1024,7 @@ pub enum MethodViolationCode {
     UndispatchableReceiver(Option<Span>),
 }
 
-/// These are the error cases for `codegen_fulfill_obligation`.
+/// These are the error cases for `codegen_select_candidate`.
 #[derive(Copy, Clone, Debug, Hash, HashStable, Encodable, Decodable)]
 pub enum CodegenObligationError {
     /// Ambiguity can happen when monomorphizing during trans
diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs
index d64de44705b..3afff7bcabf 100644
--- a/compiler/rustc_monomorphize/src/lib.rs
+++ b/compiler/rustc_monomorphize/src/lib.rs
@@ -35,7 +35,7 @@ fn custom_coerce_unsize_info<'tcx>(
         substs: tcx.mk_substs_trait(source_ty, &[target_ty.into()]),
     });
 
-    match tcx.codegen_fulfill_obligation((ty::ParamEnv::reveal_all(), trait_ref)) {
+    match tcx.codegen_select_candidate((ty::ParamEnv::reveal_all(), trait_ref)) {
         Ok(traits::ImplSource::UserDefined(traits::ImplSourceUserDefinedData {
             impl_def_id,
             ..
diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs
index 1e375deb20d..96679281f07 100644
--- a/compiler/rustc_query_impl/src/plumbing.rs
+++ b/compiler/rustc_query_impl/src/plumbing.rs
@@ -5,7 +5,7 @@
 use crate::keys::Key;
 use crate::{on_disk_cache, Queries};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_data_structures::sync::Lock;
+use rustc_data_structures::sync::{AtomicU64, Lock};
 use rustc_errors::{Diagnostic, Handler};
 use rustc_middle::dep_graph::{
     self, DepKind, DepKindStruct, DepNode, DepNodeIndex, SerializedDepNodeIndex,
@@ -499,9 +499,28 @@ macro_rules! define_queries {
     }
 }
 
+use crate::{ExternProviders, OnDiskCache, Providers};
+
+impl<'tcx> Queries<'tcx> {
+    pub fn new(
+        local_providers: Providers,
+        extern_providers: ExternProviders,
+        on_disk_cache: Option<OnDiskCache<'tcx>>,
+    ) -> Self {
+        Queries {
+            local_providers: Box::new(local_providers),
+            extern_providers: Box::new(extern_providers),
+            on_disk_cache,
+            jobs: AtomicU64::new(1),
+            ..Queries::default()
+        }
+    }
+}
+
 macro_rules! define_queries_struct {
     (
      input: ($(([$($modifiers:tt)*] [$($attr:tt)*] [$name:ident]))*)) => {
+        #[derive(Default)]
         pub struct Queries<'tcx> {
             local_providers: Box<Providers>,
             extern_providers: Box<ExternProviders>,
@@ -514,20 +533,6 @@ macro_rules! define_queries_struct {
         }
 
         impl<'tcx> Queries<'tcx> {
-            pub fn new(
-                local_providers: Providers,
-                extern_providers: ExternProviders,
-                on_disk_cache: Option<OnDiskCache<'tcx>>,
-            ) -> Self {
-                Queries {
-                    local_providers: Box::new(local_providers),
-                    extern_providers: Box::new(extern_providers),
-                    on_disk_cache,
-                    jobs: AtomicU64::new(1),
-                    $($name: Default::default()),*
-                }
-            }
-
             pub(crate) fn try_collect_active_jobs(
                 &'tcx self,
                 tcx: TyCtxt<'tcx>,
diff --git a/compiler/rustc_trait_selection/src/traits/codegen.rs b/compiler/rustc_trait_selection/src/traits/codegen.rs
index 26f8e7d34c6..08adbcbd410 100644
--- a/compiler/rustc_trait_selection/src/traits/codegen.rs
+++ b/compiler/rustc_trait_selection/src/traits/codegen.rs
@@ -18,7 +18,7 @@ use rustc_middle::ty::{self, TyCtxt};
 /// obligations *could be* resolved if we wanted to.
 ///
 /// This also expects that `trait_ref` is fully normalized.
-pub fn codegen_fulfill_obligation<'tcx>(
+pub fn codegen_select_candidate<'tcx>(
     tcx: TyCtxt<'tcx>,
     (param_env, trait_ref): (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>),
 ) -> Result<&'tcx ImplSource<'tcx, ()>, CodegenObligationError> {
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 14e07809678..40596078f04 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -971,7 +971,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
     *providers = ty::query::Providers {
         specialization_graph_of: specialize::specialization_graph_provider,
         specializes: specialize::specializes,
-        codegen_fulfill_obligation: codegen::codegen_fulfill_obligation,
+        codegen_select_candidate: codegen::codegen_select_candidate,
         own_existential_vtable_entries,
         vtable_entries,
         vtable_trait_upcasting_coercion_new_vptr_slot,
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index 661e413fc5b..b55302de2a7 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -3,113 +3,11 @@ use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::traits::CodegenObligationError;
 use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::{
-    self, Binder, Instance, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor,
-};
+use rustc_middle::ty::{self, Instance, TyCtxt, TypeVisitable};
 use rustc_span::{sym, DUMMY_SP};
 use rustc_trait_selection::traits;
 use traits::{translate_substs, Reveal};
 
-use rustc_data_structures::sso::SsoHashSet;
-use std::collections::btree_map::Entry;
-use std::collections::BTreeMap;
-use std::ops::ControlFlow;
-
-// FIXME(#86795): `BoundVarsCollector` here should **NOT** be used
-// outside of `resolve_associated_item`. It's just to address #64494,
-// #83765, and #85848 which are creating bound types/regions that lose
-// their `Binder` *unintentionally*.
-// It's ideal to remove `BoundVarsCollector` and just use
-// `ty::Binder::*` methods but we use this stopgap until we figure out
-// the "real" fix.
-struct BoundVarsCollector<'tcx> {
-    binder_index: ty::DebruijnIndex,
-    vars: BTreeMap<u32, ty::BoundVariableKind>,
-    // We may encounter the same variable at different levels of binding, so
-    // this can't just be `Ty`
-    visited: SsoHashSet<(ty::DebruijnIndex, Ty<'tcx>)>,
-}
-
-impl<'tcx> BoundVarsCollector<'tcx> {
-    fn new() -> Self {
-        BoundVarsCollector {
-            binder_index: ty::INNERMOST,
-            vars: BTreeMap::new(),
-            visited: SsoHashSet::default(),
-        }
-    }
-
-    fn into_vars(self, tcx: TyCtxt<'tcx>) -> &'tcx ty::List<ty::BoundVariableKind> {
-        let max = self.vars.iter().map(|(k, _)| *k).max().unwrap_or(0);
-        for i in 0..max {
-            if let None = self.vars.get(&i) {
-                panic!("Unknown variable: {:?}", i);
-            }
-        }
-
-        tcx.mk_bound_variable_kinds(self.vars.into_iter().map(|(_, v)| v))
-    }
-}
-
-impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> {
-    type BreakTy = ();
-
-    fn visit_binder<T: TypeVisitable<'tcx>>(
-        &mut self,
-        t: &Binder<'tcx, T>,
-    ) -> ControlFlow<Self::BreakTy> {
-        self.binder_index.shift_in(1);
-        let result = t.super_visit_with(self);
-        self.binder_index.shift_out(1);
-        result
-    }
-
-    fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
-        if t.outer_exclusive_binder() < self.binder_index
-            || !self.visited.insert((self.binder_index, t))
-        {
-            return ControlFlow::CONTINUE;
-        }
-        match *t.kind() {
-            ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => {
-                match self.vars.entry(bound_ty.var.as_u32()) {
-                    Entry::Vacant(entry) => {
-                        entry.insert(ty::BoundVariableKind::Ty(bound_ty.kind));
-                    }
-                    Entry::Occupied(entry) => match entry.get() {
-                        ty::BoundVariableKind::Ty(_) => {}
-                        _ => bug!("Conflicting bound vars"),
-                    },
-                }
-            }
-
-            _ => (),
-        };
-
-        t.super_visit_with(self)
-    }
-
-    fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
-        match *r {
-            ty::ReLateBound(index, br) if index == self.binder_index => {
-                match self.vars.entry(br.var.as_u32()) {
-                    Entry::Vacant(entry) => {
-                        entry.insert(ty::BoundVariableKind::Region(br.kind));
-                    }
-                    Entry::Occupied(entry) => match entry.get() {
-                        ty::BoundVariableKind::Region(_) => {}
-                        _ => bug!("Conflicting bound vars"),
-                    },
-                }
-            }
-
-            _ => (),
-        };
-
-        r.super_visit_with(self)
-    }
-}
-
 fn resolve_instance<'tcx>(
     tcx: TyCtxt<'tcx>,
     key: ty::ParamEnvAnd<'tcx, (DefId, SubstsRef<'tcx>)>,
@@ -201,19 +99,14 @@ fn resolve_associated_item<'tcx>(
 
     let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs);
 
-    // See FIXME on `BoundVarsCollector`.
-    let mut bound_vars_collector = BoundVarsCollector::new();
-    trait_ref.visit_with(&mut bound_vars_collector);
-    let trait_binder = ty::Binder::bind_with_vars(trait_ref, bound_vars_collector.into_vars(tcx));
-    let vtbl = match tcx.codegen_fulfill_obligation((param_env, trait_binder)) {
+    let vtbl = match tcx.codegen_select_candidate((param_env, ty::Binder::dummy(trait_ref))) {
         Ok(vtbl) => vtbl,
         Err(CodegenObligationError::Ambiguity) => {
             let reported = tcx.sess.delay_span_bug(
                 tcx.def_span(trait_item_id),
                 &format!(
-                    "encountered ambiguity selecting `{:?}` during codegen, presuming due to \
+                    "encountered ambiguity selecting `{trait_ref:?}` during codegen, presuming due to \
                      overflow or prior type error",
-                    trait_binder
                 ),
             );
             return Err(reported);
diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs
index 1152a2477a2..13a96df77b6 100644
--- a/compiler/rustc_typeck/src/check/compare_method.rs
+++ b/compiler/rustc_typeck/src/check/compare_method.rs
@@ -295,12 +295,26 @@ pub(super) fn compare_predicates_and_trait_impl_trait_tys<'tcx>(
         // type would be more appropriate. In other places we have a `Vec<Span>`
         // corresponding to their `Vec<Predicate>`, but we don't have that here.
         // Fixing this would improve the output of test `issue-83765.rs`.
-        let sub_result = infcx
+        let mut result = infcx
             .at(&cause, param_env)
             .sup(trait_fty, impl_fty)
             .map(|infer_ok| ocx.register_infer_ok_obligations(infer_ok));
 
-        if let Err(terr) = sub_result {
+        // HACK(RPITIT): #101614. When we are trying to infer the hidden types for
+        // RPITITs, we need to equate the output tys instead of just subtyping. If
+        // we just use `sup` above, we'll end up `&'static str <: _#1t`, which causes
+        // us to infer `_#1t = #'_#2r str`, where `'_#2r` is unconstrained, which gets
+        // fixed up to `ReEmpty`, and which is certainly not what we want.
+        if trait_fty.has_infer_types() {
+            result = result.and_then(|()| {
+                infcx
+                    .at(&cause, param_env)
+                    .eq(trait_sig.output(), impl_sig.output())
+                    .map(|infer_ok| ocx.register_infer_ok_obligations(infer_ok))
+            });
+        }
+
+        if let Err(terr) = result {
             debug!("sub_types failed: impl ty {:?}, trait ty {:?}", impl_fty, trait_fty);
 
             let (impl_err_span, trait_err_span) =
@@ -445,6 +459,7 @@ pub(super) fn compare_predicates_and_trait_impl_trait_tys<'tcx>(
                             region
                         }
                     });
+                    debug!(%ty);
                     collected_tys.insert(def_id, ty);
                 }
                 Err(err) => {
diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs
index a17185b6f70..ceea6986e33 100644
--- a/library/std/src/thread/mod.rs
+++ b/library/std/src/thread/mod.rs
@@ -116,7 +116,7 @@
 //! Threads are able to have associated names for identification purposes. By default, spawned
 //! threads are unnamed. To specify a name for a thread, build the thread with [`Builder`] and pass
 //! the desired thread name to [`Builder::name`]. To retrieve the thread name from within the
-//! thread, use [`Thread::name`]. A couple examples of where the name of a thread gets used:
+//! thread, use [`Thread::name`]. A couple of examples where the name of a thread gets used:
 //!
 //! * If a panic occurs in a named thread, the thread name will be printed in the panic message.
 //! * The thread name is provided to the OS where applicable (e.g., `pthread_setname_np` in
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version
index bae256fd5b3..b5d0ec558fd 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version
@@ -1 +1 @@
-0.9.7
\ No newline at end of file
+0.9.8
\ No newline at end of file
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 08b696e65eb..bca3f4db4a8 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -50,14 +50,23 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext<
     let mut inserted = FxHashSet::default();
     items.extend(doc.foreigns.iter().map(|(item, renamed)| {
         let item = clean_maybe_renamed_foreign_item(cx, item, *renamed);
-        if let Some(name) = item.name {
+        if let Some(name) = item.name && !item.attrs.lists(sym::doc).has_word(sym::hidden) {
             inserted.insert((item.type_(), name));
         }
         item
     }));
-    items.extend(doc.mods.iter().map(|x| {
-        inserted.insert((ItemType::Module, x.name));
-        clean_doc_module(x, cx)
+    items.extend(doc.mods.iter().filter_map(|x| {
+        if !inserted.insert((ItemType::Module, x.name)) {
+            return None;
+        }
+        let item = clean_doc_module(x, cx);
+        if item.attrs.lists(sym::doc).has_word(sym::hidden) {
+            // Hidden modules are stripped at a later stage.
+            // If a hidden module has the same name as a visible one, we want
+            // to keep both of them around.
+            inserted.remove(&(ItemType::Module, x.name));
+        }
+        Some(item)
     }));
 
     // Split up imports from all other items.
@@ -72,7 +81,7 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext<
         }
         let v = clean_maybe_renamed_item(cx, item, *renamed);
         for item in &v {
-            if let Some(name) = item.name {
+            if let Some(name) = item.name && !item.attrs.lists(sym::doc).has_word(sym::hidden) {
                 inserted.insert((item.type_(), name));
             }
         }
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index ca7a20bf368..c27ac0ac40e 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -164,8 +164,20 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         self.inside_public_path &= self.cx.tcx.visibility(def_id).is_public();
         for &i in m.item_ids {
             let item = self.cx.tcx.hir().item(i);
+            if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
+                continue;
+            }
             self.visit_item(item, None, &mut om);
         }
+        for &i in m.item_ids {
+            let item = self.cx.tcx.hir().item(i);
+            // To match the way import precedence works, visit glob imports last.
+            // Later passes in rustdoc will de-duplicate by name and kind, so if glob-
+            // imported items appear last, then they'll be the ones that get discarded.
+            if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
+                self.visit_item(item, None, &mut om);
+            }
+        }
         self.inside_public_path = orig_inside_public_path;
         om
     }
diff --git a/src/test/rustdoc/glob-shadowing-const.rs b/src/test/rustdoc/glob-shadowing-const.rs
new file mode 100644
index 00000000000..5b786cf53f2
--- /dev/null
+++ b/src/test/rustdoc/glob-shadowing-const.rs
@@ -0,0 +1,20 @@
+// https://github.com/rust-lang/rust/pull/83872#issuecomment-820101008
+#![crate_name="foo"]
+
+mod sub4 {
+    /// 0
+    pub const X: usize = 0;
+    pub mod inner {
+        pub use super::*;
+        /// 1
+        pub const X: usize = 1;
+    }
+}
+
+#[doc(inline)]
+pub use sub4::inner::*;
+
+// @has 'foo/index.html'
+// @has - '//div[@class="item-right docblock-short"]' '1'
+// @!has - '//div[@class="item-right docblock-short"]' '0'
+fn main() { assert_eq!(X, 1); }
diff --git a/src/test/rustdoc/glob-shadowing.rs b/src/test/rustdoc/glob-shadowing.rs
new file mode 100644
index 00000000000..66a31c42bcf
--- /dev/null
+++ b/src/test/rustdoc/glob-shadowing.rs
@@ -0,0 +1,86 @@
+// @has 'glob_shadowing/index.html'
+// @count - '//div[@class="item-left module-item"]' 6
+// @!has - '//div[@class="item-right docblock-short"]' 'sub1::describe'
+// @has - '//div[@class="item-right docblock-short"]' 'sub2::describe'
+
+// @!has - '//div[@class="item-right docblock-short"]' 'sub1::describe2'
+
+// @!has - '//div[@class="item-right docblock-short"]' 'sub1::prelude'
+// @has - '//div[@class="item-right docblock-short"]' 'mod::prelude'
+
+// @has - '//div[@class="item-right docblock-short"]' 'sub1::Foo (struct)'
+// @has - '//div[@class="item-right docblock-short"]' 'mod::Foo (function)'
+
+// @has - '//div[@class="item-right docblock-short"]' 'sub4::inner::X'
+
+// @has 'glob_shadowing/fn.describe.html'
+// @has - '//div[@class="docblock"]' 'sub2::describe'
+
+mod sub1 {
+    // this should be shadowed by sub2::describe
+    /// sub1::describe
+    pub fn describe() -> &'static str {
+        "sub1::describe"
+    }
+
+    // this should be shadowed by mod::prelude
+    /// sub1::prelude
+    pub mod prelude {
+    }
+
+    // this should *not* be shadowed, because sub1::Foo and mod::Foo are in different namespaces
+    /// sub1::Foo (struct)
+    pub struct Foo;
+
+    // this should be shadowed,
+    // because both sub1::describe2 and sub3::describe2 are from glob reexport
+    /// sub1::describe2
+    pub fn describe2() -> &'static str {
+        "sub1::describe2"
+    }
+}
+
+mod sub2 {
+    /// sub2::describe
+    pub fn describe() -> &'static str {
+        "sub2::describe"
+    }
+}
+
+mod sub3 {
+    // this should be shadowed
+    // because both sub1::describe2 and sub3::describe2 are from glob reexport
+    /// sub3::describe2
+    pub fn describe2() -> &'static str {
+        "sub3::describe2"
+    }
+}
+
+mod sub4 {
+    // this should be shadowed by sub4::inner::X
+    /// sub4::X
+    pub const X: usize = 0;
+    pub mod inner {
+        pub use super::*;
+        /// sub4::inner::X
+        pub const X: usize = 1;
+    }
+}
+
+/// mod::Foo (function)
+pub fn Foo() {}
+
+#[doc(inline)]
+pub use sub2::describe;
+
+#[doc(inline)]
+pub use sub1::*;
+
+#[doc(inline)]
+pub use sub3::*;
+
+#[doc(inline)]
+pub use sub4::inner::*;
+
+/// mod::prelude
+pub mod prelude {}
diff --git a/src/test/rustdoc/issue-83375-multiple-mods-w-same-name-doc-inline-last-item.rs b/src/test/rustdoc/issue-83375-multiple-mods-w-same-name-doc-inline-last-item.rs
new file mode 100644
index 00000000000..d3a7a870b58
--- /dev/null
+++ b/src/test/rustdoc/issue-83375-multiple-mods-w-same-name-doc-inline-last-item.rs
@@ -0,0 +1,16 @@
+#![crate_name = "foo"]
+
+pub mod sub {
+    pub struct Item;
+
+    pub mod prelude {
+        pub use super::Item;
+    }
+}
+
+#[doc(inline)]
+pub use sub::*;
+
+// @count foo/index.html '//a[@class="mod"][@title="foo::prelude mod"]' 1
+// @count foo/prelude/index.html '//div[@class="item-row"]' 0
+pub mod prelude {}
diff --git a/src/test/rustdoc/issue-83375-multiple-mods-w-same-name-doc-inline.rs b/src/test/rustdoc/issue-83375-multiple-mods-w-same-name-doc-inline.rs
new file mode 100644
index 00000000000..b8369250993
--- /dev/null
+++ b/src/test/rustdoc/issue-83375-multiple-mods-w-same-name-doc-inline.rs
@@ -0,0 +1,16 @@
+#![crate_name = "foo"]
+
+pub mod sub {
+    pub struct Item;
+
+    pub mod prelude {
+        pub use super::Item;
+    }
+}
+
+// @count foo/index.html '//a[@class="mod"][@title="foo::prelude mod"]' 1
+// @count foo/prelude/index.html '//div[@class="item-row"]' 0
+pub mod prelude {}
+
+#[doc(inline)]
+pub use sub::*;
diff --git a/src/test/ui/const-generics/issues/issue-83765.stderr b/src/test/ui/const-generics/issues/issue-83765.stderr
index 28ddddf1be6..d5f914f46f8 100644
--- a/src/test/ui/const-generics/issues/issue-83765.stderr
+++ b/src/test/ui/const-generics/issues/issue-83765.stderr
@@ -4,13 +4,13 @@ error[E0391]: cycle detected when resolving instance `<LazyUpdim<T, { T::DIM },
 LL |     const DIM: usize;
    |     ^^^^^^^^^^^^^^^^
    |
-note: ...which requires checking if `TensorDimension` fulfills its obligations...
+note: ...which requires computing candidate for `<LazyUpdim<T, { T::DIM }, DIM> as TensorDimension>`...
   --> $DIR/issue-83765.rs:4:1
    |
 LL | trait TensorDimension {
    | ^^^^^^^^^^^^^^^^^^^^^
    = note: ...which again requires resolving instance `<LazyUpdim<T, { T::DIM }, DIM> as TensorDimension>::DIM`, completing the cycle
-note: cycle used when checking if `TensorDimension` fulfills its obligations
+note: cycle used when computing candidate for `<LazyUpdim<T, { T::DIM }, DIM> as TensorDimension>`
   --> $DIR/issue-83765.rs:4:1
    |
 LL | trait TensorDimension {