@@ -3698,7 +3698,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
36983698 }
36993699 }
37003700 hir:: InlineAsmOperand :: Const { ref anon_const } => {
3701- self . check_expr_const_block ( anon_const, Expectation :: NoExpectation ) ;
3701+ // This is mostly similar to type-checking of inline const expressions `const { ... }`, however
3702+ // asm const has special coercion rules (per RFC 3848) where function items and closures are coerced to
3703+ // function pointers (while pointers and integer remain as-is).
3704+ let body = self . tcx . hir_body ( anon_const. body ) ;
3705+
3706+ let fcx = FnCtxt :: new ( self , self . param_env , anon_const. def_id ) ;
3707+ let ty = fcx. check_expr ( body. value ) ;
3708+ let target_ty = match self . structurally_resolve_type ( body. value . span , ty) . kind ( )
3709+ {
3710+ ty:: FnDef ( ..) => {
3711+ let fn_sig = ty. fn_sig ( self . tcx ( ) ) ;
3712+ Ty :: new_fn_ptr ( self . tcx ( ) , fn_sig)
3713+ }
3714+ ty:: Closure ( _, args) => {
3715+ let closure_sig = args. as_closure ( ) . sig ( ) ;
3716+ let fn_sig =
3717+ self . tcx ( ) . signature_unclosure ( closure_sig, hir:: Safety :: Safe ) ;
3718+ Ty :: new_fn_ptr ( self . tcx ( ) , fn_sig)
3719+ }
3720+ _ => ty,
3721+ } ;
3722+
3723+ if let Err ( diag) =
3724+ self . demand_coerce_diag ( & body. value , ty, target_ty, None , AllowTwoPhase :: No )
3725+ {
3726+ diag. emit ( ) ;
3727+ }
3728+
3729+ fcx. require_type_is_sized (
3730+ target_ty,
3731+ body. value . span ,
3732+ ObligationCauseCode :: SizedConstOrStatic ,
3733+ ) ;
3734+ fcx. write_ty ( anon_const. hir_id , target_ty) ;
37023735 }
37033736 hir:: InlineAsmOperand :: SymFn { expr } => {
37043737 self . check_expr ( expr) ;
0 commit comments