@@ -98,6 +98,23 @@ impl<'a, 'tcx> Deref for Coerce<'a, 'tcx> {
98
98
99
99
type CoerceResult < ' tcx > = InferResult < ' tcx , ( Vec < Adjustment < ' tcx > > , Ty < ' tcx > ) > ;
100
100
101
+ /// Make any adjustments necessary for a function signature to be compatible
102
+ /// with reification to a `fn` pointer. In particular, intrinsics are imported
103
+ /// using pseudo-ABIs (`extern "rust-intrinsic" {...}`) currently, but that's
104
+ /// an implementation detail and any `fn` pointers that may be taken to them
105
+ /// should be indistinguishable from those to regular Rust functions, in order
106
+ /// to allow e.g. libcore public APIs to be replaced with intrinsics, without
107
+ /// breaking code that was, explicitly or implicitly, creating `fn` pointers.
108
+ // FIXME(eddyb) intrinsics shouldn't use pseudo-ABIs, but rather the Rust ABI
109
+ // and some other way to indicate that they are intrinsics (e.g. new attributes).
110
+ fn prepare_fn_sig_for_reify < ' tcx > ( mut sig : ty:: FnSig < ' tcx > ) -> ty:: FnSig < ' tcx > {
111
+ if matches ! ( sig. abi, ExternAbi :: RustIntrinsic ) {
112
+ sig. abi = ExternAbi :: Rust ;
113
+ }
114
+
115
+ sig
116
+ }
117
+
101
118
/// Coercing a mutable reference to an immutable works, while
102
119
/// coercing `&T` to `&mut T` should be forbidden.
103
120
fn coerce_mutbls < ' tcx > (
@@ -911,12 +928,10 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
911
928
match b. kind ( ) {
912
929
ty:: FnPtr ( _, b_hdr) => {
913
930
let mut a_sig = a. fn_sig ( self . tcx ) ;
914
- if let ty:: FnDef ( def_id, _) = * a. kind ( ) {
915
- // Intrinsics are not coercible to function pointers
916
- if self . tcx . intrinsic ( def_id) . is_some ( ) {
917
- return Err ( TypeError :: IntrinsicCast ) ;
918
- }
931
+ // NOTE(eddyb) see comment on `prepare_fn_sig_for_reify`.
932
+ a_sig = a_sig. map_bound ( prepare_fn_sig_for_reify) ;
919
933
934
+ if let ty:: FnDef ( def_id, _) = * a. kind ( ) {
920
935
let fn_attrs = self . tcx . codegen_fn_attrs ( def_id) ;
921
936
if matches ! ( fn_attrs. inline, InlineAttr :: Force { .. } ) {
922
937
return Err ( TypeError :: ForceInlineCast ) ;
@@ -1266,10 +1281,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1266
1281
}
1267
1282
} ;
1268
1283
if let ( Some ( a_sig) , Some ( b_sig) ) = ( a_sig, b_sig) {
1269
- // Intrinsics are not coercible to function pointers.
1270
- if a_sig. abi ( ) == ExternAbi :: RustIntrinsic || b_sig. abi ( ) == ExternAbi :: RustIntrinsic {
1271
- return Err ( TypeError :: IntrinsicCast ) ;
1272
- }
1273
1284
// The signature must match.
1274
1285
let ( a_sig, b_sig) = self . normalize ( new. span , ( a_sig, b_sig) ) ;
1275
1286
let sig = self
0 commit comments