@@ -246,7 +246,9 @@ pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item, buf: &mut String)
246
246
clean:: StructItem ( ref s) => write_str ( buf, format_args ! ( "{}" , item_struct( cx, item, s) ) ) ,
247
247
clean:: UnionItem ( ref s) => write_str ( buf, format_args ! ( "{}" , item_union( cx, item, s) ) ) ,
248
248
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
+ }
250
252
clean:: MacroItem ( ref m) => item_macro ( buf, cx, item, m) ,
251
253
clean:: ProcMacroItem ( ref m) => item_proc_macro ( buf, cx, item, m) ,
252
254
clean:: PrimitiveItem ( _) => item_primitive ( buf, cx, item) ,
@@ -1261,11 +1263,15 @@ fn item_trait_alias(
1261
1263
. unwrap ( ) ;
1262
1264
}
1263
1265
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,
1269
1275
"{attrs}{vis}type {name}{generics}{where_clause} = {type_};" ,
1270
1276
attrs = render_attributes_in_pre( it, "" , cx) ,
1271
1277
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
1274
1280
where_clause =
1275
1281
print_where_clause( & t. generics, cx, 0 , Ending :: Newline ) . maybe_display( ) ,
1276
1282
type_ = t. type_. print( cx) ,
1277
- ) ,
1278
- ) ;
1279
- } ) ;
1283
+ )
1284
+ } ) ?;
1280
1285
1281
- write_str ( w, format_args ! ( "{}" , document( cx, it, None , HeadingOffset :: H2 ) ) ) ;
1286
+ write ! ( w, "{}" , document( cx, it, None , HeadingOffset :: H2 ) ) ? ;
1282
1287
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 , "" ) , ) ?;
1288
1290
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 ( ) ;
1294
1296
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;
1299
1301
1300
- write_str (
1301
- w,
1302
- format_args ! (
1302
+ write ! (
1303
+ w,
1303
1304
"enum {}{}{}" ,
1304
1305
it. name. unwrap( ) ,
1305
1306
t. generics. print( cx) ,
@@ -1312,19 +1313,17 @@ fn item_type_alias(w: &mut String, cx: &Context<'_>, it: &clean::Item, t: &clean
1312
1313
* is_non_exhaustive,
1313
1314
enum_def_id,
1314
1315
)
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;
1324
1324
1325
- write_str (
1326
- w,
1327
- format_args ! (
1325
+ write ! (
1326
+ w,
1328
1327
"union {}{}{}" ,
1329
1328
it. name. unwrap( ) ,
1330
1329
t. generics. print( cx) ,
@@ -1336,20 +1335,18 @@ fn item_type_alias(w: &mut String, cx: &Context<'_>, it: &clean::Item, t: &clean
1336
1335
true ,
1337
1336
has_stripped_fields,
1338
1337
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;
1349
1347
1350
- write_str (
1351
- w,
1352
- format_args ! (
1348
+ write ! (
1349
+ w,
1353
1350
"struct {}{}{}" ,
1354
1351
it. name. unwrap( ) ,
1355
1352
t. generics. print( cx) ,
@@ -1361,119 +1358,123 @@ fn item_type_alias(w: &mut String, cx: &Context<'_>, it: &clean::Item, t: &clean
1361
1358
true ,
1362
1359
has_stripped_fields,
1363
1360
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
+ }
1369
1366
}
1370
1367
}
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) ) ) ;
1380
1368
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 ! (
1470
1375
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,
1472
1472
"<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
+ } )
1477
1478
}
1478
1479
1479
1480
fn item_union < ' a , ' tcx > (
0 commit comments