@@ -53,6 +53,7 @@ use rustc_ast::join_path_syms;
5353use rustc_data_structures:: fx:: { FxHashSet , FxIndexMap , FxIndexSet } ;
5454use rustc_hir as hir;
5555use rustc_hir:: attrs:: { AttributeKind , DeprecatedSince , Deprecation } ;
56+ use rustc_hir:: def:: DefKind ;
5657use rustc_hir:: def_id:: { DefId , DefIdSet } ;
5758use rustc_hir:: { ConstStability , Mutability , RustcVersion , StabilityLevel , StableSince } ;
5859use rustc_middle:: ty:: print:: PrintTraitRefExt ;
@@ -2924,99 +2925,63 @@ fn render_call_locations<W: fmt::Write>(
29242925 w. write_str ( "</div>" )
29252926}
29262927
2927- struct CodeAttribute ( String ) ;
2928-
2929- fn render_code_attribute ( prefix : & str , code_attr : CodeAttribute , w : & mut impl fmt:: Write ) {
2930- write ! (
2931- w,
2932- "<div class=\" code-attribute\" >{prefix}{attr}</div>" ,
2933- prefix = prefix,
2934- attr = code_attr. 0
2935- )
2936- . unwrap ( ) ;
2937- }
2938-
2939- // When an attribute is rendered inside a <code> tag, it is formatted using
2940- // a div to produce a newline after it.
29412928fn render_attributes_in_code (
29422929 w : & mut impl fmt:: Write ,
29432930 item : & clean:: Item ,
29442931 prefix : & str ,
29452932 cx : & Context < ' _ > ,
29462933) {
2947- for attr in attributes ( item, cx. tcx ( ) , cx. cache ( ) ) {
2948- render_code_attribute ( prefix, CodeAttribute ( attr) , w) ;
2934+ for attr in & item. attrs . other_attrs {
2935+ render_code_attribute (
2936+ prefix,
2937+ match attr {
2938+ hir:: Attribute :: Parsed ( AttributeKind :: LinkSection { name, .. } ) => {
2939+ Cow :: Owned ( format ! ( "#[unsafe(link_section = \" {name}\" )]" ) )
2940+ }
2941+ hir:: Attribute :: Parsed ( AttributeKind :: NoMangle ( ..) ) => {
2942+ Cow :: Borrowed ( "#[unsafe(no_mangle)]" )
2943+ }
2944+ hir:: Attribute :: Parsed ( AttributeKind :: ExportName { name, .. } ) => {
2945+ Cow :: Owned ( format ! ( "#[unsafe(export_name = \" {name}\" )]" ) )
2946+ }
2947+ hir:: Attribute :: Parsed ( AttributeKind :: NonExhaustive ( ..) ) => {
2948+ Cow :: Borrowed ( "#[non_exhaustive]" )
2949+ }
2950+ _ => continue ,
2951+ }
2952+ . as_ref ( ) ,
2953+ w,
2954+ ) ;
29492955 }
2950- }
29512956
2952- /// used for type aliases to only render their `repr` attribute.
2953- fn render_repr_attributes_in_code (
2954- w : & mut impl fmt:: Write ,
2955- cx : & Context < ' _ > ,
2956- def_id : DefId ,
2957- item_type : ItemType ,
2958- ) {
2959- if let Some ( repr) = repr_attributes ( cx. tcx ( ) , cx. cache ( ) , def_id, item_type) {
2960- render_code_attribute ( "" , CodeAttribute ( repr) , w) ;
2957+ if let Some ( def_id) = item. def_id ( )
2958+ && let Some ( repr) = repr_attribute ( cx. tcx ( ) , cx. cache ( ) , def_id)
2959+ {
2960+ render_code_attribute ( prefix, & repr, w) ;
29612961 }
29622962}
29632963
2964- /// Get a list of attributes excluding `#[repr]` to display.
2965- fn attributes_without_repr ( item : & clean:: Item ) -> Vec < String > {
2966- item. attrs
2967- . other_attrs
2968- . iter ( )
2969- . filter_map ( |attr| match attr {
2970- hir:: Attribute :: Parsed ( AttributeKind :: LinkSection { name, .. } ) => {
2971- Some ( format ! ( "#[unsafe(link_section = \" {name}\" )]" ) )
2972- }
2973- hir:: Attribute :: Parsed ( AttributeKind :: NoMangle ( ..) ) => {
2974- Some ( "#[unsafe(no_mangle)]" . to_string ( ) )
2975- }
2976- hir:: Attribute :: Parsed ( AttributeKind :: ExportName { name, .. } ) => {
2977- Some ( format ! ( "#[unsafe(export_name = \" {name}\" )]" ) )
2978- }
2979- hir:: Attribute :: Parsed ( AttributeKind :: NonExhaustive ( ..) ) => {
2980- Some ( "#[non_exhaustive]" . to_string ( ) )
2981- }
2982- _ => None ,
2983- } )
2984- . collect ( )
2985- }
2986-
2987- /// Get a list of attributes to display on this item.
2988- fn attributes ( item : & clean:: Item , tcx : TyCtxt < ' _ > , cache : & Cache ) -> Vec < String > {
2989- let mut attrs = attributes_without_repr ( item) ;
2990-
2991- if let Some ( repr_attr) = repr ( item, tcx, cache) {
2992- attrs. push ( repr_attr) ;
2964+ fn render_repr_attribute_in_code ( w : & mut impl fmt:: Write , cx : & Context < ' _ > , def_id : DefId ) {
2965+ if let Some ( repr) = repr_attribute ( cx. tcx ( ) , cx. cache ( ) , def_id) {
2966+ render_code_attribute ( "" , & repr, w) ;
29932967 }
2994- attrs
29952968}
29962969
2997- /// Returns a stringified `#[repr(...)]` attribute.
2998- fn repr ( item : & clean:: Item , tcx : TyCtxt < ' _ > , cache : & Cache ) -> Option < String > {
2999- repr_attributes ( tcx, cache, item. def_id ( ) ?, item. type_ ( ) )
2970+ fn render_code_attribute ( prefix : & str , attr : & str , w : & mut impl fmt:: Write ) {
2971+ write ! ( w, "<div class=\" code-attribute\" >{prefix}{attr}</div>" ) . unwrap ( ) ;
30002972}
30012973
3002- /// Return a string representing the `#[repr]` attribute if present.
3003- pub ( crate ) fn repr_attributes (
3004- tcx : TyCtxt < ' _ > ,
2974+ fn repr_attribute < ' tcx > (
2975+ tcx : TyCtxt < ' tcx > ,
30052976 cache : & Cache ,
30062977 def_id : DefId ,
3007- item_type : ItemType ,
3008- ) -> Option < String > {
3009- use rustc_abi:: IntegerType ;
3010-
3011- if !matches ! ( item_type, ItemType :: Struct | ItemType :: Enum | ItemType :: Union ) {
3012- return None ;
3013- }
3014- let adt = tcx. adt_def ( def_id) ;
2978+ ) -> Option < Cow < ' static , str > > {
2979+ let adt = match tcx. def_kind ( def_id) {
2980+ DefKind :: Struct | DefKind :: Enum | DefKind :: Union => tcx. adt_def ( def_id) ,
2981+ _ => return None ,
2982+ } ;
30152983 let repr = adt. repr ( ) ;
3016- let mut out = Vec :: new ( ) ;
3017- if repr. c ( ) {
3018- out. push ( "C" ) ;
3019- }
2984+
30202985 if repr. transparent ( ) {
30212986 // Render `repr(transparent)` iff the non-1-ZST field is public or at least one
30222987 // field is public in case all fields are 1-ZST fields.
@@ -3033,34 +2998,35 @@ pub(crate) fn repr_attributes(
30332998 |field| field. vis . is_public ( ) ,
30342999 ) ;
30353000
3036- if render_transparent {
3037- out. push ( "transparent" ) ;
3038- }
3001+ // Since the transparent repr can't have any other reprs or
3002+ // repr modifiers beside it, we can safely return early here.
3003+ return render_transparent. then ( || "#[repr(transparent)]" . into ( ) ) ;
3004+ }
3005+
3006+ let mut result = Vec :: < Cow < ' _ , _ > > :: new ( ) ;
3007+
3008+ if repr. c ( ) {
3009+ result. push ( "C" . into ( ) ) ;
30393010 }
30403011 if repr. simd ( ) {
3041- out . push ( "simd" ) ;
3012+ result . push ( "simd" . into ( ) ) ;
30423013 }
3043- let pack_s;
30443014 if let Some ( pack) = repr. pack {
3045- pack_s = format ! ( "packed({})" , pack. bytes( ) ) ;
3046- out. push ( & pack_s) ;
3015+ result. push ( format ! ( "packed({})" , pack. bytes( ) ) . into ( ) ) ;
30473016 }
3048- let align_s;
30493017 if let Some ( align) = repr. align {
3050- align_s = format ! ( "align({})" , align. bytes( ) ) ;
3051- out. push ( & align_s) ;
3018+ result. push ( format ! ( "align({})" , align. bytes( ) ) . into ( ) ) ;
30523019 }
3053- let int_s;
30543020 if let Some ( int) = repr. int {
3055- int_s = match int {
3056- IntegerType :: Pointer ( is_signed) => {
3057- format ! ( "{}size" , if is_signed { 'i' } else { 'u' } )
3058- }
3059- IntegerType :: Fixed ( size, is_signed) => {
3060- format ! ( "{}{}" , if is_signed { 'i' } else { 'u' } , size. size( ) . bytes( ) * 8 )
3021+ let prefix = if int. is_signed ( ) { 'i' } else { 'u' } ;
3022+ let int = match int {
3023+ rustc_abi:: IntegerType :: Pointer ( _) => format ! ( "{prefix}size" ) ,
3024+ rustc_abi:: IntegerType :: Fixed ( int, _) => {
3025+ format ! ( "{prefix}{}" , int. size( ) . bytes( ) * 8 )
30613026 }
30623027 } ;
3063- out . push ( & int_s ) ;
3028+ result . push ( int . into ( ) ) ;
30643029 }
3065- if !out. is_empty ( ) { Some ( format ! ( "#[repr({})]" , out. join( ", " ) ) ) } else { None }
3030+
3031+ ( !result. is_empty ( ) ) . then ( || format ! ( "#[repr({})]" , result. join( ", " ) ) . into ( ) )
30663032}
0 commit comments