Skip to content

Commit

Permalink
Rollup merge of rust-lang#58717 - hellow554:nonzero_parse, r=oli-obk
Browse files Browse the repository at this point in the history
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 rust-lang#58604
  • Loading branch information
Centril authored Mar 28, 2019
2 parents 237bf32 + 8f3e862 commit f90ac4f
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 4 deletions.
24 changes: 24 additions & 0 deletions src/libcore/num/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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 {
Expand All @@ -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",
}
}
}
Expand Down
1 change: 1 addition & 0 deletions src/libcore/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#![feature(slice_internals)]
#![feature(slice_partition_dedup)]
#![feature(copy_within)]
#![feature(int_error_matching)]

extern crate core;
extern crate test;
Expand Down
26 changes: 23 additions & 3 deletions src/libcore/tests/nonzero.rs
Original file line number Diff line number Diff line change
@@ -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]
Expand Down Expand Up @@ -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)
);
}
3 changes: 2 additions & 1 deletion src/librustc_codegen_llvm/debuginfo/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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)
};

Expand Down

0 comments on commit f90ac4f

Please sign in to comment.