Rollup merge of #48265 - SimonSapin:nonzero, r=KodrAus

Add 12 num::NonZero* types for primitive integers, deprecate core::nonzero

RFC: https://github.com/rust-lang/rfcs/pull/2307
Tracking issue: ~~https://github.com/rust-lang/rust/issues/27730~~ https://github.com/rust-lang/rust/issues/49137
Fixes https://github.com/rust-lang/rust/issues/27730
This commit is contained in:
Alex Crichton 2018-03-23 09:27:06 -05:00 committed by GitHub
commit 7cf4cb5a7b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 210 additions and 89 deletions

View file

@ -43,8 +43,7 @@
use core::marker::PhantomData;
use core::mem;
use core::nonzero::NonZero;
use core::ptr::{self, Unique};
use core::ptr::{self, Unique, NonNull};
use core::slice;
use boxed::Box;
@ -149,14 +148,12 @@ impl<K, V> BoxedNode<K, V> {
}
}
unsafe fn from_ptr(ptr: NonZero<*const LeafNode<K, V>>) -> Self {
BoxedNode { ptr: Unique::new_unchecked(ptr.get() as *mut LeafNode<K, V>) }
unsafe fn from_ptr(ptr: NonNull<LeafNode<K, V>>) -> Self {
BoxedNode { ptr: Unique::from(ptr) }
}
fn as_ptr(&self) -> NonZero<*const LeafNode<K, V>> {
unsafe {
NonZero::from(self.ptr.as_ref())
}
fn as_ptr(&self) -> NonNull<LeafNode<K, V>> {
NonNull::from(self.ptr)
}
}
@ -276,7 +273,7 @@ impl<K, V> Root<K, V> {
/// `NodeRef` could be pointing to either type of node.
pub struct NodeRef<BorrowType, K, V, Type> {
height: usize,
node: NonZero<*const LeafNode<K, V>>,
node: NonNull<LeafNode<K, V>>,
// This is null unless the borrow type is `Mut`
root: *const Root<K, V>,
_marker: PhantomData<(BorrowType, Type)>
@ -302,7 +299,7 @@ unsafe impl<K: Send, V: Send, Type> Send
impl<BorrowType, K, V> NodeRef<BorrowType, K, V, marker::Internal> {
fn as_internal(&self) -> &InternalNode<K, V> {
unsafe {
&*(self.node.get() as *const InternalNode<K, V>)
&*(self.node.as_ptr() as *mut InternalNode<K, V>)
}
}
}
@ -310,7 +307,7 @@ impl<BorrowType, K, V> NodeRef<BorrowType, K, V, marker::Internal> {
impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::Internal> {
fn as_internal_mut(&mut self) -> &mut InternalNode<K, V> {
unsafe {
&mut *(self.node.get() as *mut InternalNode<K, V>)
&mut *(self.node.as_ptr() as *mut InternalNode<K, V>)
}
}
}
@ -352,7 +349,7 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
fn as_leaf(&self) -> &LeafNode<K, V> {
unsafe {
&*self.node.get()
self.node.as_ref()
}
}
@ -382,7 +379,8 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
>,
Self
> {
if let Some(non_zero) = NonZero::new(self.as_leaf().parent as *const LeafNode<K, V>) {
let parent_as_leaf = self.as_leaf().parent as *const LeafNode<K, V>;
if let Some(non_zero) = NonNull::new(parent_as_leaf as *mut _) {
Ok(Handle {
node: NodeRef {
height: self.height + 1,
@ -498,7 +496,7 @@ impl<'a, K, V, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
fn as_leaf_mut(&mut self) -> &mut LeafNode<K, V> {
unsafe {
&mut *(self.node.get() as *mut LeafNode<K, V>)
self.node.as_mut()
}
}
@ -1241,12 +1239,12 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::
}
Heap.dealloc(
right_node.node.get() as *mut u8,
right_node.node.as_ptr() as *mut u8,
Layout::new::<InternalNode<K, V>>(),
);
} else {
Heap.dealloc(
right_node.node.get() as *mut u8,
right_node.node.as_ptr() as *mut u8,
Layout::new::<LeafNode<K, V>>(),
);
}

View file

@ -146,13 +146,12 @@
//!
//! ```
//! #![feature(core_intrinsics)]
//! #![feature(shared)]
//! use std::cell::Cell;
//! use std::ptr::Shared;
//! use std::ptr::NonNull;
//! use std::intrinsics::abort;
//!
//! struct Rc<T: ?Sized> {
//! ptr: Shared<RcBox<T>>
//! ptr: NonNull<RcBox<T>>
//! }
//!
//! struct RcBox<T: ?Sized> {

View file

@ -9,9 +9,10 @@
// except according to those terms.
//! Exposes the NonZero lang item which provides optimization hints.
#![unstable(feature = "nonzero",
reason = "needs an RFC to flesh out the design",
issue = "27730")]
#![unstable(feature = "nonzero", reason = "deprecated", issue = "49137")]
#![rustc_deprecated(reason = "use `std::ptr::NonNull` or `std::num::NonZero*` instead",
since = "1.26.0")]
#![allow(deprecated)]
use ops::CoerceUnsized;
@ -62,14 +63,11 @@ impl_zeroable_for_integer_types! {
/// NULL or 0 that might allow certain optimizations.
#[lang = "non_zero"]
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
pub struct NonZero<T: Zeroable>(T);
pub struct NonZero<T: Zeroable>(pub(crate) T);
impl<T: Zeroable> NonZero<T> {
/// Creates an instance of NonZero with the provided value.
/// You must indeed ensure that the value is actually "non-zero".
#[unstable(feature = "nonzero",
reason = "needs an RFC to flesh out the design",
issue = "27730")]
#[inline]
pub const unsafe fn new_unchecked(inner: T) -> Self {
NonZero(inner)

View file

@ -15,9 +15,98 @@
use convert::TryFrom;
use fmt;
use intrinsics;
#[allow(deprecated)] use nonzero::NonZero;
use ops;
use str::FromStr;
macro_rules! impl_nonzero_fmt {
( #[$stability: meta] ( $( $Trait: ident ),+ ) for $Ty: ident ) => {
$(
#[$stability]
impl fmt::$Trait for $Ty {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.get().fmt(f)
}
}
)+
}
}
macro_rules! nonzero_integers {
( #[$stability: meta] $( $Ty: ident($Int: ty); )+ ) => {
$(
/// An integer that is known not to equal zero.
///
/// This may enable some memory layout optimization such as:
///
/// ```rust
/// # #![feature(nonzero)]
/// use std::mem::size_of;
/// assert_eq!(size_of::<Option<std::num::NonZeroU32>>(), size_of::<u32>());
/// ```
#[$stability]
#[allow(deprecated)]
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct $Ty(NonZero<$Int>);
#[allow(deprecated)]
impl $Ty {
/// Create a non-zero without checking the value.
///
/// # Safety
///
/// The value must not be zero.
#[$stability]
#[inline]
pub const unsafe fn new_unchecked(n: $Int) -> Self {
$Ty(NonZero(n))
}
/// Create a non-zero if the given value is not zero.
#[$stability]
#[inline]
pub fn new(n: $Int) -> Option<Self> {
if n != 0 {
Some($Ty(NonZero(n)))
} else {
None
}
}
/// Returns the value as a primitive type.
#[$stability]
#[inline]
pub fn get(self) -> $Int {
self.0 .0
}
}
impl_nonzero_fmt! {
#[$stability]
(Debug, Display, Binary, Octal, LowerHex, UpperHex) for $Ty
}
)+
}
}
nonzero_integers! {
#[unstable(feature = "nonzero", issue = "49137")]
NonZeroU8(u8); NonZeroI8(i8);
NonZeroU16(u16); NonZeroI16(i16);
NonZeroU32(u32); NonZeroI32(i32);
NonZeroU64(u64); NonZeroI64(i64);
NonZeroUsize(usize); NonZeroIsize(isize);
}
nonzero_integers! {
// Change this to `#[unstable(feature = "i128", issue = "35118")]`
// if other NonZero* integer types are stabilizied before 128-bit integers
#[unstable(feature = "nonzero", issue = "49137")]
NonZeroU128(u128); NonZeroI128(i128);
}
/// Provides intentionally-wrapped arithmetic on `T`.
///
/// Operations like `+` on `u32` values is intended to never overflow,

View file

@ -23,7 +23,7 @@ use fmt;
use hash;
use marker::{PhantomData, Unsize};
use mem;
use nonzero::NonZero;
#[allow(deprecated)] use nonzero::NonZero;
use cmp::Ordering::{self, Less, Equal, Greater};
@ -2285,6 +2285,7 @@ impl<T: ?Sized> PartialOrd for *mut T {
#[unstable(feature = "ptr_internals", issue = "0",
reason = "use NonNull instead and consider PhantomData<T> \
(if you also use #[may_dangle]), Send, and/or Sync")]
#[allow(deprecated)]
pub struct Unique<T: ?Sized> {
pointer: NonZero<*const T>,
// NOTE: this marker has no consequences for variance, but is necessary
@ -2332,6 +2333,7 @@ impl<T: Sized> Unique<T> {
}
#[unstable(feature = "ptr_internals", issue = "0")]
#[allow(deprecated)]
impl<T: ?Sized> Unique<T> {
/// Creates a new `Unique`.
///
@ -2339,17 +2341,21 @@ impl<T: ?Sized> Unique<T> {
///
/// `ptr` must be non-null.
pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
Unique { pointer: NonZero::new_unchecked(ptr), _marker: PhantomData }
Unique { pointer: NonZero(ptr as _), _marker: PhantomData }
}
/// Creates a new `Unique` if `ptr` is non-null.
pub fn new(ptr: *mut T) -> Option<Self> {
NonZero::new(ptr as *const T).map(|nz| Unique { pointer: nz, _marker: PhantomData })
if !ptr.is_null() {
Some(Unique { pointer: NonZero(ptr as _), _marker: PhantomData })
} else {
None
}
}
/// Acquires the underlying `*mut` pointer.
pub fn as_ptr(self) -> *mut T {
self.pointer.get() as *mut T
self.pointer.0 as *mut T
}
/// Dereferences the content.
@ -2392,16 +2398,18 @@ impl<T: ?Sized> fmt::Pointer for Unique<T> {
}
#[unstable(feature = "ptr_internals", issue = "0")]
#[allow(deprecated)]
impl<'a, T: ?Sized> From<&'a mut T> for Unique<T> {
fn from(reference: &'a mut T) -> Self {
Unique { pointer: NonZero::from(reference), _marker: PhantomData }
Unique { pointer: NonZero(reference as _), _marker: PhantomData }
}
}
#[unstable(feature = "ptr_internals", issue = "0")]
#[allow(deprecated)]
impl<'a, T: ?Sized> From<&'a T> for Unique<T> {
fn from(reference: &'a T) -> Self {
Unique { pointer: NonZero::from(reference), _marker: PhantomData }
Unique { pointer: NonZero(reference as _), _marker: PhantomData }
}
}
@ -2412,11 +2420,6 @@ impl<'a, T: ?Sized> From<NonNull<T>> for Unique<T> {
}
}
/// Previous name of `NonNull`.
#[rustc_deprecated(since = "1.25.0", reason = "renamed to `NonNull`")]
#[unstable(feature = "shared", issue = "27730")]
pub type Shared<T> = NonNull<T>;
/// `*mut T` but non-zero and covariant.
///
/// This is often the correct thing to use when building data structures using
@ -2436,7 +2439,7 @@ pub type Shared<T> = NonNull<T>;
/// provide a public API that follows the normal shared XOR mutable rules of Rust.
#[stable(feature = "nonnull", since = "1.25.0")]
pub struct NonNull<T: ?Sized> {
pointer: NonZero<*const T>,
#[allow(deprecated)] pointer: NonZero<*const T>,
}
/// `NonNull` pointers are not `Send` because the data they reference may be aliased.
@ -2463,6 +2466,7 @@ impl<T: Sized> NonNull<T> {
}
}
#[allow(deprecated)]
impl<T: ?Sized> NonNull<T> {
/// Creates a new `NonNull`.
///
@ -2471,19 +2475,23 @@ impl<T: ?Sized> NonNull<T> {
/// `ptr` must be non-null.
#[stable(feature = "nonnull", since = "1.25.0")]
pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
NonNull { pointer: NonZero::new_unchecked(ptr) }
NonNull { pointer: NonZero(ptr as _) }
}
/// Creates a new `NonNull` if `ptr` is non-null.
#[stable(feature = "nonnull", since = "1.25.0")]
pub fn new(ptr: *mut T) -> Option<Self> {
NonZero::new(ptr as *const T).map(|nz| NonNull { pointer: nz })
if !ptr.is_null() {
Some(NonNull { pointer: NonZero(ptr as _) })
} else {
None
}
}
/// Acquires the underlying `*mut` pointer.
#[stable(feature = "nonnull", since = "1.25.0")]
pub fn as_ptr(self) -> *mut T {
self.pointer.get() as *mut T
self.pointer.0 as *mut T
}
/// Dereferences the content.
@ -2581,15 +2589,17 @@ impl<T: ?Sized> From<Unique<T>> for NonNull<T> {
}
#[stable(feature = "nonnull", since = "1.25.0")]
#[allow(deprecated)]
impl<'a, T: ?Sized> From<&'a mut T> for NonNull<T> {
fn from(reference: &'a mut T) -> Self {
NonNull { pointer: NonZero::from(reference) }
NonNull { pointer: NonZero(reference as _) }
}
}
#[stable(feature = "nonnull", since = "1.25.0")]
#[allow(deprecated)]
impl<'a, T: ?Sized> From<&'a T> for NonNull<T> {
fn from(reference: &'a T) -> Self {
NonNull { pointer: NonZero::from(reference) }
NonNull { pointer: NonZero(reference as _) }
}
}

View file

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use core::nonzero::NonZero;
use core::num::NonZeroU32;
use core::option::Option;
use core::option::Option::{Some, None};
use std::mem::size_of;
@ -16,28 +16,28 @@ use std::mem::size_of;
#[test]
fn test_create_nonzero_instance() {
let _a = unsafe {
NonZero::new_unchecked(21)
NonZeroU32::new_unchecked(21)
};
}
#[test]
fn test_size_nonzero_in_option() {
assert_eq!(size_of::<NonZero<u32>>(), size_of::<Option<NonZero<u32>>>());
assert_eq!(size_of::<NonZeroU32>(), size_of::<Option<NonZeroU32>>());
}
#[test]
fn test_match_on_nonzero_option() {
let a = Some(unsafe {
NonZero::new_unchecked(42)
NonZeroU32::new_unchecked(42)
});
match a {
Some(val) => assert_eq!(val.get(), 42),
None => panic!("unexpected None while matching on Some(NonZero(_))")
None => panic!("unexpected None while matching on Some(NonZeroU32(_))")
}
match unsafe { Some(NonZero::new_unchecked(43)) } {
match unsafe { Some(NonZeroU32::new_unchecked(43)) } {
Some(val) => assert_eq!(val.get(), 43),
None => panic!("unexpected None while matching on Some(NonZero(_))")
None => panic!("unexpected None while matching on Some(NonZeroU32(_))")
}
}
@ -98,3 +98,26 @@ fn test_match_option_string() {
None => panic!("unexpected None while matching on Some(String { ... })")
}
}
mod atom {
use core::num::NonZeroU32;
#[derive(PartialEq, Eq)]
pub struct Atom {
index: NonZeroU32, // private
}
pub const FOO_ATOM: Atom = Atom { index: unsafe { NonZeroU32::new_unchecked(7) } };
}
macro_rules! atom {
("foo") => { atom::FOO_ATOM }
}
#[test]
fn test_match_nonzero_const_pattern() {
match atom!("foo") {
// Using as a pattern is supported by the compiler:
atom!("foo") => {}
_ => panic!("Expected the const item as a pattern to match.")
}
}

View file

@ -19,11 +19,11 @@ use syntax_pos::{Span, DUMMY_SP};
use rustc_data_structures::accumulate_vec::AccumulateVec;
use core::intrinsics;
use core::nonzero::NonZero;
use std::fmt;
use std::iter;
use std::marker::PhantomData;
use std::mem;
use std::num::NonZeroUsize;
/// An entity in the Rust typesystem, which can be one of
/// several kinds (only types and lifetimes for now).
@ -32,7 +32,7 @@ use std::mem;
/// indicate the type (`Ty` or `Region`) it points to.
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct Kind<'tcx> {
ptr: NonZero<usize>,
ptr: NonZeroUsize,
marker: PhantomData<(Ty<'tcx>, ty::Region<'tcx>)>
}
@ -63,7 +63,7 @@ impl<'tcx> UnpackedKind<'tcx> {
Kind {
ptr: unsafe {
NonZero::new_unchecked(ptr | tag)
NonZeroUsize::new_unchecked(ptr | tag)
},
marker: PhantomData
}

View file

@ -8,18 +8,18 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use core::nonzero::NonZero;
use std::num::NonZeroU32;
use std::u32;
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct NodeIndex {
index: NonZero<u32>,
index: NonZeroU32,
}
impl NodeIndex {
pub fn new(value: usize) -> NodeIndex {
assert!(value < (u32::MAX as usize));
NodeIndex { index: NonZero::new((value as u32) + 1).unwrap() }
NodeIndex { index: NonZeroU32::new((value as u32) + 1).unwrap() }
}
pub fn get(self) -> usize {

View file

@ -29,17 +29,17 @@ mod abs_domain;
// (which is likely to yield a subtle off-by-one error).
pub(crate) mod indexes {
use std::fmt;
use core::nonzero::NonZero;
use std::num::NonZeroUsize;
use rustc_data_structures::indexed_vec::Idx;
macro_rules! new_index {
($Index:ident, $debug_name:expr) => {
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct $Index(NonZero<usize>);
pub struct $Index(NonZeroUsize);
impl Idx for $Index {
fn new(idx: usize) -> Self {
$Index(NonZero::new(idx + 1).unwrap())
$Index(NonZeroUsize::new(idx + 1).unwrap())
}
fn index(self) -> usize {
self.0.get() - 1

View file

@ -282,6 +282,7 @@
#![feature(macro_vis_matcher)]
#![feature(needs_panic_runtime)]
#![feature(exhaustive_patterns)]
#![feature(nonzero)]
#![feature(num_bits_bytes)]
#![feature(old_wrapping)]
#![feature(on_unimplemented)]

View file

@ -21,6 +21,17 @@ pub use core::num::{FpCategory, ParseIntError, ParseFloatError, TryFromIntError}
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::num::Wrapping;
#[unstable(feature = "nonzero", issue = "49137")]
pub use core::num::{
NonZeroU8, NonZeroI8, NonZeroU16, NonZeroI16, NonZeroU32, NonZeroI32,
NonZeroU64, NonZeroI64, NonZeroUsize, NonZeroIsize,
};
// Change this to `#[unstable(feature = "i128", issue = "35118")]`
// if other NonZero* integer types are stabilizied before 128-bit integers
#[unstable(feature = "nonzero", issue = "49137")]
pub use core::num::{NonZeroU128, NonZeroI128};
#[cfg(test)] use fmt;
#[cfg(test)] use ops::{Add, Sub, Mul, Div, Rem};

View file

@ -10,10 +10,9 @@
#![feature(nonzero, core)]
extern crate core;
use core::nonzero::NonZero;
use std::mem::size_of;
use std::num::NonZeroUsize;
use std::ptr::NonNull;
use std::rc::Rc;
use std::sync::Arc;
@ -59,8 +58,8 @@ fn main() {
assert_eq!(size_of::<[Box<isize>; 1]>(), size_of::<Option<[Box<isize>; 1]>>());
// Should apply to NonZero
assert_eq!(size_of::<NonZero<usize>>(), size_of::<Option<NonZero<usize>>>());
assert_eq!(size_of::<NonZero<*mut i8>>(), size_of::<Option<NonZero<*mut i8>>>());
assert_eq!(size_of::<NonZeroUsize>(), size_of::<Option<NonZeroUsize>>());
assert_eq!(size_of::<NonNull<i8>>(), size_of::<Option<NonNull<i8>>>());
// Should apply to types that use NonZero internally
assert_eq!(size_of::<Vec<isize>>(), size_of::<Option<Vec<isize>>>());

View file

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Don't fail if we encounter a NonZero<*T> where T is an unsized type
// Don't fail if we encounter a NonNull<T> where T is an unsized type
use std::ptr::NonNull;

View file

@ -14,7 +14,7 @@
// This file illustrates how niche-filling enums are handled,
// modelled after cases like `Option<&u32>`, `Option<bool>` and such.
//
// It uses NonZero directly, rather than `&_` or `Unique<_>`, because
// It uses NonZeroU32 rather than `&_` or `Unique<_>`, because
// the test is not set up to deal with target-dependent pointer width.
//
// It avoids using u64/i64 because on some targets that is only 4-byte
@ -25,8 +25,7 @@
#![feature(nonzero)]
#![allow(dead_code)]
extern crate core;
use core::nonzero::{NonZero, Zeroable};
use std::num::NonZeroU32;
pub enum MyOption<T> { None, Some(T) }
@ -36,7 +35,7 @@ impl<T> Default for MyOption<T> {
pub enum EmbeddedDiscr {
None,
Record { pre: u8, val: NonZero<u32>, post: u16 },
Record { pre: u8, val: NonZeroU32, post: u16 },
}
impl Default for EmbeddedDiscr {
@ -44,32 +43,24 @@ impl Default for EmbeddedDiscr {
}
#[derive(Default)]
pub struct IndirectNonZero<T: Zeroable + One> {
pub struct IndirectNonZero {
pre: u8,
nested: NestedNonZero<T>,
nested: NestedNonZero,
post: u16,
}
pub struct NestedNonZero<T: Zeroable> {
pub struct NestedNonZero {
pre: u8,
val: NonZero<T>,
val: NonZeroU32,
post: u16,
}
impl<T: Zeroable+One> Default for NestedNonZero<T> {
impl Default for NestedNonZero {
fn default() -> Self {
NestedNonZero { pre: 0, val: NonZero::new(T::one()).unwrap(), post: 0 }
NestedNonZero { pre: 0, val: NonZeroU32::new(1).unwrap(), post: 0 }
}
}
pub trait One {
fn one() -> Self;
}
impl One for u32 {
fn one() -> Self { 1 }
}
pub enum Enum4<A, B, C, D> {
One(A),
Two(B),
@ -79,9 +70,9 @@ pub enum Enum4<A, B, C, D> {
#[start]
fn start(_: isize, _: *const *const u8) -> isize {
let _x: MyOption<NonZero<u32>> = Default::default();
let _x: MyOption<NonZeroU32> = Default::default();
let _y: EmbeddedDiscr = Default::default();
let _z: MyOption<IndirectNonZero<u32>> = Default::default();
let _z: MyOption<IndirectNonZero> = Default::default();
let _a: MyOption<bool> = Default::default();
let _b: MyOption<char> = Default::default();
let _c: MyOption<std::cmp::Ordering> = Default::default();

View file

@ -1,9 +1,9 @@
print-type-size type: `IndirectNonZero<u32>`: 12 bytes, alignment: 4 bytes
print-type-size type: `IndirectNonZero`: 12 bytes, alignment: 4 bytes
print-type-size field `.nested`: 8 bytes
print-type-size field `.post`: 2 bytes
print-type-size field `.pre`: 1 bytes
print-type-size end padding: 1 bytes
print-type-size type: `MyOption<IndirectNonZero<u32>>`: 12 bytes, alignment: 4 bytes
print-type-size type: `MyOption<IndirectNonZero>`: 12 bytes, alignment: 4 bytes
print-type-size variant `None`: 0 bytes
print-type-size variant `Some`: 12 bytes
print-type-size field `.0`: 12 bytes
@ -14,7 +14,7 @@ print-type-size field `.val`: 4 bytes
print-type-size field `.post`: 2 bytes
print-type-size field `.pre`: 1 bytes
print-type-size end padding: 1 bytes
print-type-size type: `NestedNonZero<u32>`: 8 bytes, alignment: 4 bytes
print-type-size type: `NestedNonZero`: 8 bytes, alignment: 4 bytes
print-type-size field `.val`: 4 bytes
print-type-size field `.post`: 2 bytes
print-type-size field `.pre`: 1 bytes
@ -32,12 +32,14 @@ print-type-size type: `MyOption<char>`: 4 bytes, alignment: 4 bytes
print-type-size variant `None`: 0 bytes
print-type-size variant `Some`: 4 bytes
print-type-size field `.0`: 4 bytes
print-type-size type: `MyOption<core::nonzero::NonZero<u32>>`: 4 bytes, alignment: 4 bytes
print-type-size type: `MyOption<std::num::NonZeroU32>`: 4 bytes, alignment: 4 bytes
print-type-size variant `None`: 0 bytes
print-type-size variant `Some`: 4 bytes
print-type-size field `.0`: 4 bytes
print-type-size type: `core::nonzero::NonZero<u32>`: 4 bytes, alignment: 4 bytes
print-type-size field `.0`: 4 bytes
print-type-size type: `std::num::NonZeroU32`: 4 bytes, alignment: 4 bytes
print-type-size field `.0`: 4 bytes
print-type-size type: `Enum4<(), (), (), MyOption<u8>>`: 2 bytes, alignment: 1 bytes
print-type-size variant `One`: 0 bytes
print-type-size field `.0`: 0 bytes