diff options
| author | bors <bors@rust-lang.org> | 2021-11-08 21:37:59 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2021-11-08 21:37:59 +0000 |
| commit | 515472757d2991e280965d7c1d235cfbb6ceb006 (patch) | |
| tree | 5f557dc1eb81b0cd54d4547582f3cfe46f768026 /src/librustdoc/clean | |
| parent | 495322d776fd6f679cd8cd4ca02b8fa834da654b (diff) | |
| parent | 5a77f3006f0e15c35e905b6f4f08a33f7005c3d1 (diff) | |
| download | rust-515472757d2991e280965d7c1d235cfbb6ceb006.tar.gz rust-515472757d2991e280965d7c1d235cfbb6ceb006.zip | |
Auto merge of #90443 - camelid:rustdoc-subst, r=GuillaumeGomez
Merge `DocContext.{ty,lt,ct}_substs` into one map
It should be impossible to have more than one entry with a particular
key across the three maps, so they should be one map. In addition to
making it impossible for multiple entries to exist, this should improve
memory usage since now only one map is allocated on the stack and heap.
r? `@GuillaumeGomez`
Diffstat (limited to 'src/librustdoc/clean')
| -rw-r--r-- | src/librustdoc/clean/mod.rs | 188 | ||||
| -rw-r--r-- | src/librustdoc/clean/types.rs | 29 |
2 files changed, 124 insertions, 93 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 } + } +} |
