Skip to content

Commit 0cdde6e

Browse files
committed
std: Stabilize FromStr and parse
This commits adds an associated type to the `FromStr` trait representing an error payload for parses which do not succeed. The previous return value, `Option<Self>` did not allow for this form of payload. After the associated type was added, the following attributes were applied: * `FromStr` is now stable * `FromStr::Err` is now stable * `FromStr::from_str` is now stable * `StrExt::parse` is now stable * `FromStr for bool` is now stable * `FromStr for $float` is now stable * `FromStr for $integral` is now stable * Errors returned from stable `FromStr` implementations are stable * Errors implement `Display` and `Error` (both impl blocks being `#[stable]`) Closes #15138
1 parent 1a51eb9 commit 0cdde6e

39 files changed

+392
-263
lines changed

src/compiletest/common.rs

+11-10
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,18 @@ pub enum Mode {
2525
}
2626

2727
impl FromStr for Mode {
28-
fn from_str(s: &str) -> Option<Mode> {
28+
type Err = ();
29+
fn from_str(s: &str) -> Result<Mode, ()> {
2930
match s {
30-
"compile-fail" => Some(CompileFail),
31-
"run-fail" => Some(RunFail),
32-
"run-pass" => Some(RunPass),
33-
"run-pass-valgrind" => Some(RunPassValgrind),
34-
"pretty" => Some(Pretty),
35-
"debuginfo-lldb" => Some(DebugInfoLldb),
36-
"debuginfo-gdb" => Some(DebugInfoGdb),
37-
"codegen" => Some(Codegen),
38-
_ => None,
31+
"compile-fail" => Ok(CompileFail),
32+
"run-fail" => Ok(RunFail),
33+
"run-pass" => Ok(RunPass),
34+
"run-pass-valgrind" => Ok(RunPassValgrind),
35+
"pretty" => Ok(Pretty),
36+
"debuginfo-lldb" => Ok(DebugInfoLldb),
37+
"debuginfo-gdb" => Ok(DebugInfoGdb),
38+
"codegen" => Ok(Codegen),
39+
_ => Err(()),
3940
}
4041
}
4142
}

src/compiletest/compiletest.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ extern crate log;
3535
use std::os;
3636
use std::old_io;
3737
use std::old_io::fs;
38-
use std::str::FromStr;
3938
use std::thunk::Thunk;
4039
use getopts::{optopt, optflag, reqopt};
4140
use common::Config;
@@ -140,9 +139,7 @@ pub fn parse_config(args: Vec<String> ) -> Config {
140139
build_base: opt_path(matches, "build-base"),
141140
aux_base: opt_path(matches, "aux-base"),
142141
stage_id: matches.opt_str("stage-id").unwrap(),
143-
mode: FromStr::from_str(matches.opt_str("mode")
144-
.unwrap()
145-
.as_slice()).expect("invalid mode"),
142+
mode: matches.opt_str("mode").unwrap().parse().ok().expect("invalid mode"),
146143
run_ignored: matches.opt_present("ignored"),
147144
filter: filter,
148145
logfile: matches.opt_str("logfile").map(|s| Path::new(s)),

src/compiletest/header.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -352,8 +352,8 @@ pub fn gdb_version_to_int(version_string: &str) -> int {
352352
panic!("{}", error_string);
353353
}
354354

355-
let major: int = components[0].parse().expect(error_string);
356-
let minor: int = components[1].parse().expect(error_string);
355+
let major: int = components[0].parse().ok().expect(error_string);
356+
let minor: int = components[1].parse().ok().expect(error_string);
357357

358358
return major * 1000 + minor;
359359
}
@@ -363,6 +363,6 @@ pub fn lldb_version_to_int(version_string: &str) -> int {
363363
"Encountered LLDB version string with unexpected format: {}",
364364
version_string);
365365
let error_string = error_string.as_slice();
366-
let major: int = version_string.parse().expect(error_string);
366+
let major: int = version_string.parse().ok().expect(error_string);
367367
return major;
368368
}

