Skip to content

Commit a07ed70

Browse files
committed
coerce_from_safe_fn is just fnptr->fnptr coercion
1 parent c888b2e commit a07ed70

File tree

1 file changed

+29
-22
lines changed

1 file changed

+29
-22
lines changed

compiler/rustc_hir_typeck/src/coercion.rs

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -743,34 +743,35 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
743743
self.unify_and(a, b, [], Adjust::ReborrowPin(mut_b))
744744
}
745745

746-
fn coerce_from_safe_fn(
746+
// Coerces an fnptr `a` to a fnptr `b`, this is only `fn(..)` to `unsafe fn(..)`.
747+
// Takes an `adjustment` used to get the `a` fnptr in the first place.
748+
fn coerce_fnptrs(
747749
&self,
748-
fn_ty_a: ty::PolyFnSig<'tcx>,
749-
b: Ty<'tcx>,
750+
a: ty::PolyFnSig<'tcx>,
751+
b: ty::PolyFnSig<'tcx>,
750752
adjustment: Option<Adjust>,
751753
) -> CoerceResult<'tcx> {
752-
debug_assert!(self.shallow_resolve(b) == b);
753-
754754
self.commit_if_ok(|snapshot| {
755755
let outer_universe = self.infcx.universe();
756756

757-
let result = if let ty::FnPtr(_, hdr_b) = b.kind()
758-
&& fn_ty_a.safety().is_safe()
759-
&& hdr_b.safety.is_unsafe()
760-
{
761-
let unsafe_a = self.tcx.safe_to_unsafe_fn_ty(fn_ty_a);
757+
let a_ty = Ty::new_fn_ptr(self.tcx, a);
758+
let b_ty = Ty::new_fn_ptr(self.tcx, b);
759+
760+
// Handle coercing `fn(..)` to `unsafe fn(..)`
761+
let result = if a.safety().is_safe() && b.safety().is_unsafe() {
762+
let unsafe_a_ty = self.tcx.safe_to_unsafe_fn_ty(a);
763+
let adjustment = adjustment.map(|kind| Adjustment { kind, target: a_ty });
764+
762765
self.unify_and(
763-
unsafe_a,
764-
b,
765-
adjustment
766-
.map(|kind| Adjustment { kind, target: Ty::new_fn_ptr(self.tcx, fn_ty_a) }),
766+
unsafe_a_ty,
767+
b_ty,
768+
adjustment,
767769
Adjust::Pointer(PointerCoercion::UnsafeFnPointer),
768770
)
769771
} else {
770-
let a = Ty::new_fn_ptr(self.tcx, fn_ty_a);
771772
match adjustment {
772-
Some(adjust) => self.unify_and(a, b, [], adjust),
773-
None => self.unify(a, b),
773+
Some(adjust) => self.unify_and(a_ty, b_ty, [], adjust),
774+
None => self.unify(a_ty, b_ty),
774775
}
775776
};
776777

@@ -788,13 +789,16 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
788789

789790
fn coerce_from_fn_pointer(
790791
&self,
791-
fn_ty_a: ty::PolyFnSig<'tcx>,
792+
a_sig: ty::PolyFnSig<'tcx>,
792793
b: Ty<'tcx>,
793794
) -> CoerceResult<'tcx> {
794-
debug!(?fn_ty_a, ?b, "coerce_from_fn_pointer");
795+
debug!(?a_sig, ?b, "coerce_from_fn_pointer");
795796
debug_assert!(self.shallow_resolve(b) == b);
796797

797-
self.coerce_from_safe_fn(fn_ty_a, b, None)
798+
match b.kind() {
799+
ty::FnPtr(_, _) => self.coerce_fnptrs(a_sig, b.fn_sig(self.tcx), None),
800+
_ => self.unify(Ty::new_fn_ptr(self.tcx, a_sig), b),
801+
}
798802
}
799803

800804
fn coerce_from_fn_item(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
@@ -838,9 +842,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
838842
let InferOk { value: a_sig, mut obligations } =
839843
self.at(&self.cause, self.param_env).normalize(a_sig);
840844

841-
let InferOk { value, obligations: o2 } = self.coerce_from_safe_fn(
845+
let InferOk { value, obligations: o2 } = self.coerce_fnptrs(
842846
a_sig,
843-
b,
847+
b.fn_sig(self.tcx),
844848
Some(Adjust::Pointer(PointerCoercion::ReifyFnPointer)),
845849
)?;
846850

@@ -887,6 +891,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
887891
let pointer_ty =
888892
Ty::new_fn_ptr(self.tcx, self.tcx.signature_unclosure(closure_sig, safety));
889893
debug!("coerce_closure_to_fn(a={:?}, b={:?}, pty={:?})", a, b, pointer_ty);
894+
895+
// We don't use `self.coerce_fnptrs` as handling `fn` to `unsafe fn`
896+
// was trivial to do so ourselves.
890897
self.unify_and(
891898
pointer_ty,
892899
b,

0 commit comments

Comments
 (0)