@@ -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,56 @@ 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+ let hir:: Attribute :: Parsed ( kind) = attr else { continue } ;
2936+ let attr = match kind {
2937+ AttributeKind :: LinkSection { name, .. } => {
2938+ Cow :: Owned ( format ! ( "#[unsafe(link_section = \" {name}\" )]" ) )
2939+ }
2940+ AttributeKind :: NoMangle ( ..) => Cow :: Borrowed ( "#[unsafe(no_mangle)]" ) ,
2941+ AttributeKind :: ExportName { name, .. } => {
2942+ Cow :: Owned ( format ! ( "#[unsafe(export_name = \" {name}\" )]" ) )
2943+ }
2944+ AttributeKind :: NonExhaustive ( ..) => Cow :: Borrowed ( "#[non_exhaustive]" ) ,
2945+ _ => continue ,
2946+ } ;
2947+ render_code_attribute ( prefix, attr. as_ref ( ) , w) ;
29492948 }
2950- }
29512949
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) ;
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) ;
29612954 }
29622955}
29632956
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) ;
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) ;
29932960 }
2994- attrs
29952961}
29962962
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_ ( ) )
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 ( ) ;
30002965}
30012966
3002- /// Return a string representing the `#[repr]` attribute if present.
3003- pub ( crate ) fn repr_attributes (
3004- tcx : TyCtxt < ' _ > ,
2967+ fn repr_attribute < ' tcx > (
2968+ tcx : TyCtxt < ' tcx > ,
30052969 cache : & Cache ,
30062970 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) ;
2971+ ) -> Option < Cow < ' static , str > > {
2972+ let adt = match tcx. def_kind ( def_id) {
2973+ DefKind :: Struct | DefKind :: Enum | DefKind :: Union => tcx. adt_def ( def_id) ,
2974+ _ => return None ,
2975+ } ;
30152976 let repr = adt. repr ( ) ;
3016- let mut out = Vec :: new ( ) ;
3017- if repr. c ( ) {
3018- out. push ( "C" ) ;
3019- }
2977+
30202978 if repr. transparent ( ) {
30212979 // Render `repr(transparent)` iff the non-1-ZST field is public or at least one
30222980 // field is public in case all fields are 1-ZST fields.
@@ -3033,34 +2991,35 @@ pub(crate) fn repr_attributes(
30332991 |field| field. vis . is_public ( ) ,
30342992 ) ;
30352993
3036- if render_transparent {
3037- out. push ( "transparent" ) ;
3038- }
2994+ // Since the transparent repr can't have any other reprs or
2995+ // repr modifiers beside it, we can safely return early here.
2996+ return render_transparent. then ( || "#[repr(transparent)]" . into ( ) ) ;
2997+ }
2998+
2999+ let mut result = Vec :: < Cow < ' _ , _ > > :: new ( ) ;
3000+
3001+ if repr. c ( ) {
3002+ result. push ( "C" . into ( ) ) ;
30393003 }
30403004 if repr. simd ( ) {
3041- out . push ( "simd" ) ;
3005+ result . push ( "simd" . into ( ) ) ;
30423006 }
3043- let pack_s;
30443007 if let Some ( pack) = repr. pack {
3045- pack_s = format ! ( "packed({})" , pack. bytes( ) ) ;
3046- out. push ( & pack_s) ;
3008+ result. push ( format ! ( "packed({})" , pack. bytes( ) ) . into ( ) ) ;
30473009 }
3048- let align_s;
30493010 if let Some ( align) = repr. align {
3050- align_s = format ! ( "align({})" , align. bytes( ) ) ;
3051- out. push ( & align_s) ;
3011+ result. push ( format ! ( "align({})" , align. bytes( ) ) . into ( ) ) ;
30523012 }
3053- let int_s;
30543013 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 )
3014+ let prefix = if int. is_signed ( ) { 'i' } else { 'u' } ;
3015+ let int = match int {
3016+ rustc_abi:: IntegerType :: Pointer ( _) => format ! ( "{prefix}size" ) ,
3017+ rustc_abi:: IntegerType :: Fixed ( int, _) => {
3018+ format ! ( "{prefix}{}" , int. size( ) . bytes( ) * 8 )
30613019 }
30623020 } ;
3063- out . push ( & int_s ) ;
3021+ result . push ( int . into ( ) ) ;
30643022 }
3065- if !out. is_empty ( ) { Some ( format ! ( "#[repr({})]" , out. join( ", " ) ) ) } else { None }
3023+
3024+ ( !result. is_empty ( ) ) . then ( || format ! ( "#[repr({})]" , result. join( ", " ) ) . into ( ) )
30663025}
0 commit comments