-
Notifications
You must be signed in to change notification settings - Fork 69
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Lang Item for Transmutability #411
Comments
This issue is not meant to be used for technical discussion. There is a Zulip stream for that. Use this issue to leave procedural comments, such as volunteering to review, indicating that you second the proposal (or third, etc), or raising a concern that you would like to be addressed. cc @rust-lang/compiler @rust-lang/compiler-contributors |
@rustbot second I would like to see this implemented experimentally so we can get some feedback on the proposed APIs and drive the safe transmute project forward. |
This initial implementation handles transmutations between primitive types and some structs. See: rust-lang/compiler-team#411
This initial implementation handles transmutations between primitive types and some structs, enums and unions. See: rust-lang/compiler-team#411
Initial implementation of transmutability trait. *T'was the night before Christmas and all through the codebase, not a miri was stirring — no hint of `unsafe`!* This PR provides an initial, **incomplete** implementation of *[MCP 411: Lang Item for Transmutability](rust-lang/compiler-team#411. The `core::mem::BikeshedIntrinsicFrom` trait provided by this PR is implemented on-the-fly by the compiler for types `Src` and `Dst` when the bits of all possible values of type `Src` are safely reinterpretable as a value of type `Dst`. What this PR provides is: - [x] [support for transmutations involving primitives](https://github.com/jswrenn/rust/tree/transmute/src/test/ui/transmutability/primitives) - [x] [support for transmutations involving arrays](https://github.com/jswrenn/rust/tree/transmute/src/test/ui/transmutability/arrays) - [x] [support for transmutations involving structs](https://github.com/jswrenn/rust/tree/transmute/src/test/ui/transmutability/structs) - [x] [support for transmutations involving enums](https://github.com/jswrenn/rust/tree/transmute/src/test/ui/transmutability/enums) - [x] [support for transmutations involving unions](https://github.com/jswrenn/rust/tree/transmute/src/test/ui/transmutability/unions) - [x] [support for weaker validity checks](https://github.com/jswrenn/rust/blob/transmute/src/test/ui/transmutability/unions/should_permit_intersecting_if_validity_is_assumed.rs) (i.e., `Assume::VALIDITY`) - [x] visibility checking What isn't yet implemented: - [ ] transmutability options passed using the `Assume` struct - [ ] [support for references](https://github.com/jswrenn/rust/blob/transmute/src/test/ui/transmutability/references.rs) - [ ] smarter error messages These features will be implemented in future PRs.
Initial implementation of transmutability trait. *T'was the night before Christmas and all through the codebase, not a miri was stirring — no hint of `unsafe`!* This PR provides an initial, **incomplete** implementation of *[MCP 411: Lang Item for Transmutability](rust-lang/compiler-team#411. The `core::mem::BikeshedIntrinsicFrom` trait provided by this PR is implemented on-the-fly by the compiler for types `Src` and `Dst` when the bits of all possible values of type `Src` are safely reinterpretable as a value of type `Dst`. What this PR provides is: - [x] [support for transmutations involving primitives](https://github.com/jswrenn/rust/tree/transmute/src/test/ui/transmutability/primitives) - [x] [support for transmutations involving arrays](https://github.com/jswrenn/rust/tree/transmute/src/test/ui/transmutability/arrays) - [x] [support for transmutations involving structs](https://github.com/jswrenn/rust/tree/transmute/src/test/ui/transmutability/structs) - [x] [support for transmutations involving enums](https://github.com/jswrenn/rust/tree/transmute/src/test/ui/transmutability/enums) - [x] [support for transmutations involving unions](https://github.com/jswrenn/rust/tree/transmute/src/test/ui/transmutability/unions) - [x] [support for weaker validity checks](https://github.com/jswrenn/rust/blob/transmute/src/test/ui/transmutability/unions/should_permit_intersecting_if_validity_is_assumed.rs) (i.e., `Assume::VALIDITY`) - [x] visibility checking What isn't yet implemented: - [ ] transmutability options passed using the `Assume` struct - [ ] [support for references](https://github.com/jswrenn/rust/blob/transmute/src/test/ui/transmutability/references.rs) - [ ] smarter error messages These features will be implemented in future PRs.
This was left as a TODO in rust-lang#92268, and brings the trait more in line with what was defined in MCP411. `Assume::visibility` has been renamed to `Assume::safety`, as library safety is what's actually being assumed; visibility is just the mechanism by which it is currently checked (this may change). ref: rust-lang/compiler-team#411 ref: rust-lang#99571
safe transmute: use `Assume` struct to provide analysis options This task was left as a TODO in rust-lang#92268; resolving it brings [`BikeshedIntrinsicFrom`](https://doc.rust-lang.org/nightly/core/mem/trait.BikeshedIntrinsicFrom.html) more in line with the API defined in [MCP411](rust-lang/compiler-team#411). **Before:** ```rust pub unsafe trait BikeshedIntrinsicFrom< Src, Context, const ASSUME_ALIGNMENT: bool, const ASSUME_LIFETIMES: bool, const ASSUME_VALIDITY: bool, const ASSUME_VISIBILITY: bool, > where Src: ?Sized, {} ``` **After:** ```rust pub unsafe trait BikeshedIntrinsicFrom<Src, Context, const ASSUME: Assume = { Assume::NOTHING }> where Src: ?Sized, {} ``` `Assume::visibility` has also been renamed to `Assume::safety`, as library safety invariants are what's actually being assumed; visibility is just the mechanism by which it is currently checked (and that may change). r? `@oli-obk` --- Related: - rust-lang/compiler-team#411 - rust-lang#99571
safe transmute: use `Assume` struct to provide analysis options This task was left as a TODO in rust-lang#92268; resolving it brings [`BikeshedIntrinsicFrom`](https://doc.rust-lang.org/nightly/core/mem/trait.BikeshedIntrinsicFrom.html) more in line with the API defined in [MCP411](rust-lang/compiler-team#411). **Before:** ```rust pub unsafe trait BikeshedIntrinsicFrom< Src, Context, const ASSUME_ALIGNMENT: bool, const ASSUME_LIFETIMES: bool, const ASSUME_VALIDITY: bool, const ASSUME_VISIBILITY: bool, > where Src: ?Sized, {} ``` **After:** ```rust pub unsafe trait BikeshedIntrinsicFrom<Src, Context, const ASSUME: Assume = { Assume::NOTHING }> where Src: ?Sized, {} ``` `Assume::visibility` has also been renamed to `Assume::safety`, as library safety invariants are what's actually being assumed; visibility is just the mechanism by which it is currently checked (and that may change). r? `@oli-obk` --- Related: - rust-lang/compiler-team#411 - rust-lang#99571
Initial implementation of transmutability trait. *T'was the night before Christmas and all through the codebase, not a miri was stirring — no hint of `unsafe`!* This PR provides an initial, **incomplete** implementation of *[MCP 411: Lang Item for Transmutability](rust-lang/compiler-team#411. The `core::mem::BikeshedIntrinsicFrom` trait provided by this PR is implemented on-the-fly by the compiler for types `Src` and `Dst` when the bits of all possible values of type `Src` are safely reinterpretable as a value of type `Dst`. What this PR provides is: - [x] [support for transmutations involving primitives](https://github.com/jswrenn/rust/tree/transmute/src/test/ui/transmutability/primitives) - [x] [support for transmutations involving arrays](https://github.com/jswrenn/rust/tree/transmute/src/test/ui/transmutability/arrays) - [x] [support for transmutations involving structs](https://github.com/jswrenn/rust/tree/transmute/src/test/ui/transmutability/structs) - [x] [support for transmutations involving enums](https://github.com/jswrenn/rust/tree/transmute/src/test/ui/transmutability/enums) - [x] [support for transmutations involving unions](https://github.com/jswrenn/rust/tree/transmute/src/test/ui/transmutability/unions) - [x] [support for weaker validity checks](https://github.com/jswrenn/rust/blob/transmute/src/test/ui/transmutability/unions/should_permit_intersecting_if_validity_is_assumed.rs) (i.e., `Assume::VALIDITY`) - [x] visibility checking What isn't yet implemented: - [ ] transmutability options passed using the `Assume` struct - [ ] [support for references](https://github.com/jswrenn/rust/blob/transmute/src/test/ui/transmutability/references.rs) - [ ] smarter error messages These features will be implemented in future PRs.
This was left as a TODO in #92268, and brings the trait more in line with what was defined in MCP411. `Assume::visibility` has been renamed to `Assume::safety`, as library safety is what's actually being assumed; visibility is just the mechanism by which it is currently checked (this may change). ref: rust-lang/compiler-team#411 ref: rust-lang/rust#99571
safe transmute: use `Assume` struct to provide analysis options This task was left as a TODO in #92268; resolving it brings [`BikeshedIntrinsicFrom`](https://doc.rust-lang.org/nightly/core/mem/trait.BikeshedIntrinsicFrom.html) more in line with the API defined in [MCP411](rust-lang/compiler-team#411). **Before:** ```rust pub unsafe trait BikeshedIntrinsicFrom< Src, Context, const ASSUME_ALIGNMENT: bool, const ASSUME_LIFETIMES: bool, const ASSUME_VALIDITY: bool, const ASSUME_VISIBILITY: bool, > where Src: ?Sized, {} ``` **After:** ```rust pub unsafe trait BikeshedIntrinsicFrom<Src, Context, const ASSUME: Assume = { Assume::NOTHING }> where Src: ?Sized, {} ``` `Assume::visibility` has also been renamed to `Assume::safety`, as library safety invariants are what's actually being assumed; visibility is just the mechanism by which it is currently checked (and that may change). r? `@oli-obk` --- Related: - rust-lang/compiler-team#411 - rust-lang/rust#99571
Initial implementation of transmutability trait. *T'was the night before Christmas and all through the codebase, not a miri was stirring — no hint of `unsafe`!* This PR provides an initial, **incomplete** implementation of *[MCP 411: Lang Item for Transmutability](rust-lang/compiler-team#411. The `core::mem::BikeshedIntrinsicFrom` trait provided by this PR is implemented on-the-fly by the compiler for types `Src` and `Dst` when the bits of all possible values of type `Src` are safely reinterpretable as a value of type `Dst`. What this PR provides is: - [x] [support for transmutations involving primitives](https://github.com/jswrenn/rust/tree/transmute/src/test/ui/transmutability/primitives) - [x] [support for transmutations involving arrays](https://github.com/jswrenn/rust/tree/transmute/src/test/ui/transmutability/arrays) - [x] [support for transmutations involving structs](https://github.com/jswrenn/rust/tree/transmute/src/test/ui/transmutability/structs) - [x] [support for transmutations involving enums](https://github.com/jswrenn/rust/tree/transmute/src/test/ui/transmutability/enums) - [x] [support for transmutations involving unions](https://github.com/jswrenn/rust/tree/transmute/src/test/ui/transmutability/unions) - [x] [support for weaker validity checks](https://github.com/jswrenn/rust/blob/transmute/src/test/ui/transmutability/unions/should_permit_intersecting_if_validity_is_assumed.rs) (i.e., `Assume::VALIDITY`) - [x] visibility checking What isn't yet implemented: - [ ] transmutability options passed using the `Assume` struct - [ ] [support for references](https://github.com/jswrenn/rust/blob/transmute/src/test/ui/transmutability/references.rs) - [ ] smarter error messages These features will be implemented in future PRs.
safe transmute: use `Assume` struct to provide analysis options This task was left as a TODO in #92268; resolving it brings [`BikeshedIntrinsicFrom`](https://doc.rust-lang.org/nightly/core/mem/trait.BikeshedIntrinsicFrom.html) more in line with the API defined in [MCP411](rust-lang/compiler-team#411). **Before:** ```rust pub unsafe trait BikeshedIntrinsicFrom< Src, Context, const ASSUME_ALIGNMENT: bool, const ASSUME_LIFETIMES: bool, const ASSUME_VALIDITY: bool, const ASSUME_VISIBILITY: bool, > where Src: ?Sized, {} ``` **After:** ```rust pub unsafe trait BikeshedIntrinsicFrom<Src, Context, const ASSUME: Assume = { Assume::NOTHING }> where Src: ?Sized, {} ``` `Assume::visibility` has also been renamed to `Assume::safety`, as library safety invariants are what's actually being assumed; visibility is just the mechanism by which it is currently checked (and that may change). r? `@oli-obk` --- Related: - rust-lang/compiler-team#411 - rust-lang/rust#99571
Initial implementation of transmutability trait. *T'was the night before Christmas and all through the codebase, not a miri was stirring — no hint of `unsafe`!* This PR provides an initial, **incomplete** implementation of *[MCP 411: Lang Item for Transmutability](rust-lang/compiler-team#411. The `core::mem::BikeshedIntrinsicFrom` trait provided by this PR is implemented on-the-fly by the compiler for types `Src` and `Dst` when the bits of all possible values of type `Src` are safely reinterpretable as a value of type `Dst`. What this PR provides is: - [x] [support for transmutations involving primitives](https://github.com/jswrenn/rust/tree/transmute/src/test/ui/transmutability/primitives) - [x] [support for transmutations involving arrays](https://github.com/jswrenn/rust/tree/transmute/src/test/ui/transmutability/arrays) - [x] [support for transmutations involving structs](https://github.com/jswrenn/rust/tree/transmute/src/test/ui/transmutability/structs) - [x] [support for transmutations involving enums](https://github.com/jswrenn/rust/tree/transmute/src/test/ui/transmutability/enums) - [x] [support for transmutations involving unions](https://github.com/jswrenn/rust/tree/transmute/src/test/ui/transmutability/unions) - [x] [support for weaker validity checks](https://github.com/jswrenn/rust/blob/transmute/src/test/ui/transmutability/unions/should_permit_intersecting_if_validity_is_assumed.rs) (i.e., `Assume::VALIDITY`) - [x] visibility checking What isn't yet implemented: - [ ] transmutability options passed using the `Assume` struct - [ ] [support for references](https://github.com/jswrenn/rust/blob/transmute/src/test/ui/transmutability/references.rs) - [ ] smarter error messages These features will be implemented in future PRs.
safe transmute: use `Assume` struct to provide analysis options This task was left as a TODO in #92268; resolving it brings [`BikeshedIntrinsicFrom`](https://doc.rust-lang.org/nightly/core/mem/trait.BikeshedIntrinsicFrom.html) more in line with the API defined in [MCP411](rust-lang/compiler-team#411). **Before:** ```rust pub unsafe trait BikeshedIntrinsicFrom< Src, Context, const ASSUME_ALIGNMENT: bool, const ASSUME_LIFETIMES: bool, const ASSUME_VALIDITY: bool, const ASSUME_VISIBILITY: bool, > where Src: ?Sized, {} ``` **After:** ```rust pub unsafe trait BikeshedIntrinsicFrom<Src, Context, const ASSUME: Assume = { Assume::NOTHING }> where Src: ?Sized, {} ``` `Assume::visibility` has also been renamed to `Assume::safety`, as library safety invariants are what's actually being assumed; visibility is just the mechanism by which it is currently checked (and that may change). r? `@oli-obk` --- Related: - rust-lang/compiler-team#411 - rust-lang/rust#99571
This MCP is a recommendation of the Safe Transmute Working Group. It provides a minimum, compiler-supported API surface that is capable of supporting the breadth of use-cases that involve auditing and abstracting over transmutability. This API will provide a tangible foundation for experimentation.
Proposal
Add a compiler-implemented trait to
core::mem
for checking the soundness of bit-reinterpretation casts (e.g.,mem::transmute
,union
, pointer casting):The remainder of this MCP provides supporting documentation for this design:
Assume
?Context
?Context
ensure safety?When is a bit-reinterpretation cast sound?
A bit-reinterpretation cast (henceforth: "transmutation") is sound if it is both well-defined and safe.
A transmutation is well-defined if any possible values of type
Src
are a valid instance ofDst
. The compiler determines this by inspecting the layouts ofSrc
andDst
.In order to be safe, any safe use of the transmutation result cannot cause memory unsafety. Namely, a transmutation is generally unsafe if it allows you to:
Dst
typeSrc
typeDst
typeWhether these conditions are satisfied depends on the scope the transmutation occurs in. The existing mechanism of type privacy will ensure that first condition is satisfied. To enforce the second and third conditions, we introduce the
Context
type parameter (see below).What is
Assume
?The
Assume
parameter encodes the set of properties that the compiler should assume (rather than check) when determining transmutability. These checks include:The ability to omit particular static checks makes
BikeshedIntrinsicFrom
useful in scenarios where aspects of well-definedness and safety are ensured through other means (e.g., domain knowledge or runtime checks).What is
Context
?The
Context
parameter ofBikeshedIntrinsicFrom
is used to ensure that the second and third safety conditions are satisfied.When visibility is enforced,
Context
must be instantiated with any private (i.e.,pub(self)
type. The compiler pretends that it is at the defining scope of that type, and checks that the necessary fields ofSrc
andDst
are visible/constructible. Specifically:Dst
must be fully implicitly constructible (i.e., can be instantiated only using the implicit constructors of the involved types, without resorting to user-defined constructors)Dst
is&mut
, the fields of&mut Src
which could be mutated post-transmutation must be visibleWhen visibility is assumed, the
Context
parameter is ignored.Why is safety dependent on context?
In order to be safe, a well-defined transmutation must also not allow you to:
Dst
typeSrc
typeDst
typeWhether these conditions are satisfied depends on the context of the transmutation, because scope determines the visibility of fields. Consider:
The function
b::new
is unsound, because it constructs an instance of a type without a public constructor.How does
Context
ensure safety?It's generally unsound to construct instances of types for which you do not have a constructor. If
BikeshedIntrinsicFrom
lacked aContext
parameter; e.g.,:...we could not use it to check the soundness of the transmutations in this example:
In module
a
,NoPublicConstructor
must implementBikeshedIntrinsicFrom<u32>
. In moduleb
, it must not. This inconsistency is incompatible with Rust's trait system.Solution
We resolve this inconsistency by introducing a type parameter,
Context
, that allows Rust to distinguish between these two contexts:Context
must be instantiated with any private (i.e.,pub(self)
type. To determine whether a transmutation is safe, the compiler pretends that it is at the defining scope of that type, and checks that the necessary fields ofSrc
andDst
are visible.For example:
In module
a
,NoPublicConstructor
implementsBikeshedIntrinsicFrom<u32, A>
. In moduleb
,NoPublicConstructor
does not implementBikeshedIntrinsicFrom<u32, B>
. There is no inconsistency.Can't Context be elided?
Not generally. Consider a hypothetical
FromZeros
trait that indicates whetherSelf
is safely initializable from a sufficiently large buffer of zero-initialized bytes:The above definition leaves ambiguous (
???
) the context in which the constructability ofDst
is checked: is it from the perspective of where this trait is defined, or where this trait is used? In this example, you probably do not intend for this trait to only be usable withDst
types that are defined in the same scope as theFromZeros
trait!An explicit
Context
parameter onFromZeros
makes this unambiguous; the transmutability ofDst
should be assessed from where the trait is used, not where it is defined:External Documents and Discussion
This proposal:
Prior proposal:
Mentors or Reviewers
@jackh726 and @wesleywiser have volunteered to do reviews.
Process
The main points of the Major Change Process is as follows:
@rustbot second
.-C flag
, then full team check-off is required.@rfcbot fcp merge
on either the MCP or the PR.You can read more about Major Change Proposals on forge.
Comments
This issue is not meant to be used for technical discussion. There is a Zulip stream for that. Use this issue to leave procedural comments, such as volunteering to review, indicating that you second the proposal (or third, etc), or raising a concern that you would like to be addressed.
The text was updated successfully, but these errors were encountered: