@@ -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
14791480fn item_union < ' a , ' tcx > (
0 commit comments