about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustdoc/clean/mod.rs188
-rw-r--r--src/librustdoc/clean/types.rs29
-rw-r--r--src/librustdoc/core.rs32
-rw-r--r--src/librustdoc/lib.rs1
4 files changed, 132 insertions, 118 deletions
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 9d893f3d06d..3db0ef17fd8 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -190,7 +190,7 @@ impl Clean<Lifetime> for hir::Lifetime {
             | rl::Region::Free(_, node_id),
         ) = def
         {
-            if let Some(lt) = cx.lt_substs.get(&node_id).cloned() {
+            if let Some(lt) = cx.substs.get(&node_id).and_then(|p| p.as_lt()).cloned() {
                 return lt;
             }
         }
@@ -1120,7 +1120,6 @@ impl Clean<Item> for ty::AssocItem {
 }
 
 fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
-    use rustc_hir::GenericParamCount;
     let hir::Ty { hir_id: _, span, ref kind } = *hir_ty;
     let qpath = match kind {
         hir::TyKind::Path(qpath) => qpath,
@@ -1130,7 +1129,7 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
     match qpath {
         hir::QPath::Resolved(None, ref path) => {
             if let Res::Def(DefKind::TyParam, did) = path.res {
-                if let Some(new_ty) = cx.ty_substs.get(&did).cloned() {
+                if let Some(new_ty) = cx.substs.get(&did).and_then(|p| p.as_ty()).cloned() {
                     return new_ty;
                 }
                 if let Some(bounds) = cx.impl_trait_bounds.remove(&did.into()) {
@@ -1138,97 +1137,12 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
                 }
             }
 
-            let mut alias = None;
-            if let Res::Def(DefKind::TyAlias, def_id) = path.res {
-                // Substitute private type aliases
-                if let Some(def_id) = def_id.as_local() {
-                    let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id);
-                    if !cx.cache.access_levels.is_exported(def_id.to_def_id()) {
-                        alias = Some(&cx.tcx.hir().expect_item(hir_id).kind);
-                    }
-                }
-            };
-
-            if let Some(&hir::ItemKind::TyAlias(ref ty, ref generics)) = alias {
-                let provided_params = &path.segments.last().expect("segments were empty");
-                let mut ty_substs = FxHashMap::default();
-                let mut lt_substs = FxHashMap::default();
-                let mut ct_substs = FxHashMap::default();
-                let generic_args = provided_params.args();
-                {
-                    let mut indices: GenericParamCount = Default::default();
-                    for param in generics.params.iter() {
-                        match param.kind {
-                            hir::GenericParamKind::Lifetime { .. } => {
-                                let mut j = 0;
-                                let lifetime = generic_args.args.iter().find_map(|arg| match arg {
-                                    hir::GenericArg::Lifetime(lt) => {
-                                        if indices.lifetimes == j {
-                                            return Some(lt);
-                                        }
-                                        j += 1;
-                                        None
-                                    }
-                                    _ => None,
-                                });
-                                if let Some(lt) = lifetime.cloned() {
-                                    let lt_def_id = cx.tcx.hir().local_def_id(param.hir_id);
-                                    let cleaned = if !lt.is_elided() {
-                                        lt.clean(cx)
-                                    } else {
-                                        self::types::Lifetime::elided()
-                                    };
-                                    lt_substs.insert(lt_def_id.to_def_id(), cleaned);
-                                }
-                                indices.lifetimes += 1;
-                            }
-                            hir::GenericParamKind::Type { ref default, .. } => {
-                                let ty_param_def_id = cx.tcx.hir().local_def_id(param.hir_id);
-                                let mut j = 0;
-                                let type_ = generic_args.args.iter().find_map(|arg| match arg {
-                                    hir::GenericArg::Type(ty) => {
-                                        if indices.types == j {
-                                            return Some(ty);
-                                        }
-                                        j += 1;
-                                        None
-                                    }
-                                    _ => None,
-                                });
-                                if let Some(ty) = type_ {
-                                    ty_substs.insert(ty_param_def_id.to_def_id(), ty.clean(cx));
-                                } else if let Some(default) = *default {
-                                    ty_substs
-                                        .insert(ty_param_def_id.to_def_id(), default.clean(cx));
-                                }
-                                indices.types += 1;
-                            }
-                            hir::GenericParamKind::Const { .. } => {
-                                let const_param_def_id = cx.tcx.hir().local_def_id(param.hir_id);
-                                let mut j = 0;
-                                let const_ = generic_args.args.iter().find_map(|arg| match arg {
-                                    hir::GenericArg::Const(ct) => {
-                                        if indices.consts == j {
-                                            return Some(ct);
-                                        }
-                                        j += 1;
-                                        None
-                                    }
-                                    _ => None,
-                                });
-                                if let Some(ct) = const_ {
-                                    ct_substs.insert(const_param_def_id.to_def_id(), ct.clean(cx));
-                                }
-                                // FIXME(const_generics_defaults)
-                                indices.consts += 1;
-                            }
-                        }
-                    }
-                }
-                return cx.enter_alias(ty_substs, lt_substs, ct_substs, |cx| ty.clean(cx));
+            if let Some(expanded) = maybe_expand_private_type_alias(cx, path) {
+                expanded
+            } else {
+                let path = path.clean(cx);
+                resolve_type(cx, path)
             }
-            let path = path.clean(cx);
-            resolve_type(cx, path)
         }
         hir::QPath::Resolved(Some(ref qself), p) => {
             // Try to normalize `<X as Y>::T` to a type
@@ -1272,6 +1186,94 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
     }
 }
 
+fn maybe_expand_private_type_alias(cx: &mut DocContext<'_>, path: &hir::Path<'_>) -> Option<Type> {
+    let Res::Def(DefKind::TyAlias, def_id) = path.res else { return None };
+    // Substitute private type aliases
+    let Some(def_id) = def_id.as_local() else { return None };
+    let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id);
+    let alias = if !cx.cache.access_levels.is_exported(def_id.to_def_id()) {
+        &cx.tcx.hir().expect_item(hir_id).kind
+    } else {
+        return None;
+    };
+    let hir::ItemKind::TyAlias(ty, generics) = alias else { return None };
+
+    let provided_params = &path.segments.last().expect("segments were empty");
+    let mut substs = FxHashMap::default();
+    let generic_args = provided_params.args();
+
+    let mut indices: hir::GenericParamCount = Default::default();
+    for param in generics.params.iter() {
+        match param.kind {
+            hir::GenericParamKind::Lifetime { .. } => {
+                let mut j = 0;
+                let lifetime = generic_args.args.iter().find_map(|arg| match arg {
+                    hir::GenericArg::Lifetime(lt) => {
+                        if indices.lifetimes == j {
+                            return Some(lt);
+                        }
+                        j += 1;
+                        None
+                    }
+                    _ => None,
+                });
+                if let Some(lt) = lifetime.cloned() {
+                    let lt_def_id = cx.tcx.hir().local_def_id(param.hir_id);
+                    let cleaned = if !lt.is_elided() {
+                        lt.clean(cx)
+                    } else {
+                        self::types::Lifetime::elided()
+                    };
+                    substs.insert(lt_def_id.to_def_id(), SubstParam::Lifetime(cleaned));
+                }
+                indices.lifetimes += 1;
+            }
+            hir::GenericParamKind::Type { ref default, .. } => {
+                let ty_param_def_id = cx.tcx.hir().local_def_id(param.hir_id);
+                let mut j = 0;
+                let type_ = generic_args.args.iter().find_map(|arg| match arg {
+                    hir::GenericArg::Type(ty) => {
+                        if indices.types == j {
+                            return Some(ty);
+                        }
+                        j += 1;
+                        None
+                    }
+                    _ => None,
+                });
+                if let Some(ty) = type_ {
+                    substs.insert(ty_param_def_id.to_def_id(), SubstParam::Type(ty.clean(cx)));
+                } else if let Some(default) = *default {
+                    substs.insert(ty_param_def_id.to_def_id(), SubstParam::Type(default.clean(cx)));
+                }
+                indices.types += 1;
+            }
+            hir::GenericParamKind::Const { .. } => {
+                let const_param_def_id = cx.tcx.hir().local_def_id(param.hir_id);
+                let mut j = 0;
+                let const_ = generic_args.args.iter().find_map(|arg| match arg {
+                    hir::GenericArg::Const(ct) => {
+                        if indices.consts == j {
+                            return Some(ct);
+                        }
+                        j += 1;
+                        None
+                    }
+                    _ => None,
+                });
+                if let Some(ct) = const_ {
+                    substs
+                        .insert(const_param_def_id.to_def_id(), SubstParam::Constant(ct.clean(cx)));
+                }
+                // FIXME(const_generics_defaults)
+                indices.consts += 1;
+            }
+        }
+    }
+
+    Some(cx.enter_alias(substs, |cx| ty.clean(cx)))
+}
+
 impl Clean<Type> for hir::Ty<'_> {
     fn clean(&self, cx: &mut DocContext<'_>) -> Type {
         use rustc_hir::*;
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 0dc1c24b16e..fd4d620c959 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -2279,3 +2279,32 @@ impl TypeBinding {
         }
     }
 }
+
+/// The type, lifetime, or constant that a private type alias's parameter should be
+/// replaced with when expanding a use of that type alias.
+///
+/// For example:
+///
+/// ```
+/// type PrivAlias<T> = Vec<T>;
+///
+/// pub fn public_fn() -> PrivAlias<i32> { vec![] }
+/// ```
+///
+/// `public_fn`'s docs will show it as returning `Vec<i32>`, since `PrivAlias` is private.
+/// [`SubstParam`] is used to record that `T` should be mapped to `i32`.
+crate enum SubstParam {
+    Type(Type),
+    Lifetime(Lifetime),
+    Constant(Constant),
+}
+
+impl SubstParam {
+    crate fn as_ty(&self) -> Option<&Type> {
+        if let Self::Type(ty) = self { Some(ty) } else { None }
+    }
+
+    crate fn as_lt(&self) -> Option<&Lifetime> {
+        if let Self::Lifetime(lt) = self { Some(lt) } else { None }
+    }
+}
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index b7251e8f571..7fa6484d238 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -54,14 +54,10 @@ crate struct DocContext<'tcx> {
     /// Used while populating `external_traits` to ensure we don't process the same trait twice at
     /// the same time.
     crate active_extern_traits: FxHashSet<DefId>,
-    // The current set of type and lifetime substitutions,
+    // The current set of parameter substitutions,
     // for expanding type aliases at the HIR level:
-    /// Table `DefId` of type parameter -> substituted type
-    crate ty_substs: FxHashMap<DefId, clean::Type>,
-    /// Table `DefId` of lifetime parameter -> substituted lifetime
-    crate lt_substs: FxHashMap<DefId, clean::Lifetime>,
-    /// Table `DefId` of const parameter -> substituted const
-    crate ct_substs: FxHashMap<DefId, clean::Constant>,
+    /// Table `DefId` of type, lifetime, or const parameter -> substituted type, lifetime, or const
+    crate substs: FxHashMap<DefId, clean::SubstParam>,
     /// Table synthetic type parameter for `impl Trait` in argument position -> bounds
     crate impl_trait_bounds: FxHashMap<ImplTraitParam, Vec<clean::GenericBound>>,
     /// Auto-trait or blanket impls processed so far, as `(self_ty, trait_def_id)`.
@@ -104,25 +100,13 @@ impl<'tcx> DocContext<'tcx> {
 
     /// Call the closure with the given parameters set as
     /// the substitutions for a type alias' RHS.
-    crate fn enter_alias<F, R>(
-        &mut self,
-        ty_substs: FxHashMap<DefId, clean::Type>,
-        lt_substs: FxHashMap<DefId, clean::Lifetime>,
-        ct_substs: FxHashMap<DefId, clean::Constant>,
-        f: F,
-    ) -> R
+    crate fn enter_alias<F, R>(&mut self, substs: FxHashMap<DefId, clean::SubstParam>, f: F) -> R
     where
         F: FnOnce(&mut Self) -> R,
     {
-        let (old_tys, old_lts, old_cts) = (
-            mem::replace(&mut self.ty_substs, ty_substs),
-            mem::replace(&mut self.lt_substs, lt_substs),
-            mem::replace(&mut self.ct_substs, ct_substs),
-        );
+        let old_substs = mem::replace(&mut self.substs, substs);
         let r = f(self);
-        self.ty_substs = old_tys;
-        self.lt_substs = old_lts;
-        self.ct_substs = old_cts;
+        self.substs = old_substs;
         r
     }
 
@@ -350,9 +334,7 @@ crate fn run_global_ctxt(
         param_env: ParamEnv::empty(),
         external_traits: Default::default(),
         active_extern_traits: Default::default(),
-        ty_substs: Default::default(),
-        lt_substs: Default::default(),
-        ct_substs: Default::default(),
+        substs: Default::default(),
         impl_trait_bounds: Default::default(),
         generated_synthetics: Default::default(),
         auto_traits: tcx
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 7eeb9d1fcaa..938a0c507a5 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -9,6 +9,7 @@
 #![feature(control_flow_enum)]
 #![feature(box_syntax)]
 #![feature(in_band_lifetimes)]
+#![feature(let_else)]
 #![feature(nll)]
 #![feature(test)]
 #![feature(crate_visibility_modifier)]