@@ -53,6 +53,7 @@ use rustc_ast::join_path_syms;
53
53
use rustc_data_structures:: fx:: { FxHashSet , FxIndexMap , FxIndexSet } ;
54
54
use rustc_hir as hir;
55
55
use rustc_hir:: attrs:: { AttributeKind , DeprecatedSince , Deprecation } ;
56
+ use rustc_hir:: def:: DefKind ;
56
57
use rustc_hir:: def_id:: { DefId , DefIdSet } ;
57
58
use rustc_hir:: { ConstStability , Mutability , RustcVersion , StabilityLevel , StableSince } ;
58
59
use rustc_middle:: ty:: print:: PrintTraitRefExt ;
@@ -2924,99 +2925,56 @@ fn render_call_locations<W: fmt::Write>(
2924
2925
w. write_str ( "</div>" )
2925
2926
}
2926
2927
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.
2941
2928
fn render_attributes_in_code (
2942
2929
w : & mut impl fmt:: Write ,
2943
2930
item : & clean:: Item ,
2944
2931
prefix : & str ,
2945
2932
cx : & Context < ' _ > ,
2946
2933
) {
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) ;
2949
2948
}
2950
- }
2951
2949
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) ;
2961
2954
}
2962
2955
}
2963
2956
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) ;
2993
2960
}
2994
- attrs
2995
2961
}
2996
2962
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 ( ) ;
3000
2965
}
3001
2966
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 > ,
3005
2969
cache : & Cache ,
3006
2970
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
+ } ;
3015
2976
let repr = adt. repr ( ) ;
3016
- let mut out = Vec :: new ( ) ;
3017
- if repr. c ( ) {
3018
- out. push ( "C" ) ;
3019
- }
2977
+
3020
2978
if repr. transparent ( ) {
3021
2979
// Render `repr(transparent)` iff the non-1-ZST field is public or at least one
3022
2980
// field is public in case all fields are 1-ZST fields.
@@ -3033,34 +2991,35 @@ pub(crate) fn repr_attributes(
3033
2991
|field| field. vis . is_public ( ) ,
3034
2992
) ;
3035
2993
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 ( ) ) ;
3039
3003
}
3040
3004
if repr. simd ( ) {
3041
- out . push ( "simd" ) ;
3005
+ result . push ( "simd" . into ( ) ) ;
3042
3006
}
3043
- let pack_s;
3044
3007
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 ( ) ) ;
3047
3009
}
3048
- let align_s;
3049
3010
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 ( ) ) ;
3052
3012
}
3053
- let int_s;
3054
3013
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 )
3061
3019
}
3062
3020
} ;
3063
- out . push ( & int_s ) ;
3021
+ result . push ( int . into ( ) ) ;
3064
3022
}
3065
- if !out. is_empty ( ) { Some ( format ! ( "#[repr({})]" , out. join( ", " ) ) ) } else { None }
3023
+
3024
+ ( !result. is_empty ( ) ) . then ( || format ! ( "#[repr({})]" , result. join( ", " ) ) . into ( ) )
3066
3025
}
0 commit comments