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:
commit
7cf4cb5a7b
15 changed files with 210 additions and 89 deletions
|
|
@ -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>>(),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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> {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 _) }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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};
|
||||
|
||||
|
|
|
|||
|
|
@ -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>>>());
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue