@@ -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,13 +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 = 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( ) ,
869867 where_clause = print_where_clause( g, cx, indent, end_newline) ,
870- )
868+ ) ;
871869}
872870
873871/// 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(
967965 item : & clean:: Item ,
968966 link : AssocItemLink < ' _ > ,
969967 parent : ItemType ,
970- cx : & Context < ' _ > ,
968+ cx : & mut Context < ' _ > ,
971969 render_mode : RenderMode ,
972970) {
973971 match & * item. kind {
@@ -1277,8 +1275,8 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) ->
12771275 }
12781276}
12791277
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 ;
12821280
12831281 let did = ty. def_id ( cx. cache ( ) ) ?;
12841282
@@ -1291,6 +1289,7 @@ fn notable_traits_decl(ty: &clean::Type, cx: &Context<'_>) -> Option<String> {
12911289 {
12921290 return None ;
12931291 }
1292+
12941293 if let Some ( impls) = cx. cache ( ) . impls . get ( & did) {
12951294 for i in impls {
12961295 let impl_ = i. inner_impl ( ) ;
@@ -1304,56 +1303,106 @@ fn notable_traits_decl(ty: &clean::Type, cx: &Context<'_>) -> Option<String> {
13041303
13051304 if cx. cache ( ) . traits . get ( & trait_did) . map_or ( false , |t| t. is_notable_trait ( cx. tcx ( ) ) )
13061305 {
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" ) ;
13151329
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 ( ) {
13171344 write ! (
13181345 & 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)
13211349 ) ;
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>" ) ;
13391374 }
13401375 }
13411376 }
13421377 }
13431378 }
1344-
13451379 if out. is_empty ( ) {
1346- return None ;
1380+ write ! ( & mut out , "</code></pre>" , ) ;
13471381 }
13481382
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+ }
13551385
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" )
13571406}
13581407
13591408#[ derive( Clone , Copy , Debug ) ]
0 commit comments