@@ -2,9 +2,10 @@ use rustc_ast::Attribute;
2
2
use rustc_hir:: def:: DefKind ;
3
3
use rustc_hir:: def_id:: DefId ;
4
4
use 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 } ;
6
6
use rustc_span:: source_map:: Spanned ;
7
7
use rustc_span:: symbol:: sym;
8
+ use rustc_target:: abi:: call:: FnAbi ;
8
9
9
10
use crate :: errors:: { AbiOf , UnrecognizedField } ;
10
11
@@ -17,15 +18,20 @@ pub fn test_abi(tcx: TyCtxt<'_>) {
17
18
match tcx. def_kind ( id. owner_id ) {
18
19
DefKind :: Fn => {
19
20
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) ;
21
27
}
22
28
}
23
29
DefKind :: Impl { .. } => {
24
30
// To find associated functions we need to go into the child items here.
25
31
for & id in tcx. associated_item_def_ids ( id. owner_id ) {
26
32
if matches ! ( tcx. def_kind( id) , DefKind :: AssocFn ) {
27
33
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) ;
29
35
}
30
36
}
31
37
}
@@ -35,7 +41,32 @@ pub fn test_abi(tcx: TyCtxt<'_>) {
35
41
}
36
42
}
37
43
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 ) {
39
70
let param_env = tcx. param_env ( item_def_id) ;
40
71
let args = GenericArgs :: identity_for_item ( tcx, item_def_id) ;
41
72
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) {
51
82
}
52
83
Err ( _guaranteed) => return ,
53
84
} ;
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
+ ) ;
69
90
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
+ } ) ;
74
103
}
75
- }
76
104
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
+ }
82
108
}
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
+ }
91
141
}
92
142
}
93
143
}
0 commit comments