src/doc/reference.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -2994,7 +2994,7 @@ Some examples of call expressions:
29942994
# fn add(x: i32, y: i32) -> i32 { 0 }
29952995
29962996
let x: i32 = add(1i32, 2i32);
2997-
let pi: Option<f32> = "3.14".parse();
2997+
let pi: Option<f32> = "3.14".parse().ok();
29982998
```
29992999

30003000
### Lambda expressions

src/doc/trpl/guessing-game.md

+13-11
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,7 @@ a function for that:
400400
let input = old_io::stdin().read_line()
401401
.ok()
402402
.expect("Failed to read line");
403-
let input_num: Option<u32> = input.parse();
403+
let input_num: Option<u32> = input.parse().ok();
404404
```
405405
406406
The `parse` function takes in a `&str` value and converts it into something.
@@ -422,11 +422,13 @@ In this case, we say `x` is a `u32` explicitly, so Rust is able to properly
422422
tell `random()` what to generate. In a similar fashion, both of these work:
423423
424424
```{rust,ignore}
425-
let input_num = "5".parse::<u32>(); // input_num: Option<u32>
426-
let input_num: Option<u32> = "5".parse(); // input_num: Option<u32>
425+
let input_num = "5".parse::<u32>().ok(); // input_num: Option<u32>
426+
let input_num: Option<u32> = "5".parse().ok(); // input_num: Option<u32>
427427
```
428428
429-
Anyway, with us now converting our input to a number, our code looks like this:
429+
Here we're converting the `Result` returned by `parse` to an `Option` by using
430+
the `ok` method as well. Anyway, with us now converting our input to a number,
431+
our code looks like this:
430432
431433
```{rust,ignore}
432434
use std::old_io;
@@ -445,7 +447,7 @@ fn main() {
445447
let input = old_io::stdin().read_line()
446448
.ok()
447449
.expect("Failed to read line");
448-
let input_num: Option<u32> = input.parse();
450+
let input_num: Option<u32> = input.parse().ok();
449451
450452
println!("You guessed: {}", input_num);
451453
@@ -495,7 +497,7 @@ fn main() {
495497
let input = old_io::stdin().read_line()
496498
.ok()
497499
.expect("Failed to read line");
498-
let input_num: Option<u32> = input.parse();
500+
let input_num: Option<u32> = input.parse().ok();
499501

500502
let num = match input_num {
501503
Some(num) => num,
@@ -562,7 +564,7 @@ fn main() {
562564
let input = old_io::stdin().read_line()
563565
.ok()
564566
.expect("Failed to read line");
565-
let input_num: Option<u32> = input.trim().parse();
567+
let input_num: Option<u32> = input.trim().parse().ok();
566568

567569
let num = match input_num {
568570
Some(num) => num,
@@ -638,7 +640,7 @@ fn main() {
638640
let input = old_io::stdin().read_line()
639641
.ok()
640642
.expect("Failed to read line");
641-
let input_num: Option<u32> = input.trim().parse();
643+
let input_num: Option<u32> = input.trim().parse().ok();
642644
643645
let num = match input_num {
644646
Some(num) => num,
@@ -714,7 +716,7 @@ fn main() {
714716
let input = old_io::stdin().read_line()
715717
.ok()
716718
.expect("Failed to read line");
717-
let input_num: Option<u32> = input.trim().parse();
719+
let input_num: Option<u32> = input.trim().parse().ok();
718720

719721
let num = match input_num {
720722
Some(num) => num,
@@ -770,7 +772,7 @@ fn main() {
770772
let input = old_io::stdin().read_line()
771773
.ok()
772774
.expect("Failed to read line");
773-
let input_num: Option<u32> = input.trim().parse();
775+
let input_num: Option<u32> = input.trim().parse().ok();
774776

775777
let num = match input_num {
776778
Some(num) => num,
@@ -847,7 +849,7 @@ fn main() {
847849
let input = old_io::stdin().read_line()
848850
.ok()
849851
.expect("Failed to read line");
850-
let input_num: Option<u32> = input.trim().parse();
852+
let input_num: Option<u32> = input.trim().parse().ok();
851853

852854
let num = match input_num {
853855
Some(num) => num,

src/libcollections/str.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ use core::ops::FullRange;
6868
#[cfg(not(stage0))]
6969
use core::ops::RangeFull;
7070
use core::option::Option::{self, Some, None};
71+
use core::result::Result;
7172
use core::slice::AsSlice;
7273
use core::str as core_str;
7374
use unicode::str::{UnicodeStr, Utf16Encoder};
@@ -1231,13 +1232,12 @@ pub trait StrExt: Index<RangeFull, Output = str> {
12311232
/// # Example
12321233
///
12331234
/// ```
1234-
/// assert_eq!("4".parse::<u32>(), Some(4));
1235-
/// assert_eq!("j".parse::<u32>(), None);
1235+
/// assert_eq!("4".parse::<u32>(), Ok(4));
1236+
/// assert!("j".parse::<u32>().is_err());
12361237
/// ```
12371238
#[inline]
1238-
#[unstable(feature = "collections",
1239-
reason = "this method was just created")]
1240-
fn parse<F: FromStr>(&self) -> Option<F> {
1239+
#[stable(feature = "rust1", since = "1.0.0")]
1240+
fn parse<F: FromStr>(&self) -> Result<F, F::Err> {
12411241
core_str::StrExt::parse(&self[])
12421242
}
12431243

src/libcollections/string.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -940,10 +940,12 @@ pub fn as_string<'a>(x: &'a str) -> DerefString<'a> {
940940
DerefString { x: as_vec(x.as_bytes()) }
941941
}
942942

943+
#[unstable(feature = "collections", reason = "associated error type may change")]
943944
impl FromStr for String {
945+
type Err = ();
944946
#[inline]
945-
fn from_str(s: &str) -> Option<String> {
946-
Some(String::from_str(s))
947+
fn from_str(s: &str) -> Result<String, ()> {
948+
Ok(String::from_str(s))
947949
}
948950
}
949951

@@ -1016,7 +1018,7 @@ mod tests {
10161018

10171019
#[test]
10181020
fn test_from_str() {
1019-
let owned: Option<::std::string::String> = "string".parse();
1021+
let owned: Option<::std::string::String> = "string".parse().ok();
10201022
assert_eq!(owned.as_ref().map(|s| s.as_slice()), Some("string"));
10211023
}
10221024

0 commit comments

Comments
 (0)