Skip to content

Commit

Permalink
Lower MSRV to 1.60
Browse files Browse the repository at this point in the history
Modify the way that certain memory safety properties are validated in
our `transmute!`, `transmute_ref!`, and `transmute_mut!` macros to allow
that code to compile on 1.60.

Makes progress on #554
  • Loading branch information
joshlf committed Oct 27, 2023
1 parent f47b4df commit c8a55d6
Show file tree
Hide file tree
Showing 74 changed files with 1,546 additions and 313 deletions.
12 changes: 6 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@
[workspace]

[package]
edition = "2021"
edition = "2018"
name = "zerocopy"
version = "0.7.18"
version = "0.7.19"
authors = ["Joshua Liebow-Feeser <[email protected]>"]
description = "Utilities for zero-copy parsing and serialization"
license = "BSD-2-Clause OR Apache-2.0 OR MIT"
repository = "https://github.com/google/zerocopy"
rust-version = "1.61.0"
rust-version = "1.60.0"

exclude = [".*"]

Expand All @@ -45,7 +45,7 @@ simd-nightly = ["simd"]
__internal_use_only_features_that_work_on_stable = ["alloc", "derive", "simd"]

[dependencies]
zerocopy-derive = { version = "=0.7.18", path = "zerocopy-derive", optional = true }
zerocopy-derive = { version = "=0.7.19", path = "zerocopy-derive", optional = true }

[dependencies.byteorder]
version = "1.3"
Expand All @@ -56,7 +56,7 @@ optional = true
# zerocopy-derive remain equal, even if the 'derive' feature isn't used.
# See: https://github.com/matklad/macro-dep-test
[target.'cfg(any())'.dependencies]
zerocopy-derive = { version = "=0.7.18", path = "zerocopy-derive" }
zerocopy-derive = { version = "=0.7.19", path = "zerocopy-derive" }

[dev-dependencies]
assert_matches = "1.5"
Expand All @@ -71,4 +71,4 @@ testutil = { path = "testutil" }
# CI test failures.
trybuild = { version = "=1.0.85", features = ["diff"] }
# In tests, unlike in production, zerocopy-derive is not optional
zerocopy-derive = { version = "=0.7.18", path = "zerocopy-derive" }
zerocopy-derive = { version = "=0.7.19", path = "zerocopy-derive" }
70 changes: 56 additions & 14 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2007,10 +2007,14 @@ macro_rules! transmute {
// This branch, though never taken, ensures that the type of `e` is
// `AsBytes` and that the type of this macro invocation expression
// is `FromBytes`.
const fn transmute<T: $crate::AsBytes, U: $crate::FromBytes>(_t: T) -> U {
loop {}
}
transmute(e)

struct AssertIsAsBytes<T: $crate::AsBytes>(T);
let _ = AssertIsAsBytes(e);

struct AssertIsFromBytes<U: $crate::FromBytes>(U);
#[allow(unused, unreachable_code)]
let u = AssertIsFromBytes(loop {});
u.0
} else {
// SAFETY: `core::mem::transmute` ensures that the type of `e` and
// the type of this macro invocation expression have the same size.
Expand Down Expand Up @@ -2092,7 +2096,18 @@ macro_rules! transmute_ref {
// `&T` where `T: 't + Sized + AsBytes`, that the type of this macro
// expression is `&U` where `U: 'u + Sized + FromBytes`, and that
// `'t` outlives `'u`.
const fn transmute<'u, 't: 'u, T: 't + Sized + $crate::AsBytes, U: 'u + Sized + $crate::FromBytes>(_t: &'t T) -> &'u U {

struct AssertIsAsBytes<'a, T: ::core::marker::Sized + $crate::AsBytes>(&'a T);
let _ = AssertIsAsBytes(e);

