@@ -84,6 +84,23 @@ impl<'a, 'tcx> Deref for Coerce<'a, 'tcx> {
84
84
85
85
type CoerceResult < ' tcx > = InferResult < ' tcx , ( Vec < Adjustment < ' tcx > > , Ty < ' tcx > ) > ;
86
86
87
+ /// Make any adjustments necessary for a function signature to be compatible
88
+ /// with reification to a `fn` pointer. In particular, intrinsics are imported
89
+ /// using pseudo-ABIs (`extern "rust-intrinsic" {...}`) currently, but that's
90
+ /// an implementation detail and any `fn` pointers that may be taken to them
91
+ /// should be indistinguishable from those to regular Rust functions, in order
92
+ /// to allow e.g. libcore public APIs to be replaced with intrinsics, without
93
+ /// breaking code that was, explicitly or implicitly, creating `fn` pointers.
94
+ // FIXME(eddyb) intrinsics shouldn't use pseudo-ABIs, but rather the Rust ABI
95
+ // and some other way to indicate that they are intrinsics (e.g. new attributes).
96
+ fn prepare_fn_sig_for_reify ( mut sig : ty:: FnSig < ' tcx > ) -> ty:: FnSig < ' tcx > {
97
+ if matches ! ( sig. abi, Abi :: RustIntrinsic | Abi :: PlatformIntrinsic ) {
98
+ sig. abi = Abi :: Rust ;
99
+ }
100
+
101
+ sig
102
+ }
103
+
87
104
/// Coercing a mutable reference to an immutable works, while
88
105
/// coercing `&T` to `&mut T` should be forbidden.
89
106
fn coerce_mutbls < ' tcx > (
@@ -779,10 +796,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
779
796
match b. kind ( ) {
780
797
ty:: FnPtr ( b_sig) => {
781
798
let a_sig = a. fn_sig ( self . tcx ) ;
782
- // Intrinsics are not coercible to function pointers
783
- if a_sig. abi ( ) == Abi :: RustIntrinsic || a_sig. abi ( ) == Abi :: PlatformIntrinsic {
784
- return Err ( TypeError :: IntrinsicCast ) ;
785
- }
799
+
800
+ // NOTE(eddyb) see comment on `prepare_fn_sig_for_reify`.
801
+ let a_sig = a_sig. map_bound ( prepare_fn_sig_for_reify) ;
786
802
787
803
// Safe `#[target_feature]` functions are not assignable to safe fn pointers (RFC 2396).
788
804
if let ty:: FnDef ( def_id, _) = * a. kind ( ) {
@@ -1043,14 +1059,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1043
1059
}
1044
1060
} ;
1045
1061
if let ( Some ( a_sig) , Some ( b_sig) ) = ( a_sig, b_sig) {
1046
- // Intrinsics are not coercible to function pointers.
1047
- if a_sig. abi ( ) == Abi :: RustIntrinsic
1048
- || a_sig. abi ( ) == Abi :: PlatformIntrinsic
1049
- || b_sig. abi ( ) == Abi :: RustIntrinsic
1050
- || b_sig. abi ( ) == Abi :: PlatformIntrinsic
1051
- {
1052
- return Err ( TypeError :: IntrinsicCast ) ;
1053
- }
1062
+ // NOTE(eddyb) see comment on `prepare_fn_sig_for_reify`.
1063
+ let a_sig = a_sig. map_bound ( prepare_fn_sig_for_reify) ;
1064
+ let b_sig = b_sig. map_bound ( prepare_fn_sig_for_reify) ;
1065
+
1054
1066
// The signature must match.
1055
1067
let a_sig = self . normalize_associated_types_in ( new. span , a_sig) ;
1056
1068
let b_sig = self . normalize_associated_types_in ( new. span , b_sig) ;
0 commit comments