Skip to content

Commit e5ff932

Browse files
committed
Add FnDef/Closure -> FnPtr coercion for inline asm const operand
1 parent 0116942 commit e5ff932

File tree

1 file changed

+34
-1
lines changed
  • compiler/rustc_hir_typeck/src

1 file changed

+34
-1
lines changed

compiler/rustc_hir_typeck/src/expr.rs

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)