Skip to content

Commit be8fdd7

Browse files
committed
Lower MSRV to 1.56
Makes progress on #554
1 parent 9890e55 commit be8fdd7

File tree

54 files changed

+737
-861
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+737
-861
lines changed

Cargo.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ authors = ["Joshua Liebow-Feeser <[email protected]>"]
2020
description = "Utilities for zero-copy parsing and serialization"
2121
license = "BSD-2-Clause OR Apache-2.0 OR MIT"
2222
repository = "https://github.com/google/zerocopy"
23-
rust-version = "1.57.0"
23+
rust-version = "1.56.0"
2424

2525
exclude = [".*"]
2626

@@ -35,6 +35,9 @@ exclude = [".*"]
3535
# versions, these types require the "simd-nightly" feature.
3636
zerocopy-aarch64-simd = "1.59.0"
3737

38+
# Permit panicking in `const fn`s.
39+
zerocopy-panic-in-const = "1.57.0"
40+
3841
[package.metadata.ci]
3942
# The versions of the stable and nightly compiler toolchains to use in CI.
4043
pinned-stable = "1.75.0"

src/lib.rs

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -363,13 +363,15 @@ pub struct DstLayout {
363363
size_info: SizeInfo,
364364
}
365365

366-
#[cfg_attr(any(kani, test), derive(Copy, Clone, Debug, PartialEq, Eq))]
366+
#[cfg_attr(any(kani, test), derive(Debug, PartialEq, Eq))]
367+
#[derive(Copy, Clone)]
367368
enum SizeInfo<E = usize> {
368369
Sized { _size: usize },
369370
SliceDst(TrailingSliceLayout<E>),
370371
}
371372

