about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-06-21 13:53:11 +0000
committerbors <bors@rust-lang.org>2023-06-21 13:53:11 +0000
commit536635c89b2b6ec7054473f85a9b7a01932bd7e7 (patch)
tree58343f0a2ea23db3920c4258b33dba735c0ce5f6
parent38b44eb2335885844137f918c44c437f5a8da951 (diff)
parenta687a96df0512c67616085da5b72692d697cc2b3 (diff)
Auto merge of #112890 - GuillaumeGomez:rollup-7e01q69, r=GuillaumeGomez
Rollup of 7 pull requests

Successful merges:

 - #99587 (Document memory orderings of `thread::{park, unpark}`)
 - #112836 ([rustdoc] partially fix invalid files creation)
 - #112853 (Add `lazy_type_alias` feature gate)
 - #112863 (Fix copy-paste typo in `eprint(ln)` docs)
 - #112883 (Make queries traceable again)
 - #112885 (Fix msg passed to span_bug)
 - #112886 (Revert 'Rename profile=user to profile=dist')

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_expand/src/mbe/macro_rules.rs2
-rw-r--r--compiler/rustc_feature/src/active.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs2
-rw-r--r--compiler/rustc_query_impl/src/plumbing.rs10
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--library/std/src/macros.rs4
-rw-r--r--library/std/src/thread/mod.rs32
-rw-r--r--src/bootstrap/setup.rs14
-rw-r--r--src/librustdoc/clean/mod.rs21
-rw-r--r--src/librustdoc/clean/types.rs22
-rw-r--r--src/librustdoc/formats/cache.rs5
-rw-r--r--src/librustdoc/html/render/context.rs41
-rw-r--r--src/librustdoc/visit_ast.rs7
-rw-r--r--tests/rustdoc/alias-reexport.rs16
-rw-r--r--tests/rustdoc/alias-reexport2.rs16
-rw-r--r--tests/rustdoc/auxiliary/alias-reexport.rs3
-rw-r--r--tests/rustdoc/auxiliary/alias-reexport2.rs12
-rw-r--r--tests/rustdoc/files-creation-hidden.rs23
-rw-r--r--tests/rustdoc/files-creation-private.rs18
-rw-r--r--tests/rustdoc/issue-111064-reexport-trait-from-hidden-2.rs8
-rw-r--r--tests/rustdoc/issue-111249-file-creation.rs34
-rw-r--r--tests/rustdoc/redirect.rs2
22 files changed, 246 insertions, 49 deletions
diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs
index ee9616a0f0a..4a8a14994ff 100644
--- a/compiler/rustc_expand/src/mbe/macro_rules.rs
+++ b/compiler/rustc_expand/src/mbe/macro_rules.rs
@@ -535,7 +535,7 @@ pub fn compile_declarative_macro(
                     .pop()
                     .unwrap();
                 }
