@@ -2,9 +2,10 @@ use rustc_ast::Attribute;
22use rustc_hir:: def:: DefKind ;
33use rustc_hir:: def_id:: DefId ;
44use rustc_middle:: ty:: layout:: { FnAbiError , LayoutError } ;
5- use rustc_middle:: ty:: { self , GenericArgs , Instance , TyCtxt } ;
5+ use rustc_middle:: ty:: { self , GenericArgs , Instance , Ty , TyCtxt } ;
66use rustc_span:: source_map:: Spanned ;
77use rustc_span:: symbol:: sym;
8+ use rustc_target:: abi:: call:: FnAbi ;
89
910use crate :: errors:: { AbiOf , UnrecognizedField } ;
1011
@@ -17,15 +18,20 @@ pub fn test_abi(tcx: TyCtxt<'_>) {
1718 match tcx. def_kind ( id. owner_id ) {
1819 DefKind :: Fn => {
1920 for attr in tcx. get_attrs ( id. owner_id , sym:: rustc_abi) {
20- dump_abi_of ( tcx, id. owner_id . def_id . into ( ) , attr) ;
21+ dump_abi_of_fn_item ( tcx, id. owner_id . def_id . into ( ) , attr) ;
22+ }
23+ }
24+ DefKind :: TyAlias { .. } => {
25+ for attr in tcx. get_attrs ( id. owner_id , sym:: rustc_abi) {
26+ dump_abi_of_fn_type ( tcx, id. owner_id . def_id . into ( ) , attr) ;
2127 }
2228 }
2329 DefKind :: Impl { .. } => {
2430 // To find associated functions we need to go into the child items here.
2531 for & id in tcx. associated_item_def_ids ( id. owner_id ) {
2632 if matches ! ( tcx. def_kind( id) , DefKind :: AssocFn ) {
2733 for attr in tcx. get_attrs ( id, sym:: rustc_abi) {
28- dump_abi_of ( tcx, id, attr) ;
34+ dump_abi_of_fn_item ( tcx, id, attr) ;
2935 }
3036 }
3137 }
@@ -35,7 +41,32 @@ pub fn test_abi(tcx: TyCtxt<'_>) {
3541 }
3642}
3743
38- fn dump_abi_of ( tcx : TyCtxt < ' _ > , item_def_id : DefId , attr : & Attribute ) {
44+ fn unwrap_fn_abi < ' tcx > (
45+ abi : Result < & ' tcx FnAbi < ' tcx , Ty < ' tcx > > , & ' tcx FnAbiError < ' tcx > > ,
46+ tcx : TyCtxt < ' tcx > ,
47+ item_def_id : DefId ,
48+ ) -> & ' tcx FnAbi < ' tcx , Ty < ' tcx > > {
49+ match abi {
50+ Ok ( abi) => abi,
51+ Err ( FnAbiError :: Layout ( layout_error) ) => {
52+ tcx. sess . emit_fatal ( Spanned {
53+ node : layout_error. into_diagnostic ( ) ,
54+ span : tcx. def_span ( item_def_id) ,
55+ } ) ;
56+ }
57+ Err ( FnAbiError :: AdjustForForeignAbi ( e) ) => {
58+ // Sadly there seems to be no `into_diagnostic` for this case... and I am not sure if
59+ // this can even be reached. Anyway this is a perma-unstable debug attribute, an ICE
60+ // isn't the worst thing. Also this matches what codegen does.
61+ span_bug ! (
62+ tcx. def_span( item_def_id) ,
63+ "error computing fn_abi_of_instance, cannot adjust for foreign ABI: {e:?}" ,
64+ )
65+ }
66+ }
67+ }
68+
69+ fn dump_abi_of_fn_item ( tcx : TyCtxt < ' _ > , item_def_id : DefId , attr : & Attribute ) {
3970 let param_env = tcx. param_env ( item_def_id) ;
4071 let args = GenericArgs :: identity_for_item ( tcx, item_def_id) ;
4172 let instance = match Instance :: resolve ( tcx, param_env, item_def_id, args) {
@@ -51,43 +82,62 @@ fn dump_abi_of(tcx: TyCtxt<'_>, item_def_id: DefId, attr: &Attribute) {
5182 }
5283 Err ( _guaranteed) => return ,
5384 } ;
54- match tcx. fn_abi_of_instance ( param_env. and ( ( instance, /* extra_args */ ty:: List :: empty ( ) ) ) ) {
55- Ok ( abi) => {
56- // Check out the `#[rustc_abi(..)]` attribute to tell what to dump.
57- // The `..` are the names of fields to dump.
58- let meta_items = attr. meta_item_list ( ) . unwrap_or_default ( ) ;
59- for meta_item in meta_items {
60- match meta_item. name_or_empty ( ) {
61- sym:: debug => {
62- let fn_name = tcx. item_name ( item_def_id) ;
63- tcx. sess . emit_err ( AbiOf {
64- span : tcx. def_span ( item_def_id) ,
65- fn_name,
66- fn_abi : format ! ( "{:#?}" , abi) ,
67- } ) ;
68- }
85+ let abi = unwrap_fn_abi (
86+ tcx. fn_abi_of_instance ( param_env. and ( ( instance, /* extra_args */ ty:: List :: empty ( ) ) ) ) ,
87+ tcx,
88+ item_def_id,
89+ ) ;
6990
70- name => {
71- tcx. sess . emit_err ( UnrecognizedField { span : meta_item. span ( ) , name } ) ;
72- }
73- }
91+ // Check out the `#[rustc_abi(..)]` attribute to tell what to dump.
92+ // The `..` are the names of fields to dump.
93+ let meta_items = attr. meta_item_list ( ) . unwrap_or_default ( ) ;
94+ for meta_item in meta_items {
95+ match meta_item. name_or_empty ( ) {
96+ sym:: debug => {
97+ let fn_name = tcx. item_name ( item_def_id) ;
98+ tcx. sess . emit_err ( AbiOf {
99+ span : tcx. def_span ( item_def_id) ,
100+ fn_name,
101+ fn_abi : format ! ( "{:#?}" , abi) ,
102+ } ) ;
74103 }
75- }
76104
77- Err ( FnAbiError :: Layout ( layout_error) ) => {
78- tcx. sess . emit_fatal ( Spanned {
79- node : layout_error. into_diagnostic ( ) ,
80- span : tcx. def_span ( item_def_id) ,
81- } ) ;
105+ name => {
106+ tcx. sess . emit_err ( UnrecognizedField { span : meta_item. span ( ) , name } ) ;
107+ }
82108 }
83- Err ( FnAbiError :: AdjustForForeignAbi ( e) ) => {
84- // Sadly there seems to be no `into_diagnostic` for this case... and I am not sure if
85- // this can even be reached. Anyway this is a perma-unstable debug attribute, an ICE
86- // isn't the worst thing. Also this matches what codegen does.
87- span_bug ! (
88- tcx. def_span( item_def_id) ,
89- "error computing fn_abi_of_instance, cannot adjust for foreign ABI: {e:?}" ,
90- )
109+ }
110+ }
111+
112+ fn dump_abi_of_fn_type ( tcx : TyCtxt < ' _ > , item_def_id : DefId , attr : & Attribute ) {
113+ let param_env = tcx. param_env ( item_def_id) ;
114+ let ty = tcx. type_of ( item_def_id) . instantiate_identity ( ) ;
115+ let meta_items = attr. meta_item_list ( ) . unwrap_or_default ( ) ;
116+ for meta_item in meta_items {
117+ match meta_item. name_or_empty ( ) {
118+ sym:: debug => {
119+ let ty:: FnPtr ( sig) = ty. kind ( ) else {
120+ span_bug ! (
121+ meta_item. span( ) ,
122+ "`#[rustc_abi(debug)]` on a type alias requires function pointer type"
123+ ) ;
124+ } ;
125+ let abi = unwrap_fn_abi (
126+ tcx. fn_abi_of_fn_ptr ( param_env. and ( ( * sig, /* extra_args */ ty:: List :: empty ( ) ) ) ) ,
127+ tcx,
128+ item_def_id,
129+ ) ;
130+
131+ let fn_name = tcx. item_name ( item_def_id) ;
132+ tcx. sess . emit_err ( AbiOf {
133+ span : tcx. def_span ( item_def_id) ,
134+ fn_name,
135+ fn_abi : format ! ( "{:#?}" , abi) ,
136+ } ) ;
137+ }
138+ name => {
139+ tcx. sess . emit_err ( UnrecognizedField { span : meta_item. span ( ) , name } ) ;
140+ }
91141 }
92142 }
93143}
0 commit comments