372-
#[cfg_attr(any(kani, test), derive(Copy, Clone, Debug, PartialEq, Eq))]
373+
#[cfg_attr(any(kani, test), derive(Debug, PartialEq, Eq))]
374+
#[derive(Copy, Clone)]
373375
struct TrailingSliceLayout<E = usize> {
374376
// The offset of the first byte of the trailing slice field. Note that this
375377
// is NOT the same as the minimum size of the type. For example, consider
@@ -419,7 +421,7 @@ impl DstLayout {
419421
/// The minimum possible alignment of a type.
420422
const MIN_ALIGN: NonZeroUsize = match NonZeroUsize::new(1) {
421423
Some(min_align) => min_align,
422-
None => unreachable!(),
424+
None => loop {},
423425
};
424426

425427
/// The maximum theoretic possible alignment of a type.
@@ -430,7 +432,7 @@ impl DstLayout {
430432
const THEORETICAL_MAX_ALIGN: NonZeroUsize =
431433
match NonZeroUsize::new(1 << (POINTER_WIDTH_BITS - 1)) {
432434
Some(max_align) => max_align,
433-
None => unreachable!(),
435+
None => loop {},
434436
};
435437

436438
/// The current, documented max alignment of a type \[1\].
@@ -439,10 +441,10 @@ impl DstLayout {
439441
///
440442
/// The alignment value must be a power of two from 1 up to
441443
/// 2<sup>29</sup>.
442-
#[cfg(not(kani))]
444+
#[cfg(all(not(kani), any(test, zerocopy_panic_in_const)))]
443445
const CURRENT_MAX_ALIGN: NonZeroUsize = match NonZeroUsize::new(1 << 28) {
444446
Some(max_align) => max_align,
445-
None => unreachable!(),
447+
None => loop {},
446448
};
447449

448450
/// Constructs a `DstLayout` for a zero-sized type with `repr_align`
@@ -464,7 +466,7 @@ impl DstLayout {
464466
None => Self::MIN_ALIGN,
465467
};
466468

467-
assert!(align.get().is_power_of_two());
469+
const_assert!(align.get().is_power_of_two());
468470

469471
DstLayout { align, size_info: SizeInfo::Sized { _size: 0 } }
470472
}
@@ -483,7 +485,7 @@ impl DstLayout {
483485
DstLayout {
484486
align: match NonZeroUsize::new(mem::align_of::<T>()) {
485487
Some(align) => align,
486-
None => unreachable!(),
488+
None => loop {},
487489
},
488490
size_info: SizeInfo::Sized { _size: mem::size_of::<T>() },
489491
}
@@ -506,7 +508,7 @@ impl DstLayout {
506508
DstLayout {
507509
align: match NonZeroUsize::new(mem::align_of::<T>()) {
508510
Some(align) => align,
509-
None => unreachable!(),
511+
None => loop {},
510512
},
511513
size_info: SizeInfo::SliceDst(TrailingSliceLayout {
512514
_offset: 0,
@@ -552,12 +554,12 @@ impl DstLayout {
552554
None => Self::THEORETICAL_MAX_ALIGN,
553555
};
554556

555-
assert!(max_align.get().is_power_of_two());
557+
const_assert!(max_align.get().is_power_of_two());
556558

557559
// We use Kani to prove that this method is robust to future increases
558560
// in Rust's maximum allowed alignment. However, if such a change ever
559561
// actually occurs, we'd like to be notified via assertion failures.
560-
#[cfg(not(kani))]
562+
#[cfg(all(not(kani), zerocopy_panic_in_const))]
561563
{
562564
debug_assert!(self.align.get() <= DstLayout::CURRENT_MAX_ALIGN.get());
563565
debug_assert!(field.align.get() <= DstLayout::CURRENT_MAX_ALIGN.get());
@@ -583,7 +585,7 @@ impl DstLayout {
583585
let size_info = match self.size_info {
584586
// If the layout is already a DST, we panic; DSTs cannot be extended
585587
// with additional fields.
586-
SizeInfo::SliceDst(..) => panic!("Cannot extend a DST with additional fields."),
588+
SizeInfo::SliceDst(..) => const_panic!("Cannot extend a DST with additional fields."),
587589

588590
SizeInfo::Sized { _size: preceding_size } => {
589591
// Compute the minimum amount of inter-field padding needed to
@@ -604,7 +606,7 @@ impl DstLayout {
604606
// exceeding `isize::MAX`).
605607
let offset = match preceding_size.checked_add(padding) {
606608
Some(offset) => offset,
607-
None => panic!("Adding padding to `self`'s size overflows `usize`."),
609+
None => const_panic!("Adding padding to `self`'s size overflows `usize`."),
608610
};
609611

610612
match field.size_info {
@@ -622,7 +624,7 @@ impl DstLayout {
622624
// `usize::MAX`).
623625
let size = match offset.checked_add(field_size) {
624626
Some(size) => size,
625-
None => panic!("`field` cannot be appended without the total size overflowing `usize`"),
627+
None => const_panic!("`field` cannot be appended without the total size overflowing `usize`"),
626628
};
627629
SizeInfo::Sized { _size: size }
628630
}
@@ -644,7 +646,7 @@ impl DstLayout {
644646
// `usize::MAX`).
645647
let offset = match offset.checked_add(trailing_offset) {
646648
Some(offset) => offset,
647-
None => panic!("`field` cannot be appended without the total size overflowing `usize`"),
649+
None => const_panic!("`field` cannot be appended without the total size overflowing `usize`"),
648650
};
649651
SizeInfo::SliceDst(TrailingSliceLayout { _offset: offset, _elem_size })
650652
}
@@ -691,7 +693,7 @@ impl DstLayout {
691693
let padding = padding_needed_for(unpadded_size, self.align);
692694
let size = match unpadded_size.checked_add(padding) {
693695
Some(size) => size,
694-
None => panic!("Adding padding caused size to overflow `usize`."),
696+
None => const_panic!("Adding padding caused size to overflow `usize`."),
695697
};
696698
SizeInfo::Sized { _size: size }
697699
}
@@ -776,9 +778,11 @@ impl DstLayout {
776778
bytes_len: usize,
777779
cast_type: _CastType,
778780
) -> Option<(usize, usize)> {
779-
// `debug_assert!`, but with `#[allow(clippy::arithmetic_side_effects)]`.
781+
// `debug_assert!`, but with `#[allow(clippy::arithmetic_side_effects)]`
782+
// and `#[cfg(zerocopy_panic_in_const)]`.
780783
macro_rules! __debug_assert {
781784
($e:expr $(, $msg:expr)?) => {
785+
#[cfg(zerocopy_panic_in_const)]
782786
debug_assert!({
783787
#[allow(clippy::arithmetic_side_effects)]
784788
let e = $e;
@@ -798,7 +802,7 @@ impl DstLayout {
798802
// https://blog.rust-lang.org/2022/11/03/Rust-1.65.0.html#let-else-statements
799803
let size_info = match self.size_info.try_to_nonzero_elem_size() {
800804
Some(size_info) => size_info,
801-
None => panic!("attempted to cast to slice type with zero-sized element"),
805+
None => const_panic!("attempted to cast to slice type with zero-sized element"),
802806
};
803807

804808
// Precondition
@@ -3953,7 +3957,7 @@ macro_rules! transmute_ref {
39533957

39543958
// `t` is inferred to have type `T` because it's assigned to `e` (of
39553959
// type `&T`) as `&t`.
3956-
let mut t = unreachable!();
3960+
let mut t = loop {};
39573961
e = &t;
39583962

39593963
// `u` is inferred to have type `U` because it's used as `&u` as the
@@ -5326,7 +5330,7 @@ impl<'a> sealed::ByteSliceSealed for cell::Ref<'a, [u8]> {}
53265330
#[allow(clippy::undocumented_unsafe_blocks)]
53275331
unsafe impl<'a> ByteSlice for cell::Ref<'a, [u8]> {
53285332
const INTO_REF_INTO_MUT_ARE_SOUND: bool = if !cfg!(doc) {
5329-
panic!("Ref::into_ref and Ref::into_mut are unsound when used with core::cell::Ref; see https://github.com/google/zerocopy/issues/716")
5333+
const_panic!("Ref::into_ref and Ref::into_mut are unsound when used with core::cell::Ref; see https://github.com/google/zerocopy/issues/716")
53305334
} else {
53315335
// When compiling documentation, allow the evaluation of this constant
53325336
// to succeed. This doesn't represent a soundness hole - it just delays
@@ -5346,7 +5350,7 @@ impl<'a> sealed::ByteSliceSealed for RefMut<'a, [u8]> {}
53465350
#[allow(clippy::undocumented_unsafe_blocks)]
53475351
unsafe impl<'a> ByteSlice for RefMut<'a, [u8]> {
53485352
const INTO_REF_INTO_MUT_ARE_SOUND: bool = if !cfg!(doc) {
5349-
panic!("Ref::into_ref and Ref::into_mut are unsound when used with core::cell::RefMut; see https://github.com/google/zerocopy/issues/716")
5353+
const_panic!("Ref::into_ref and Ref::into_mut are unsound when used with core::cell::RefMut; see https://github.com/google/zerocopy/issues/716")
53505354
} else {
53515355
// When compiling documentation, allow the evaluation of this constant
53525356
// to succeed. This doesn't represent a soundness hole - it just delays
@@ -5812,7 +5816,7 @@ mod tests {
58125816
// attempt to expose UB.
58135817
#[test]
58145818
#[cfg_attr(miri, ignore)]
5815-
fn testvalidate_cast_and_convert_metadata() {
5819+
fn test_validate_cast_and_convert_metadata() {
58165820
impl From<usize> for SizeInfo {
58175821
fn from(_size: usize) -> SizeInfo {
58185822
SizeInfo::Sized { _size }

src/macros.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,3 +416,43 @@ macro_rules! assert_unaligned {
416416
$(assert_unaligned!($ty);)*
417417
};
418418
}
419+
420+
/// Either panic (if the current Rust toolchain supports panicking in `const
421+
/// fn`) or evaluate a constant that will cause an array indexing error whose
422+
/// error message will include the format string.
423+
///
424+
/// The type that this expression evaluates to must be `Copy`, or else the
425+
/// non-panicking desugaring will fail to compile.
426+
macro_rules! const_panic {
427+
($fmt:literal) => {{
428+
#[cfg(zerocopy_panic_in_const)]
429+
panic!($fmt);
430+
#[cfg(not(zerocopy_panic_in_const))]
431+
const_panic!(@non_panic $fmt)
432+
}};
433+
(@non_panic $fmt:expr) => {{
434+
// This will type check to whatever type is expected based on the call
435+
// site.
436+
let panic: [_; 0] = [];
437+
// This will always fail (since we're indexing into an array of size 0.
438+
#[allow(unconditional_panic)]
439+
panic[0]
440+
}}
441+
}
442+
443+
/// Either assert (if the current Rust toolchain supports panicking in `const
444+
/// fn`) or evaluate the expression and, if it evaluates to `false`, call
445+
/// `const_panic!`.
446+
macro_rules! const_assert {
447+
($e:expr) => {{
448+
#[cfg(zerocopy_panic_in_const)]
449+
assert!($e);
450+
#[cfg(not(zerocopy_panic_in_const))]
451+
{
452+
let e = $e;
453+
if !e {
454+
let _: () = const_panic!(@non_panic concat!("assertion failed: ", stringify!($e)));
455+
}
456+
}
457+
}}
458+
}

src/util.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ pub(crate) const fn round_down_to_next_multiple_of_alignment(
129129
align: NonZeroUsize,
130130
) -> usize {
131131
let align = align.get();
132+
#[cfg(zerocopy_panic_in_const)]
132133
debug_assert!(align.is_power_of_two());
133134

134135
// Subtraction can't underflow because `align.get() >= 1`.
@@ -275,6 +276,13 @@ mod tests {
275276
}
276277
}
277278
}
279+
280+
#[rustversion::since(1.57.0)]
281+
#[test]
282+
#[should_panic]
283+
fn test_round_down_to_next_multiple_of_alignment_panic_in_const() {
284+
round_down_to_next_multiple_of_alignment(0, NonZeroUsize::new(3).unwrap());
285+
}
278286
}
279287

280288
#[cfg(kani)]

src/wrappers.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,7 @@ mod tests {
477477
let au64 = unsafe { x.t.deref_unchecked() };
478478
match au64 {
479479
AU64(123) => {}
480-
_ => unreachable!(),
480+
_ => loop {},
481481
}
482482
};
483483
}

tests/ui-stable/include_value_not_from_bytes.stderr

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,11 @@ error[E0277]: the trait bound `NotZerocopy<u32>: FromBytes` is not satisfied
22
--> tests/ui-stable/include_value_not_from_bytes.rs:13:42
33
|
44
13 | const NOT_FROM_BYTES: NotZerocopy<u32> = include_value!("../../testdata/include_value/data");
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6-
| |
7-
| the trait `FromBytes` is not implemented for `NotZerocopy<u32>`
8-
| required by a bound introduced by this call
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `FromBytes` is not implemented for `NotZerocopy<u32>`
96
|
10-
= help: the following other types implement trait `FromBytes`:
11-
isize
12-
i8
13-
i16
14-
i32
15-
i64
16-
i128
17-
usize
18-
u8
19-
and $N others
20-
note: required by a bound in `AssertIsFromBytes`
7+
note: required by `AssertIsFromBytes`
218
--> tests/ui-stable/include_value_not_from_bytes.rs:13:42
229
|
2310
13 | const NOT_FROM_BYTES: NotZerocopy<u32> = include_value!("../../testdata/include_value/data");
24-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AssertIsFromBytes`
25-
= note: this error originates in the macro `$crate::transmute` which comes from the expansion of the macro `include_value` (in Nightly builds, run with -Z macro-backtrace for more info)
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
= note: this error originates in the macro `$crate::transmute` (in Nightly builds, run with -Z macro-backtrace for more info)

tests/ui-stable/include_value_wrong_size.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ error[E0512]: cannot transmute between types of different sizes, or dependently-
66
|
77
= note: source type: `[u8; 4]` (32 bits)
88
= note: target type: `u64` (64 bits)
9-
= note: this error originates in the macro `$crate::transmute` which comes from the expansion of the macro `include_value` (in Nightly builds, run with -Z macro-backtrace for more info)
9+
= note: this error originates in the macro `$crate::transmute` (in Nightly builds, run with -Z macro-backtrace for more info)

0 commit comments

Comments
 (0)