@@ -59,7 +59,7 @@ use rustc_span::{
59
59
symbol:: { sym, Symbol } ,
60
60
BytePos , FileName , RealFileName ,
61
61
} ;
62
- use serde:: ser:: SerializeSeq ;
62
+ use serde:: ser:: { SerializeMap , SerializeSeq } ;
63
63
use serde:: { Serialize , Serializer } ;
64
64
65
65
use crate :: clean:: { self , ItemId , RenderedLink , SelfTy } ;
@@ -803,7 +803,7 @@ fn assoc_method(
803
803
d : & clean:: FnDecl ,
804
804
link : AssocItemLink < ' _ > ,
805
805
parent : ItemType ,
806
- cx : & Context < ' _ > ,
806
+ cx : & mut Context < ' _ > ,
807
807
render_mode : RenderMode ,
808
808
) {
809
809
let tcx = cx. tcx ( ) ;
@@ -836,6 +836,8 @@ fn assoc_method(
836
836
+ name. as_str ( ) . len ( )
837
837
+ generics_len;
838
838
839
+ let notable_traits = d. output . as_return ( ) . and_then ( |output| notable_traits_button ( output, cx) ) ;
840
+
839
841
let ( indent, indent_str, end_newline) = if parent == ItemType :: Trait {
840
842
header_len += 4 ;
841
843
let indent_str = " " ;
@@ -861,9 +863,9 @@ fn assoc_method(
861
863
name = name,
862
864
generics = g. print( cx) ,
863
865
decl = d. full_print( header_len, indent, cx) ,
864
- notable_traits = notable_traits_decl ( d , cx ) ,
866
+ notable_traits = notable_traits . unwrap_or_default ( ) ,
865
867
where_clause = print_where_clause( g, cx, indent, end_newline) ,
866
- )
868
+ ) ;
867
869
}
868
870
869
871
/// Writes a span containing the versions at which an item became stable and/or const-stable. For
@@ -963,7 +965,7 @@ fn render_assoc_item(
963
965
item : & clean:: Item ,
964
966
link : AssocItemLink < ' _ > ,
965
967
parent : ItemType ,
966
- cx : & Context < ' _ > ,
968
+ cx : & mut Context < ' _ > ,
967
969
render_mode : RenderMode ,
968
970
) {
969
971
match & * item. kind {
@@ -1273,88 +1275,135 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) ->
1273
1275
}
1274
1276
}
1275
1277
1276
- fn notable_traits_decl ( decl : & clean:: FnDecl , cx : & Context < ' _ > ) -> String {
1277
- let mut out = Buffer :: html ( ) ;
1278
+ pub ( crate ) fn notable_traits_button ( ty : & clean:: Type , cx : & mut Context < ' _ > ) -> Option < String > {
1279
+ let mut has_notable_trait = false ;
1280
+
1281
+ let did = ty. def_id ( cx. cache ( ) ) ?;
1278
1282
1279
- if let Some ( ( did, ty) ) = decl. output . as_return ( ) . and_then ( |t| Some ( ( t. def_id ( cx. cache ( ) ) ?, t) ) )
1283
+ // Box has pass-through impls for Read, Write, Iterator, and Future when the
1284
+ // boxed type implements one of those. We don't want to treat every Box return
1285
+ // as being notably an Iterator (etc), though, so we exempt it. Pin has the same
1286
+ // issue, with a pass-through impl for Future.
1287
+ if Some ( did) == cx. tcx ( ) . lang_items ( ) . owned_box ( )
1288
+ || Some ( did) == cx. tcx ( ) . lang_items ( ) . pin_type ( )
1280
1289
{
1281
- // Box has pass-through impls for Read, Write, Iterator, and Future when the
1282
- // boxed type implements one of those. We don't want to treat every Box return
1283
- // as being notably an Iterator (etc), though, so we exempt it. Pin has the same
1284
- // issue, with a pass-through impl for Future.
1285
- if Some ( did) == cx. tcx ( ) . lang_items ( ) . owned_box ( )
1286
- || Some ( did) == cx. tcx ( ) . lang_items ( ) . pin_type ( )
1287
- {
1288
- return "" . to_string ( ) ;
1289
- }
1290
- if let Some ( impls) = cx. cache ( ) . impls . get ( & did) {
1291
- for i in impls {
1292
- let impl_ = i. inner_impl ( ) ;
1293
- if !impl_. for_ . without_borrowed_ref ( ) . is_same ( ty. without_borrowed_ref ( ) , cx. cache ( ) )
1290
+ return None ;
1291
+ }
1292
+
1293
+ if let Some ( impls) = cx. cache ( ) . impls . get ( & did) {
1294
+ for i in impls {
1295
+ let impl_ = i. inner_impl ( ) ;
1296
+ if !impl_. for_ . without_borrowed_ref ( ) . is_same ( ty. without_borrowed_ref ( ) , cx. cache ( ) ) {
1297
+ // Two different types might have the same did,
1298
+ // without actually being the same.
1299
+ continue ;
1300
+ }
1301
+ if let Some ( trait_) = & impl_. trait_ {
1302
+ let trait_did = trait_. def_id ( ) ;
1303
+
1304
+ if cx. cache ( ) . traits . get ( & trait_did) . map_or ( false , |t| t. is_notable_trait ( cx. tcx ( ) ) )
1294
1305
{
1295
- // Two different types might have the same did,
1296
- // without actually being the same.
1297
- continue ;
1306
+ has_notable_trait = true ;
1307
+ }
1308
+ }
1309
+ }
1310
+ }
1311
+
1312
+ if has_notable_trait {
1313
+ cx. types_with_notable_traits . insert ( ty. clone ( ) ) ;
1314
+ Some ( format ! (
1315
+ "<span class=\" notable-traits\" data-ty=\" {ty}\" >\
1316
+ <span class=\" notable-traits-tooltip\" >ⓘ</span>\
1317
+ </span>",
1318
+ ty = Escape ( & format!( "{:#}" , ty. print( cx) ) ) ,
1319
+ ) )
1320
+ } else {
1321
+ None
1322
+ }
1323
+ }
1324
+
1325
+ fn notable_traits_decl ( ty : & clean:: Type , cx : & Context < ' _ > ) -> ( String , String ) {
1326
+ let mut out = Buffer :: html ( ) ;
1327
+
1328
+ let did = ty. def_id ( cx. cache ( ) ) . expect ( "notable_traits_button already checked this" ) ;
1329
+
1330
+ let impls = cx. cache ( ) . impls . get ( & did) . expect ( "notable_traits_button already checked this" ) ;
1331
+
1332
+ for i in impls {
1333
+ let impl_ = i. inner_impl ( ) ;
1334
+ if !impl_. for_ . without_borrowed_ref ( ) . is_same ( ty. without_borrowed_ref ( ) , cx. cache ( ) ) {
1335
+ // Two different types might have the same did,
1336
+ // without actually being the same.
1337
+ continue ;
1338
+ }
1339
+ if let Some ( trait_) = & impl_. trait_ {
1340
+ let trait_did = trait_. def_id ( ) ;
1341
+
1342
+ if cx. cache ( ) . traits . get ( & trait_did) . map_or ( false , |t| t. is_notable_trait ( cx. tcx ( ) ) ) {
1343
+ if out. is_empty ( ) {
1344
+ write ! (
1345
+ & mut out,
1346
+ "<h3 class=\" notable\" >Notable traits for <code>{}</code></h3>\
1347
+ <pre class=\" content\" ><code>",
1348
+ impl_. for_. print( cx)
1349
+ ) ;
1298
1350
}
1299
- if let Some ( trait_) = & impl_. trait_ {
1300
- let trait_did = trait_. def_id ( ) ;
1301
-
1302
- if cx
1303
- . cache ( )
1304
- . traits
1305
- . get ( & trait_did)
1306
- . map_or ( false , |t| t. is_notable_trait ( cx. tcx ( ) ) )
1307
- {
1308
- if out. is_empty ( ) {
1309
- write ! (
1310
- & mut out,
1311
- "<span class=\" notable\" >Notable traits for {}</span>\
1312
- <code class=\" content\" >",
1313
- impl_. for_. print( cx)
1314
- ) ;
1315
- }
1316
1351
1317
- //use the "where" class here to make it small
1318
- write ! (
1352
+ //use the "where" class here to make it small
1353
+ write ! (
1354
+ & mut out,
1355
+ "<span class=\" where fmt-newline\" >{}</span>" ,
1356
+ impl_. print( false , cx)
1357
+ ) ;
1358
+ for it in & impl_. items {
1359
+ if let clean:: AssocTypeItem ( ref tydef, ref _bounds) = * it. kind {
1360
+ out. push_str ( "<span class=\" where fmt-newline\" > " ) ;
1361
+ let empty_set = FxHashSet :: default ( ) ;
1362
+ let src_link = AssocItemLink :: GotoSource ( trait_did. into ( ) , & empty_set) ;
1363
+ assoc_type (
1319
1364
& mut out,
1320
- "<span class=\" where fmt-newline\" >{}</span>" ,
1321
- impl_. print( false , cx)
1365
+ it,
1366
+ & tydef. generics ,
1367
+ & [ ] , // intentionally leaving out bounds
1368
+ Some ( & tydef. type_ ) ,
1369
+ src_link,
1370
+ 0 ,
1371
+ cx,
1322
1372
) ;
1323
- for it in & impl_. items {
1324
- if let clean:: AssocTypeItem ( ref tydef, ref _bounds) = * it. kind {
1325
- out. push_str ( "<span class=\" where fmt-newline\" > " ) ;
1326
- let empty_set = FxHashSet :: default ( ) ;
1327
- let src_link =
1328
- AssocItemLink :: GotoSource ( trait_did. into ( ) , & empty_set) ;
1329
- assoc_type (
1330
- & mut out,
1331
- it,
1332
- & tydef. generics ,
1333
- & [ ] , // intentionally leaving out bounds
1334
- Some ( & tydef. type_ ) ,
1335
- src_link,
1336
- 0 ,
1337
- cx,
1338
- ) ;
1339
- out. push_str ( ";</span>" ) ;
1340
- }
1341
- }
1373
+ out. push_str ( ";</span>" ) ;
1342
1374
}
1343
1375
}
1344
1376
}
1345
1377
}
1346
1378
}
1347
-
1348
- if !out. is_empty ( ) {
1349
- out. insert_str (
1350
- 0 ,
1351
- "<span class=\" notable-traits\" ><span class=\" notable-traits-tooltip\" >ⓘ\
1352
- <span class=\" notable-traits-tooltiptext\" ><span class=\" docblock\" >",
1353
- ) ;
1354
- out. push_str ( "</code></span></span></span></span>" ) ;
1379
+ if out. is_empty ( ) {
1380
+ write ! ( & mut out, "</code></pre>" , ) ;
1355
1381
}
1356
1382
1357
- out. into_inner ( )
1383
+ ( format ! ( "{:#}" , ty. print( cx) ) , out. into_inner ( ) )
1384
+ }
1385
+
1386
+ pub ( crate ) fn notable_traits_json < ' a > (
1387
+ tys : impl Iterator < Item = & ' a clean:: Type > ,
1388
+ cx : & Context < ' _ > ,
1389
+ ) -> String {
1390
+ let mut mp: Vec < ( String , String ) > = tys. map ( |ty| notable_traits_decl ( ty, cx) ) . collect ( ) ;
1391
+ mp. sort_by ( |( name1, _html1) , ( name2, _html2) | name1. cmp ( name2) ) ;
1392
+ struct NotableTraitsMap ( Vec < ( String , String ) > ) ;
1393
+ impl Serialize for NotableTraitsMap {
1394
+ fn serialize < S > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error >
1395
+ where
1396
+ S : Serializer ,
1397
+ {
1398
+ let mut map = serializer. serialize_map ( Some ( self . 0 . len ( ) ) ) ?;
1399
+ for item in & self . 0 {
1400
+ map. serialize_entry ( & item. 0 , & item. 1 ) ?;
1401
+ }
1402
+ map. end ( )
1403
+ }
1404
+ }
1405
+ serde_json:: to_string ( & NotableTraitsMap ( mp) )
1406
+ . expect ( "serialize (string, string) -> json object cannot fail" )
1358
1407
}
1359
1408
1360
1409
#[ derive( Clone , Copy , Debug ) ]
0 commit comments