Skip to content

Commit 5154727

Browse files
committed
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`
2 parents 495322d + 5a77f30 commit 5154727

File tree

4 files changed

+132
-118
lines changed

4 files changed

+132
-118
lines changed

src/librustdoc/clean/mod.rs

+95-93
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ impl Clean<Lifetime> for hir::Lifetime {
190190
| rl::Region::Free(_, node_id),
191191
) = def
192192
{
193-
if let Some(lt) = cx.lt_substs.get(&node_id).cloned() {
193+
if let Some(lt) = cx.substs.get(&node_id).and_then(|p| p.as_lt()).cloned() {
194194
return lt;
195195
}
196196
}
@@ -1120,7 +1120,6 @@ impl Clean<Item> for ty::AssocItem {
11201120
}
11211121

11221122
fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
1123-
use rustc_hir::GenericParamCount;
11241123
let hir::Ty { hir_id: _, span, ref kind } = *hir_ty;
11251124
let qpath = match kind {
11261125
hir::TyKind::Path(qpath) => qpath,
@@ -1130,105 +1129,20 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
11301129
match qpath {
11311130
hir::QPath::Resolved(None, ref path) => {
11321131
if let Res::Def(DefKind::TyParam, did) = path.res {
1133-
if let Some(new_ty) = cx.ty_substs.get(&did).cloned() {
1132+
if let Some(new_ty) = cx.substs.get(&did).and_then(|p| p.as_ty()).cloned() {
11341133
return new_ty;
11351134
}
11361135
if let Some(bounds) = cx.impl_trait_bounds.remove(&did.into()) {
11371136
return ImplTrait(bounds);
11381137
}
11391138
}
11401139

1141-
let mut alias = None;
1142-
if let Res::Def(DefKind::TyAlias, def_id) = path.res {
1143-
// Substitute private type aliases
1144-
if let Some(def_id) = def_id.as_local() {
1145-
let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id);
1146-
if !cx.cache.access_levels.is_exported(def_id.to_def_id()) {
1147-
alias = Some(&cx.tcx.hir().expect_item(hir_id).kind);
1148-
}
1149-
}
1150-
};
1151-
1152-
if let Some(&hir::ItemKind::TyAlias(ref ty, ref generics)) = alias {
1153-
let provided_params = &path.segments.last().expect("segments were empty");
1154-
let mut ty_substs = FxHashMap::default();
1155-
let mut lt_substs = FxHashMap::default();
1156-
let mut ct_substs = FxHashMap::default();
1157-
let generic_args = provided_params.args();
1158-
{
1159-
let mut indices: GenericParamCount = Default::default();
1160-
for param in generics.params.iter() {
1161-
match param.kind {
1162-
hir::GenericParamKind::Lifetime { .. } => {
1163-
let mut j = 0;
1164-
let lifetime = generic_args.args.iter().find_map(|arg| match arg {
1165-
hir::GenericArg::Lifetime(lt) => {
1166-
if indices.lifetimes == j {
1167-
return Some(lt);
1168-
}
1169-
j += 1;
1170-
None
1171-
}
1172-
_ => None,
1173-
});
1174-
if let Some(lt) = lifetime.cloned() {
1175-
let lt_def_id = cx.tcx.hir().local_def_id(param.hir_id);
1176-
let cleaned = if !lt.is_elided() {
1177-
lt.clean(cx)
1178-
} else {
1179-
self::types::Lifetime::elided()
1180-
};
1181-
lt_substs.insert(lt_def_id.to_def_id(), cleaned);
1182-
}
1183-
indices.lifetimes += 1;
1184-
}
1185-
hir::GenericParamKind::Type { ref default, .. } => {
1186-
let ty_param_def_id = cx.tcx.hir().local_def_id(param.hir_id);
1187-
let mut j = 0;
1188-
let type_ = generic_args.args.iter().find_map(|arg| match arg {
1189-
hir::GenericArg::Type(ty) => {
1190-
if indices.types == j {
1191-
return Some(ty);
1192-
}
1193-
j += 1;
1194-
None
1195-
}
1196-
_ => None,
1197-
});
1198-
if let Some(ty) = type_ {
1199-
ty_substs.insert(ty_param_def_id.to_def_id(), ty.clean(cx));
1200-
} else if let Some(default) = *default {
1201-
ty_substs
1202-
.insert(ty_param_def_id.to_def_id(), default.clean(cx));
1203-
}
1204-
indices.types += 1;
1205-
}
1206-
hir::GenericParamKind::Const { .. } => {
1207-
let const_param_def_id = cx.tcx.hir().local_def_id(param.hir_id);
1208-
let mut j = 0;
1209-
let const_ = generic_args.args.iter().find_map(|arg| match arg {
1210-
hir::GenericArg::Const(ct) => {
1211-
if indices.consts == j {
1212-
return Some(ct);
1213-
}
1214-
j += 1;
1215-
None
1216-
}
1217-
_ => None,
1218-
});
1219-
if let Some(ct) = const_ {
1220-
ct_substs.insert(const_param_def_id.to_def_id(), ct.clean(cx));
1221-
}
1222-
// FIXME(const_generics_defaults)
1223-
indices.consts += 1;
1224-
}
1225-
}
1226-
}
1227-
}
1228-
return cx.enter_alias(ty_substs, lt_substs, ct_substs, |cx| ty.clean(cx));
1140+
if let Some(expanded) = maybe_expand_private_type_alias(cx, path) {
1141+
expanded
1142+
} else {
1143+
let path = path.clean(cx);
1144+
resolve_type(cx, path)
12291145
}
1230-
let path = path.clean(cx);
1231-
resolve_type(cx, path)
12321146
}
12331147
hir::QPath::Resolved(Some(ref qself), p) => {
12341148
// 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 {
12721186
}
12731187
}
12741188

1189+
fn maybe_expand_private_type_alias(cx: &mut DocContext<'_>, path: &hir::Path<'_>) -> Option<Type> {
1190+
let Res::Def(DefKind::TyAlias, def_id) = path.res else { return None };
1191+
// Substitute private type aliases
1192+
let Some(def_id) = def_id.as_local() else { return None };
1193+
let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id);
1194+
let alias = if !cx.cache.access_levels.is_exported(def_id.to_def_id()) {
1195+
&cx.tcx.hir().expect_item(hir_id).kind
1196+
} else {
1197+
return None;
1198+
};
1199+
let hir::ItemKind::TyAlias(ty, generics) = alias else { return None };
1200+
1201+
let provided_params = &path.segments.last().expect("segments were empty");
1202+
let mut substs = FxHashMap::default();
1203+
let generic_args = provided_params.args();
1204+
1205+
let mut indices: hir::GenericParamCount = Default::default();
1206+
for param in generics.params.iter() {
1207+
match param.kind {
1208+
hir::GenericParamKind::Lifetime { .. } => {
1209+
let mut j = 0;
1210+
let lifetime = generic_args.args.iter().find_map(|arg| match arg {
1211+
hir::GenericArg::Lifetime(lt) => {
1212+
if indices.lifetimes == j {
1213+
return Some(lt);
1214+
}
1215+
j += 1;
1216+
None
1217+
}
1218+
_ => None,
1219+
});
1220+
if let Some(lt) = lifetime.cloned() {
1221+
let lt_def_id = cx.tcx.hir().local_def_id(param.hir_id);
1222+
let cleaned = if !lt.is_elided() {
1223+
lt.clean(cx)
1224+
} else {
1225+
self::types::Lifetime::elided()
1226+
};
1227+
substs.insert(lt_def_id.to_def_id(), SubstParam::Lifetime(cleaned));
1228+
}
1229+
indices.lifetimes += 1;
1230+
}
1231+
hir::GenericParamKind::Type { ref default, .. } => {
1232+
let ty_param_def_id = cx.tcx.hir().local_def_id(param.hir_id);
1233+
let mut j = 0;
1234+
let type_ = generic_args.args.iter().find_map(|arg| match arg {
1235+
hir::GenericArg::Type(ty) => {
1236+
if indices.types == j {
1237+
return Some(ty);
1238+
}
1239+
j += 1;
1240+
None
1241+
}
1242+
_ => None,
1243+
});
1244+
if let Some(ty) = type_ {
1245+
substs.insert(ty_param_def_id.to_def_id(), SubstParam::Type(ty.clean(cx)));
1246+
} else if let Some(default) = *default {
1247+
substs.insert(ty_param_def_id.to_def_id(), SubstParam::Type(default.clean(cx)));
1248+
}
1249+
indices.types += 1;
1250+
}
1251+
hir::GenericParamKind::Const { .. } => {
1252+
let const_param_def_id = cx.tcx.hir().local_def_id(param.hir_id);
1253+
let mut j = 0;
1254+
let const_ = generic_args.args.iter().find_map(|arg| match arg {
1255+
hir::GenericArg::Const(ct) => {
1256+
if indices.consts == j {
1257+
return Some(ct);
1258+
}
1259+
j += 1;
1260+
None
1261+
}
1262+
_ => None,
1263+
});
1264+
if let Some(ct) = const_ {
1265+
substs
1266+
.insert(const_param_def_id.to_def_id(), SubstParam::Constant(ct.clean(cx)));
1267+
}
1268+
// FIXME(const_generics_defaults)
1269+
indices.consts += 1;
1270+
}
1271+
}
1272+
}
1273+
1274+
Some(cx.enter_alias(substs, |cx| ty.clean(cx)))
1275+
}
1276+
12751277
impl Clean<Type> for hir::Ty<'_> {
12761278
fn clean(&self, cx: &mut DocContext<'_>) -> Type {
12771279
use rustc_hir::*;

src/librustdoc/clean/types.rs

+29
Original file line numberDiff line numberDiff line change
@@ -2279,3 +2279,32 @@ impl TypeBinding {
22792279
}
22802280
}
22812281
}
2282+
2283+
/// The type, lifetime, or constant that a private type alias's parameter should be
2284+
/// replaced with when expanding a use of that type alias.
2285+
///
2286+
/// For example:
2287+
///
2288+
/// ```
2289+
/// type PrivAlias<T> = Vec<T>;
2290+
///
2291+
/// pub fn public_fn() -> PrivAlias<i32> { vec![] }
2292+
/// ```
2293+
///
2294+
/// `public_fn`'s docs will show it as returning `Vec<i32>`, since `PrivAlias` is private.
2295+
/// [`SubstParam`] is used to record that `T` should be mapped to `i32`.
2296+
crate enum SubstParam {
2297+
Type(Type),
2298+
Lifetime(Lifetime),
2299+
Constant(Constant),
2300+
}
2301+
2302+
impl SubstParam {
2303+
crate fn as_ty(&self) -> Option<&Type> {
2304+
if let Self::Type(ty) = self { Some(ty) } else { None }
2305+
}
2306+
2307+
crate fn as_lt(&self) -> Option<&Lifetime> {
2308+
if let Self::Lifetime(lt) = self { Some(lt) } else { None }
2309+
}
2310+
}

