@@ -2,12 +2,12 @@ mod adt;
22
33use std:: borrow:: Cow ;
44
5- use rustc_abi:: { FieldIdx , VariantIdx } ;
5+ use rustc_abi:: { ExternAbi , FieldIdx , VariantIdx } ;
66use rustc_ast:: Mutability ;
77use rustc_hir:: LangItem ;
88use rustc_middle:: span_bug;
99use rustc_middle:: ty:: layout:: TyAndLayout ;
10- use rustc_middle:: ty:: { self , Const , ScalarInt , Ty } ;
10+ use rustc_middle:: ty:: { self , Const , FnHeader , FnSigTys , ScalarInt , Ty , TyCtxt } ;
1111use rustc_span:: { Symbol , sym} ;
1212
1313use crate :: const_eval:: CompileTimeMachine ;
@@ -188,10 +188,21 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
188188 self . write_dyn_trait_type_info ( dyn_place, * predicates, * region) ?;
189189 variant
190190 }
191+ ty:: FnPtr ( sig, fn_header) => {
192+ let ( variant, variant_place) =
193+ self . downcast ( & field_dest, sym:: FnPtr ) ?;
194+ let fn_ptr_place =
195+ self . project_field ( & variant_place, FieldIdx :: ZERO ) ?;
196+
197+ // FIXME: handle lifetime bounds
198+ let sig = sig. skip_binder ( ) ;
199+
200+ self . write_fn_ptr_type_info ( fn_ptr_place, & sig, fn_header) ?;
201+ variant
202+ }
191203 ty:: Foreign ( _)
192204 | ty:: Pat ( _, _)
193205 | ty:: FnDef ( ..)
194- | ty:: FnPtr ( ..)
195206 | ty:: UnsafeBinder ( ..)
196207 | ty:: Closure ( ..)
197208 | ty:: CoroutineClosure ( ..)
@@ -402,6 +413,65 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
402413 interp_ok ( ( ) )
403414 }
404415
416+ pub ( crate ) fn write_fn_ptr_type_info (
417+ & mut self ,
418+ place : impl Writeable < ' tcx , CtfeProvenance > ,
419+ sig : & FnSigTys < TyCtxt < ' tcx > > ,
420+ fn_header : & FnHeader < TyCtxt < ' tcx > > ,
421+ ) -> InterpResult < ' tcx > {
422+ let FnHeader { safety, c_variadic, abi } = fn_header;
423+
424+ for ( field_idx, field) in
425+ place. layout ( ) . ty . ty_adt_def ( ) . unwrap ( ) . non_enum_variant ( ) . fields . iter_enumerated ( )
426+ {
427+ let field_place = self . project_field ( & place, field_idx) ?;
428+
429+ match field. name {
430+ sym:: unsafety => {
431+ self . write_scalar ( Scalar :: from_bool ( safety. is_unsafe ( ) ) , & field_place) ?;
432+ }
433+ sym:: abi => match abi {
434+ ExternAbi :: C { .. } => {
435+ let ( rust_variant, _rust_place) =
436+ self . downcast ( & field_place, sym:: ExternC ) ?;
437+ self . write_discriminant ( rust_variant, & field_place) ?;
438+ }
439+ ExternAbi :: Rust => {
440+ let ( rust_variant, _rust_place) =
441+ self . downcast ( & field_place, sym:: ExternRust ) ?;
442+ self . write_discriminant ( rust_variant, & field_place) ?;
443+ }
444+ other_abi => {
445+ let ( variant, variant_place) = self . downcast ( & field_place, sym:: Named ) ?;
446+ let str_place = self . allocate_str_dedup ( other_abi. as_str ( ) ) ?;
447+ let str_ref = self . mplace_to_ref ( & str_place) ?;
448+ let payload = self . project_field ( & variant_place, FieldIdx :: ZERO ) ?;
449+ self . write_immediate ( * str_ref, & payload) ?;
450+ self . write_discriminant ( variant, & field_place) ?;
451+ }
452+ } ,
453+ sym:: inputs => {
454+ let inputs = sig. inputs ( ) ;
455+ self . allocate_fill_and_write_slice_ptr (
456+ field_place,
457+ inputs. len ( ) as _ ,
458+ |this, i, place| this. write_type_id ( inputs[ i as usize ] , & place) ,
459+ ) ?;
460+ }
461+ sym:: output => {
462+ let output = sig. output ( ) ;
463+ self . write_type_id ( output, & field_place) ?;
464+ }
465+ sym:: variadic => {
466+ self . write_scalar ( Scalar :: from_bool ( * c_variadic) , & field_place) ?;
467+ }
468+ other => span_bug ! ( self . tcx. def_span( field. did) , "unimplemented field {other}" ) ,
469+ }
470+ }
471+
472+ interp_ok ( ( ) )
473+ }
474+
405475 pub ( crate ) fn write_pointer_type_info (
406476 & mut self ,
407477 place : impl Writeable < ' tcx , CtfeProvenance > ,
0 commit comments