struct AssertIsFromBytes<'a, U: ::core::marker::Sized + $crate::FromBytes>(&'a U);
#[allow(unused, unreachable_code)]
let u = AssertIsFromBytes(loop {});
u.0
} else if false {
// This branch, though never taken, ensures that the source lifetime
// is not shorter than the destination lifetime.
const fn transmute<'u, 't: 'u, T: 't, U: 'u>(t: &'t T) -> &'u U {
loop {}
}
transmute(e)
Expand Down Expand Up @@ -2191,19 +2206,46 @@ macro_rules! transmute_mut {
// because there's no way, in a generic context, to enforce that two
// types have the same size or alignment.

let e = $e;
// Ensure that the source type is a mutable reference.
let e = &mut *$e;

#[allow(unused, clippy::diverging_sub_expression)]
if false {
// This branch, though never taken, ensures that the type of `e` is
// `&mut T` where `T: 't + Sized + AsBytes + FromBytes`, that the
// `&mut T` where `T: 't + Sized + FromBytes + AsBytes`, that the
// type of this macro expression is `&mut U` where `U: 'u + Sized +
// AsBytes + FromBytes`.
fn transmute<'t, T, U>(_t: &'t mut T) -> &'t mut U
where
T: 't + Sized + $crate::AsBytes + $crate::FromBytes,
U: 't + Sized + $crate::AsBytes + $crate::FromBytes,
{
// FromBytes + AsBytes`.

// We use immutable references here rather than mutable so that, if
// this macro is used in a const context (in which, as of this
// writing, mutable references are banned), the error message
// appears to originate in the user's code rather than in the
// internals of this macro.
struct AssertSrcIsFromBytes<'a, T: ::core::marker::Sized + $crate::FromBytes>(&'a T);
struct AssertSrcIsAsBytes<'a, T: ::core::marker::Sized + $crate::AsBytes>(&'a T);
struct AssertDstIsFromBytes<'a, T: ::core::marker::Sized + $crate::FromBytes>(&'a T);
struct AssertDstIsAsBytes<'a, T: ::core::marker::Sized + $crate::AsBytes>(&'a T);

if true {
let _ = AssertSrcIsFromBytes(&*e);
} else {
let _ = AssertSrcIsAsBytes(&*e);
}

