From 3a82feea92f0d165bd8225835e88e790b6adf0cd Mon Sep 17 00:00:00 2001 From: Malobre Date: Mon, 11 May 2020 18:51:56 +0200 Subject: [PATCH 1/9] Create 0000-deprecate-fromstr.md --- text/0000-deprecate-fromstr.md | 83 ++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 text/0000-deprecate-fromstr.md diff --git a/text/0000-deprecate-fromstr.md b/text/0000-deprecate-fromstr.md new file mode 100644 index 00000000000..579ce4aada8 --- /dev/null +++ b/text/0000-deprecate-fromstr.md @@ -0,0 +1,83 @@ +- Feature Name: deprecate_fromstr +- Start Date: 2020-05-11 +- RFC PR: TBD +- Rust Issue: TBD + +# Summary +[summary]: #summary + +Deprecate [`FromStr`](https://doc.rust-lang.org/std/str/trait.FromStr.html) in favor of [`TryFrom<&str>`](https://doc.rust-lang.org/std/convert/trait.TryFrom.html) + +# Motivation +[motivation]: #motivation + +`FromStr` was created when `TryFrom` did not exist. + +As such, `FromStr` is now superfluous. + +# Guide-level explanation +[guide-level-explanation]: #guide-level-explanation + +Basic implementation: +```rust +use std::convert::TryFrom; +use std::num::ParseIntError; + +#[derive(Debug, PartialEq)] +struct Point { + x: i32, + y: i32, +} + +impl From<&str> for Point { + type Error = ParseIntError; + + fn try_from(s: &str) -> Result { + let coords: Vec<&str> = s + .trim_matches(|p| p == '(' || p == ')') + .split(',') + .collect(); + + let x_fromstr = i32::try_from(coords[0])?; + let y_fromstr = i32::try_from(coords[1])?; + + Ok(Point { + x: x_fromstr, + y: y_fromstr, + }) + } +} +``` + +Example: +```rust +let p = Point::try_from("(1,2)"); +assert_eq!(p.unwrap(), Point { x: 1, y: 2 }) +``` + +# Reference-level explanation +[reference-level-explanation]: #reference-level-explanation + +- Replace all `FromStr` implementation in `std` with the corresponding `TryFrom<&str>` +- Rewrite `str::parse()` to use `TryFrom<&str>` +- Mark `FromStr` as deprecated + +# Drawbacks +[drawbacks]: #drawbacks + +- Backward compatibility will be broken +- `TryFrom<&str> for U` implies `TryInto for &str` which may be unwanted + +# Rationale and alternatives +[rationale-and-alternatives]: #rationale-and-alternatives + +# Prior art +[prior-art]: #prior-art + +Some discussion about a tangential problem https://github.com/rust-lang/rfcs/issues/2143 + +# Unresolved questions +[unresolved-questions]: #unresolved-questions + +# Future possibilities +[future-possibilities]: #future-possibilities From f283086759cc786345ff1d783bd6baba9b1776b9 Mon Sep 17 00:00:00 2001 From: Malobre Date: Mon, 11 May 2020 18:55:00 +0200 Subject: [PATCH 2/9] Update 0000-deprecate-fromstr.md --- text/0000-deprecate-fromstr.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/text/0000-deprecate-fromstr.md b/text/0000-deprecate-fromstr.md index 579ce4aada8..a6cd3b5daf0 100644 --- a/text/0000-deprecate-fromstr.md +++ b/text/0000-deprecate-fromstr.md @@ -11,9 +11,7 @@ Deprecate [`FromStr`](https://doc.rust-lang.org/std/str/trait.FromStr.html) in f # Motivation [motivation]: #motivation -`FromStr` was created when `TryFrom` did not exist. - -As such, `FromStr` is now superfluous. +`FromStr` was created when `TryFrom` did not exist, `FromStr` is now superfluous. # Guide-level explanation [guide-level-explanation]: #guide-level-explanation From 0e9307ad96f88d92d1975324d63390fd142c2d01 Mon Sep 17 00:00:00 2001 From: Malobre Date: Mon, 11 May 2020 19:01:56 +0200 Subject: [PATCH 3/9] Add PR link --- text/0000-deprecate-fromstr.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-deprecate-fromstr.md b/text/0000-deprecate-fromstr.md index a6cd3b5daf0..8ec88dde998 100644 --- a/text/0000-deprecate-fromstr.md +++ b/text/0000-deprecate-fromstr.md @@ -1,6 +1,6 @@ - Feature Name: deprecate_fromstr - Start Date: 2020-05-11 -- RFC PR: TBD +- RFC PR: [#2924](https://github.com/rust-lang/rfcs/pull/2924) - Rust Issue: TBD # Summary From c8675c2fa205b4aeba328fc2922433658c1374bd Mon Sep 17 00:00:00 2001 From: Malobre Date: Mon, 11 May 2020 19:26:47 +0200 Subject: [PATCH 4/9] Update 0000-deprecate-fromstr.md --- text/0000-deprecate-fromstr.md | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/text/0000-deprecate-fromstr.md b/text/0000-deprecate-fromstr.md index 8ec88dde998..978bcd95842 100644 --- a/text/0000-deprecate-fromstr.md +++ b/text/0000-deprecate-fromstr.md @@ -27,7 +27,7 @@ struct Point { y: i32, } -impl From<&str> for Point { +impl TryFrom<&str> for Point { type Error = ParseIntError; fn try_from(s: &str) -> Result { @@ -56,14 +56,25 @@ assert_eq!(p.unwrap(), Point { x: 1, y: 2 }) # Reference-level explanation [reference-level-explanation]: #reference-level-explanation -- Replace all `FromStr` implementation in `std` with the corresponding `TryFrom<&str>` -- Rewrite `str::parse()` to use `TryFrom<&str>` - Mark `FromStr` as deprecated +- Mark `std::parse()` as deprecated +- Make `FromStr` implement `TryFrom<&str>`: +```rust +impl TryFrom for T +where + T: FromStr, +{ + type Error = ::Err; + + fn try_from(value: String) -> Result { + value.parse() + } +} +``` # Drawbacks [drawbacks]: #drawbacks -- Backward compatibility will be broken - `TryFrom<&str> for U` implies `TryInto for &str` which may be unwanted # Rationale and alternatives From 2f05e2412ca1844afe452ac0faa91e18f416306c Mon Sep 17 00:00:00 2001 From: Malobre Date: Mon, 11 May 2020 19:30:52 +0200 Subject: [PATCH 5/9] Fix typo --- text/0000-deprecate-fromstr.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-deprecate-fromstr.md b/text/0000-deprecate-fromstr.md index 978bcd95842..e3fd82bf494 100644 --- a/text/0000-deprecate-fromstr.md +++ b/text/0000-deprecate-fromstr.md @@ -57,7 +57,7 @@ assert_eq!(p.unwrap(), Point { x: 1, y: 2 }) [reference-level-explanation]: #reference-level-explanation - Mark `FromStr` as deprecated -- Mark `std::parse()` as deprecated +- Mark `str::parse()` as deprecated - Make `FromStr` implement `TryFrom<&str>`: ```rust impl TryFrom for T From 096c81c5ec9c7618bd9d55423bab96eef2450377 Mon Sep 17 00:00:00 2001 From: Malobre Date: Mon, 11 May 2020 19:38:15 +0200 Subject: [PATCH 6/9] Add links to the mentionned types, functions --- text/0000-deprecate-fromstr.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/text/0000-deprecate-fromstr.md b/text/0000-deprecate-fromstr.md index e3fd82bf494..679e7a4c977 100644 --- a/text/0000-deprecate-fromstr.md +++ b/text/0000-deprecate-fromstr.md @@ -11,7 +11,7 @@ Deprecate [`FromStr`](https://doc.rust-lang.org/std/str/trait.FromStr.html) in f # Motivation [motivation]: #motivation -`FromStr` was created when `TryFrom` did not exist, `FromStr` is now superfluous. +[`FromStr`](https://doc.rust-lang.org/std/str/trait.FromStr.html) was created when [`TryFrom`](https://doc.rust-lang.org/std/convert/trait.TryFrom.html) did not exist, [`FromStr`](https://doc.rust-lang.org/std/str/trait.FromStr.html) is now superfluous. # Guide-level explanation [guide-level-explanation]: #guide-level-explanation @@ -56,9 +56,9 @@ assert_eq!(p.unwrap(), Point { x: 1, y: 2 }) # Reference-level explanation [reference-level-explanation]: #reference-level-explanation -- Mark `FromStr` as deprecated -- Mark `str::parse()` as deprecated -- Make `FromStr` implement `TryFrom<&str>`: +- Mark [`FromStr`](https://doc.rust-lang.org/std/str/trait.FromStr.html) as deprecated +- Mark [`str::parse()`](https://doc.rust-lang.org/std/primitive.str.html#method.parse) as deprecated +- Make [`FromStr`](https://doc.rust-lang.org/std/str/trait.FromStr.html) implement `TryFrom<&str>` with [specialization](https://github.com/rust-lang/rfcs/pull/1210): ```rust impl TryFrom for T where From 2c60940b14db96a1913ff09a208941f7b07ac0bf Mon Sep 17 00:00:00 2001 From: Malobre Date: Mon, 11 May 2020 20:48:46 +0200 Subject: [PATCH 7/9] Add some content, fix a few typos --- text/0000-deprecate-fromstr.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/text/0000-deprecate-fromstr.md b/text/0000-deprecate-fromstr.md index 679e7a4c977..41c801a0d69 100644 --- a/text/0000-deprecate-fromstr.md +++ b/text/0000-deprecate-fromstr.md @@ -11,7 +11,9 @@ Deprecate [`FromStr`](https://doc.rust-lang.org/std/str/trait.FromStr.html) in f # Motivation [motivation]: #motivation -[`FromStr`](https://doc.rust-lang.org/std/str/trait.FromStr.html) was created when [`TryFrom`](https://doc.rust-lang.org/std/convert/trait.TryFrom.html) did not exist, [`FromStr`](https://doc.rust-lang.org/std/str/trait.FromStr.html) is now superfluous. +[`FromStr`](https://doc.rust-lang.org/std/str/trait.FromStr.html) was created when [`TryFrom`](https://doc.rust-lang.org/std/convert/trait.TryFrom.html) did not exist. + +However now that [`TryFrom`](https://doc.rust-lang.org/std/convert/trait.TryFrom.html) is stable [`FromStr`](https://doc.rust-lang.org/std/str/trait.FromStr.html) become superfluous. # Guide-level explanation [guide-level-explanation]: #guide-level-explanation @@ -58,9 +60,9 @@ assert_eq!(p.unwrap(), Point { x: 1, y: 2 }) - Mark [`FromStr`](https://doc.rust-lang.org/std/str/trait.FromStr.html) as deprecated - Mark [`str::parse()`](https://doc.rust-lang.org/std/primitive.str.html#method.parse) as deprecated -- Make [`FromStr`](https://doc.rust-lang.org/std/str/trait.FromStr.html) implement `TryFrom<&str>` with [specialization](https://github.com/rust-lang/rfcs/pull/1210): +- Create a new blanket implementation for `TryFrom<&str>` (requires [specialization](https://github.com/rust-lang/rfcs/pull/1210)): ```rust -impl TryFrom for T +impl TryFrom<&str> for T where T: FromStr, { @@ -83,7 +85,7 @@ where # Prior art [prior-art]: #prior-art -Some discussion about a tangential problem https://github.com/rust-lang/rfcs/issues/2143 +Some discussion about a tangential problem: https://github.com/rust-lang/rfcs/issues/2143 # Unresolved questions [unresolved-questions]: #unresolved-questions From a59024502e5068b8a0ff8df827819810de1df2d9 Mon Sep 17 00:00:00 2001 From: Malobre Date: Tue, 12 May 2020 15:17:30 +0200 Subject: [PATCH 8/9] Add content to motivations, minor modifications --- text/0000-deprecate-fromstr.md | 87 +++++++++++++++++++++++++++------- 1 file changed, 70 insertions(+), 17 deletions(-) diff --git a/text/0000-deprecate-fromstr.md b/text/0000-deprecate-fromstr.md index 41c801a0d69..6afb408b864 100644 --- a/text/0000-deprecate-fromstr.md +++ b/text/0000-deprecate-fromstr.md @@ -6,14 +6,73 @@ # Summary [summary]: #summary -Deprecate [`FromStr`](https://doc.rust-lang.org/std/str/trait.FromStr.html) in favor of [`TryFrom<&str>`](https://doc.rust-lang.org/std/convert/trait.TryFrom.html) +Deprecate [`FromStr`](https://doc.rust-lang.org/std/str/trait.FromStr.html) in favor of [`TryFrom<&str>`](https://doc.rust-lang.org/std/convert/trait.TryFrom.html) and [`From<&str>`](https://doc.rust-lang.org/std/convert/trait.From.html). # Motivation [motivation]: #motivation -[`FromStr`](https://doc.rust-lang.org/std/str/trait.FromStr.html) was created when [`TryFrom`](https://doc.rust-lang.org/std/convert/trait.TryFrom.html) did not exist. +[`FromStr`](https://doc.rust-lang.org/std/str/trait.FromStr.html) was created when [`TryFrom`](https://doc.rust-lang.org/std/convert/trait.TryFrom.html) didn't exist. Now that it is stable, [`FromStr`](https://doc.rust-lang.org/std/str/trait.FromStr.html) becomes superfluous. -However now that [`TryFrom`](https://doc.rust-lang.org/std/convert/trait.TryFrom.html) is stable [`FromStr`](https://doc.rust-lang.org/std/str/trait.FromStr.html) become superfluous. +[`FromStr`](https://doc.rust-lang.org/std/str/trait.FromStr.html) definition is virtually identical to [`TryFrom<&str>`](https://doc.rust-lang.org/std/convert/trait.TryFrom.html): +```rust +pub trait FromStr: Sized { + type Err; + + fn from_str(s: &str) -> Result; +} + +// Where T is &str +pub trait TryFrom: Sized { + type Error; + + fn try_from(value: T) -> Result; +} +``` + +Infallible conversions become more idiomatic: +```rust +struct Dummy(String); + +impl std::str::FromStr for Dummy { + type Err = core::convert::Infallible; + + fn from_str(s: &str) -> Result { + Ok(Dummy(s.to_owned())) + } +} + +//vs + +impl From<&str> for Dummy { + + fn from(s: &str) -> Self { + Dummy(s.to_owned()) + } +} +``` + +[`FromStr`](https://doc.rust-lang.org/std/str/trait.FromStr.html) limits lifetimes in a way that prevents borrowing the passed string: +```rust +struct Dummy<'a>(&'a str); + +// This doesn't compile +impl<'a> FromStr for Dummy<'a> { + type Err = core::convert::Infallible; + + fn from_str(s: &str) -> Result { + Ok(Dummy(s)) + } +} + +//This works +impl<'a> From<&'a str> for Dummy<'a> { + + fn from(s: &'a str) -> Self { + Dummy(s) + } +} + +``` # Guide-level explanation [guide-level-explanation]: #guide-level-explanation @@ -60,28 +119,18 @@ assert_eq!(p.unwrap(), Point { x: 1, y: 2 }) - Mark [`FromStr`](https://doc.rust-lang.org/std/str/trait.FromStr.html) as deprecated - Mark [`str::parse()`](https://doc.rust-lang.org/std/primitive.str.html#method.parse) as deprecated -- Create a new blanket implementation for `TryFrom<&str>` (requires [specialization](https://github.com/rust-lang/rfcs/pull/1210)): -```rust -impl TryFrom<&str> for T -where - T: FromStr, -{ - type Error = ::Err; - - fn try_from(value: String) -> Result { - value.parse() - } -} -``` +- Implement [`TryFrom<&str>`](https://doc.rust-lang.org/std/convert/trait.TryFrom.html) for all types implementing [`FromStr`](https://doc.rust-lang.org/std/str/trait.FromStr.html) # Drawbacks [drawbacks]: #drawbacks -- `TryFrom<&str> for U` implies `TryInto for &str` which may be unwanted +To be discussed # Rationale and alternatives [rationale-and-alternatives]: #rationale-and-alternatives +To be discussed + # Prior art [prior-art]: #prior-art @@ -90,5 +139,9 @@ Some discussion about a tangential problem: https://github.com/rust-lang/rfcs/is # Unresolved questions [unresolved-questions]: #unresolved-questions +To be discussed + # Future possibilities [future-possibilities]: #future-possibilities + +To be discussed From 9bb83eb3cbd01a7f64dc48122bdbdf62dc4839fc Mon Sep 17 00:00:00 2001 From: Malobre Date: Tue, 12 May 2020 16:17:22 +0200 Subject: [PATCH 9/9] Update 0000-deprecate-fromstr.md --- text/0000-deprecate-fromstr.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-deprecate-fromstr.md b/text/0000-deprecate-fromstr.md index 6afb408b864..a7e4106c1fc 100644 --- a/text/0000-deprecate-fromstr.md +++ b/text/0000-deprecate-fromstr.md @@ -56,7 +56,7 @@ impl From<&str> for Dummy { struct Dummy<'a>(&'a str); // This doesn't compile -impl<'a> FromStr for Dummy<'a> { +impl<'a> std::str::FromStr for Dummy<'a> { type Err = core::convert::Infallible; fn from_str(s: &str) -> Result {