Skip to content

Commit 68806a5

Browse files
committed
coerce_from_safe_fn is just fnptr->fnptr coercion
1 parent ea8f813 commit 68806a5

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
@@ -772,34 +772,35 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
772772
self.unify_and(a, b, [], Adjust::ReborrowPin(mut_b))
773773
}
774774

775-
fn coerce_from_safe_fn(
775+
// Coerces an fnptr `a` to a fnptr `b`, this is only `fn(..)` to `unsafe fn(..)`.
776+
// Takes an `adjustment` used to get the `a` fnptr in the first place.
777+
fn coerce_fnptrs(
776778
&self,
777-
fn_ty_a: ty::PolyFnSig<'tcx>,
778-
b: Ty<'tcx>,
779+
a: ty::PolyFnSig<'tcx>,
780+
b: ty::PolyFnSig<'tcx>,
779781
adjustment: Option<Adjust>,
780782
) -> CoerceResult<'tcx> {
781-
debug_assert!(self.shallow_resolve(b) == b);
782-
783783
self.commit_if_ok(|snapshot| {
784784
let outer_universe = self.infcx.universe();
785785

786-
let result = if let ty::FnPtr(_, hdr_b) = b.kind()
787-
&& fn_ty_a.safety().is_safe()
788-
&& hdr_b.safety.is_unsafe()
789-
{
790-
let unsafe_a = self.tcx.safe_to_unsafe_fn_ty(fn_ty_a);
786+
let a_ty = Ty::new_fn_ptr(self.tcx, a);
787+
let b_ty = Ty::new_fn_ptr(self.tcx, b);
788+
789+
// Handle coercing `fn(..)` to `unsafe fn(..)`
790+
let result = if a.safety().is_safe() && b.safety().is_unsafe() {
791+
let unsafe_a_ty = self.tcx.safe_to_unsafe_fn_ty(a);
792+
let adjustment = adjustment.map(|kind| Adjustment { kind, target: a_ty });
793+
791794
self.unify_and(
792-
unsafe_a,
793-
b,
794-
adjustment
795-
.map(|kind| Adjustment { kind, target: Ty::new_fn_ptr(self.tcx, fn_ty_a) }),
795+
unsafe_a_ty,
796+
b_ty,
797+
adjustment,
796798
Adjust::Pointer(PointerCoercion::UnsafeFnPointer),
797799
)
798800
} else {
799-
let a = Ty::new_fn_ptr(self.tcx, fn_ty_a);
800801
match adjustment {
801-
Some(adjust) => self.unify_and(a, b, [], adjust),
802-
None => self.unify(a, b),
802+
Some(adjust) => self.unify_and(a_ty, b_ty, [], adjust),
803+
None => self.unify(a_ty, b_ty),
803804
}
804805
};
805806

@@ -817,13 +818,16 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
817818

818819
fn coerce_from_fn_pointer(
819820
&self,
820-
fn_ty_a: ty::PolyFnSig<'tcx>,
821+
a_sig: ty::PolyFnSig<'tcx>,
821822
b: Ty<'tcx>,
822823
) -> CoerceResult<'tcx> {
823-
debug!(?fn_ty_a, ?b, "coerce_from_fn_pointer");
824+
debug!(?a_sig, ?b, "coerce_from_fn_pointer");
824825
debug_assert!(self.shallow_resolve(b) == b);
825826

826-
self.coerce_from_safe_fn(fn_ty_a, b, None)
827+
match b.kind() {
828+
ty::FnPtr(_, _) => self.coerce_fnptrs(a_sig, b.fn_sig(self.tcx), None),
829+
_ => self.unify(Ty::new_fn_ptr(self.tcx, a_sig), b),
830+
}
827831
}
828832

829833
fn coerce_from_fn_item(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
@@ -867,9 +871,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
867871
let InferOk { value: a_sig, mut obligations } =
868872
self.at(&self.cause, self.param_env).normalize(a_sig);
869873

870-
let InferOk { value, obligations: o2 } = self.coerce_from_safe_fn(
874+
let InferOk { value, obligations: o2 } = self.coerce_fnptrs(
871875
a_sig,
872-
b,
876+
b.fn_sig(self.tcx),
873877
Some(Adjust::Pointer(PointerCoercion::ReifyFnPointer)),
874878
)?;
875879

@@ -916,6 +920,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
916920
let pointer_ty =
917921
Ty::new_fn_ptr(self.tcx, self.tcx.signature_unclosure(closure_sig, safety));
918922
debug!("coerce_closure_to_fn(a={:?}, b={:?}, pty={:?})", a, b, pointer_ty);
923+
924+
// We don't use `self.coerce_fnptrs` as handling `fn` to `unsafe fn`
925+
// was trivial to do so ourselves.
919926
self.unify_and(
920927
pointer_ty,
921928
b,

0 commit comments

Comments
 (0)