@@ -51,7 +51,9 @@ use askama::Template;
5151use  itertools:: Either ; 
5252use  rustc_ast:: join_path_syms; 
5353use  rustc_data_structures:: fx:: { FxHashSet ,  FxIndexMap ,  FxIndexSet } ; 
54- use  rustc_hir:: attrs:: { DeprecatedSince ,  Deprecation } ; 
54+ use  rustc_hir as  hir; 
55+ use  rustc_hir:: attrs:: { AttributeKind ,  DeprecatedSince ,  Deprecation } ; 
56+ use  rustc_hir:: def:: DefKind ; 
5557use  rustc_hir:: def_id:: { DefId ,  DefIdSet } ; 
5658use  rustc_hir:: { ConstStability ,  Mutability ,  RustcVersion ,  StabilityLevel ,  StableSince } ; 
5759use  rustc_middle:: ty:: print:: PrintTraitRefExt ; 
@@ -1310,43 +1312,6 @@ fn render_assoc_item(
13101312    } ) 
13111313} 
13121314
1313- struct  CodeAttribute ( String ) ; 
1314- 
1315- fn  render_code_attribute ( prefix :  & str ,  code_attr :  CodeAttribute ,  w :  & mut  impl  fmt:: Write )  { 
1316-     write ! ( 
1317-         w, 
1318-         "<div class=\" code-attribute\" >{prefix}{attr}</div>" , 
1319-         prefix = prefix, 
1320-         attr = code_attr. 0 
1321-     ) 
1322-     . unwrap ( ) ; 
1323- } 
1324- 
1325- // When an attribute is rendered inside a <code> tag, it is formatted using 
1326- // a div to produce a newline after it. 
1327- fn  render_attributes_in_code ( 
1328-     w :  & mut  impl  fmt:: Write , 
1329-     it :  & clean:: Item , 
1330-     prefix :  & str , 
1331-     cx :  & Context < ' _ > , 
1332- )  { 
1333-     for  attr in  it. attributes ( cx. tcx ( ) ,  cx. cache ( ) )  { 
1334-         render_code_attribute ( prefix,  CodeAttribute ( attr) ,  w) ; 
1335-     } 
1336- } 
1337- 
1338- /// used for type aliases to only render their `repr` attribute. 
1339- fn  render_repr_attributes_in_code ( 
1340-     w :  & mut  impl  fmt:: Write , 
1341-     cx :  & Context < ' _ > , 
1342-     def_id :  DefId , 
1343-     item_type :  ItemType , 
1344- )  { 
1345-     if  let  Some ( repr)  = clean:: repr_attributes ( cx. tcx ( ) ,  cx. cache ( ) ,  def_id,  item_type)  { 
1346-         render_code_attribute ( "" ,  CodeAttribute ( repr) ,  w) ; 
1347-     } 
1348- } 
1349- 
13501315#[ derive( Copy ,  Clone ) ]  
13511316enum  AssocItemLink < ' a >  { 
13521317    Anchor ( Option < & ' a  str > ) , 
@@ -2959,3 +2924,142 @@ fn render_call_locations<W: fmt::Write>(
29592924
29602925    w. write_str ( "</div>" ) 
29612926} 
2927+ 
2928+ fn  render_attributes_in_code ( 
2929+     w :  & mut  impl  fmt:: Write , 
2930+     item :  & clean:: Item , 
2931+     prefix :  & str , 
2932+     cx :  & Context < ' _ > , 
2933+ )  { 
2934+     for  attr in  & item. attrs . other_attrs  { 
2935+         let  hir:: Attribute :: Parsed ( kind)  = attr else  {  continue  } ; 
2936+         let  attr = match  kind { 
2937+             AttributeKind :: LinkSection  {  name,  .. }  => { 
2938+                 Cow :: Owned ( format ! ( "#[unsafe(link_section = {})]" ,  Escape ( & format!( "{name:?}" ) ) ) ) 
2939+             } 
2940+             AttributeKind :: NoMangle ( ..)  => Cow :: Borrowed ( "#[unsafe(no_mangle)]" ) , 
2941+             AttributeKind :: ExportName  {  name,  .. }  => { 
2942+                 Cow :: Owned ( format ! ( "#[unsafe(export_name = {})]" ,  Escape ( & format!( "{name:?}" ) ) ) ) 
2943+             } 
2944+             AttributeKind :: NonExhaustive ( ..)  => Cow :: Borrowed ( "#[non_exhaustive]" ) , 
2945+             _ => continue , 
2946+         } ; 
2947+         render_code_attribute ( prefix,  attr. as_ref ( ) ,  w) ; 
2948+     } 
2949+ 
2950+     if  let  Some ( def_id)  = item. def_id ( ) 
2951+         && let  Some ( repr)  = repr_attribute ( cx. tcx ( ) ,  cx. cache ( ) ,  def_id) 
2952+     { 
2953+         render_code_attribute ( prefix,  & repr,  w) ; 
2954+     } 
2955+ } 
2956+ 
2957+ fn  render_repr_attribute_in_code ( w :  & mut  impl  fmt:: Write ,  cx :  & Context < ' _ > ,  def_id :  DefId )  { 
2958+     if  let  Some ( repr)  = repr_attribute ( cx. tcx ( ) ,  cx. cache ( ) ,  def_id)  { 
2959+         render_code_attribute ( "" ,  & repr,  w) ; 
2960+     } 
2961+ } 
2962+ 
2963+ fn  render_code_attribute ( prefix :  & str ,  attr :  & str ,  w :  & mut  impl  fmt:: Write )  { 
2964+     write ! ( w,  "<div class=\" code-attribute\" >{prefix}{attr}</div>" ) . unwrap ( ) ; 
2965+ } 
2966+ 
2967+ /// Compute the *public* `#[repr]` of the item given by `DefId`. 
2968+ /// 
2969+ /// Read more about it here: 
2970+ /// <https://doc.rust-lang.org/nightly/rustdoc/advanced-features.html#repr-documenting-the-representation-of-a-type>. 
2971+ fn  repr_attribute < ' tcx > ( 
2972+     tcx :  TyCtxt < ' tcx > , 
2973+     cache :  & Cache , 
2974+     def_id :  DefId , 
2975+ )  -> Option < Cow < ' static ,  str > >  { 
2976+     let  adt = match  tcx. def_kind ( def_id)  { 
2977+         DefKind :: Struct  | DefKind :: Enum  | DefKind :: Union  => tcx. adt_def ( def_id) , 
2978+         _ => return  None , 
2979+     } ; 
2980+     let  repr = adt. repr ( ) ; 
2981+ 
2982+     let  is_visible = |def_id| cache. document_hidden  || !tcx. is_doc_hidden ( def_id) ; 
2983+     let  is_public_field = |field :  & ty:: FieldDef | { 
2984+         ( cache. document_private  || field. vis . is_public ( ) )  && is_visible ( field. did ) 
2985+     } ; 
2986+ 
2987+     if  repr. transparent ( )  { 
2988+         // The transparent repr is public iff the non-1-ZST field is public and visible or 
2989+         // – in case all fields are 1-ZST fields — at least one field is public and visible. 
2990+         let  is_public = ' is_public:  { 
2991+             // `#[repr(transparent)]` can only be applied to structs and single-variant enums. 
2992+             let  var = adt. variant ( rustc_abi:: FIRST_VARIANT ) ;  // the first and only variant 
2993+ 
2994+             if  !is_visible ( var. def_id )  { 
2995+                 break  ' is_public false ; 
2996+             } 
2997+ 
2998+             // Side note: There can only ever be one or zero non-1-ZST fields. 
2999+             let  non_1zst_field = var. fields . iter ( ) . find ( |field| { 
3000+                 let  ty = ty:: TypingEnv :: post_analysis ( tcx,  field. did ) 
3001+                     . as_query_input ( tcx. type_of ( field. did ) . instantiate_identity ( ) ) ; 
3002+                 tcx. layout_of ( ty) . is_ok_and ( |layout| !layout. is_1zst ( ) ) 
3003+             } ) ; 
3004+ 
3005+             match  non_1zst_field { 
3006+                 Some ( field)  => is_public_field ( field) , 
3007+                 None  => var. fields . is_empty ( )  || var. fields . iter ( ) . any ( is_public_field) , 
3008+             } 
3009+         } ; 
3010+ 
3011+         // Since the transparent repr can't have any other reprs or 
3012+         // repr modifiers beside it, we can safely return early here. 
3013+         return  is_public. then ( || "#[repr(transparent)]" . into ( ) ) ; 
3014+     } 
3015+ 
3016+     // Fast path which avoids looking through the variants and fields in 
3017+     // the common case of no `#[repr]` or in the case of `#[repr(Rust)]`. 
3018+     // FIXME: This check is not very robust / forward compatible! 
3019+     if  !repr. c ( ) 
3020+         && !repr. simd ( ) 
3021+         && repr. int . is_none ( ) 
3022+         && repr. pack . is_none ( ) 
3023+         && repr. align . is_none ( ) 
3024+     { 
3025+         return  None ; 
3026+     } 
3027+ 
3028+     // The repr is public iff all components are public and visible. 
3029+     let  is_public = adt
3030+         . variants ( ) 
3031+         . iter ( ) 
3032+         . all ( |variant| is_visible ( variant. def_id )  && variant. fields . iter ( ) . all ( is_public_field) ) ; 
3033+     if  !is_public { 
3034+         return  None ; 
3035+     } 
3036+ 
3037+     let  mut  result = Vec :: < Cow < ' _ ,  _ > > :: new ( ) ; 
3038+ 
3039+     if  repr. c ( )  { 
3040+         result. push ( "C" . into ( ) ) ; 
3041+     } 
3042+     if  repr. simd ( )  { 
3043+         result. push ( "simd" . into ( ) ) ; 
3044+     } 
3045+     if  let  Some ( int)  = repr. int  { 
3046+         let  prefix = if  int. is_signed ( )  {  'i'  }  else  {  'u'  } ; 
3047+         let  int = match  int { 
3048+             rustc_abi:: IntegerType :: Pointer ( _)  => format ! ( "{prefix}size" ) , 
3049+             rustc_abi:: IntegerType :: Fixed ( int,  _)  => { 
3050+                 format ! ( "{prefix}{}" ,  int. size( ) . bytes( )  *  8 ) 
3051+             } 
3052+         } ; 
3053+         result. push ( int. into ( ) ) ; 
3054+     } 
3055+ 
3056+     // Render modifiers last. 
3057+     if  let  Some ( pack)  = repr. pack  { 
3058+         result. push ( format ! ( "packed({})" ,  pack. bytes( ) ) . into ( ) ) ; 
3059+     } 
3060+     if  let  Some ( align)  = repr. align  { 
3061+         result. push ( format ! ( "align({})" ,  align. bytes( ) ) . into ( ) ) ; 
3062+     } 
3063+ 
3064+     ( !result. is_empty ( ) ) . then ( || format ! ( "#[repr({})]" ,  result. join( ", " ) ) . into ( ) ) 
3065+ } 
0 commit comments