Skip to content

Commit f90ac4f

Browse files
authored
Rollup merge of rust-lang#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 rust-lang#58604
2 parents 237bf32 + 8f3e862 commit f90ac4f

File tree

4 files changed

+50
-4
lines changed

4 files changed

+50
-4
lines changed

src/libcore/num/mod.rs

+24
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,24 @@ nonzero_integers! {
112112
#[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroIsize(isize);
113113
}
114114

115+
macro_rules! from_str_radix_nzint_impl {
116+
($($t:ty)*) => {$(
117+
#[stable(feature = "nonzero_parse", since = "1.35.0")]
118+
impl FromStr for $t {
119+
type Err = ParseIntError;
120+
fn from_str(src: &str) -> Result<Self, Self::Err> {
121+
Self::new(from_str_radix(src, 10)?)
122+
.ok_or(ParseIntError {
123+
kind: IntErrorKind::Zero
124+
})
125+
}
126+
}
127+
)*}
128+
}
129+
130+
from_str_radix_nzint_impl! { NonZeroU8 NonZeroU16 NonZeroU32 NonZeroU64 NonZeroU128 NonZeroUsize
131+
NonZeroI8 NonZeroI16 NonZeroI32 NonZeroI64 NonZeroI128 NonZeroIsize }
132+
115133
/// Provides intentionally-wrapped arithmetic on `T`.
116134
///
117135
/// Operations like `+` on `u32` values is intended to never overflow,
@@ -4768,6 +4786,11 @@ pub enum IntErrorKind {
47684786
Overflow,
47694787
/// Integer is too small to store in target integer type.
47704788
Underflow,
4789+
/// Value was Zero
4790+
///
4791+
/// This variant will be emitted when the parsing string has a value of zero, which
4792+
/// would be illegal for non-zero types.
4793+
Zero,
47714794
}
47724795

47734796
impl ParseIntError {
@@ -4790,6 +4813,7 @@ impl ParseIntError {
47904813
IntErrorKind::InvalidDigit => "invalid digit found in string",
47914814
IntErrorKind::Overflow => "number too large to fit in target type",
47924815
IntErrorKind::Underflow => "number too small to fit in target type",
4816+
IntErrorKind::Zero => "number would be zero for non-zero type",
47934817
}
47944818
}
47954819
}

src/libcore/tests/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#![feature(slice_internals)]
3232
#![feature(slice_partition_dedup)]
3333
#![feature(copy_within)]
34+
#![feature(int_error_matching)]
3435

3536
extern crate core;
3637
extern crate test;

src/libcore/tests/nonzero.rs

+23-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
use core::num::{NonZeroU32, NonZeroI32};
2-
use core::option::Option;
3-
use core::option::Option::{Some, None};
1+
use core::num::{IntErrorKind, NonZeroI32, NonZeroI8, NonZeroU32, NonZeroU8};
2+
use core::option::Option::{self, None, Some};
43
use std::mem::size_of;
54

65
#[test]
@@ -126,3 +125,24 @@ fn test_from_signed_nonzero() {
126125
let num: i32 = nz.into();
127126
assert_eq!(num, 1i32);
128127
}
128+
129+
#[test]
130+
fn test_from_str() {
131+
assert_eq!("123".parse::<NonZeroU8>(), Ok(NonZeroU8::new(123).unwrap()));
132+
assert_eq!(
133+
"0".parse::<NonZeroU8>().err().map(|e| e.kind().clone()),
134+
Some(IntErrorKind::Zero)
135+
);
136+
assert_eq!(
137+
"-1".parse::<NonZeroU8>().err().map(|e| e.kind().clone()),
138+
Some(IntErrorKind::InvalidDigit)
139+
);
140+
assert_eq!(
141+
"-129".parse::<NonZeroI8>().err().map(|e| e.kind().clone()),
142+
Some(IntErrorKind::Underflow)
143+
);
144+
assert_eq!(
145+
"257".parse::<NonZeroU8>().err().map(|e| e.kind().clone()),
146+
Some(IntErrorKind::Overflow)
147+
);
148+
}

src/librustc_codegen_llvm/debuginfo/metadata.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use rustc::hir::CodegenFnAttrFlags;
2222
use rustc::hir::def::CtorKind;
2323
use rustc::hir::def_id::{DefId, CrateNum, LOCAL_CRATE};
2424
use rustc::ich::NodeIdHashingMode;
25+
use rustc::mir::interpret::truncate;
2526
use rustc_data_structures::fingerprint::Fingerprint;
2627
use rustc::ty::Instance;
2728
use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt};
@@ -1368,7 +1369,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
13681369
let value = (i.as_u32() as u128)
13691370
.wrapping_sub(niche_variants.start().as_u32() as u128)
13701371
.wrapping_add(niche_start);
1371-
let value = value & ((1u128 << niche.value.size(cx).bits()) - 1);
1372+
let value = truncate(value, niche.value.size(cx));
13721373
Some(value as u64)
13731374
};
13741375

0 commit comments

Comments
 (0)