Skip to content

Commit 37350c1

Browse files
committed
make item_type_alias return impl fmt::Display
1 parent 1942752 commit 37350c1

File tree

1 file changed

+161
-160
lines changed

1 file changed

+161
-160
lines changed

src/librustdoc/html/render/print_item.rs

Lines changed: 161 additions & 160 deletions
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,9 @@ pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item, buf: &mut String)
246246
clean::StructItem(ref s) => write_str(buf, format_args!("{}", item_struct(cx, item, s))),
247247
clean::UnionItem(ref s) => write_str(buf, format_args!("{}", item_union(cx, item, s))),
248248
clean::EnumItem(ref e) => write_str(buf, format_args!("{}", item_enum(cx, item, e))),
249-
clean::TypeAliasItem(ref t) => item_type_alias(buf, cx, item, t),
249+
clean::TypeAliasItem(ref t) => {
250+
write_str(buf, format_args!("{}", item_type_alias(cx, item, t)))
251+
}
250252
clean::MacroItem(ref m) => item_macro(buf, cx, item, m),
251253
clean::ProcMacroItem(ref m) => item_proc_macro(buf, cx, item, m),
252254
clean::PrimitiveItem(_) => item_primitive(buf, cx, item),
@@ -1261,11 +1263,15 @@ fn item_trait_alias(
12611263
.unwrap();
12621264
}
12631265

