about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2019-03-28 13:35:29 +0100
committerGitHub <noreply@github.com>2019-03-28 13:35:29 +0100
commitf90ac4f04a740e1f676847209d1f376753bca0d7 (patch)
treebeb20e940c85cf0f5afb2bf6e896beb45cd44b05
parent237bf3244fffef501cf37d4bda00e1fce3fcfb46 (diff)
parent8f3e862797ecf83e89245d3f28532ab285c780ef (diff)
downloadrust-f90ac4f04a740e1f676847209d1f376753bca0d7.tar.gz
rust-f90ac4f04a740e1f676847209d1f376753bca0d7.zip
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
-rw-r--r--src/libcore/num/mod.rs24
-rw-r--r--src/libcore/tests/lib.rs1
-rw-r--r--src/libcore/tests/nonzero.rs26
-rw-r--r--src/librustc_codegen_llvm/debuginfo/metadata.rs3
4 files changed, 50 insertions, 4 deletions
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index 3fcae6b94b0..01da5518868 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -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",
         }
     }
 }
diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs
index 08dda4bcc3d..2ed25a34102 100644
--- a/src/libcore/tests/lib.rs
+++ b/src/libcore/tests/lib.rs
@@ -31,6 +31,7 @@
 #![feature(slice_internals)]
 #![feature(slice_partition_dedup)]
 #![feature(copy_within)]
+#![feature(int_error_matching)]
 
 extern crate core;
 extern crate test;
diff --git a/src/libcore/tests/nonzero.rs b/src/libcore/tests/nonzero.rs
index 4532568ee0c..77e484601bc 100644
--- a/src/libcore/tests/nonzero.rs
+++ b/src/libcore/tests/nonzero.rs
@@ -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)
+    );
+}
diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs
index 8efa025e3dd..042a8c60cfa 100644
--- a/src/librustc_codegen_llvm/debuginfo/metadata.rs
+++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs
@@ -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)
                         };