1- use rustc_hir:: Attribute ;
1+ use rustc_hir:: attrs :: { AttributeKind , RustcAbiAttrKind } ;
22use rustc_hir:: def:: DefKind ;
33use rustc_hir:: def_id:: LocalDefId ;
4+ use rustc_hir:: find_attr;
45use rustc_middle:: span_bug;
56use rustc_middle:: ty:: layout:: { FnAbiError , LayoutError } ;
67use rustc_middle:: ty:: { self , GenericArgs , Instance , Ty , TyCtxt } ;
8+ use rustc_span:: Span ;
79use rustc_span:: source_map:: Spanned ;
8- use rustc_span:: sym;
910use rustc_target:: callconv:: FnAbi ;
1011
1112use super :: layout_test:: ensure_wf;
@@ -17,17 +18,19 @@ pub fn test_abi(tcx: TyCtxt<'_>) {
1718 return ;
1819 }
1920 for id in tcx. hir_crate_items ( ( ) ) . definitions ( ) {
20- for attr in tcx. get_attrs ( id, sym:: rustc_abi) {
21- match tcx. def_kind ( id) {
22- DefKind :: Fn | DefKind :: AssocFn => {
23- dump_abi_of_fn_item ( tcx, id, attr) ;
24- }
25- DefKind :: TyAlias => {
26- dump_abi_of_fn_type ( tcx, id, attr) ;
27- }
28- _ => {
29- tcx. dcx ( ) . emit_err ( AbiInvalidAttribute { span : tcx. def_span ( id) } ) ;
30- }
21+ let Some ( ( attr_span, attr_kind) ) = find_attr ! ( tcx. get_all_attrs( id) , AttributeKind :: RustcAbi { attr_span, kind } => ( * attr_span, * kind) )
22+ else {
23+ continue ;
24+ } ;
25+ match tcx. def_kind ( id) {
26+ DefKind :: Fn | DefKind :: AssocFn => {
27+ dump_abi_of_fn_item ( tcx, id, attr_span, attr_kind) ;
28+ }
29+ DefKind :: TyAlias => {
30+ dump_abi_of_fn_type ( tcx, id, attr_span, attr_kind) ;
31+ }
32+ _ => {
33+ tcx. dcx ( ) . emit_err ( AbiInvalidAttribute { span : tcx. def_span ( id) } ) ;
3134 }
3235 }
3336 }
@@ -49,7 +52,12 @@ fn unwrap_fn_abi<'tcx>(
4952 }
5053}
5154
52- fn dump_abi_of_fn_item ( tcx : TyCtxt < ' _ > , item_def_id : LocalDefId , attr : & Attribute ) {
55+ fn dump_abi_of_fn_item (
56+ tcx : TyCtxt < ' _ > ,
57+ item_def_id : LocalDefId ,
58+ attr_span : Span ,
59+ attr_kind : RustcAbiAttrKind ,
60+ ) {
5361 let typing_env = ty:: TypingEnv :: post_analysis ( tcx, item_def_id) ;
5462 let args = GenericArgs :: identity_for_item ( tcx, item_def_id) ;
5563 let instance = match Instance :: try_resolve ( tcx, typing_env, item_def_id. into ( ) , args) {
@@ -75,22 +83,18 @@ fn dump_abi_of_fn_item(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut
7583
7684 // Check out the `#[rustc_abi(..)]` attribute to tell what to dump.
7785 // The `..` are the names of fields to dump.
78- let meta_items = attr. meta_item_list ( ) . unwrap_or_default ( ) ;
79- for meta_item in meta_items {
80- match meta_item. name ( ) {
81- Some ( sym:: debug) => {
82- let fn_name = tcx. item_name ( item_def_id) ;
83- tcx. dcx ( ) . emit_err ( AbiOf {
84- span : tcx. def_span ( item_def_id) ,
85- fn_name,
86- // FIXME: using the `Debug` impl here isn't ideal.
87- fn_abi : format ! ( "{:#?}" , abi) ,
88- } ) ;
89- }
90-
91- _ => {
92- tcx. dcx ( ) . emit_err ( UnrecognizedArgument { span : meta_item. span ( ) } ) ;
93- }
86+ match attr_kind {
87+ RustcAbiAttrKind :: Debug => {
88+ let fn_name = tcx. item_name ( item_def_id) ;
89+ tcx. dcx ( ) . emit_err ( AbiOf {
90+ span : tcx. def_span ( item_def_id) ,
91+ fn_name,
92+ // FIXME: using the `Debug` impl here isn't ideal.
93+ fn_abi : format ! ( "{:#?}" , abi) ,
94+ } ) ;
95+ }
96+ _ => {
97+ tcx. dcx ( ) . emit_err ( UnrecognizedArgument { span : attr_span } ) ;
9498 }
9599 }
96100}
@@ -109,24 +113,29 @@ fn test_abi_eq<'tcx>(abi1: &'tcx FnAbi<'tcx, Ty<'tcx>>, abi2: &'tcx FnAbi<'tcx,
109113 && abi1. args . iter ( ) . zip ( abi2. args . iter ( ) ) . all ( |( arg1, arg2) | arg1. eq_abi ( arg2) )
110114}
111115
112- fn dump_abi_of_fn_type ( tcx : TyCtxt < ' _ > , item_def_id : LocalDefId , attr : & Attribute ) {
116+ fn dump_abi_of_fn_type (
117+ tcx : TyCtxt < ' _ > ,
118+ item_def_id : LocalDefId ,
119+ attr_span : Span ,
120+ attr_kind : RustcAbiAttrKind ,
121+ ) {
113122 let typing_env = ty:: TypingEnv :: post_analysis ( tcx, item_def_id) ;
114123 let ty = tcx. type_of ( item_def_id) . instantiate_identity ( ) ;
115124 let span = tcx. def_span ( item_def_id) ;
116125 if !ensure_wf ( tcx, typing_env, ty, item_def_id, span) {
117126 return ;
118127 }
119- let meta_items = attr . meta_item_list ( ) . unwrap_or_default ( ) ;
120- for meta_item in meta_items {
121- match meta_item . name ( ) {
122- Some ( sym :: debug ) => {
123- let ty :: FnPtr ( sig_tys , hdr ) = ty . kind ( ) else {
124- span_bug ! (
125- meta_item . span ( ) ,
126- "`#[rustc_abi(debug)]` on a type alias requires function pointer type"
127- ) ;
128- } ;
129- let abi = unwrap_fn_abi (
128+
129+ match attr_kind {
130+ RustcAbiAttrKind :: Debug => {
131+ let ty :: FnPtr ( sig_tys , hdr ) = ty . kind ( ) else {
132+ span_bug ! (
133+ attr_span ,
134+ "`#[rustc_abi(debug)]` on a type alias requires function pointer type"
135+ ) ;
136+ } ;
137+ let abi =
138+ unwrap_fn_abi (
130139 tcx. fn_abi_of_fn_ptr ( typing_env. as_query_input ( (
131140 sig_tys. with ( * hdr) ,
132141 /* extra_args */ ty:: List :: empty ( ) ,
@@ -135,61 +144,57 @@ fn dump_abi_of_fn_type(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut
135144 item_def_id,
136145 ) ;
137146
138- let fn_name = tcx. item_name ( item_def_id) ;
139- tcx. dcx ( ) . emit_err ( AbiOf { span, fn_name, fn_abi : format ! ( "{:#?}" , abi) } ) ;
140- }
141- Some ( sym:: assert_eq) => {
142- let ty:: Tuple ( fields) = ty. kind ( ) else {
143- span_bug ! (
144- meta_item. span( ) ,
145- "`#[rustc_abi(assert_eq)]` on a type alias requires pair type"
146- ) ;
147- } ;
148- let [ field1, field2] = * * * fields else {
149- span_bug ! (
150- meta_item. span( ) ,
151- "`#[rustc_abi(assert_eq)]` on a type alias requires pair type"
152- ) ;
153- } ;
154- let ty:: FnPtr ( sig_tys1, hdr1) = field1. kind ( ) else {
155- span_bug ! (
156- meta_item. span( ) ,
157- "`#[rustc_abi(assert_eq)]` on a type alias requires pair of function pointer types"
158- ) ;
159- } ;
160- let abi1 = unwrap_fn_abi (
161- tcx. fn_abi_of_fn_ptr ( typing_env. as_query_input ( (
162- sig_tys1. with ( * hdr1) ,
163- /* extra_args */ ty:: List :: empty ( ) ,
164- ) ) ) ,
165- tcx,
166- item_def_id,
147+ let fn_name = tcx. item_name ( item_def_id) ;
148+ tcx. dcx ( ) . emit_err ( AbiOf { span, fn_name, fn_abi : format ! ( "{:#?}" , abi) } ) ;
149+ }
150+ RustcAbiAttrKind :: AssertEq => {
151+ let ty:: Tuple ( fields) = ty. kind ( ) else {
152+ span_bug ! (
153+ attr_span,
154+ "`#[rustc_abi(assert_eq)]` on a type alias requires pair type"
167155 ) ;
168- let ty:: FnPtr ( sig_tys2, hdr2) = field2. kind ( ) else {
169- span_bug ! (
170- meta_item. span( ) ,
171- "`#[rustc_abi(assert_eq)]` on a type alias requires pair of function pointer types"
172- ) ;
173- } ;
174- let abi2 = unwrap_fn_abi (
175- tcx. fn_abi_of_fn_ptr ( typing_env. as_query_input ( (
176- sig_tys2. with ( * hdr2) ,
177- /* extra_args */ ty:: List :: empty ( ) ,
178- ) ) ) ,
179- tcx,
180- item_def_id,
156+ } ;
157+ let [ field1, field2] = * * * fields else {
158+ span_bug ! (
159+ attr_span,
160+ "`#[rustc_abi(assert_eq)]` on a type alias requires pair type"
161+ ) ;
162+ } ;
163+ let ty:: FnPtr ( sig_tys1, hdr1) = field1. kind ( ) else {
164+ span_bug ! (
165+ attr_span,
166+ "`#[rustc_abi(assert_eq)]` on a type alias requires pair of function pointer types"
181167 ) ;
168+ } ;
169+ let abi1 = unwrap_fn_abi (
170+ tcx. fn_abi_of_fn_ptr ( typing_env. as_query_input ( (
171+ sig_tys1. with ( * hdr1) ,
172+ /* extra_args */ ty:: List :: empty ( ) ,
173+ ) ) ) ,
174+ tcx,
175+ item_def_id,
176+ ) ;
177+ let ty:: FnPtr ( sig_tys2, hdr2) = field2. kind ( ) else {
178+ span_bug ! (
179+ attr_span,
180+ "`#[rustc_abi(assert_eq)]` on a type alias requires pair of function pointer types"
181+ ) ;
182+ } ;
183+ let abi2 = unwrap_fn_abi (
184+ tcx. fn_abi_of_fn_ptr ( typing_env. as_query_input ( (
185+ sig_tys2. with ( * hdr2) ,
186+ /* extra_args */ ty:: List :: empty ( ) ,
187+ ) ) ) ,
188+ tcx,
189+ item_def_id,
190+ ) ;
182191
183- if !test_abi_eq ( abi1, abi2) {
184- tcx. dcx ( ) . emit_err ( AbiNe {
185- span,
186- left : format ! ( "{:#?}" , abi1) ,
187- right : format ! ( "{:#?}" , abi2) ,
188- } ) ;
189- }
190- }
191- _ => {
192- tcx. dcx ( ) . emit_err ( UnrecognizedArgument { span : meta_item. span ( ) } ) ;
192+ if !test_abi_eq ( abi1, abi2) {
193+ tcx. dcx ( ) . emit_err ( AbiNe {
194+ span,
195+ left : format ! ( "{:#?}" , abi1) ,
196+ right : format ! ( "{:#?}" , abi2) ,
197+ } ) ;
193198 }
194199 }
195200 }
0 commit comments