Rollup merge of #58717 - hellow554:nonzero_parse, r=oli-obk

Add FromStr impl for NonZero types

This is a WIP implementation because I do have some questions regarding the solution.

Somebody should ping the lang team on this I guess.
Please see the annotations on the code for more details.

Closes #58604
This commit is contained in:
Mazdak Farrokhzad 2019-03-28 13:35:29 +01:00 committed by GitHub
commit f90ac4f04a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 50 additions and 4 deletions

View File

@ -112,6 +112,24 @@ nonzero_integers! {
#[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroIsize(isize);
}
macro_rules! from_str_radix_nzint_impl {
($($t:ty)*) => {$(
#[stable(feature = "nonzero_parse", since = "1.35.0")]
impl FromStr for $t {
type Err = ParseIntError;
fn from_str(src: &str) -> Result<Self, Self::Err> {
Self::new(from_str_radix(src, 10)?)
.ok_or(ParseIntError {
kind: IntErrorKind::Zero
})
}
}
)*}
}
from_str_radix_nzint_impl! { NonZeroU8 NonZeroU16 NonZeroU32 NonZeroU64 NonZeroU128 NonZeroUsize
NonZeroI8 NonZeroI16 NonZeroI32 NonZeroI64 NonZeroI128 NonZeroIsize }
/// Provides intentionally-wrapped arithmetic on `T`.
///
/// Operations like `+` on `u32` values is intended to never overflow,
@ -4768,6 +4786,11 @@ pub enum IntErrorKind {
Overflow,
/// Integer is too small to store in target integer type.
Underflow,
/// Value was Zero
///
/// This variant will be emitted when the parsing string has a value of zero, which
/// would be illegal for non-zero types.
Zero,
}
impl ParseIntError {
@ -4790,6 +4813,7 @@ impl ParseIntError {
IntErrorKind::InvalidDigit => "invalid digit found in string",
IntErrorKind::Overflow => "number too large to fit in target type",
IntErrorKind::Underflow => "number too small to fit in target type",
IntErrorKind::Zero => "number would be zero for non-zero type",
}
}
}

View File

@ -31,6 +31,7 @@
#![feature(slice_internals)]
#![feature(slice_partition_dedup)]
#![feature(copy_within)]
#![feature(int_error_matching)]
extern crate core;
extern crate test;

View File

@ -1,6 +1,5 @@
use core::num::{NonZeroU32, NonZeroI32};
use core::option::Option;
use core::option::Option::{Some, None};
use core::num::{IntErrorKind, NonZeroI32, NonZeroI8, NonZeroU32, NonZeroU8};
use core::option::Option::{self, None, Some};
use std::mem::size_of;
#[test]
@ -126,3 +125,24 @@ fn test_from_signed_nonzero() {
let num: i32 = nz.into();
assert_eq!(num, 1i32);
}
#[test]
fn test_from_str() {
assert_eq!("123".parse::<NonZeroU8>(), Ok(NonZeroU8::new(123).unwrap()));
assert_eq!(
"0".parse::<NonZeroU8>().err().map(|e| e.kind().clone()),
Some(IntErrorKind::Zero)
);
assert_eq!(
"-1".parse::<NonZeroU8>().err().map(|e| e.kind().clone()),
Some(IntErrorKind::InvalidDigit)
);
assert_eq!(
"-129".parse::<NonZeroI8>().err().map(|e| e.kind().clone()),
Some(IntErrorKind::Underflow)
);
assert_eq!(
"257".parse::<NonZeroU8>().err().map(|e| e.kind().clone()),
Some(IntErrorKind::Overflow)
);
}

View File

@ -22,6 +22,7 @@ use rustc::hir::CodegenFnAttrFlags;
use rustc::hir::def::CtorKind;
use rustc::hir::def_id::{DefId, CrateNum, LOCAL_CRATE};
use rustc::ich::NodeIdHashingMode;
use rustc::mir::interpret::truncate;
use rustc_data_structures::fingerprint::Fingerprint;
use rustc::ty::Instance;
use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt};
@ -1368,7 +1369,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
let value = (i.as_u32() as u128)
.wrapping_sub(niche_variants.start().as_u32() as u128)
.wrapping_add(niche_start);
let value = value & ((1u128 << niche.value.size(cx).bits()) - 1);
let value = truncate(value, niche.value.size(cx));
Some(value as u64)
};