@@ -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,13 +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 = d
865
- . output
866
- . as_return( )
867
- . and_then( |output| notable_traits_decl( output, cx) )
868
- . unwrap_or_default( ) ,
866
+ notable_traits = notable_traits. unwrap_or_default( ) ,
869
867
where_clause = print_where_clause( g, cx, indent, end_newline) ,
870
- )
868
+ ) ;
871
869
}
872
870
873
871
/// Writes a span containing the versions at which an item became stable and/or const-stable. For
@@ -967,7 +965,7 @@ fn render_assoc_item(
967
965
item : & clean:: Item ,
968
966
link : AssocItemLink < ' _ > ,
969
967
parent : ItemType ,
970
- cx : & Context < ' _ > ,
968
+ cx : & mut Context < ' _ > ,
971
969
render_mode : RenderMode ,
972
970
) {
973
971
match & * item. kind {
@@ -1277,8 +1275,8 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) ->
1277
1275
}
1278
1276
}
1279
1277
1280
- fn notable_traits_decl ( ty : & clean:: Type , cx : & Context < ' _ > ) -> Option < String > {
1281
- 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 ;
1282
1280
1283
1281
let did = ty. def_id ( cx. cache ( ) ) ?;
1284
1282
@@ -1291,6 +1289,7 @@ fn notable_traits_decl(ty: &clean::Type, cx: &Context<'_>) -> Option<String> {
1291
1289
{
1292
1290
return None ;
1293
1291
}
1292
+
1294
1293
if let Some ( impls) = cx. cache ( ) . impls . get ( & did) {
1295
1294
for i in impls {
1296
1295
let impl_ = i. inner_impl ( ) ;
@@ -1304,56 +1303,106 @@ fn notable_traits_decl(ty: &clean::Type, cx: &Context<'_>) -> Option<String> {
1304
1303
1305
1304
if cx. cache ( ) . traits . get ( & trait_did) . map_or ( false , |t| t. is_notable_trait ( cx. tcx ( ) ) )
1306
1305
{
1307
- if out. is_empty ( ) {
1308
- write ! (
1309
- & mut out,
1310
- "<span class=\" notable\" >Notable traits for {}</span>\
1311
- <code class=\" content\" >",
1312
- impl_. for_. print( cx)
1313
- ) ;
1314
- }
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 = 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" ) ;
1315
1329
1316
- //use the "where" class here to make it small
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 ( ) {
1317
1344
write ! (
1318
1345
& mut out,
1319
- "<span class=\" where fmt-newline\" >{}</span>" ,
1320
- impl_. print( false , cx)
1346
+ "<h3 class=\" notable\" >Notable traits for <code>{}</code></h3>\
1347
+ <pre class=\" content\" ><code>",
1348
+ impl_. for_. print( cx)
1321
1349
) ;
1322
- for it in & impl_. items {
1323
- if let clean:: AssocTypeItem ( ref tydef, ref _bounds) = * it. kind {
1324
- out. push_str ( "<span class=\" where fmt-newline\" > " ) ;
1325
- let empty_set = FxHashSet :: default ( ) ;
1326
- let src_link = AssocItemLink :: GotoSource ( trait_did. into ( ) , & empty_set) ;
1327
- assoc_type (
1328
- & mut out,
1329
- it,
1330
- & tydef. generics ,
1331
- & [ ] , // intentionally leaving out bounds
1332
- Some ( & tydef. type_ ) ,
1333
- src_link,
1334
- 0 ,
1335
- cx,
1336
- ) ;
1337
- out. push_str ( ";</span>" ) ;
1338
- }
1350
+ }
1351
+
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 (
1364
+ & mut out,
1365
+ it,
1366
+ & tydef. generics ,
1367
+ & [ ] , // intentionally leaving out bounds
1368
+ Some ( & tydef. type_ ) ,
1369
+ src_link,
1370
+ 0 ,
1371
+ cx,
1372
+ ) ;
1373
+ out. push_str ( ";</span>" ) ;
1339
1374
}
1340
1375
}
1341
1376
}
1342
1377
}
1343
1378
}
1344
-
1345
1379
if out. is_empty ( ) {
1346
- return None ;
1380
+ write ! ( & mut out , "</code></pre>" , ) ;
1347
1381
}
1348
1382
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>" ) ;
1383
+ ( format ! ( "{:#}" , ty. print( cx) ) , out. into_inner ( ) )
1384
+ }
1355
1385
1356
- Some ( out. into_inner ( ) )
1386
+ pub ( crate ) fn notable_traits_json < ' a > (
1387
+ tys : impl Iterator < Item = & ' a clean:: Type > ,
1388
+ cx : & Context < ' _ > ,
1389
+ ) -> String {
1390
+ let mp: Vec < ( String , String ) > = tys. map ( |ty| notable_traits_decl ( ty, cx) ) . collect ( ) ;
1391
+ struct NotableTraitsMap ( Vec < ( String , String ) > ) ;
1392
+ impl Serialize for NotableTraitsMap {
1393
+ fn serialize < S > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error >
1394
+ where
1395
+ S : Serializer ,
1396
+ {
1397
+ let mut map = serializer. serialize_map ( Some ( self . 0 . len ( ) ) ) ?;
1398
+ for item in & self . 0 {
1399
+ map. serialize_entry ( & item. 0 , & item. 1 ) ?;
1400
+ }
1401
+ map. end ( )
1402
+ }
1403
+ }
1404
+ serde_json:: to_string ( & NotableTraitsMap ( mp) )
1405
+ . expect ( "serialize (string, string) -> json object cannot fail" )
1357
1406
}
1358
1407
1359
1408
#[ derive( Clone , Copy , Debug ) ]
0 commit comments