Allow reifying intrinsics to fn pointers. by eddyb · Pull Request #86699 · rust-lang/rust (original) (raw)

The main change is in ty/instance.rs, which is to simply have resolve_for_fn_ptr handle InstanceDef::Intrinsic the same way it does the other existing cases where a shim is needed to be able to have a fn pointer in the first place (virtual methods i.e. <dyn Trait as Trait>::method, and #[track_caller] functions).

However, there is another important change, which is that unlike other functions, intrinsics have their type-level ABI change from the extern "rust-intrinsic" fn "pseudo-ABI" to the normal Rust ABI.
This is possible because pseudo-ABIs like extern "rust-intrinsic" do not actually change the call ABI, but rather are used as a side-channel (instead of a more principled solution, like some #[rustc_intrinsic] attribute).

What this all means for the user is that they can/have to do transmute as unsafe fn(T) -> U, without the fact that the function was an intrinsic showing up in the typesystem at all.

That type-level ABI aspect also ties in with the motivation for finally fixing this, which is #84297, where ptr::{copy,copy_nonoverlapping} becoming stable reexports of the intrinsics in #81238 was backwards incompatible - with this PR, that shouldn't be an issue anymore.

(I also have a revert for #86003 ready - at least the parts not reverted already by e.g. #86295, if this PR is accepted; cc @pnkfelix)


In terms of this capability being insta-stable, we still get to control that via which intrinsics we mark stable.
The only one I could find right now is mem::transmute (and I've added a test that its size check still works when going through a fn pointer), and if we do the above mentioned #86003 revert, we'd also have ptr::{copy,copy_nonoverlapping}.