Skip to content

Commit df0f1ae

Browse files
committed
Carry index of InvalidDigit on IntErrorKind
1 parent a0d66b5 commit df0f1ae

File tree

5 files changed

+33
-28
lines changed

5 files changed

+33
-28
lines changed

compiler/rustc_middle/src/middle/limits.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ fn update_limit(
4949
let error_str = match e.kind() {
5050
IntErrorKind::PosOverflow => "`limit` is too large",
5151
IntErrorKind::Empty => "`limit` must be a non-negative integer",
52-
IntErrorKind::InvalidDigit => "not a valid integer",
52+
IntErrorKind::InvalidDigit(_) => "not a valid integer",
5353
IntErrorKind::NegOverflow => {
5454
bug!("`limit` should never negatively overflow")
5555
}

library/core/src/num/error.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,14 +95,14 @@ pub enum IntErrorKind {
9595
///
9696
/// Among other causes, this variant will be constructed when parsing an empty string.
9797
Empty,
98-
/// Contains an invalid digit in its context.
98+
/// Contains an invalid digit at the index provided.
9999
///
100100
/// Among other causes, this variant will be constructed when parsing a string that
101101
/// contains a non-ASCII char.
102102
///
103103
/// This variant is also constructed when a `+` or `-` is misplaced within a string
104104
/// either on its own or in the middle of a number.
105-
InvalidDigit,
105+
InvalidDigit(usize),
106106
/// Integer is too large to store in target integer type.
107107
PosOverflow,
108108
/// Integer is too small to store in target integer type.
@@ -135,7 +135,7 @@ impl ParseIntError {
135135
pub fn __description(&self) -> &str {
136136
match self.kind {
137137
IntErrorKind::Empty => "cannot parse integer from empty string",
138-
IntErrorKind::InvalidDigit => "invalid digit found in string",
138+
IntErrorKind::InvalidDigit(_) => "invalid digit found in string",
139139
IntErrorKind::PosOverflow => "number too large to fit in target type",
140140
IntErrorKind::NegOverflow => "number too small to fit in target type",
141141
IntErrorKind::Zero => "number would be zero for non-zero type",

library/core/src/num/mod.rs

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -824,34 +824,39 @@ fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) -> Result<T, Par
824824
radix
825825
);
826826

827-
if src.is_empty() {
828-
return Err(PIE { kind: Empty });
829-
}
830-
831827
let is_signed_ty = T::from_u32(0) > T::min_value();
832828

833829
// all valid digits are ascii, so we will just iterate over the utf8 bytes
834830
// and cast them to chars. .to_digit() will safely return None for anything
835831
// other than a valid ascii digit for the given radix, including the first-byte
836832
// of multi-byte sequences
837-
let src = src.as_bytes();
838-
839-
let (is_positive, digits) = match src[0] {
840-
b'+' | b'-' if src[1..].is_empty() => {
841-
return Err(PIE { kind: InvalidDigit });
833+
let mut src = src.as_bytes().iter().enumerate().peekable();
834+
835+
let first_digit = src.peek().ok_or(PIE { kind: Empty })?.1;
836+
837+
let (is_positive, digits) = match first_digit {
838+
b'+' | b'-' => {
839+
src.next();
840+
if src.peek().is_none() {
841+
return Err(PIE { kind: InvalidDigit(0) });
842+
} else {
843+
match first_digit {
844+
b'+' => (true, src),
845+
b'-' if is_signed_ty => (false, src),
846+
_ => return Err(PIE { kind: InvalidDigit(0) }),
847+
}
848+
}
842849
}
843-
b'+' => (true, &src[1..]),
844-
b'-' if is_signed_ty => (false, &src[1..]),
845850
_ => (true, src),
846851
};
847852

848853
let mut result = T::from_u32(0);
849854
if is_positive {
850855
// The number is positive
851-
for &c in digits {
856+
for (index, &c) in digits {
852857
let x = match (c as char).to_digit(radix) {
853858
Some(x) => x,
854-
None => return Err(PIE { kind: InvalidDigit }),
859+
None => return Err(PIE { kind: InvalidDigit(index) }),
855860
};
856861
result = match result.checked_mul(radix) {
857862
Some(result) => result,
@@ -864,10 +869,10 @@ fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) -> Result<T, Par
864869
}
865870
} else {
866871
// The number is negative
867-
for &c in digits {
872+
for (index, &c) in digits {
868873
let x = match (c as char).to_digit(radix) {
869874
Some(x) => x,
870-
None => return Err(PIE { kind: InvalidDigit }),
875+
None => return Err(PIE { kind: InvalidDigit(index) }),
871876
};
872877
result = match result.checked_mul(radix) {
873878
Some(result) => result,

library/core/tests/nonzero.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ fn test_from_str() {
134134
assert_eq!("0".parse::<NonZeroU8>().err().map(|e| e.kind().clone()), Some(IntErrorKind::Zero));
135135
assert_eq!(
136136
"-1".parse::<NonZeroU8>().err().map(|e| e.kind().clone()),
137-
Some(IntErrorKind::InvalidDigit)
137+
Some(IntErrorKind::InvalidDigit(0))
138138
);
139139
assert_eq!(
140140
"-129".parse::<NonZeroI8>().err().map(|e| e.kind().clone()),

library/core/tests/num/mod.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -124,14 +124,14 @@ fn test_leading_plus() {
124124

125125
#[test]
126126
fn test_invalid() {
127-
test_parse::<i8>("--129", Err(IntErrorKind::InvalidDigit));
128-
test_parse::<i8>("++129", Err(IntErrorKind::InvalidDigit));
129-
test_parse::<u8>("Съешь", Err(IntErrorKind::InvalidDigit));
130-
test_parse::<u8>("123Hello", Err(IntErrorKind::InvalidDigit));
131-
test_parse::<i8>("--", Err(IntErrorKind::InvalidDigit));
132-
test_parse::<i8>("-", Err(IntErrorKind::InvalidDigit));
133-
test_parse::<i8>("+", Err(IntErrorKind::InvalidDigit));
134-
test_parse::<u8>("-1", Err(IntErrorKind::InvalidDigit));
127+
test_parse::<i8>("--129", Err(IntErrorKind::InvalidDigit(1)));
128+
test_parse::<i8>("++129", Err(IntErrorKind::InvalidDigit(1)));
129+
test_parse::<u8>("Съешь", Err(IntErrorKind::InvalidDigit(0)));
130+
test_parse::<u8>("123Hello", Err(IntErrorKind::InvalidDigit(3)));
131+
test_parse::<i8>("--", Err(IntErrorKind::InvalidDigit(1)));
132+
test_parse::<i8>("-", Err(IntErrorKind::InvalidDigit(0)));
133+
test_parse::<i8>("+", Err(IntErrorKind::InvalidDigit(0)));
134+
test_parse::<u8>("-1", Err(IntErrorKind::InvalidDigit(0)));
135135
}
136136

137137
#[test]

0 commit comments

Comments
 (0)