Skip to content

Commit 77aedb3

Browse files
committed
Permit shrinking transmutes in transmute machinery
Makes progress on #2701, #1940, #1852 gherrit-pr-id: Gd9d1c0de851091ffe6161889d21ca2167845a591
1 parent f0a5b8c commit 77aedb3

File tree

1 file changed

+32
-23
lines changed

1 file changed

+32
-23
lines changed

src/pointer/transmute.rs

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ use core::{
1313
};
1414

1515
use crate::{
16-
pointer::{cast, invariant::*},
1716
FromBytes, Immutable, IntoBytes, Unalign,
17+
pointer::{cast, invariant::*},
1818
};
1919

2020
/// Transmutations which are sound to attempt, conditional on validating the bit
@@ -46,15 +46,14 @@ use crate::{
4646
/// - So long as `dst` is active, no mutation of `dst`'s referent is allowed
4747
/// except via `dst` itself
4848
/// - The set of `DV`-valid referents of `dst` is a superset of the set of
49-
/// `SV`-valid referents of `src` (NOTE: this condition effectively bans
50-
/// shrinking or overwriting transmutes, which cannot satisfy this
51-
/// condition)
49+
/// (the prefixes of) `SV`-valid referents of `src`. The "prefix" caveat is
50+
/// necessary since this may be a shrinking transmute – ie, `dst` addresses
51+
/// a smaller referent than `src`.
5252
/// - Reverse transmutation: Either of the following hold:
5353
/// - `dst` does not permit mutation of its referent
54-
/// - The set of `DV`-valid referents of `dst` is a subset of the set of
55-
/// `SV`-valid referents of `src` (NOTE: this condition effectively bans
56-
/// shrinking or overwriting transmutes, which cannot satisfy this
57-
/// condition)
54+
/// - `<Dst as SizeEq<Src>>::CastFrom: CastExact`, and the set of `DV`-valid
55+
/// referents of `dst` is a subset of the set of `SV`-valid referents of
56+
/// `src`
5857
/// - No safe code, given access to `src` and `dst`, can cause undefined
5958
/// behavior: Any of the following hold:
6059
/// - `A` is `Exclusive`
@@ -94,18 +93,21 @@ use crate::{
9493
/// as an `SV`-valid `Src`. It is guaranteed to remain so, as either of the
9594
/// following hold:
9695
/// - `dst` does not permit mutation of its referent.
97-
/// - The set of `DV`-valid referents of `dst` is a subset of the set of
98-
/// `SV`-valid referents of `src`. Thus, any value written via `dst` is
99-
/// guaranteed to be an `SV`-valid referent of `src`.
96+
/// - `<Dst as SizeEq<Src>>::CastFrom: CastExact`, and the set of `DV`-valid
97+
/// referents of `dst` is a subset of the set of `SV`-valid referents of
98+
/// `src`. By `CastExact`, `src` and `dst` address the same number of bytes.
99+
/// Thus, any value written via `dst` is guaranteed to be an `SV`-valid
100+
/// referent of `src`.
100101
///
101102
/// Fourth, `dst`'s validity is satisfied. It is a given of this proof that the
102103
/// referent is `DV`-valid for `Dst`. It is guaranteed to remain so, as either
103104
/// of the following hold:
104105
/// - So long as `dst` is active, no mutation of the referent is allowed except
105106
/// via `dst` itself.
106107
/// - The set of `DV`-valid referents of `dst` is a superset of the set of
107-
/// `SV`-valid referents of `src`. Thus, any value written via `src` is
108-
/// guaranteed to be a `DV`-valid referent of `dst`.
108+
/// (the prefixes of) `SV`-valid referents of `src`. Thus, (the prefix of) any
109+
/// value written via `src` is guaranteed to be a `DV`-valid referent of
110+
/// `dst`.
109111
pub unsafe trait TryTransmuteFromPtr<Src: ?Sized, A: Aliasing, SV: Validity, DV: Validity, R>:
110112
SizeEq<Src>
111113
{
@@ -123,14 +125,14 @@ pub enum BecauseMutationCompatible {}
123125
// exists, no mutation is permitted except via that `Ptr`
124126
// - Aliasing is `Shared`, `Src: Immutable`, and `Dst: Immutable`, in which
125127
// case no mutation is possible via either `Ptr`
126-
// - Since the underlying cast is performed using `<Dst as SizeEq<Src>>
127-
// ::CastFrom::project`, `dst` addresses the same bytes as `src`. By `Dst:
128-
// TransmuteFrom<Src, SV, DV>`, the set of `DV`-valid referents of `dst` is a
129-
// supserset of the set of `SV`-valid referents of `src`.
128+
// - By `Dst: TransmuteFrom<Src, SV, DV>`, the set of `DV`-valid referents of
129+
// `dst` is a supserset of the set of (the prefixes of) `SV`-valid referents
130+
// of `src`.
130131
// - Reverse transmutation: Since the underlying cast is performed using `<Dst
131-
// as SizeEq<Src>>::CastFrom::project`, `dst` addresses the same bytes as
132-
// `src`. By `Src: TransmuteFrom<Dst, DV, SV>`, the set of `DV`-valid
133-
// referents of `dst` is a subset of the set of `SV`-valid referents of `src`.
132+
// as SizeEq<Src>>::CastFrom::project`, and since `Dst::CastFrom: CastExact`,
133+
// `dst` addresses the same bytes as `src`. By `Src: TransmuteFrom<Dst, DV,
134+
// SV>`, the set of `DV`-valid referents of `dst` is a subset of the set of
135+
// `SV`-valid referents of `src`.
134136
// - No safe code, given access to `src` and `dst`, can cause undefined
135137
// behavior: By `Dst: MutationCompatible<Src, A, SV, DV, _>`, at least one of
136138
// the following holds:
@@ -146,6 +148,7 @@ where
146148
DV: Validity,
147149
Src: TransmuteFrom<Dst, DV, SV> + ?Sized,
148150
Dst: MutationCompatible<Src, A, SV, DV, R> + SizeEq<Src> + ?Sized,
151+
Dst::CastFrom: cast::CastExact<Src, Dst>,
149152
{
150153
}
151154

@@ -267,6 +270,12 @@ where
267270
{
268271
}
269272

273+
// TODO: We need to update the invariant of `TransmuteFrom` in order to make the
274+
// "reverse transmutation" impl of `TryTransmuteFromPtr` sound – currently, it
275+
// says that `Dst: TransmuteFrom<Src>` guarantees transmutation *even in the
276+
// case of a shrinking transmute*, but that's not currently guaranteed by
277+
// `TransmuteFrom`'s safety invariant.
278+
270279
/// Denotes that any `SV`-valid `Src` may soundly be transmuted into a
271280
/// `DV`-valid `Self`.
272281
///
@@ -292,12 +301,12 @@ pub unsafe trait TransmuteFrom<Src: ?Sized, SV, DV> {}
292301
///
293302
/// `SizeEq` on its own conveys no safety guarantee. Any safety guarantees come
294303
/// from the safety invariants on the associated [`CastFrom`] type, specifically
295-
/// the [`CastExact`] bound.
304+
/// the [`Cast`] bound.
296305
///
297306
/// [`CastFrom`]: SizeEq::CastFrom
298-
/// [`CastExact`]: cast::CastExact
307+
/// [`Cast`]: cast::Cast
299308
pub trait SizeEq<Src: ?Sized> {
300-
type CastFrom: cast::CastExact<Src, Self>;
309+
type CastFrom: cast::Cast<Src, Self>;
301310
}
302311

303312
impl<T: ?Sized> SizeEq<T> for T {

0 commit comments

Comments
 (0)