# \[Pre-RFC\] Safer Transmutation

**URL:** <https://internals.rust-lang.org/t/pre-rfc-safer-transmutation/12926>\
**Category:** language design\
**Created:** [August 19, 2020, 11:09pm UTC](https://internals.rust-lang.org/t/pre-rfc-safer-transmutation/12926 "2020-08-19T23:09:28Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![jack](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jack/32/3724_2.png) [@jack](https://internals.rust-lang.org/u/jack)\
**Post date:** [August 19, 2020, 11:09pm UTC](https://internals.rust-lang.org/t/pre-rfc-safer-transmutation/12926/1 "2020-08-19T23:09:28Z")

</div>

[**UPDATE: _This proposal has been formally submitted as an RFC!_**](https://github.com/rust-lang/rfcs/pull/2981)

* * *

As part of [Project Safe Transmute](https://github.com/rust-lang/project-safe-transmute), I, @rylev @joshlf and others have drafted a design of a compiler-supported API for safer transmutation. At the heart of the proposal is a trait that is implemented _automatically_ by the compiler for all types where a transmutation is statically guaranteed to be _sound_, _safe_, and _stable_.

- Click [**here**](https://jswrenn.github.io/safer-transmute-rustdoc/rfc/core/convert/transmute/index.html) for a rustdoc overview of the proposed API.
- Click [**here**](https://github.com/rust-lang/project-safe-transmute/pull/5) to read the pre-RFC in its entirety (warning: _long!_).

Compared to [prior art](https://github.com/jswrenn/project-safe-transmute/blob/rfc/rfcs/0000-safe-transmute.md#prior-art), this proposal contributes a design for truly _general_ transmutation (just like `mem::transmute`), that does not compromise on [safety](https://github.com/jswrenn/project-safe-transmute/blob/rfc/rfcs/0000-safe-transmute.md#-when-is-a-transmutation-safe) and does not pose a [stability](https://github.com/jswrenn/project-safe-transmute/blob/rfc/rfcs/0000-safe-transmute.md#-when-is-a-transmutation-stable) hazard. With this API, it might someday be possible deprecate `mem::transmute` altogether!

Please let us know what you think! I am especially interested in any use-cases which are _not_ covered by our proposal.

---

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [August 19, 2020, 11:47pm UTC](https://internals.rust-lang.org/t/pre-rfc-safer-transmutation/12926/2 "2020-08-19T23:47:48Z")

</div>

One small thing I'm worried about is `NeglectStability`.

As of current, it is _impossible_ for me to write _safe_ Rust code which relies on nonpublic details of dependencies (so long as said nonpublic details are actually nonpublic and not just `#[doc(hidden)]` and exposed for e.g. macros). If I want to reach through the stability barrier, I need to reach for the unsafe `transmute`.

Given a safe `NeglectStability`, though, we've added a _safe_ way to rely on implementation details of a dependency. This is still explicitly opted into (probably, if `NeglectStability` is _never_ inferred, in _any_ way) but scares me.

Specifically because I can write a case where data changes without the representation changing, so the client code wouldn't stop compiling, it would just silently be wrong.

```rust
#[repr(C)]
pub struct Complicated {
    pub public_data: u8,
    pub(self) private_a: u8,
    pub(self) private_b: u8,
}

#[repr(C)]
pub struct ComplicatedHead {
    pub public_data: u8,
}

```

I don't know the exact options required to opt-in to just this, but say I want to stably allow transmuting `&Complicated` to `&ComplicatedHead`.

If a consumer neglects stability and transmutes `&Complicated` to `&[u8; 3]`, they can read my private fields. If I change the order of them in a subsequent release, their code is now silently giving the wrong results.

The ability of using `NeglectStability` to read (or even change) private fields that could have arbitrary safety requirements _thoroughly_ scares me. I know you address some of this with the talk of implicit constructability, but as of my last reading I'm not yet convinced that every pitfall around private data (within a fixed, defined space) is guarded against in the face of `NeglectStability`.

---

<div class="post-metadata">

**Author:** ![jack](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jack/32/3724_2.png) [@jack](https://internals.rust-lang.org/u/jack)\
**Post date:** [August 20, 2020, 12:08am UTC](https://internals.rust-lang.org/t/pre-rfc-safer-transmutation/12926/3 "2020-08-20T00:08:12Z")

</div>

@CAD97 The proposed design of `NeglectStability` should _not_, under any circumstances, allow you to read or change private fields. [As the RFC notes, bypassing restricted constructability is unsafe.](https://github.com/jswrenn/project-safe-transmute/blob/rfc/rfcs/0000-safe-transmute.md#-when-is-a-transmutation-safe)

> I'm not yet convinced that every pitfall around private data (within a fixed, defined space) is guarded against in the face of `NeglectStability` .

Since constructability is _really_ subtle to get right, the RFC _also_ proposes [a simpler, incomplete](https://github.com/jswrenn/project-safe-transmute/blob/rfc/rfcs/0000-safe-transmute.md#simplifying-constructability) formulation of constructability. Because this simpler formulation of constructability is incomplete, `NeglectStability` can pose a [safety hazard](https://github.com/jswrenn/project-safe-transmute/blob/rfc/rfcs/0000-safe-transmute.md#at-the-cost-of-safety). **We therefore [recommend](https://github.com/jswrenn/project-safe-transmute/blob/rfc/rfcs/0000-safe-transmute.md#recommendation) that `NeglectStability` is initially _not_ a safe transmutation option.**

---

<div class="post-metadata">

**Author:** ![jhpratt](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jhpratt/32/11640_2.png) [@jhpratt](https://internals.rust-lang.org/u/jhpratt)\
**Post date:** [August 20, 2020, 8:05am UTC](https://internals.rust-lang.org/t/pre-rfc-safer-transmutation/12926/4 "2020-08-20T08:05:08Z")

</div>

> [@jack](#):
>
> With this API, it might someday be possible deprecate `mem::transmute` altogether!

What reasons might one have for _not_ wanting a safe transmute? Or is that what you're asking at the end?

---

<div class="post-metadata">

**Author:** ![HerrJemine](https://avatars.discourse-cdn.com/v4/letter/h/7ba0ec/32.png) [@HerrJemine](https://internals.rust-lang.org/u/HerrJemine)\
**Post date:** [August 20, 2020, 10:08am UTC](https://internals.rust-lang.org/t/pre-rfc-safer-transmutation/12926/5 "2020-08-20T10:08:11Z")

</div>

> [@jack](#):
>
> **We therefore [recommend](https://github.com/jswrenn/project-safe-transmute/blob/rfc/rfcs/0000-safe-transmute.md#recommendation) that `NeglectStability` is initially _not_ a safe transmutation option.**

I think your solution is safe (and I'm very impressed by the RFC in general), but is there not a backwards compatibility problem when the compiler transitions from the simplified to the more exact constructability criteria?

As I understand it the simplified criteria allows more cases (at the cost of making NeglectStability an unsafe option only).

But couldn't there be unsafe\_transmute (with NeglectStability) calls that are allowed under simplified constructability, but forbidden under the more precise constructability criteria?

---

<div class="post-metadata">

**Author:** ![HerrJemine](https://avatars.discourse-cdn.com/v4/letter/h/7ba0ec/32.png) [@HerrJemine](https://internals.rust-lang.org/u/HerrJemine)\
**Post date:** [August 20, 2020, 11:09am UTC](https://internals.rust-lang.org/t/pre-rfc-safer-transmutation/12926/6 "2020-08-20T11:09:02Z")

</div>

Independently I think there is some overlap between this RFC and ABI stability that could be discussed in the RFC:

1. The RFC requires repr(C), but if there is another stable representation such as discussed in the stable modular ABI thread, it should also work.

2. derive(PromiseTransmutable) seems to correspond to library ABI stability for this type. Maybe in the future this could thus be required for public types of stable ABI crates. Considering this use case, maybe a more neutral name could be chosen, thus as derive(StableLayoutGuarantee).

---

<div class="post-metadata">

**Author:** ![jack](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jack/32/3724_2.png) [@jack](https://internals.rust-lang.org/u/jack)\
**Post date:** [August 20, 2020, 2:25pm UTC](https://internals.rust-lang.org/t/pre-rfc-safer-transmutation/12926/7 "2020-08-20T14:25:21Z")

</div>

> [@jhpratt](#):
>
> What reasons might one have for _not_ wanting a safe transmute? Or is that what you're asking at the end?

There are plenty of situations where you want a _safer_ transmute, but not necessarily a _safe_ transmute. This is where the [options system](https://jswrenn.github.io/safer-transmute-rustdoc/convert/transmute/options/index.html) of the RFC comes in. You might _want_ to give up some static guarantees of safety when there is a more powerful runtime check you can perform; e.g., [`NeglectAlignment`](https://jswrenn.github.io/safer-transmute-rustdoc/convert/transmute/options/struct.NeglectAlignment.html) unsafely disables the static alignment check.

Without the options system, the only way to perform a conditionally-safe transmutation would be to use the **wildly unsafe** _`mem::transmute` and company_.

My hope is that additional options will be added in the future until there is no conditionally-safe use-case that _isn't_ solved by this RFC with the right set of options! A `NeglectConstructability` option is one such possible future option, but requires [a _lot_ of design work to get right](https://github.com/jswrenn/project-safe-transmute/blob/rfc/rfcs/0000-safe-transmute.md#design-of-neglectconstructability).

---

<div class="post-metadata">

**Author:** ![jack](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jack/32/3724_2.png) [@jack](https://internals.rust-lang.org/u/jack)\
**Post date:** [August 20, 2020, 2:33pm UTC](https://internals.rust-lang.org/t/pre-rfc-safer-transmutation/12926/8 "2020-08-20T14:33:27Z")

</div>

> [@HerrJemine](#):
>
> I think your solution is safe (and I'm very impressed by the RFC in general), but is there not a backwards compatibility problem when the compiler transitions from the simplified to the more exact constructability criteria?

Someday moving to the complete formulation of constructability should _generally_ not cause backcompat issues.

The [exception](https://github.com/jswrenn/project-safe-transmute/blob/rfc/rfcs/0000-safe-transmute.md#at-the-cost-of-safety) to this rule is the pub-in-priv trick. The documentation for the stability declaration traits should be clear you should _not_ implement these traits for your type if you are using the pub-in-priv trick to restrict their [implicit constructability](https://github.com/jswrenn/project-safe-transmute/blob/rfc/rfcs/0000-safe-transmute.md#implicit-constructability).

* * *

> [@HerrJemine](#):
>
> - The RFC requires repr(C), but if there is another stable representation such as discussed in the stable modular ABI thread, it should also work.

Agree completely! The RFC actually only requires that the [transmuted types have a well-defined representation](https://github.com/jswrenn/project-safe-transmute/blob/rfc/rfcs/0000-safe-transmute.md#well-defined-representation). This does not necessarily mean `#[repr(C)]`; e.g., the layout of [certain option-like types is well-defined](https://github.com/rust-lang/rust/pull/60300).

---

<div class="post-metadata">

**Author:** ![jethrogb](https://avatars.discourse-cdn.com/v4/letter/j/43a26b/32.png) [@jethrogb](https://internals.rust-lang.org/u/jethrogb)\
**Post date:** [August 20, 2020, 2:44pm UTC](https://internals.rust-lang.org/t/pre-rfc-safer-transmutation/12926/9 "2020-08-20T14:44:45Z")

</div>

I'm surprised the RFC doesn't mention integer byte order concerns. I think it should be explicit about whether e.g. a `u32` \<-\> `[u8; 4]` conversion is or isn't considered a “safe transmute”.

---

<div class="post-metadata">

**Author:** ![jack](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jack/32/3724_2.png) [@jack](https://internals.rust-lang.org/u/jack)\
**Post date:** [August 20, 2020, 2:53pm UTC](https://internals.rust-lang.org/t/pre-rfc-safer-transmutation/12926/10 "2020-08-20T14:53:43Z")

</div>

> [@jethrogb](#):
>
> I'm surprised the RFC doesn't mention integer byte order concerns. I think it should be explicit about whether e.g. a `u32` \<-\> `[u8; 4]` conversion is or isn't considered a “safe transmute”.

There is [a section on platform-dependent layouts](https://github.com/jswrenn/project-safe-transmute/blob/rfc/rfcs/0000-safe-transmute.md#no-notion-of-platform-stability), but it's not (yet) explicit that endianness is a kind of platform-dependent layout. **Our RFC is expressly oblivious to platform-dependent layouts.** Safety, in this RFC, is [scoped](https://github.com/jswrenn/project-safe-transmute/blob/rfc/rfcs/0000-safe-transmute.md#-safety) to _memory safety_. A transmutation from `u32` to `[u8; 4]` might be _inconsistent_ between platforms, but it is not _unsafe_.

---

<div class="post-metadata">

**Author:** ![brson](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/brson/32/5197_2.png) [@brson](https://internals.rust-lang.org/u/brson)\
**Post date:** [August 25, 2020, 10:06pm UTC](https://internals.rust-lang.org/t/pre-rfc-safer-transmutation/12926/11 "2020-08-25T22:06:38Z")

</div>

This is a very worthy project. The first obvious thing that strikes me about it is that the reuse of the rust-specific term "transmute" will be potentially confusing in the future. "mem::transmute" and this API are quite different. Talking about "transmute" when it means two different things will be complicated and pretty much guarantee the term is always accompanied with a clarifying adjective, like "unsafe transmute" vs "safe transmute".

I'd suggest giving this a new name, maybe with "cast" in it. This could be an opportunity to use the C++ "reinterpret" terminology, like "ReinterpretInto", "ReinterpretFrom", but anything else will make it easier to discuss. If we want to keep it cute and magic themed, maybe come up with another magical word that also has a connotation of safety.

---

<div class="post-metadata">

**Author:** ![jack](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jack/32/3724_2.png) [@jack](https://internals.rust-lang.org/u/jack)\
**Post date:** [August 25, 2020, 10:59pm UTC](https://internals.rust-lang.org/t/pre-rfc-safer-transmutation/12926/12 "2020-08-25T22:59:04Z")

</div>

> [@brson](#):
>
> "mem::transmute" and this API are quite different.

Could you elaborate? The lense through which I've always seen this proposal (and, before it, [typic](https://github.com/jswrenn/typic)), has been: _What's the trait bound we add to `mem::transmute` to make it safe?_ And this RFC's answer is:

```rust
pub fn transmute<Src, Dst>(src: Src)
where
    Dst: TransmuteFrom<Src>
{
    ...
}

```

(Of course, we cannot _literally_ just slap trait bound on `mem::transmute`—that would a breaking change. I propose two free functions, [`safe_transmute`](https://jswrenn.github.io/safer-transmute-rustdoc/rfc/core/convert/transmute/fn.safe_transmute.html) and [`unsafe_transmute`](https://jswrenn.github.io/safer-transmute-rustdoc/rfc/core/convert/transmute/fn.unsafe_transmute.html), and that we perhaps someday deprecate `mem::transmute`.)

---

<div class="post-metadata">

**Author:** ![carbotaniuman](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/carbotaniuman/32/6981_2.png) [@carbotaniuman](https://internals.rust-lang.org/u/carbotaniuman)\
**Post date:** [August 25, 2020, 11:27pm UTC](https://internals.rust-lang.org/t/pre-rfc-safer-transmutation/12926/13 "2020-08-25T23:27:23Z")

</div>

Would there ever be any scenario in which a user has to manually state every single tuple combination of these options?

---

<div class="post-metadata">

**Author:** ![jack](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jack/32/3724_2.png) [@jack](https://internals.rust-lang.org/u/jack)\
**Post date:** [August 25, 2020, 11:57pm UTC](https://internals.rust-lang.org/t/pre-rfc-safer-transmutation/12926/14 "2020-08-25T23:57:13Z")

</div>

_Maybe?_ I suspect that would be _very_ uncommon. I don't think we even have a complete sense of all the options that might eventually exist. For instance, a hypothetical [`NeglectConstructability`](https://github.com/jswrenn/project-safe-transmute/blob/rfc/rfcs/0000-safe-transmute.md#design-of-neglectconstructability) option would have subtle interactions with `!Send`, `!Sync`, `UnsafeCell` and any abstraction whose safety depends on restricting visibility. Deciding if and how to partition that space of dangerous transmutations between different options is going to be a substantial undertaking.

What's important is that the API surface can handle that future work, and it can: those additional options can be freely added in the future if they're deemed necessary. I would _love_ for this API to eventually get to a place where _any_ use of `mem::transmute` necessitated by a lack of neglectable checks in the safe API was an indicator of unsoundness.

---

<div class="post-metadata">

**Author:** ![carbotaniuman](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/carbotaniuman/32/6981_2.png) [@carbotaniuman](https://internals.rust-lang.org/u/carbotaniuman)\
**Post date:** [August 26, 2020, 4:07am UTC](https://internals.rust-lang.org/t/pre-rfc-safer-transmutation/12926/15 "2020-08-26T04:07:50Z")

</div>

Is there a way for something like NonZeroU8 to be transmutable via ignoring validity?

Also how does this act in generic code? Will the fixed/fully completed constructibility check be dependent on which module the code is in? (Would transmuting a struct with a pub(crate) field inside that crate work?)

---

<div class="post-metadata">

**Author:** ![brson](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/brson/32/5197_2.png) [@brson](https://internals.rust-lang.org/u/brson)\
**Post date:** [August 26, 2020, 6:22am UTC](https://internals.rust-lang.org/t/pre-rfc-safer-transmutation/12926/16 "2020-08-26T06:22:37Z")

</div>

> [@jack](#):
>
> Could you elaborate?

mem::transmute is unsafe and this api is safe

---

<div class="post-metadata">

**Author:** ![rylev](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/rylev/32/5366_2.png) [@rylev](https://internals.rust-lang.org/u/rylev)\
**Post date:** [August 26, 2020, 11:57am UTC](https://internals.rust-lang.org/t/pre-rfc-safer-transmutation/12926/17 "2020-08-26T11:57:10Z")

</div>

I agree that it can be slightly confusing to talk about when the APIs are not qualified as unsafe vs safe, though I think the RFC does a good job of making it clear when the safe variety is meant and when the unsafe one is. I do, however, like the idea of borrowing terminology from C++ rather than using the prefix `safe_` to distinguish it with the existing API. I don't think that that needs to be decided in this RFC, however.

---

<div class="post-metadata">

**Author:** ![jack](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jack/32/3724_2.png) [@jack](https://internals.rust-lang.org/u/jack)\
**Post date:** [August 26, 2020, 2:31pm UTC](https://internals.rust-lang.org/t/pre-rfc-safer-transmutation/12926/18 "2020-08-26T14:31:22Z")

</div>

> [@carbotaniuman](#):
>
> Is there a way for something like NonZeroU8 to be transmutable via ignoring validity?

Yes, this is precisely the sort of situation where the proposed `NeglectValidity` option is useful!

> [@carbotaniuman](#):
>
> Also how does this act in generic code? Will the fixed/fully completed constructibility check be dependent on which module the code is in? (Would transmuting a struct with a pub(crate) field inside that crate work?)

Yes, the full formulation of constructability is intrinsically tied to scope. So, whether you can transmute a struct with a `pub(crate)` field inside it would depend on where you attempt to do it.

The complete details of this full formulation are not totally fleshed out. It won't be as simple as \*assess constructability at the point where `TransmuteFrom` occurs. `TransmuteInto`, for instance, is just a blanket implementation over `TransmuteFrom`—but _no_ end-users types are constructible from the libcore! You really need to assess the _provenance_ of the `TransmuteFrom` bound.

I'm least confident about the feasibility of this, hence the [proposed initial simplification of constructability](https://github.com/jswrenn/project-safe-transmute/blob/rfc/rfcs/0000-safe-transmute.md#simplifying-constructability).

---

<div class="post-metadata">

**Author:** ![burntsushi](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/burntsushi/32/279_2.png) [@burntsushi](https://internals.rust-lang.org/u/burntsushi)\
**Post date:** [August 26, 2020, 2:53pm UTC](https://internals.rust-lang.org/t/pre-rfc-safer-transmutation/12926/19 "2020-08-26T14:53:15Z")

</div>

I don't have anything to add other than overwhelming positive feedback and appreciation for the work that has gone into this. Having this kind of functionality in the language and in std makes me downright giddy. It will be a dramatic improvement to many types of `unsafe` code, and will also open the doors to writing safe code that we can be sure is correct. Doing this in Rust today is of course possible, but there are so many invariants to check that I often avoid doing it because it isn't worth the _risk_. But this RFC appears to largely de-risk it, which I think will be a huge boon.

Thank you so much for putting together this RFC. 😃

---

<div class="post-metadata">

**Author:** ![carbotaniuman](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/carbotaniuman/32/6981_2.png) [@carbotaniuman](https://internals.rust-lang.org/u/carbotaniuman)\
**Post date:** [August 26, 2020, 3:02pm UTC](https://internals.rust-lang.org/t/pre-rfc-safer-transmutation/12926/20 "2020-08-26T15:02:55Z")

</div>

Is there a reason pub(crate) is being considered here, instead of just defining constructibility as having all bare pub files recursively and treating pub(crate) as private? Given this is purely for backwards compatibility, I agree that a complex definition might not be useful. (Crate authors wanting to use these impls can/should just use the PromiseTransmutable\* traits instead).

[Next page](https://internals.rust-lang.org/t/pre-rfc-safer-transmutation/12926.md?page=2)