if true {
#[allow(unused, unreachable_code)]
let u = AssertDstIsFromBytes(loop {});
&mut *u.0
} else {
#[allow(unused, unreachable_code)]
let u = AssertDstIsAsBytes(loop {});
&mut *u.0
}
} else if false {
// This branch, though never taken, ensures that the source lifetime
// is not shorter than the destination lifetime, and that the source
// type is a mutable (rather than immutable) reference.
fn transmute<'u, 't: 'u, T: 't, U: 'u>(t: &'t mut T) -> &'u mut U {
loop {}
}
transmute(e)
Expand Down Expand Up @@ -3654,7 +3696,7 @@ pub use alloc_support::*;
mod tests {
#![allow(clippy::unreadable_literal)]

use core::ops::Deref;
use core::{convert::TryInto as _, ops::Deref};

use static_assertions::assert_impl_all;

Expand Down
4 changes: 2 additions & 2 deletions tests/ui-msrv/include_value_not_from_bytes.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ error[E0277]: the trait bound `UnsafeCell<u32>: FromBytes` is not satisfied
12 | include_value!("../../testdata/include_value/data");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromBytes` is not implemented for `UnsafeCell<u32>`
|
note: required by a bound in `NOT_FROM_BYTES::transmute`
note: required by a bound in `AssertIsFromBytes`
--> tests/ui-msrv/include_value_not_from_bytes.rs:12:5
|
12 | include_value!("../../testdata/include_value/data");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `NOT_FROM_BYTES::transmute`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsFromBytes`
= note: this error originates in the macro `$crate::transmute` (in Nightly builds, run with -Z macro-backtrace for more info)
4 changes: 2 additions & 2 deletions tests/ui-msrv/transmute-dst-not-frombytes.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ error[E0277]: the trait bound `NotZerocopy: FromBytes` is not satisfied
18 | const DST_NOT_FROM_BYTES: NotZerocopy = transmute!(AU16(0));
| ^^^^^^^^^^^^^^^^^^^ the trait `FromBytes` is not implemented for `NotZerocopy`
|
note: required by a bound in `DST_NOT_FROM_BYTES::transmute`
note: required by a bound in `AssertIsFromBytes`
--> tests/ui-msrv/transmute-dst-not-frombytes.rs:18:41
|
18 | const DST_NOT_FROM_BYTES: NotZerocopy = transmute!(AU16(0));
| ^^^^^^^^^^^^^^^^^^^ required by this bound in `DST_NOT_FROM_BYTES::transmute`
| ^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsFromBytes`
= note: this error originates in the macro `transmute` (in Nightly builds, run with -Z macro-backtrace for more info)
20 changes: 20 additions & 0 deletions tests/ui-msrv/transmute-mut-dst-not-a-reference.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,23 @@ error[E0308]: mismatched types
= note: expected type `usize`
found mutable reference `&mut _`
= note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0308]: mismatched types
--> tests/ui-msrv/transmute-mut-dst-not-a-reference.rs:17:36
|
17 | const DST_NOT_A_REFERENCE: usize = transmute_mut!(&mut 0u8);
| ^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&mut _`
|
= note: expected type `usize`
found mutable reference `&mut _`
= note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0308]: mismatched types
--> tests/ui-msrv/transmute-mut-dst-not-a-reference.rs:17:36
|
17 | const DST_NOT_A_REFERENCE: usize = transmute_mut!(&mut 0u8);
| ^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&mut _`
|
= note: expected type `usize`
found mutable reference `&mut _`
= note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
7 changes: 2 additions & 5 deletions tests/ui-msrv/transmute-mut-dst-not-asbytes.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,9 @@ error[E0277]: the trait bound `Dst: AsBytes` is not satisfied
24 | const DST_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src);
| ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsBytes` is not implemented for `Dst`
|
note: required by a bound in `DST_NOT_AS_BYTES::transmute`
note: required by a bound in `AssertDstIsAsBytes`
--> tests/ui-msrv/transmute-mut-dst-not-asbytes.rs:24:36
|
24 | const DST_NOT_AS_BYTES: &mut Dst = transmute_mut!(&mut Src);
| ^^^^^^^^^^^^^^^^^^^^^^^^
| |
| required by a bound in this
| required by this bound in `DST_NOT_AS_BYTES::transmute`
| ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertDstIsAsBytes`
= note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
7 changes: 2 additions & 5 deletions tests/ui-msrv/transmute-mut-dst-not-frombytes.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,9 @@ error[E0277]: the trait bound `Dst: FromBytes` is not satisfied
24 | const DST_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src);
| ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromBytes` is not implemented for `Dst`
|
note: required by a bound in `DST_NOT_FROM_BYTES::transmute`
note: required by a bound in `AssertDstIsFromBytes`
--> tests/ui-msrv/transmute-mut-dst-not-frombytes.rs:24:38
|
24 | const DST_NOT_FROM_BYTES: &mut Dst = transmute_mut!(&mut Src);
| ^^^^^^^^^^^^^^^^^^^^^^^^
| |
| required by a bound in this
| required by this bound in `DST_NOT_FROM_BYTES::transmute`
| ^^^^^^^^^^^^^^^^^^^^^^^^ 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)
36 changes: 32 additions & 4 deletions tests/ui-msrv/transmute-mut-dst-unsized.stderr
Original file line number Diff line number Diff line change
@@ -1,3 +1,31 @@
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
--> tests/ui-msrv/transmute-mut-dst-unsized.rs:17:32
|
17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `[u8]`
note: required by a bound in `AssertDstIsFromBytes`
--> tests/ui-msrv/transmute-mut-dst-unsized.rs:17:32
|
17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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 size for values of type `[u8]` cannot be known at compilation time
--> tests/ui-msrv/transmute-mut-dst-unsized.rs:17:32
|
17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `[u8]`
note: required by a bound in `AssertDstIsAsBytes`
--> tests/ui-msrv/transmute-mut-dst-unsized.rs:17:32
|
17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertDstIsAsBytes`
= note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
--> tests/ui-msrv/transmute-mut-dst-unsized.rs:17:32
|
Expand All @@ -11,6 +39,10 @@ note: required by a bound in `DST_UNSIZED::transmute`
17 | const DST_UNSIZED: &mut [u8] = transmute_mut!(&mut [0u8; 1]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `DST_UNSIZED::transmute`
= note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider relaxing the implicit `Sized` restriction
|
224| fn transmute<'u, 't: 'u, T: 't, U: 'u + ?Sized>(t: &'t mut T) -> &'u mut U {
| ++++++++

error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
--> tests/ui-msrv/transmute-mut-dst-unsized.rs:17:32
Expand Down Expand Up @@ -45,10 +77,6 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation
|
= help: the trait `Sized` is not implemented for `[u8]`
note: required by a bound in `std::intrinsics::transmute`
--> $RUST/core/src/intrinsics.rs
|
| pub fn transmute<T, U>(e: T) -> U;
| ^ required by this bound in `std::intrinsics::transmute`
= note: this error originates in the macro `$crate::assert_size_eq` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
Expand Down
19 changes: 2 additions & 17 deletions tests/ui-msrv/transmute-mut-src-dst-not-references.stderr
Original file line number Diff line number Diff line change
@@ -1,22 +1,7 @@
error[E0308]: mismatched types
error[E0614]: type `usize` cannot be dereferenced
--> tests/ui-msrv/transmute-mut-src-dst-not-references.rs:17:44
|
17 | const SRC_DST_NOT_REFERENCES: &mut usize = transmute_mut!(0usize);
| ^^^^^^^^^^^^^^^^^^^^^^ expected `&mut _`, found `usize`
| ^^^^^^^^^^^^^^^^^^^^^^
|
= note: expected mutable reference `&mut _`
found type `usize`
= note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0308]: mismatched types
--> tests/ui-msrv/transmute-mut-src-dst-not-references.rs:17:44
|
17 | const SRC_DST_NOT_REFERENCES: &mut usize = transmute_mut!(0usize);
| ^^^^^^^^^^^^^^^------^
| | |
| | expected due to this value
| expected `usize`, found `&mut _`
|
= note: expected type `usize`
found mutable reference `&mut _`
= note: this error originates in the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
Loading

0 comments on commit c8a55d6

Please sign in to comment.