1264-
fn item_type_alias(w: &mut String, cx: &Context<'_>, it: &clean::Item, t: &clean::TypeAlias) {
1265-
wrap_item(w, |w| {
1266-
write_str(
1267-
w,
1268-
format_args!(
1266+
fn item_type_alias<'a, 'tcx>(
1267+
cx: &'a Context<'tcx>,
1268+
it: &'a clean::Item,
1269+
t: &'a clean::TypeAlias,
1270+
) -> impl fmt::Display + 'a + Captures<'tcx> {
1271+
fmt::from_fn(|w| {
1272+
wrap_item(w, |w| {
1273+
write!(
1274+
w,
12691275
"{attrs}{vis}type {name}{generics}{where_clause} = {type_};",
12701276
attrs = render_attributes_in_pre(it, "", cx),
12711277
vis = visibility_print_with_space(it, cx),
@@ -1274,32 +1280,27 @@ fn item_type_alias(w: &mut String, cx: &Context<'_>, it: &clean::Item, t: &clean
12741280
where_clause =
12751281
print_where_clause(&t.generics, cx, 0, Ending::Newline).maybe_display(),
12761282
type_ = t.type_.print(cx),
1277-
),
1278-
);
1279-
});
1283+
)
1284+
})?;
12801285

1281-
write_str(w, format_args!("{}", document(cx, it, None, HeadingOffset::H2)));
1286+
write!(w, "{}", document(cx, it, None, HeadingOffset::H2))?;
12821287

1283-
if let Some(inner_type) = &t.inner_type {
1284-
write_str(
1285-
w,
1286-
format_args!("{}", write_section_heading("Aliased Type", "aliased-type", None, "")),
1287-
);
1288+
if let Some(inner_type) = &t.inner_type {
1289+
write!(w, "{}", write_section_heading("Aliased Type", "aliased-type", None, ""),)?;
12881290

1289-
match inner_type {
1290-
clean::TypeAliasInnerType::Enum { variants, is_non_exhaustive } => {
1291-
let variants_iter = || variants.iter().filter(|i| !i.is_stripped());
1292-
let ty = cx.tcx().type_of(it.def_id().unwrap()).instantiate_identity();
1293-
let enum_def_id = ty.ty_adt_def().unwrap().did();
1291+
match inner_type {
1292+
clean::TypeAliasInnerType::Enum { variants, is_non_exhaustive } => {
1293+
let variants_iter = || variants.iter().filter(|i| !i.is_stripped());
1294+
let ty = cx.tcx().type_of(it.def_id().unwrap()).instantiate_identity();
1295+
let enum_def_id = ty.ty_adt_def().unwrap().did();
12941296

1295-
wrap_item(w, |w| {
1296-
let variants_len = variants.len();
1297-
let variants_count = variants_iter().count();
1298-
let has_stripped_entries = variants_len != variants_count;
1297+
wrap_item(w, |w| {
1298+
let variants_len = variants.len();
1299+
let variants_count = variants_iter().count();
1300+
let has_stripped_entries = variants_len != variants_count;
12991301

1300-
write_str(
1301-
w,
1302-
format_args!(
1302+
write!(
1303+
w,
13031304
"enum {}{}{}",
13041305
it.name.unwrap(),
13051306
t.generics.print(cx),
@@ -1312,19 +1313,17 @@ fn item_type_alias(w: &mut String, cx: &Context<'_>, it: &clean::Item, t: &clean
13121313
*is_non_exhaustive,
13131314
enum_def_id,
13141315
)
1315-
),
1316-
)
1317-
});
1318-
write_str(w, format_args!("{}", item_variants(cx, it, variants, enum_def_id)));
1319-
}
1320-
clean::TypeAliasInnerType::Union { fields } => {
1321-
wrap_item(w, |w| {
1322-
let fields_count = fields.iter().filter(|i| !i.is_stripped()).count();
1323-
let has_stripped_fields = fields.len() != fields_count;
1316+
)
1317+
})?;
1318+
write!(w, "{}", item_variants(cx, it, variants, enum_def_id))?;
1319+
}
1320+
clean::TypeAliasInnerType::Union { fields } => {
1321+
wrap_item(w, |w| {
1322+
let fields_count = fields.iter().filter(|i| !i.is_stripped()).count();
1323+
let has_stripped_fields = fields.len() != fields_count;
13241324

1325-
write_str(
1326-
w,
1327-
format_args!(
1325+
write!(
1326+
w,
13281327
"union {}{}{}",
13291328
it.name.unwrap(),
13301329
t.generics.print(cx),
@@ -1336,20 +1335,18 @@ fn item_type_alias(w: &mut String, cx: &Context<'_>, it: &clean::Item, t: &clean
13361335
true,
13371336
has_stripped_fields,
13381337
cx,
1339-
)
1340-
),
1341-
);
1342-
});
1343-
write_str(w, format_args!("{}", item_fields(cx, it, fields, None)));
1344-
}
1345-
clean::TypeAliasInnerType::Struct { ctor_kind, fields } => {
1346-
wrap_item(w, |w| {
1347-
let fields_count = fields.iter().filter(|i| !i.is_stripped()).count();
1348-
let has_stripped_fields = fields.len() != fields_count;
1338+
),
1339+
)
1340+
})?;
1341+
write!(w, "{}", item_fields(cx, it, fields, None))?;
1342+
}
1343+
clean::TypeAliasInnerType::Struct { ctor_kind, fields } => {
1344+
wrap_item(w, |w| {
1345+
let fields_count = fields.iter().filter(|i| !i.is_stripped()).count();
1346+
let has_stripped_fields = fields.len() != fields_count;
13491347

1350-
write_str(
1351-
w,
1352-
format_args!(
1348+
write!(
1349+
w,
13531350
"struct {}{}{}",
13541351
it.name.unwrap(),
13551352
t.generics.print(cx),
@@ -1361,119 +1358,123 @@ fn item_type_alias(w: &mut String, cx: &Context<'_>, it: &clean::Item, t: &clean
13611358
true,
13621359
has_stripped_fields,
13631360
cx,
1364-
)
1365-
),
1366-
);
1367-
});
1368-
write_str(w, format_args!("{}", item_fields(cx, it, fields, None)));
1361+
),
1362+
)
1363+
})?;
1364+
write!(w, "{}", item_fields(cx, it, fields, None))?;
1365+
}
13691366
}
13701367
}
1371-
}
1372-
1373-
let def_id = it.item_id.expect_def_id();
1374-
// Render any items associated directly to this alias, as otherwise they
1375-
// won't be visible anywhere in the docs. It would be nice to also show
1376-
// associated items from the aliased type (see discussion in #32077), but
1377-
// we need #14072 to make sense of the generics.
1378-
write_str(w, format_args!("{}", render_assoc_items(cx, it, def_id, AssocItemRender::All)));
1379-
write_str(w, format_args!("{}", document_type_layout(cx, def_id)));
13801368

1381-
// [RUSTDOCIMPL] type.impl
1382-
//
1383-
// Include type definitions from the alias target type.
1384-
//
1385-
// Earlier versions of this code worked by having `render_assoc_items`
1386-
// include this data directly. That generates *O*`(types*impls)` of HTML
1387-
// text, and some real crates have a lot of types and impls.
1388-
//
1389-
// To create the same UX without generating half a gigabyte of HTML for a
1390-
// crate that only contains 20 megabytes of actual documentation[^115718],
1391-
// rustdoc stashes these type-alias-inlined docs in a [JSONP]
1392-
// "database-lite". The file itself is generated in `write_shared.rs`,
1393-
// and hooks into functions provided by `main.js`.
1394-
//
1395-
// The format of `trait.impl` and `type.impl` JS files are superficially
1396-
// similar. Each line, except the JSONP wrapper itself, belongs to a crate,
1397-
// and they are otherwise separate (rustdoc should be idempotent). The
1398-
// "meat" of the file is HTML strings, so the frontend code is very simple.
1399-
// Links are relative to the doc root, though, so the frontend needs to fix
1400-
// that up, and inlined docs can reuse these files.
1401-
//
1402-
// However, there are a few differences, caused by the sophisticated
1403-
// features that type aliases have. Consider this crate graph:
1404-
//
1405-
// ```text
1406-
// ---------------------------------
1407-
// | crate A: struct Foo<T> |
1408-
// | type Bar = Foo<i32> |
1409-
// | impl X for Foo<i8> |
1410-
// | impl Y for Foo<i32> |
1411-
// ---------------------------------
1412-
// |
1413-
// ----------------------------------
1414-
// | crate B: type Baz = A::Foo<i8> |
1415-
// | type Xyy = A::Foo<i8> |
1416-
// | impl Z for Xyy |
1417-
// ----------------------------------
1418-
// ```
1419-
//
1420-
// The type.impl/A/struct.Foo.js JS file has a structure kinda like this:
1421-
//
1422-
// ```js
1423-
// JSONP({
1424-
// "A": [["impl Y for Foo<i32>", "Y", "A::Bar"]],
1425-
// "B": [["impl X for Foo<i8>", "X", "B::Baz", "B::Xyy"], ["impl Z for Xyy", "Z", "B::Baz"]],
1426-
// });
1427-
// ```
1428-
//
1429-
// When the type.impl file is loaded, only the current crate's docs are
1430-
// actually used. The main reason to bundle them together is that there's
1431-
// enough duplication in them for DEFLATE to remove the redundancy.
1432-
//
1433-
// The contents of a crate are a list of impl blocks, themselves
1434-
// represented as lists. The first item in the sublist is the HTML block,
1435-
// the second item is the name of the trait (which goes in the sidebar),
1436-
// and all others are the names of type aliases that successfully match.
1437-
//
1438-
// This way:
1439-
//
1440-
// - There's no need to generate these files for types that have no aliases
1441-
// in the current crate. If a dependent crate makes a type alias, it'll
1442-
// take care of generating its own docs.
1443-
// - There's no need to reimplement parts of the type checker in
1444-
// JavaScript. The Rust backend does the checking, and includes its
1445-
// results in the file.
1446-
// - Docs defined directly on the type alias are dropped directly in the
1447-
// HTML by `render_assoc_items`, and are accessible without JavaScript.
1448-
// The JSONP file will not list impl items that are known to be part
1449-
// of the main HTML file already.
1450-
//
1451-
// [JSONP]: https://en.wikipedia.org/wiki/JSONP
1452-
// [^115718]: https://github.com/rust-lang/rust/issues/115718
1453-
let cache = &cx.shared.cache;
1454-
if let Some(target_did) = t.type_.def_id(cache) &&
1455-
let get_extern = { || cache.external_paths.get(&target_did) } &&
1456-
let Some(&(ref target_fqp, target_type)) = cache.paths.get(&target_did).or_else(get_extern) &&
1457-
target_type.is_adt() && // primitives cannot be inlined
1458-
let Some(self_did) = it.item_id.as_def_id() &&
1459-
let get_local = { || cache.paths.get(&self_did).map(|(p, _)| p) } &&
1460-
let Some(self_fqp) = cache.exact_paths.get(&self_did).or_else(get_local)
1461-
{
1462-
let mut js_src_path: UrlPartsBuilder = std::iter::repeat("..")
1463-
.take(cx.current.len())
1464-
.chain(std::iter::once("type.impl"))
1465-
.collect();
1466-
js_src_path.extend(target_fqp[..target_fqp.len() - 1].iter().copied());
1467-
js_src_path.push_fmt(format_args!("{target_type}.{}.js", target_fqp.last().unwrap()));
1468-
let self_path = fmt::from_fn(|f| self_fqp.iter().joined("::", f));
1469-
write_str(
1369+
let def_id = it.item_id.expect_def_id();
1370+
// Render any items associated directly to this alias, as otherwise they
1371+
// won't be visible anywhere in the docs. It would be nice to also show
1372+
// associated items from the aliased type (see discussion in #32077), but
1373+
// we need #14072 to make sense of the generics.
1374+
write!(
14701375
w,
1471-
format_args!(
1376+
"{}{}",
1377+
render_assoc_items(cx, it, def_id, AssocItemRender::All),
1378+
document_type_layout(cx, def_id)
1379+
)?;
1380+
1381+
// [RUSTDOCIMPL] type.impl
1382+
//
1383+
// Include type definitions from the alias target type.
1384+
//
1385+
// Earlier versions of this code worked by having `render_assoc_items`
1386+
// include this data directly. That generates *O*`(types*impls)` of HTML
1387+
// text, and some real crates have a lot of types and impls.
1388+
//
1389+
// To create the same UX without generating half a gigabyte of HTML for a
1390+
// crate that only contains 20 megabytes of actual documentation[^115718],
1391+
// rustdoc stashes these type-alias-inlined docs in a [JSONP]
1392+
// "database-lite". The file itself is generated in `write_shared.rs`,
1393+
// and hooks into functions provided by `main.js`.
1394+
//
1395+
// The format of `trait.impl` and `type.impl` JS files are superficially
1396+
// similar. Each line, except the JSONP wrapper itself, belongs to a crate,
1397+
// and they are otherwise separate (rustdoc should be idempotent). The
1398+
// "meat" of the file is HTML strings, so the frontend code is very simple.
1399+
// Links are relative to the doc root, though, so the frontend needs to fix
1400+
// that up, and inlined docs can reuse these files.
1401+
//
1402+
// However, there are a few differences, caused by the sophisticated
1403+
// features that type aliases have. Consider this crate graph:
1404+
//
1405+
// ```text
1406+
// ---------------------------------
1407+
// | crate A: struct Foo<T> |
1408+
// | type Bar = Foo<i32> |
1409+
// | impl X for Foo<i8> |
1410+
// | impl Y for Foo<i32> |
1411+
// ---------------------------------
1412+
// |
1413+
// ----------------------------------
1414+
// | crate B: type Baz = A::Foo<i8> |
1415+
// | type Xyy = A::Foo<i8> |
1416+
// | impl Z for Xyy |
1417+
// ----------------------------------
1418+
// ```
1419+
//
1420+
// The type.impl/A/struct.Foo.js JS file has a structure kinda like this:
1421+
//
1422+
// ```js
1423+
// JSONP({
1424+
// "A": [["impl Y for Foo<i32>", "Y", "A::Bar"]],
1425+
// "B": [["impl X for Foo<i8>", "X", "B::Baz", "B::Xyy"], ["impl Z for Xyy", "Z", "B::Baz"]],
1426+
// });
1427+
// ```
1428+
//
1429+
// When the type.impl file is loaded, only the current crate's docs are
1430+
// actually used. The main reason to bundle them together is that there's
1431+
// enough duplication in them for DEFLATE to remove the redundancy.
1432+
//
1433+
// The contents of a crate are a list of impl blocks, themselves
1434+
// represented as lists. The first item in the sublist is the HTML block,
1435+
// the second item is the name of the trait (which goes in the sidebar),
1436+
// and all others are the names of type aliases that successfully match.
1437+
//
1438+
// This way:
1439+
//
1440+
// - There's no need to generate these files for types that have no aliases
1441+
// in the current crate. If a dependent crate makes a type alias, it'll
1442+
// take care of generating its own docs.
1443+
// - There's no need to reimplement parts of the type checker in
1444+
// JavaScript. The Rust backend does the checking, and includes its
1445+
// results in the file.
1446+
// - Docs defined directly on the type alias are dropped directly in the
1447+
// HTML by `render_assoc_items`, and are accessible without JavaScript.
1448+
// The JSONP file will not list impl items that are known to be part
1449+
// of the main HTML file already.
1450+
//
1451+
// [JSONP]: https://en.wikipedia.org/wiki/JSONP
1452+
// [^115718]: https://github.com/rust-lang/rust/issues/115718
1453+
let cache = &cx.shared.cache;
1454+
if let Some(target_did) = t.type_.def_id(cache)
1455+
&& let get_extern = { || cache.external_paths.get(&target_did) }
1456+
&& let Some(&(ref target_fqp, target_type)) =
1457+
cache.paths.get(&target_did).or_else(get_extern)
1458+
&& target_type.is_adt() // primitives cannot be inlined
1459+
&& let Some(self_did) = it.item_id.as_def_id()
1460+
&& let get_local = { || cache.paths.get(&self_did).map(|(p, _)| p) }
1461+
&& let Some(self_fqp) = cache.exact_paths.get(&self_did).or_else(get_local)
1462+
{
1463+
let mut js_src_path: UrlPartsBuilder = std::iter::repeat("..")
1464+
.take(cx.current.len())
1465+
.chain(std::iter::once("type.impl"))
1466+
.collect();
1467+
js_src_path.extend(target_fqp[..target_fqp.len() - 1].iter().copied());
1468+
js_src_path.push_fmt(format_args!("{target_type}.{}.js", target_fqp.last().unwrap()));
1469+
let self_path = fmt::from_fn(|f| self_fqp.iter().joined("::", f));
1470+
write!(
1471+
w,
14721472
"<script src=\"{src}\" data-self-path=\"{self_path}\" async></script>",
1473-
src = js_src_path.finish()
1474-
),
1475-
);
1476-
}
1473+
src = js_src_path.finish(),
1474+
)?;
1475+
}
1476+
Ok(())
1477+
})
14771478
}
14781479

14791480
fn item_union<'a, 'tcx>(

0 commit comments

Comments
 (0)