@@ -99,6 +99,23 @@ impl<'a, 'tcx> Deref for Coerce<'a, 'tcx> {
99
99
100
100
type CoerceResult < ' tcx > = InferResult < ' tcx , ( Vec < Adjustment < ' tcx > > , Ty < ' tcx > ) > ;
101
101
102
+ /// Make any adjustments necessary for a function signature to be compatible
103
+ /// with reification to a `fn` pointer. In particular, intrinsics are imported
104
+ /// using pseudo-ABIs (`extern "rust-intrinsic" {...}`) currently, but that's
105
+ /// an implementation detail and any `fn` pointers that may be taken to them
106
+ /// should be indistinguishable from those to regular Rust functions, in order
107
+ /// to allow e.g. libcore public APIs to be replaced with intrinsics, without
108
+ /// breaking code that was, explicitly or implicitly, creating `fn` pointers.
109
+ // FIXME(eddyb) intrinsics shouldn't use pseudo-ABIs, but rather the Rust ABI
110
+ // and some other way to indicate that they are intrinsics (e.g. new attributes).
111
+ fn prepare_fn_sig_for_reify < ' tcx > ( mut sig : ty:: FnSig < ' tcx > ) -> ty:: FnSig < ' tcx > {
112
+ if matches ! ( sig. abi, Abi :: RustIntrinsic ) {
113
+ sig. abi = Abi :: Rust ;
114
+ }
115
+
116
+ sig
117
+ }
118
+
102
119
/// Coercing a mutable reference to an immutable works, while
103
120
/// coercing `&T` to `&mut T` should be forbidden.
104
121
fn coerce_mutbls < ' tcx > (
@@ -915,12 +932,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
915
932
match b. kind ( ) {
916
933
ty:: FnPtr ( _, b_hdr) => {
917
934
let a_sig = a. fn_sig ( self . tcx ) ;
935
+ // NOTE(eddyb) see comment on `prepare_fn_sig_for_reify`.
936
+ let a_sig = a_sig. map_bound ( prepare_fn_sig_for_reify) ;
918
937
if let ty:: FnDef ( def_id, _) = * a. kind ( ) {
919
- // Intrinsics are not coercible to function pointers
920
- if self . tcx . intrinsic ( def_id) . is_some ( ) {
921
- return Err ( TypeError :: IntrinsicCast ) ;
922
- }
923
-
924
938
// Safe `#[target_feature]` functions are not assignable to safe fn pointers (RFC 2396).
925
939
926
940
if b_hdr. safety == hir:: Safety :: Safe
@@ -1246,10 +1260,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1246
1260
}
1247
1261
} ;
1248
1262
if let ( Some ( a_sig) , Some ( b_sig) ) = ( a_sig, b_sig) {
1249
- // Intrinsics are not coercible to function pointers.
1250
- if a_sig. abi ( ) == Abi :: RustIntrinsic || b_sig. abi ( ) == Abi :: RustIntrinsic {
1251
- return Err ( TypeError :: IntrinsicCast ) ;
1252
- }
1263
+ // NOTE(eddyb) see comment on `prepare_fn_sig_for_reify`.
1264
+ let a_sig = a_sig. map_bound ( prepare_fn_sig_for_reify) ;
1265
+ let b_sig = b_sig. map_bound ( prepare_fn_sig_for_reify) ;
1253
1266
// The signature must match.
1254
1267
let ( a_sig, b_sig) = self . normalize ( new. span , ( a_sig, b_sig) ) ;
1255
1268
let sig = self
0 commit comments