@@ -51,7 +51,8 @@ use askama::Template;
51
51
use itertools:: Either ;
52
52
use rustc_ast:: join_path_syms;
53
53
use 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 } ;
55
56
use rustc_hir:: def_id:: { DefId , DefIdSet } ;
56
57
use rustc_hir:: { ConstStability , Mutability , RustcVersion , StabilityLevel , StableSince } ;
57
58
use rustc_middle:: ty:: print:: PrintTraitRefExt ;
@@ -1310,43 +1311,6 @@ fn render_assoc_item(
1310
1311
} )
1311
1312
}
1312
1313
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
-
1350
1314
#[ derive( Copy , Clone ) ]
1351
1315
enum AssocItemLink < ' a > {
1352
1316
Anchor ( Option < & ' a str > ) ,
@@ -2959,3 +2923,144 @@ fn render_call_locations<W: fmt::Write>(
2959
2923
2960
2924
w. write_str ( "</div>" )
2961
2925
}
2926
+
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
+ fn render_attributes_in_code (
2942
+ w : & mut impl fmt:: Write ,
2943
+ item : & clean:: Item ,
2944
+ prefix : & str ,
2945
+ cx : & Context < ' _ > ,
2946
+ ) {
2947
+ for attr in attributes ( item, cx. tcx ( ) , cx. cache ( ) ) {
2948
+ render_code_attribute ( prefix, CodeAttribute ( attr) , w) ;
2949
+ }
2950
+ }
2951
+
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) ;
2961
+ }
2962
+ }
2963
+
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) ;
2993
+ }
2994
+ attrs
2995
+ }
2996
+
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_ ( ) )
3000
+ }
3001
+
3002
+ /// Return a string representing the `#[repr]` attribute if present.
3003
+ pub ( crate ) fn repr_attributes (
3004
+ tcx : TyCtxt < ' _ > ,
3005
+ cache : & Cache ,
3006
+ 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) ;
3015
+ let repr = adt. repr ( ) ;
3016
+ let mut out = Vec :: new ( ) ;
3017
+ if repr. c ( ) {
3018
+ out. push ( "C" ) ;
3019
+ }
3020
+ if repr. transparent ( ) {
3021
+ // Render `repr(transparent)` iff the non-1-ZST field is public or at least one
3022
+ // field is public in case all fields are 1-ZST fields.
3023
+ let render_transparent = cache. document_private
3024
+ || adt
3025
+ . all_fields ( )
3026
+ . find ( |field| {
3027
+ let ty = field. ty ( tcx, ty:: GenericArgs :: identity_for_item ( tcx, field. did ) ) ;
3028
+ tcx. layout_of ( ty:: TypingEnv :: post_analysis ( tcx, field. did ) . as_query_input ( ty) )
3029
+ . is_ok_and ( |layout| !layout. is_1zst ( ) )
3030
+ } )
3031
+ . map_or_else (
3032
+ || adt. all_fields ( ) . any ( |field| field. vis . is_public ( ) ) ,
3033
+ |field| field. vis . is_public ( ) ,
3034
+ ) ;
3035
+
3036
+ if render_transparent {
3037
+ out. push ( "transparent" ) ;
3038
+ }
3039
+ }
3040
+ if repr. simd ( ) {
3041
+ out. push ( "simd" ) ;
3042
+ }
3043
+ let pack_s;
3044
+ if let Some ( pack) = repr. pack {
3045
+ pack_s = format ! ( "packed({})" , pack. bytes( ) ) ;
3046
+ out. push ( & pack_s) ;
3047
+ }
3048
+ let align_s;
3049
+ if let Some ( align) = repr. align {
3050
+ align_s = format ! ( "align({})" , align. bytes( ) ) ;
3051
+ out. push ( & align_s) ;
3052
+ }
3053
+ let int_s;
3054
+ 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 )
3061
+ }
3062
+ } ;
3063
+ out. push ( & int_s) ;
3064
+ }
3065
+ if !out. is_empty ( ) { Some ( format ! ( "#[repr({})]" , out. join( ", " ) ) ) } else { None }
3066
+ }
0 commit comments