-                sess.parse_sess.span_diagnostic.span_bug(def.span, "wrong-structured lhs")
+                sess.parse_sess.span_diagnostic.span_bug(def.span, "wrong-structured rhs")
             })
             .collect::<Vec<mbe::TokenTree>>(),
         _ => sess.parse_sess.span_diagnostic.span_bug(def.span, "wrong-structured rhs"),
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index 20a33e7fb36..93f968aa851 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -442,6 +442,8 @@ declare_features! (
     (active, intra_doc_pointers, "1.51.0", Some(80896), None),
     // Allows setting the threshold for the `large_assignments` lint.
     (active, large_assignments, "1.52.0", Some(83518), None),
+    /// Allow to have type alias types for inter-crate use.
+    (active, lazy_type_alias, "CURRENT_RUSTC_VERSION", Some(112792), None),
     /// Allows `if/while p && let q = r && ...` chains.
     (active, let_chains, "1.37.0", Some(53667), None),
     /// Allows using `reason` in lint attributes and the `#[expect(lint)]` lint check.
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 12f66779522..41a6d94b278 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -896,7 +896,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         let ty = self.tcx().at(span).type_of(did);
 
         if matches!(self.tcx().def_kind(did), DefKind::TyAlias)
-            && ty.skip_binder().has_opaque_types()
+            && (ty.skip_binder().has_opaque_types() || self.tcx().features().lazy_type_alias)
         {
             // Type aliases referring to types that contain opaque types (but aren't just directly
             // referencing a single opaque type) get encoded as a type alias that normalization will
diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs
index 244f0e84b43..cb0df1d1b82 100644
--- a/compiler/rustc_query_impl/src/plumbing.rs
+++ b/compiler/rustc_query_impl/src/plumbing.rs
@@ -531,6 +531,8 @@ macro_rules! define_queries {
                     key: queries::$name::Key<'tcx>,
                     mode: QueryMode,
                 ) -> Option<Erase<queries::$name::Value<'tcx>>> {
+                    #[cfg(debug_assertions)]
+                    let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered();
                     get_query_incr(
                         QueryType::config(tcx),
                         QueryCtxt::new(tcx),
@@ -571,10 +573,16 @@ macro_rules! define_queries {
                     cache_on_disk: |tcx, key| ::rustc_middle::query::cached::$name(tcx, key),
                     execute_query: |tcx, key| erase(tcx.$name(key)),
                     compute: |tcx, key| {
+                        #[cfg(debug_assertions)]
+                        let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered();
                         __rust_begin_short_backtrace(||
                             queries::$name::provided_to_erased(
                                 tcx,
-                                call_provider!([$($modifiers)*][tcx, $name, key])
+                                {
+                                    let ret = call_provider!([$($modifiers)*][tcx, $name, key]);
+                                    tracing::trace!(?ret);
+                                    ret
+                                }
                             )
                         )
                     },
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index f15d2c22da4..c71ed2097b8 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -871,6 +871,7 @@ symbols! {
         large_assignments,
         lateout,
         lazy_normalization_consts,
+        lazy_type_alias,
         le,
         len,
         let_chains,
diff --git a/library/std/src/macros.rs b/library/std/src/macros.rs
index fcc5cfafd80..ba1b8cbfa56 100644
--- a/library/std/src/macros.rs
+++ b/library/std/src/macros.rs
@@ -154,7 +154,7 @@ macro_rules! println {
 ///
 /// Panics if writing to `io::stderr` fails.
 ///
-/// Writing to non-blocking stdout can cause an error, which will lead
+/// Writing to non-blocking stderr can cause an error, which will lead
 /// this macro to panic.
 ///
 /// # Examples
@@ -189,7 +189,7 @@ macro_rules! eprint {
 ///
 /// Panics if writing to `io::stderr` fails.
 ///
-/// Writing to non-blocking stdout can cause an error, which will lead
+/// Writing to non-blocking stderr can cause an error, which will lead
 /// this macro to panic.
 ///
 /// # Examples
diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs
index 1230bb5deed..e4581c2de78 100644
--- a/library/std/src/thread/mod.rs
+++ b/library/std/src/thread/mod.rs
@@ -889,7 +889,7 @@ impl Drop for PanicGuard {
 /// it is guaranteed that this function will not panic (it may abort the
 /// process if the implementation encounters some rare errors).
 ///
-/// # park and unpark
+/// # `park` and `unpark`
 ///
 /// Every thread is equipped with some basic low-level blocking support, via the
 /// [`thread::park`][`park`] function and [`thread::Thread::unpark`][`unpark`]
@@ -910,14 +910,6 @@ impl Drop for PanicGuard {
 ///   if it wasn't already. Because the token is initially absent, [`unpark`]
 ///   followed by [`park`] will result in the second call returning immediately.
 ///
-/// In other words, each [`Thread`] acts a bit like a spinlock that can be
-/// locked and unlocked using `park` and `unpark`.
-///
-/// Notice that being unblocked does not imply any synchronization with someone
-/// that unparked this thread, it could also be spurious.
-/// For example, it would be a valid, but inefficient, implementation to make both [`park`] and
-/// [`unpark`] return immediately without doing anything.
-///
 /// The API is typically used by acquiring a handle to the current thread,
 /// placing that handle in a shared data structure so that other threads can
 /// find it, and then `park`ing in a loop. When some desired condition is met, another
@@ -931,6 +923,23 @@ impl Drop for PanicGuard {
 ///
 /// * It can be implemented very efficiently on many platforms.
 ///
+/// # Memory Ordering
+///
+/// Calls to `park` _synchronize-with_ calls to `unpark`, meaning that memory
+/// operations performed before a call to `unpark` are made visible to the thread that
+/// consumes the token and returns from `park`. Note that all `park` and `unpark`
+/// operations for a given thread form a total order and `park` synchronizes-with
+/// _all_ prior `unpark` operations.
+///
+/// In atomic ordering terms, `unpark` performs a `Release` operation and `park`
+/// performs the corresponding `Acquire` operation. Calls to `unpark` for the same
+/// thread form a [release sequence].
+///
+/// Note that being unblocked does not imply a call was made to `unpark`, because
+/// wakeups can also be spurious. For example, a valid, but inefficient,
+/// implementation could have `park` and `unpark` return immediately without doing anything,
+/// making *all* wakeups spurious.
+///
 /// # Examples
 ///
 /// ```
@@ -944,7 +953,7 @@ impl Drop for PanicGuard {
 /// let parked_thread = thread::spawn(move || {
 ///     // We want to wait until the flag is set. We *could* just spin, but using
 ///     // park/unpark is more efficient.
-///     while !flag2.load(Ordering::Acquire) {
+///     while !flag2.load(Ordering::Relaxed) {
 ///         println!("Parking thread");
 ///         thread::park();
 ///         // We *could* get here spuriously, i.e., way before the 10ms below are over!
@@ -961,7 +970,7 @@ impl Drop for PanicGuard {
 /// // There is no race condition here, if `unpark`
 /// // happens first, `park` will return immediately.
 /// // Hence there is no risk of a deadlock.
-/// flag.store(true, Ordering::Release);
+/// flag.store(true, Ordering::Relaxed);
 /// println!("Unpark the thread");
 /// parked_thread.thread().unpark();
 ///
@@ -970,6 +979,7 @@ impl Drop for PanicGuard {
 ///
 /// [`unpark`]: Thread::unpark
 /// [`thread::park_timeout`]: park_timeout
+/// [release sequence]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release_sequence
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn park() {
     let guard = PanicGuard;
diff --git a/src/bootstrap/setup.rs b/src/bootstrap/setup.rs
index e13f3f0bd5e..7eb70de91f8 100644
--- a/src/bootstrap/setup.rs
+++ b/src/bootstrap/setup.rs
@@ -20,7 +20,7 @@ pub enum Profile {
     Codegen,
     Library,
     Tools,
-    Dist,
+    User,
     None,
 }
 
@@ -43,7 +43,7 @@ impl Profile {
     pub fn all() -> impl Iterator<Item = Self> {
         use Profile::*;
         // N.B. these are ordered by how they are displayed, not alphabetically
-        [Library, Compiler, Codegen, Tools, Dist, None].iter().copied()
+        [Library, Compiler, Codegen, Tools, User, None].iter().copied()
     }
 
     pub fn purpose(&self) -> String {
@@ -53,7 +53,7 @@ impl Profile {
             Compiler => "Contribute to the compiler itself",
             Codegen => "Contribute to the compiler, and also modify LLVM or codegen",
             Tools => "Contribute to tools which depend on the compiler, but do not modify it directly (e.g. rustdoc, clippy, miri)",
-            Dist => "Install Rust from source",
+            User => "Install Rust from source",
             None => "Do not modify `config.toml`"
         }
         .to_string()
@@ -73,7 +73,7 @@ impl Profile {
             Profile::Codegen => "codegen",
             Profile::Library => "library",
             Profile::Tools => "tools",
-            Profile::Dist => "dist",
+            Profile::User => "user",
             Profile::None => "none",
         }
     }
@@ -87,7 +87,7 @@ impl FromStr for Profile {
             "lib" | "library" => Ok(Profile::Library),
             "compiler" => Ok(Profile::Compiler),
             "llvm" | "codegen" => Ok(Profile::Codegen),
-            "maintainer" | "dist" => Ok(Profile::Dist),
+            "maintainer" | "user" => Ok(Profile::User),
             "tools" | "tool" | "rustdoc" | "clippy" | "miri" | "rustfmt" | "rls" => {
                 Ok(Profile::Tools)
             }
@@ -160,7 +160,7 @@ pub fn setup(config: &Config, profile: Profile) {
             "test src/tools/rustfmt",
         ],
         Profile::Library => &["check", "build", "test library/std", "doc"],
-        Profile::Dist => &["dist", "build"],
+        Profile::User => &["dist", "build"],
     };
 
     println!();
@@ -170,7 +170,7 @@ pub fn setup(config: &Config, profile: Profile) {
         println!("- `x.py {}`", cmd);
     }
 
-    if profile != Profile::Dist {
+    if profile != Profile::User {
         println!(
             "For more suggestions, see https://rustc-dev-guide.rust-lang.org/building/suggested.html"
         );
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 162fc831ad2..9a815694e1b 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -2023,8 +2023,8 @@ pub(crate) fn clean_middle_ty<'tcx>(
             Tuple(t.iter().map(|t| clean_middle_ty(bound_ty.rebind(t), cx, None, None)).collect())
         }
 
-        ty::Alias(ty::Projection, ref data) => {
-            clean_projection(bound_ty.rebind(*data), cx, parent_def_id)
+        ty::Alias(ty::Projection, data) => {
+            clean_projection(bound_ty.rebind(data), cx, parent_def_id)
         }
 
         ty::Alias(ty::Inherent, alias_ty) => {
@@ -2052,8 +2052,21 @@ pub(crate) fn clean_middle_ty<'tcx>(
         }
 
         ty::Alias(ty::Weak, data) => {
-            let ty = cx.tcx.type_of(data.def_id).subst(cx.tcx, data.substs);
-            clean_middle_ty(bound_ty.rebind(ty), cx, None, None)
+            if cx.tcx.features().lazy_type_alias {
+                // Weak type alias `data` represents the `type X` in `type X = Y`. If we need `Y`,
+                // we need to use `type_of`.
+                let path = external_path(
+                    cx,
+                    data.def_id,
+                    false,
+                    ThinVec::new(),
+                    bound_ty.rebind(data.substs),
+                );
+                Type::Path { path }
+            } else {
+                let ty = cx.tcx.type_of(data.def_id).subst(cx.tcx, data.substs);
+                clean_middle_ty(bound_ty.rebind(ty), cx, None, None)
+            }
         }
 
         ty::Param(ref p) => {
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index fc5f03568a9..5f5cade67a2 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -358,15 +358,15 @@ fn is_field_vis_inherited(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
 
 impl Item {
     pub(crate) fn stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<Stability> {
-        self.item_id.as_def_id().and_then(|did| tcx.lookup_stability(did))
+        self.def_id().and_then(|did| tcx.lookup_stability(did))
     }
 
     pub(crate) fn const_stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<ConstStability> {
-        self.item_id.as_def_id().and_then(|did| tcx.lookup_const_stability(did))
+        self.def_id().and_then(|did| tcx.lookup_const_stability(did))
     }
 
     pub(crate) fn deprecation(&self, tcx: TyCtxt<'_>) -> Option<Deprecation> {
-        self.item_id.as_def_id().and_then(|did| tcx.lookup_deprecation(did))
+        self.def_id().and_then(|did| tcx.lookup_deprecation(did))
     }
 
     pub(crate) fn inner_docs(&self, tcx: TyCtxt<'_>) -> bool {
@@ -391,7 +391,7 @@ impl Item {
                     panic!("blanket impl item has non-blanket ID")
                 }
             }
-            _ => self.item_id.as_def_id().map(|did| rustc_span(did, tcx)),
+            _ => self.def_id().map(|did| rustc_span(did, tcx)),
         }
     }
 
@@ -501,7 +501,7 @@ impl Item {
     }
 
     pub(crate) fn is_crate(&self) -> bool {
-        self.is_mod() && self.item_id.as_def_id().map_or(false, |did| did.is_crate_root())
+        self.is_mod() && self.def_id().map_or(false, |did| did.is_crate_root())
     }
     pub(crate) fn is_mod(&self) -> bool {
         self.type_() == ItemType::Module
@@ -638,11 +638,11 @@ impl Item {
         }
         let header = match *self.kind {
             ItemKind::ForeignFunctionItem(_) => {
-                let def_id = self.item_id.as_def_id().unwrap();
+                let def_id = self.def_id().unwrap();
                 let abi = tcx.fn_sig(def_id).skip_binder().abi();
                 hir::FnHeader {
                     unsafety: if abi == Abi::RustIntrinsic {
-                        intrinsic_operation_unsafety(tcx, self.item_id.as_def_id().unwrap())
+                        intrinsic_operation_unsafety(tcx, self.def_id().unwrap())
                     } else {
                         hir::Unsafety::Unsafe
                     },
@@ -659,7 +659,7 @@ impl Item {
                 }
             }
             ItemKind::FunctionItem(_) | ItemKind::MethodItem(_, _) | ItemKind::TyMethodItem(_) => {
-                let def_id = self.item_id.as_def_id().unwrap();
+                let def_id = self.def_id().unwrap();
                 build_fn_header(def_id, tcx, tcx.asyncness(def_id))
             }
             _ => return None,
@@ -738,7 +738,7 @@ impl Item {
                 }
             })
             .collect();
-        if let Some(def_id) = self.item_id.as_def_id() &&
+        if let Some(def_id) = self.def_id() &&
             !def_id.is_local() &&
             // This check is needed because `adt_def` will panic if not a compatible type otherwise...
             matches!(self.type_(), ItemType::Struct | ItemType::Enum | ItemType::Union)
@@ -787,6 +787,10 @@ impl Item {
     pub fn is_doc_hidden(&self) -> bool {
         self.attrs.is_doc_hidden()
     }
+
+    pub fn def_id(&self) -> Option<DefId> {
+        self.item_id.as_def_id()
+    }
 }
 
 #[derive(Clone, Debug)]
diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs
index 8aaad8bce1b..dac762e9ff9 100644
--- a/src/librustdoc/formats/cache.rs
+++ b/src/librustdoc/formats/cache.rs
@@ -121,6 +121,11 @@ pub(crate) struct Cache {
     pub(crate) intra_doc_links: FxHashMap<ItemId, FxIndexSet<clean::ItemLink>>,
     /// Cfg that have been hidden via #![doc(cfg_hide(...))]
     pub(crate) hidden_cfg: FxHashSet<clean::cfg::Cfg>,
+
+    /// Contains the list of `DefId`s which have been inlined. It is used when generating files
+    /// to check if a stripped item should get its file generated or not: if it's inside a
+    /// `#[doc(hidden)]` item or a private one and not inlined, it shouldn't get a file.
+    pub(crate) inlined_items: DefIdSet,
 }
 
 /// This struct is used to wrap the `cache` and `tcx` in order to run `DocFolder`.
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index 56af257fd5e..4c476263635 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -73,6 +73,8 @@ pub(crate) struct Context<'tcx> {
     pub(crate) include_sources: bool,
     /// Collection of all types with notable traits referenced in the current module.
     pub(crate) types_with_notable_traits: FxHashSet<clean::Type>,
+    /// Field used during rendering, to know if we're inside an inlined item.
+    pub(crate) is_inside_inlined_module: bool,
 }
 
 // `Context` is cloned a lot, so we don't want the size to grow unexpectedly.
@@ -171,6 +173,19 @@ impl<'tcx> Context<'tcx> {
     }
 
     fn render_item(&mut self, it: &clean::Item, is_module: bool) -> String {
+        let mut render_redirect_pages = self.render_redirect_pages;
+        // If the item is stripped but inlined, links won't point to the item so no need to generate
+        // a file for it.
+        if it.is_stripped() &&
+            let Some(def_id) = it.def_id() &&
+            def_id.is_local()
+        {
+            if self.is_inside_inlined_module || self.shared.cache.inlined_items.contains(&def_id) {
+                // For now we're forced to generate a redirect page for stripped items until
+                // `record_extern_fqn` correctly points to external items.
+                render_redirect_pages = true;
+            }
+        }
         let mut title = String::new();
         if !is_module {
             title.push_str(it.name.unwrap().as_str());
@@ -205,7 +220,7 @@ impl<'tcx> Context<'tcx> {
             tyname.as_str()
         };
 
-        if !self.render_redirect_pages {
+        if !render_redirect_pages {
             let clone_shared = Rc::clone(&self.shared);
             let page = layout::Page {
                 css_class: tyname_s,
@@ -545,6 +560,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
             shared: Rc::new(scx),
             include_sources,
             types_with_notable_traits: FxHashSet::default(),
+            is_inside_inlined_module: false,
         };
 
         if emit_crate {
@@ -574,6 +590,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
             shared: Rc::clone(&self.shared),
             include_sources: self.include_sources,
             types_with_notable_traits: FxHashSet::default(),
+            is_inside_inlined_module: self.is_inside_inlined_module,
         }
     }
 
@@ -768,12 +785,22 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
 
         info!("Recursing into {}", self.dst.display());
 
-        let buf = self.render_item(item, true);
-        // buf will be empty if the module is stripped and there is no redirect for it
-        if !buf.is_empty() {
-            self.shared.ensure_dir(&self.dst)?;
-            let joint_dst = self.dst.join("index.html");
-            self.shared.fs.write(joint_dst, buf)?;
+        if !item.is_stripped() {
+            let buf = self.render_item(item, true);
+            // buf will be empty if the module is stripped and there is no redirect for it
+            if !buf.is_empty() {
+                self.shared.ensure_dir(&self.dst)?;
+                let joint_dst = self.dst.join("index.html");
+                self.shared.fs.write(joint_dst, buf)?;
+            }
+        }
+        if !self.is_inside_inlined_module {
+            if let Some(def_id) = item.def_id() && self.cache().inlined_items.contains(&def_id) {
+                self.is_inside_inlined_module = true;
+            }
+        } else if item.is_doc_hidden() {
+            // We're not inside an inlined module anymore since this one cannot be re-exported.
+            self.is_inside_inlined_module = false;
         }
 
         // Render sidebar-items.js used throughout this module.
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 22c8cc09243..fcf591a9328 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -313,7 +313,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
             return false;
         }
 
-        let ret = match tcx.hir().get_by_def_id(res_did) {
+        let inlined = match tcx.hir().get_by_def_id(res_did) {
             // Bang macros are handled a bit on their because of how they are handled by the
             // compiler. If they have `#[doc(hidden)]` and the re-export doesn't have
             // `#[doc(inline)]`, then we don't inline it.
@@ -344,7 +344,10 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
             _ => false,
         };
         self.view_item_stack.remove(&res_did);
-        ret
+        if inlined {
+            self.cx.cache.inlined_items.insert(res_did.to_def_id());
+        }
+        inlined
     }
 
     /// Returns `true` if the item is visible, meaning it's not `#[doc(hidden)]` or private.
diff --git a/tests/rustdoc/alias-reexport.rs b/tests/rustdoc/alias-reexport.rs
new file mode 100644
index 00000000000..a2a8e651caf
--- /dev/null
+++ b/tests/rustdoc/alias-reexport.rs
@@ -0,0 +1,16 @@
+// aux-build:alias-reexport.rs
+// aux-build:alias-reexport2.rs
+
+#![crate_name = "foo"]
+#![feature(lazy_type_alias)]
+
+extern crate alias_reexport2;
+
+// @has 'foo/reexport/fn.foo.html'
+// @has - '//*[@class="rust item-decl"]' 'pub fn foo() -> Reexported'
+// @has 'foo/reexport/fn.foo2.html'
+// @has - '//*[@class="rust item-decl"]' 'pub fn foo2() -> Result<Reexported, ()>'
+// @has 'foo/reexport/type.Reexported.html'
+// @has - '//*[@class="rust item-decl"]' 'pub type Reexported = u8;'
+#[doc(inline)]
+pub use alias_reexport2 as reexport;
diff --git a/tests/rustdoc/alias-reexport2.rs b/tests/rustdoc/alias-reexport2.rs
new file mode 100644
index 00000000000..85d3cdad962
--- /dev/null
+++ b/tests/rustdoc/alias-reexport2.rs
@@ -0,0 +1,16 @@
+// gate-test-lazy_type_alias
+// aux-build:alias-reexport.rs
+
+#![crate_name = "foo"]
+#![feature(lazy_type_alias)]
+
+extern crate alias_reexport;
+
+use alias_reexport::Reexported;
+
+// @has 'foo/fn.foo.html'
+// @has - '//*[@class="rust item-decl"]' 'pub fn foo() -> Reexported'
+pub fn foo() -> Reexported { 0 }
+// @has 'foo/fn.foo2.html'
+// @has - '//*[@class="rust item-decl"]' 'pub fn foo2() -> Result<Reexported, ()>'
+pub fn foo2() -> Result<Reexported, ()> { Ok(0) }
diff --git a/tests/rustdoc/auxiliary/alias-reexport.rs b/tests/rustdoc/auxiliary/alias-reexport.rs
new file mode 100644
index 00000000000..14fafc02d36
--- /dev/null
+++ b/tests/rustdoc/auxiliary/alias-reexport.rs
@@ -0,0 +1,3 @@
+#![feature(lazy_type_alias)]
+
+pub type Reexported = u8;
diff --git a/tests/rustdoc/auxiliary/alias-reexport2.rs b/tests/rustdoc/auxiliary/alias-reexport2.rs
new file mode 100644
index 00000000000..9f6910572ad
--- /dev/null
+++ b/tests/rustdoc/auxiliary/alias-reexport2.rs
@@ -0,0 +1,12 @@
+#![feature(lazy_type_alias)]
+
+extern crate alias_reexport;
+
+pub use alias_reexport::Reexported;
+
+// @has 'foo/fn.foo.html'
+// @has - '//*[@class="docblock item-decl"]' 'pub fn foo() -> Reexported'
+pub fn foo() -> Reexported { 0 }
+// @has 'foo/fn.foo2.html'
+// @has - '//*[@class="docblock item-decl"]' 'pub fn foo2() -> Result<Reexported, ()>'
+pub fn foo2() -> Result<Reexported, ()> { Ok(0) }
diff --git a/tests/rustdoc/files-creation-hidden.rs b/tests/rustdoc/files-creation-hidden.rs
new file mode 100644
index 00000000000..bcabbfc91e8
--- /dev/null
+++ b/tests/rustdoc/files-creation-hidden.rs
@@ -0,0 +1,23 @@
+#![crate_name="foo"]
+
+// @!has "foo/struct.Foo.html"
+#[doc(hidden)]
+pub struct Foo;
+
+// @!has "foo/struct.Bar.html"
+pub use crate::Foo as Bar;
+
+// @!has "foo/struct.Baz.html"
+#[doc(hidden)]
+pub use crate::Foo as Baz;
+
+// @!has "foo/foo/index.html"
+#[doc(hidden)]
+pub mod foo {}
+
+// @!has "foo/bar/index.html"
+pub use crate::foo as bar;
+
+// @!has "foo/baz/index.html"
+#[doc(hidden)]
+pub use crate::foo as baz;
diff --git a/tests/rustdoc/files-creation-private.rs b/tests/rustdoc/files-creation-private.rs
new file mode 100644
index 00000000000..ca2327e0f91
--- /dev/null
+++ b/tests/rustdoc/files-creation-private.rs
@@ -0,0 +1,18 @@
+#![crate_name="foo"]
+
+// @!has "foo/priv/index.html"
+// @!has "foo/priv/struct.Foo.html"
+mod private {
+    pub struct Foo;
+}
+
+// @has "foo/struct.Bar.html"
+pub use crate::private::Foo as Bar;
+
+// @!has "foo/foo/index.html"
+mod foo {
+    pub mod subfoo {}
+}
+
+// @has "foo/bar/index.html"
+pub use crate::foo::subfoo as bar;
diff --git a/tests/rustdoc/issue-111064-reexport-trait-from-hidden-2.rs b/tests/rustdoc/issue-111064-reexport-trait-from-hidden-2.rs
index 8e1029a1ca3..d6832bb7a09 100644
--- a/tests/rustdoc/issue-111064-reexport-trait-from-hidden-2.rs
+++ b/tests/rustdoc/issue-111064-reexport-trait-from-hidden-2.rs
@@ -3,10 +3,10 @@
 #![crate_name = "foo"]
 
 // @!has 'foo/hidden/index.html'
-// FIXME: add missing `@` for the two next tests once issue is fixed!
-// To be done in <https://github.com/rust-lang/rust/issues/111249>.
-// !has 'foo/hidden/inner/index.html'
-// !has 'foo/hidden/inner/trait.Foo.html'
+// @!has 'foo/hidden/inner/index.html'
+// FIXME: Should be `@!has`: https://github.com/rust-lang/rust/issues/111249
+// @has 'foo/hidden/inner/trait.Foo.html'
+// @matchesraw - '<meta http-equiv="refresh" content="0;URL=../../../foo/visible/trait.Foo.html">'
 #[doc(hidden)]
 pub mod hidden {
     pub mod inner {
diff --git a/tests/rustdoc/issue-111249-file-creation.rs b/tests/rustdoc/issue-111249-file-creation.rs
new file mode 100644
index 00000000000..d2042b231e4
--- /dev/null
+++ b/tests/rustdoc/issue-111249-file-creation.rs
@@ -0,0 +1,34 @@
+#![crate_name = "foo"]
+#![feature(no_core)]
+#![no_core]
+
+// The following five should not fail!
+// @!has 'foo/hidden/index.html'
+// @!has 'foo/hidden/inner/index.html'
+// FIXME: Should be `@!has`: https://github.com/rust-lang/rust/issues/111249
+// @has 'foo/hidden/inner/trait.Foo.html'
+// @matchesraw - '<meta http-equiv="refresh" content="0;URL=../../../foo/visible/trait.Foo.html">'
+// @!has 'foo/hidden/inner/inner_hidden/index.html'
+// @!has 'foo/hidden/inner/inner_hidden/trait.HiddenFoo.html'
+#[doc(hidden)]
+pub mod hidden {
+    pub mod inner {
+        pub trait Foo {}
+
+        #[doc(hidden)]
+        pub mod inner_hidden {
+            pub trait HiddenFoo {}
+        }
+    }
+}
+
+// @has 'foo/visible/index.html'
+// @has 'foo/visible/trait.Foo.html'
+#[doc(inline)]
+pub use hidden::inner as visible;
+
+// @has 'foo/struct.Bar.html'
+// @count - '//*[@id="impl-Foo-for-Bar"]' 1
+pub struct Bar;
+
+impl visible::Foo for Bar {}
diff --git a/tests/rustdoc/redirect.rs b/tests/rustdoc/redirect.rs
index 5b7a76e1a77..4fb81c23d39 100644
--- a/tests/rustdoc/redirect.rs
+++ b/tests/rustdoc/redirect.rs
@@ -10,7 +10,9 @@ pub trait Foo {}
 // @has - '//code' 'pub use reexp_stripped::Bar'
 // @has - '//code/a' 'Bar'
 // @has - '//a[@href="../reexp_stripped/hidden/struct.Bar.html"]' 'Bar'
+// FIXME: Should be `@!has`: https://github.com/rust-lang/rust/issues/111249
 // @has reexp_stripped/hidden/struct.Bar.html
+// @matchesraw - '<meta http-equiv="refresh" content="0;URL=../../reexp_stripped/struct.Bar.html">'
 // @has 'reexp_stripped/struct.Bar.html'
 // @has - '//a[@href="struct.Bar.html"]' 'Bar'
 #[doc(no_inline)]