Skip to content

Commit

Permalink
Make more fns/macros const, update MSRV to 1.61.0
Browse files Browse the repository at this point in the history
Make more functions and the `transmute!` macro const. This requires
updating our MSRV to 1.61.0.

While we're doing this, document our MSRV in the crate root and our
`README.md`.
  • Loading branch information
joshlf committed Oct 17, 2022
1 parent e5e9b1f commit 0393b20
Show file tree
Hide file tree
Showing 13 changed files with 172 additions and 19 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ jobs:
matrix:
# See `INTERNAL.md` for an explanation of these pinned toolchain
# versions.
channel: [ "1.56.1", "1.64.0", "nightly-2022-09-26" ]
channel: [ "1.61.0", "1.64.0", nightly-2022-09-26 ]
target: [ "i686-unknown-linux-gnu", "x86_64-unknown-linux-gnu", "arm-unknown-linux-gnueabi", "aarch64-unknown-linux-gnu", "powerpc-unknown-linux-gnu", "powerpc64-unknown-linux-gnu", "wasm32-wasi" ]
features: [ "" , "alloc,simd", "alloc,simd,simd-nightly" ]
exclude:
# Exclude any combination which uses a non-nightly toolchain but
# enables nightly features.
- channel: "1.56.1"
- channel: "1.61.0"
features: "alloc,simd,simd-nightly"
- channel: "1.64.0"
features: "alloc,simd,simd-nightly"
Expand Down
12 changes: 6 additions & 6 deletions INTERNAL.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ locations.
## CI and toolchain versions