src/librustdoc/core.rs

+7-25
Original file line numberDiff line numberDiff line change
@@ -54,14 +54,10 @@ crate struct DocContext<'tcx> {
5454
/// Used while populating `external_traits` to ensure we don't process the same trait twice at
5555
/// the same time.
5656
crate active_extern_traits: FxHashSet<DefId>,
57-
// The current set of type and lifetime substitutions,
57+
// The current set of parameter substitutions,
5858
// for expanding type aliases at the HIR level:
59-
/// Table `DefId` of type parameter -> substituted type
60-
crate ty_substs: FxHashMap<DefId, clean::Type>,
61-
/// Table `DefId` of lifetime parameter -> substituted lifetime
62-
crate lt_substs: FxHashMap<DefId, clean::Lifetime>,
63-
/// Table `DefId` of const parameter -> substituted const
64-
crate ct_substs: FxHashMap<DefId, clean::Constant>,
59+
/// Table `DefId` of type, lifetime, or const parameter -> substituted type, lifetime, or const
60+
crate substs: FxHashMap<DefId, clean::SubstParam>,
6561
/// Table synthetic type parameter for `impl Trait` in argument position -> bounds
6662
crate impl_trait_bounds: FxHashMap<ImplTraitParam, Vec<clean::GenericBound>>,
6763
/// Auto-trait or blanket impls processed so far, as `(self_ty, trait_def_id)`.
@@ -104,25 +100,13 @@ impl<'tcx> DocContext<'tcx> {
104100

105101
/// Call the closure with the given parameters set as
106102
/// the substitutions for a type alias' RHS.
107-
crate fn enter_alias<F, R>(
108-
&mut self,
109-
ty_substs: FxHashMap<DefId, clean::Type>,
110-
lt_substs: FxHashMap<DefId, clean::Lifetime>,
111-
ct_substs: FxHashMap<DefId, clean::Constant>,
112-
f: F,
113-
) -> R
103+
crate fn enter_alias<F, R>(&mut self, substs: FxHashMap<DefId, clean::SubstParam>, f: F) -> R
114104
where
115105
F: FnOnce(&mut Self) -> R,
116106
{
117-
let (old_tys, old_lts, old_cts) = (
118-
mem::replace(&mut self.ty_substs, ty_substs),
119-
mem::replace(&mut self.lt_substs, lt_substs),
120-
mem::replace(&mut self.ct_substs, ct_substs),
121-
);
107+
let old_substs = mem::replace(&mut self.substs, substs);
122108
let r = f(self);
123-
self.ty_substs = old_tys;
124-
self.lt_substs = old_lts;
125-
self.ct_substs = old_cts;
109+
self.substs = old_substs;
126110
r
127111
}
128112

@@ -350,9 +334,7 @@ crate fn run_global_ctxt(
350334
param_env: ParamEnv::empty(),
351335
external_traits: Default::default(),
352336
active_extern_traits: Default::default(),
353-
ty_substs: Default::default(),
354-
lt_substs: Default::default(),
355-
ct_substs: Default::default(),
337+
substs: Default::default(),
356338
impl_trait_bounds: Default::default(),
357339
generated_synthetics: Default::default(),
358340
auto_traits: tcx

src/librustdoc/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#![feature(control_flow_enum)]
1010
#![feature(box_syntax)]
1111
#![feature(in_band_lifetimes)]
12+
#![feature(let_else)]
1213
#![feature(nll)]
1314
#![feature(test)]
1415
#![feature(crate_visibility_modifier)]

0 commit comments

Comments
 (0)