@@ -59,7 +59,7 @@ use rustc_span::{
5959 symbol:: { sym, Symbol } ,
6060 BytePos , FileName , RealFileName ,
6161} ;
62- use serde:: ser:: SerializeSeq ;
62+ use serde:: ser:: { SerializeMap , SerializeSeq } ;
6363use serde:: { Serialize , Serializer } ;
6464
6565use crate :: clean:: { self , ItemId , RenderedLink , SelfTy } ;
@@ -803,7 +803,7 @@ fn assoc_method(
803803 d : & clean:: FnDecl ,
804804 link : AssocItemLink < ' _ > ,
805805 parent : ItemType ,
806- cx : & Context < ' _ > ,
806+ cx : & mut Context < ' _ > ,
807807 render_mode : RenderMode ,
808808) {
809809 let tcx = cx. tcx ( ) ;
@@ -836,6 +836,8 @@ fn assoc_method(
836836 + name. as_str ( ) . len ( )
837837 + generics_len;
838838
839+ let notable_traits = d. output . as_return ( ) . and_then ( |output| notable_traits_button ( output, cx) ) ;
840+
839841 let ( indent, indent_str, end_newline) = if parent == ItemType :: Trait {
840842 header_len += 4 ;
841843 let indent_str = " " ;
@@ -861,9 +863,9 @@ fn assoc_method(
861863 name = name,
862864 generics = g. print( cx) ,
863865 decl = d. full_print( header_len, indent, cx) ,
864- notable_traits = notable_traits_decl ( d , cx ) ,
866+ notable_traits = notable_traits . unwrap_or_default ( ) ,
865867 where_clause = print_where_clause( g, cx, indent, end_newline) ,
866- )
868+ ) ;
867869}
868870
869871/// 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(
963965 item : & clean:: Item ,
964966 link : AssocItemLink < ' _ > ,
965967 parent : ItemType ,
966- cx : & Context < ' _ > ,
968+ cx : & mut Context < ' _ > ,
967969 render_mode : RenderMode ,
968970) {
969971 match & * item. kind {
@@ -1273,88 +1275,135 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) ->
12731275 }
12741276}
12751277
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 ( ) ) ?;
12781282
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 ( )
12801289 {
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 ( ) ) )
12941305 {
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+ ) ;
12981350 }
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- }
13161351
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 (
13191364 & 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,
13221372 ) ;
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>" ) ;
13421374 }
13431375 }
13441376 }
13451377 }
13461378 }
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>" , ) ;
13551381 }
13561382
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" )
13581407}
13591408
13601409#[ derive( Clone , Copy , Debug ) ]
0 commit comments