In CI (`.github/workflows/ci.yml`), we pin to specific versions or dates of the
stable and nightly toolchains. The reason is twofold: First, `zerocopy-derive`'s
UI tests (see `zerocopy-derive/tests/trybuild.rs`) depend on the format of
rustc's error messages, and that format can change between toolchain versions
(we also maintain multiple copies of our UI tests - one for each toolchain
version pinned in CI - for this reason). Second, not all nightlies have a
working Miri, so we need to pin to one that does (see
stable and nightly toolchains. The reason is twofold: First, our UI tests (see
`tests/trybuild.rs` and `zerocopy-derive/tests/trybuild.rs`) depend on the
format of rustc's error messages, and that format can change between toolchain
versions (we also maintain multiple copies of our UI tests - one for each
toolchain version pinned in CI - for this reason). Second, not all nightlies
have a working Miri, so we need to pin to one that does (see
https://rust-lang.github.io/rustup-components-history/).

Updating the versions pinned in CI may cause the UI tests to break. In order to
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ packed SIMD vectors][simd-layout].
which are only available on nightly. Since these types are unstable, support
for any type may be removed at any point in the future.

## Minimum Supported Rust Version (MSRV)

zerocopy's MSRV is 1.61.0.

[simd-layout]: https://rust-lang.github.io/unsafe-code-guidelines/layout/packed-simd-vectors.html

## Dislcaimer
Expand Down
41 changes: 34 additions & 7 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@
//! which are only available on nightly. Since these types are unstable, support
//! for any type may be removed at any point in the future.
//!
//! # Minimum Supported Rust Version (MSRV)
//!
//! zerocopy's MSRV is 1.61.0.
//!
//! [simd-layout]: https://rust-lang.github.io/unsafe-code-guidelines/layout/packed-simd-vectors.html
#![deny(
Expand Down Expand Up @@ -117,7 +121,7 @@ use core::{
cmp::Ordering,
fmt::{self, Debug, Display, Formatter},
marker::PhantomData,
mem::{self, MaybeUninit},
mem::{self, ManuallyDrop, MaybeUninit},
num::{
NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, NonZeroU128,
NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize, Wrapping,
Expand Down Expand Up @@ -808,14 +812,29 @@ impl<T: Copy> Clone for Unalign<T> {

impl<T> Unalign<T> {
/// Constructs a new `Unalign`.
pub fn new(val: T) -> Unalign<T> {
pub const fn new(val: T) -> Unalign<T> {
Unalign(val)
}

/// Consumes `self`, returning the inner `T`.
pub fn into_inner(self) -> T {
let Unalign(val) = self;
val
pub const fn into_inner(self) -> T {
// Use this instead of `mem::transmute` since the latter can't tell
// that `Unalign<T>` and `T` have the same size.
union Transmute<T> {
u: ManuallyDrop<Unalign<T>>,
t: ManuallyDrop<T>,
}

// SAFETY: Since `Unalign` is `#[repr(C, packed)]`, it has the same
// layout as `T`. `ManuallyDrop<U>` is guaranteed to have the same
// layout as `U`, and so `ManuallyDrop<Unalign<T>>` has the same layout
// as `ManuallyDrop<T>`. We do this instead of just destructuring in
// order to prevent `Unalign`'s `Drop::drop` from being run, since
// dropping is not supported in `const fn`s.
//
// TODO(https://github.com/rust-lang/rust/issues/73255): Destructure
// instead of using unsafe.
unsafe { ManuallyDrop::into_inner(Transmute { u: ManuallyDrop::new(self) }.t) }
}

/// Gets an unaligned raw pointer to the inner `T`.
Expand All @@ -832,7 +851,7 @@ impl<T> Unalign<T> {
/// [`read_unaligned`].
///
/// [`read_unaligned`]: core::ptr::read_unaligned
pub fn get_ptr(&self) -> *const T {
pub const fn get_ptr(&self) -> *const T {
ptr::addr_of!(self.0)
}

Expand All @@ -850,13 +869,15 @@ impl<T> Unalign<T> {
/// [`read_unaligned`].
///
/// [`read_unaligned`]: core::ptr::read_unaligned
// TODO(https://github.com/rust-lang/rust/issues/57349): Make this `const`.
pub fn get_mut_ptr(&mut self) -> *mut T {
ptr::addr_of_mut!(self.0)
}
}

impl<T: Copy> Unalign<T> {
/// Gets a copy of the inner `T`.
// TODO(https://github.com/rust-lang/rust/issues/57349): Make this `const`.
pub fn get(&self) -> T {
let Unalign(val) = *self;
val
Expand Down Expand Up @@ -904,7 +925,7 @@ 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`.
fn transmute<T: $crate::AsBytes, U: $crate::FromBytes>(_t: T) -> U {
const fn transmute<T: $crate::AsBytes, U: $crate::FromBytes>(_t: T) -> U {
unreachable!()
}
transmute(e)
Expand Down Expand Up @@ -2462,6 +2483,12 @@ mod tests {
}
}
let _: () = transmute!(PanicOnDrop(()));

// Test that `transmute!` is legal in a const context.
const ARRAY_OF_U8S: [u8; 8] = [0u8, 1, 2, 3, 4, 5, 6, 7];
const ARRAY_OF_ARRAYS: [[u8; 2]; 4] = [[0, 1], [2, 3], [4, 5], [6, 7]];
const X: [[u8; 2]; 4] = transmute!(ARRAY_OF_U8S);
assert_eq!(X, ARRAY_OF_ARRAYS);
}

#[test]
Expand Down
24 changes: 22 additions & 2 deletions tests/trybuild.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,29 @@
// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// UI tests depend on the exact error messages emitted by rustc, but those error
// messages are not stable, and sometimes change between Rust versions. Thus, we
// maintain one set of UI tests for each Rust version that we test in CI, and we
// pin to specific versions in CI (a specific stable version, a specific date of
// the nightly compiler, and a specific MSRV). Updating those pinned versions
// may also require updating these tests.
// - `tests/ui` - Contains the source of truth for our UI test source files
// (`.rs`), and contains `.err` and `.out` files for nightly and beta
// - `tests/ui-stable` - Contains symlinks to the `.rs` files in `tests/ui`, and
// contains `.err` and `.out` files for stable
// - `tests/ui-msrv` - Contains symlinks to the `.rs` files in `tests/ui`, and
// contains `.err` and `.out` files for MSRV

#[rustversion::any(nightly, beta)]
const SOURCE_FILES_GLOB: &str = "tests/ui/*.rs";
#[rustversion::all(stable, not(stable(1.61.0)))]
const SOURCE_FILES_GLOB: &str = "tests/ui-stable/*.rs";
#[rustversion::stable(1.61.0)]
const SOURCE_FILES_GLOB: &str = "tests/ui-msrv/*.rs";

#[test]
fn ui() {
let t = trybuild::TestCases::new();
t.compile_fail("tests/ui/*.rs");
t.compile_fail(SOURCE_FILES_GLOB);
}
1 change: 1 addition & 0 deletions tests/ui-msrv/transmute-illegal.rs
24 changes: 24 additions & 0 deletions tests/ui-msrv/transmute-illegal.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
error[E0601]: `main` function not found in crate `$CRATE`
--> tests/ui-msrv/transmute-illegal.rs:8:76
|
8 | const POINTER_VALUE: usize = zerocopy::transmute!(&0usize as *const usize);
| ^ consider adding a `main` function to `$DIR/tests/ui-msrv/transmute-illegal.rs`

error[E0277]: the trait bound `*const usize: AsBytes` is not satisfied
--> tests/ui-msrv/transmute-illegal.rs:8:30
|
8 | const POINTER_VALUE: usize = zerocopy::transmute!(&0usize as *const usize);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsBytes` is not implemented for `*const usize`
|
= help: the following implementations were found:
<usize as AsBytes>
<f32 as AsBytes>
<f64 as AsBytes>
<i128 as AsBytes>
and 10 others
note: required by a bound in `POINTER_VALUE::transmute`
--> tests/ui-msrv/transmute-illegal.rs:8:30
|
8 | const POINTER_VALUE: usize = zerocopy::transmute!(&0usize as *const usize);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `POINTER_VALUE::transmute`
= note: this error originates in the macro `zerocopy::transmute` (in Nightly builds, run with -Z macro-backtrace for more info)
1 change: 1 addition & 0 deletions tests/ui-stable/transmute-illegal.rs
28 changes: 28 additions & 0 deletions tests/ui-stable/transmute-illegal.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
error[E0601]: `main` function not found in crate `$CRATE`
--> tests/ui-stable/transmute-illegal.rs:8:76
|
8 | const POINTER_VALUE: usize = zerocopy::transmute!(&0usize as *const usize);
| ^ consider adding a `main` function to `$DIR/tests/ui-stable/transmute-illegal.rs`

error[E0277]: the trait bound `*const usize: AsBytes` is not satisfied
--> tests/ui-stable/transmute-illegal.rs:8:30
|
8 | const POINTER_VALUE: usize = zerocopy::transmute!(&0usize as *const usize);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsBytes` is not implemented for `*const usize`
|
= help: the following other types implement trait `AsBytes`:
f32
f64
i128
i16
i32
i64
i8
isize
and 6 others
note: required by a bound in `POINTER_VALUE::transmute`
--> tests/ui-stable/transmute-illegal.rs:8:30
|
8 | const POINTER_VALUE: usize = zerocopy::transmute!(&0usize as *const usize);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `POINTER_VALUE::transmute`
= note: this error originates in the macro `zerocopy::transmute` (in Nightly builds, run with -Z macro-backtrace for more info)
8 changes: 8 additions & 0 deletions tests/ui/transmute-illegal.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

extern crate zerocopy;

// It is unsound to inspect the usize value of a pointer during const eval.
const POINTER_VALUE: usize = zerocopy::transmute!(&0usize as *const usize);
31 changes: 31 additions & 0 deletions tests/ui/transmute-illegal.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
error[E0601]: `main` function not found in crate `$CRATE`
--> tests/ui/transmute-illegal.rs:8:76
|
8 | const POINTER_VALUE: usize = zerocopy::transmute!(&0usize as *const usize);
| ^ consider adding a `main` function to `$DIR/tests/ui/transmute-illegal.rs`

error[E0277]: the trait bound `*const usize: AsBytes` is not satisfied
--> tests/ui/transmute-illegal.rs:8:30
|
8 | const POINTER_VALUE: usize = zerocopy::transmute!(&0usize as *const usize);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| the trait `AsBytes` is not implemented for `*const usize`
| required by a bound introduced by this call
|
= help: the following other types implement trait `AsBytes`:
f32
f64
i128
i16
i32
i64
i8
isize
and 6 others
note: required by a bound in `POINTER_VALUE::transmute`
--> tests/ui/transmute-illegal.rs:8:30
|
8 | const POINTER_VALUE: usize = zerocopy::transmute!(&0usize as *const usize);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `POINTER_VALUE::transmute`
= note: this error originates in the macro `zerocopy::transmute` (in Nightly builds, run with -Z macro-backtrace for more info)
4 changes: 2 additions & 2 deletions zerocopy-derive/tests/trybuild.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@

#[rustversion::any(nightly, beta)]
const SOURCE_FILES_GLOB: &str = "tests/ui/*.rs";
#[rustversion::all(stable, not(stable(1.56.1)))]
#[rustversion::all(stable, not(stable(1.61.0)))]
const SOURCE_FILES_GLOB: &str = "tests/ui-stable/*.rs";
#[rustversion::stable(1.56.1)]
#[rustversion::stable(1.61.0)]
const SOURCE_FILES_GLOB: &str = "tests/ui-msrv/*.rs";

#[test]
Expand Down
9 changes: 9 additions & 0 deletions zerocopy-derive/tests/ui-msrv/late_compile_pass.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ error[E0277]: the trait bound `u16: Unaligned` is not satisfied
38 | #[derive(Unaligned)]
| ^^^^^^^^^ the trait `Unaligned` is not implemented for `u16`
|
= help: the following implementations were found:
<i8 as Unaligned>
<u8 as Unaligned>
note: required by a bound in `<Unaligned1 as Unaligned>::only_derive_is_allowed_to_implement_this_trait::ImplementsUnaligned`
--> tests/ui-msrv/late_compile_pass.rs:38:10
|
Expand All @@ -45,6 +48,9 @@ error[E0277]: the trait bound `u16: Unaligned` is not satisfied
46 | #[derive(Unaligned)]
| ^^^^^^^^^ the trait `Unaligned` is not implemented for `u16`
|
= help: the following implementations were found:
<i8 as Unaligned>
<u8 as Unaligned>
note: required by a bound in `<Unaligned2 as Unaligned>::only_derive_is_allowed_to_implement_this_trait::ImplementsUnaligned`
--> tests/ui-msrv/late_compile_pass.rs:46:10
|
Expand All @@ -58,6 +64,9 @@ error[E0277]: the trait bound `u16: Unaligned` is not satisfied
53 | #[derive(Unaligned)]
| ^^^^^^^^^ the trait `Unaligned` is not implemented for `u16`
|
= help: the following implementations were found:
<i8 as Unaligned>
<u8 as Unaligned>
note: required by a bound in `<Unaligned3 as Unaligned>::only_derive_is_allowed_to_implement_this_trait::ImplementsUnaligned`
--> tests/ui-msrv/late_compile_pass.rs:53:10
|
Expand Down

0 comments on commit 0393b20

Please # to comment.