Skip to content
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

Enforce Src: FromBytes in try_transmute_mut! #2229

Open
wants to merge 1 commit into
base: v0.8.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 3 additions & 8 deletions src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -577,7 +577,7 @@ macro_rules! try_transmute_ref {
/// ```ignore
/// fn try_transmute_mut<Src, Dst>(src: &mut Src) -> Result<&mut Dst, ValidityError<&mut Src, Dst>>
/// where
/// Src: IntoBytes,
/// Src: FromByte + IntoBytes,
/// Dst: TryFromBytes,
/// size_of::<Src>() == size_of::<Dst>(),
/// align_of::<Src>() >= align_of::<Dst>(),
Expand Down Expand Up @@ -888,11 +888,6 @@ mod tests {
#[test]
fn test_try_transmute_mut() {
// Test that memory is transmuted with `try_transmute_mut` as expected.
let array_of_bools = &mut [false, true, false, true, false, true, false, true];
let array_of_arrays = &mut [[0u8, 1], [0, 1], [0, 1], [0, 1]];
let x: Result<&mut [[u8; 2]; 4], _> = try_transmute_mut!(array_of_bools);
assert_eq!(x, Ok(array_of_arrays));

let array_of_bools = &mut [false, true, false, true, false, true, false, true];
let array_of_arrays = &mut [[0u8, 1], [0, 1], [0, 1], [0, 1]];
let x: Result<&mut [bool; 8], _> = try_transmute_mut!(array_of_arrays);
Expand All @@ -903,8 +898,8 @@ mod tests {
let array_of_bools = &mut [false, true, false, true, false, true, false, true];
let array_of_arrays = &mut [[0u8, 1], [0, 1], [0, 1], [0, 1]];
{
let x: Result<&mut [[u8; 2]; 4], _> = try_transmute_mut!(array_of_bools);
assert_eq!(x, Ok(array_of_arrays));
let x: Result<&mut [bool; 8], _> = try_transmute_mut!(array_of_arrays);
assert_eq!(x, Ok(array_of_bools));
}

// Test that `try_transmute_mut!` supports decreasing alignment.
Expand Down
4 changes: 2 additions & 2 deletions src/util/macro_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use crate::{
invariant::{self, AtLeast, Invariants},
AliasingSafe, AliasingSafeReason, BecauseExclusive, BecauseImmutable,
},
Immutable, IntoBytes, Ptr, TryFromBytes, Unalign, ValidityError,
FromBytes, Immutable, IntoBytes, Ptr, TryFromBytes, Unalign, ValidityError,
};

/// Projects the type of the field at `Index` in `Self`.
Expand Down Expand Up @@ -675,7 +675,7 @@ where
#[inline(always)]
pub fn try_transmute_mut<Src, Dst>(src: &mut Src) -> Result<&mut Dst, ValidityError<&mut Src, Dst>>
where
Src: IntoBytes,
Src: FromBytes + IntoBytes,
Dst: TryFromBytes,
{
match try_cast_or_pme::<Src, Dst, _, BecauseExclusive>(Ptr::from_mut(src)) {
Expand Down
1 change: 1 addition & 0 deletions tests/ui-msrv/try_transmute_mut-src-not-frombytes.rs
51 changes: 51 additions & 0 deletions tests/ui-msrv/try_transmute_mut-src-not-frombytes.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
error[E0277]: the trait bound `Src: FromBytes` is not satisfied
--> tests/ui-msrv/try_transmute_mut-src-not-frombytes.rs:23:40
|
23 | let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src);
| ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromBytes` is not implemented for `Src`
|
note: required by `AssertSrcIsFromBytes`
--> tests/ui-msrv/try_transmute_mut-src-not-frombytes.rs:23:40
|
23 | let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src);
| ^^^^^^^^^^^^^^^^^^^^^^^^
= note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `Src: FromBytes` is not satisfied
--> tests/ui-msrv/try_transmute_mut-src-not-frombytes.rs:23:40
|
23 | let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src);
| ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromBytes` is not implemented for `Src`
|
note: required by a bound in `AssertSrcIsFromBytes`
--> tests/ui-msrv/try_transmute_mut-src-not-frombytes.rs:23:40
|
23 | let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src);
| ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsFromBytes`
= note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `Dst: FromBytes` is not satisfied
--> tests/ui-msrv/try_transmute_mut-src-not-frombytes.rs:23:40
|
23 | let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src);
| ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromBytes` is not implemented for `Dst`
|
note: required by `AssertDstIsFromBytes`
--> tests/ui-msrv/try_transmute_mut-src-not-frombytes.rs:23:40
|
23 | let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src);
| ^^^^^^^^^^^^^^^^^^^^^^^^
= note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `Dst: IntoBytes` is not satisfied
--> tests/ui-msrv/try_transmute_mut-src-not-frombytes.rs:23:40
|
23 | let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src);
| ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `IntoBytes` is not implemented for `Dst`
|
note: required by `AssertDstIsIntoBytes`
--> tests/ui-msrv/try_transmute_mut-src-not-frombytes.rs:23:40
|
23 | let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src);
| ^^^^^^^^^^^^^^^^^^^^^^^^
= note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
57 changes: 48 additions & 9 deletions tests/ui-msrv/try_transmute_mut-src-not-intobytes.stderr
Original file line number Diff line number Diff line change
@@ -1,12 +1,51 @@
error[E0277]: the trait bound `NotZerocopy<AU16>: zerocopy::IntoBytes` is not satisfied
--> tests/ui-msrv/try_transmute_mut-src-not-intobytes.rs:19:52
error[E0277]: the trait bound `Src: IntoBytes` is not satisfied
--> tests/ui-msrv/try_transmute_mut-src-not-intobytes.rs:23:40
|
19 | let src_not_into_bytes: Result<&mut AU16, _> = try_transmute_mut!(src);
| ^^^^^^^^^^^^^^^^^^^^^^^ the trait `zerocopy::IntoBytes` is not implemented for `NotZerocopy<AU16>`
23 | let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src);
| ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `IntoBytes` is not implemented for `Src`
|
note: required by a bound in `try_transmute_mut`
--> src/util/macro_util.rs
note: required by `AssertSrcIsIntoBytes`
--> tests/ui-msrv/try_transmute_mut-src-not-intobytes.rs:23:40
|
| Src: IntoBytes,
| ^^^^^^^^^ required by this bound in `try_transmute_mut`
= note: this error originates in the macro `try_transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
23 | let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src);
| ^^^^^^^^^^^^^^^^^^^^^^^^
= note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `Src: IntoBytes` is not satisfied
--> tests/ui-msrv/try_transmute_mut-src-not-intobytes.rs:23:40
|
23 | let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src);
| ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `IntoBytes` is not implemented for `Src`
|
note: required by a bound in `AssertSrcIsIntoBytes`
--> tests/ui-msrv/try_transmute_mut-src-not-intobytes.rs:23:40
|
23 | let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src);
| ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsIntoBytes`
= note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `Dst: FromBytes` is not satisfied
--> tests/ui-msrv/try_transmute_mut-src-not-intobytes.rs:23:40
|
23 | let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src);
| ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromBytes` is not implemented for `Dst`
|
note: required by `AssertDstIsFromBytes`
--> tests/ui-msrv/try_transmute_mut-src-not-intobytes.rs:23:40
|
23 | let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src);
| ^^^^^^^^^^^^^^^^^^^^^^^^
= note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `Dst: IntoBytes` is not satisfied
--> tests/ui-msrv/try_transmute_mut-src-not-intobytes.rs:23:40
|
23 | let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src);
| ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `IntoBytes` is not implemented for `Dst`
|
note: required by `AssertDstIsIntoBytes`
--> tests/ui-msrv/try_transmute_mut-src-not-intobytes.rs:23:40
|
23 | let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src);
| ^^^^^^^^^^^^^^^^^^^^^^^^
= note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
24 changes: 24 additions & 0 deletions tests/ui-nightly/try_transmute_mut-src-not-frombytes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright 2024 The Fuchsia Authors
//
// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
// This file may not be copied, modified, or distributed except according to
// those terms.

extern crate zerocopy;

use zerocopy::transmute_mut;

#[derive(zerocopy::IntoBytes)]
#[repr(C)]
struct Src;

#[derive(zerocopy::TryFromBytes)]
#[repr(C)]
struct Dst;

fn main() {
// `try_transmute_mut` requires that the source type implements `FromBytes`
let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src);
}
104 changes: 104 additions & 0 deletions tests/ui-nightly/try_transmute_mut-src-not-frombytes.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
error[E0277]: the trait bound `Src: FromBytes` is not satisfied
--> tests/ui-nightly/try_transmute_mut-src-not-frombytes.rs:23:40
|
23 | let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src);
| ^^^^^^^^^^^^^^^^^^^^^^^^
| |
| the trait `FromBytes` is not implemented for `Src`
| required by a bound introduced by this call
|
= note: Consider adding `#[derive(FromBytes)]` to `Src`
= help: the following other types implement trait `FromBytes`:
()
AtomicI16
AtomicI32
AtomicI64
AtomicI8
AtomicIsize
AtomicU16
AtomicU32
and $N others
note: required by a bound in `AssertSrcIsFromBytes`
--> tests/ui-nightly/try_transmute_mut-src-not-frombytes.rs:23:40
|
23 | let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src);
| ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsFromBytes`
= note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `Src: FromBytes` is not satisfied
--> tests/ui-nightly/try_transmute_mut-src-not-frombytes.rs:23:40
|
23 | let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src);
| ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromBytes` is not implemented for `Src`
|
= note: Consider adding `#[derive(FromBytes)]` to `Src`
= help: the following other types implement trait `FromBytes`:
()
AtomicI16
AtomicI32
AtomicI64
AtomicI8
AtomicIsize
AtomicU16
AtomicU32
and $N others
note: required by a bound in `AssertSrcIsFromBytes`
--> tests/ui-nightly/try_transmute_mut-src-not-frombytes.rs:23:40
|
23 | let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src);
| ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertSrcIsFromBytes`
= note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `Dst: FromBytes` is not satisfied
--> tests/ui-nightly/try_transmute_mut-src-not-frombytes.rs:23:40
|
23 | let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src);
| ^^^^^^^^^^^^^^^^^^^^^^^^
| |
| the trait `FromBytes` is not implemented for `Dst`
| required by a bound introduced by this call
|
= note: Consider adding `#[derive(FromBytes)]` to `Dst`
= help: the following other types implement trait `FromBytes`:
()
AtomicI16
AtomicI32
AtomicI64
AtomicI8
AtomicIsize
AtomicU16
AtomicU32
and $N others
note: required by a bound in `AssertDstIsFromBytes`
--> tests/ui-nightly/try_transmute_mut-src-not-frombytes.rs:23:40
|
23 | let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src);
| ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertDstIsFromBytes`
= note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `Dst: IntoBytes` is not satisfied
--> tests/ui-nightly/try_transmute_mut-src-not-frombytes.rs:23:40
|
23 | let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src);
| ^^^^^^^^^^^^^^^^^^^^^^^^
| |
| the trait `IntoBytes` is not implemented for `Dst`
| required by a bound introduced by this call
|
= note: Consider adding `#[derive(IntoBytes)]` to `Dst`
= help: the following other types implement trait `IntoBytes`:
()
AtomicBool
AtomicI16
AtomicI32
AtomicI64
AtomicI8
AtomicIsize
AtomicU16
and $N others
note: required by a bound in `AssertDstIsIntoBytes`
--> tests/ui-nightly/try_transmute_mut-src-not-frombytes.rs:23:40
|
23 | let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src);
| ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertDstIsIntoBytes`
= note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
16 changes: 10 additions & 6 deletions tests/ui-nightly/try_transmute_mut-src-not-intobytes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,19 @@
// This file may not be copied, modified, or distributed except according to
// those terms.

include!("../../zerocopy-derive/tests/include.rs");

extern crate zerocopy;

use util::{NotZerocopy, AU16};
use zerocopy::try_transmute_mut;
use zerocopy::transmute_mut;

#[derive(zerocopy::FromBytes)]
#[repr(C)]
struct Src;

#[derive(zerocopy::TryFromBytes)]
#[repr(C)]
struct Dst;

fn main() {
// `try_transmute_mut` requires that the source type implements `IntoBytes`
let src = &mut NotZerocopy(AU16(0));
let src_not_into_bytes: Result<&mut AU16, _> = try_transmute_mut!(src);
let src_not_from_bytes: &mut Dst = transmute_mut!(&mut Src);
}
Loading
Loading