From dd8fb120951e82cef61c78cbf2a5c1d010baac20 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 19 Jan 2018 16:48:18 +0100 Subject: [PATCH 1/7] rfc, convert_id: initial version. --- text/0000-convert-id.md | 201 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 text/0000-convert-id.md diff --git a/text/0000-convert-id.md b/text/0000-convert-id.md new file mode 100644 index 00000000000..e0cee24a1f6 --- /dev/null +++ b/text/0000-convert-id.md @@ -0,0 +1,201 @@ +- Feature Name: convert_id +- Start Date: 2018-01-19 +- RFC PR: (leave this empty) +- Rust Issue: (leave this empty) + +# Summary +[summary]: #summary + +Adds an identity function `pub fn id(x: T) -> T { x }` as `core::convert::id`. +The function is also re-exported to `std::convert::id` as well as the prelude of +both libcore and libstd. + +# Motivation +[motivation]: #motivation + +## The identity function is useful + +While it might seem strange to have a function that just returns back the input, +there are some cases where the function is useful. + +### Using `id` to do nothing among a collection of mappers + +When you have collections such as maps or arrays of mapping functions like +below and you watch to dispatch to those you sometimes need the identity +function as a way of not transforming the input. You can use the identity +function to achieve this. + +```rust +// Let's assume that this and other functions do something non-trivial. +fn do_interesting_stuff(x: u32) -> u32 { .. } + +// A dispatch-map of mapping functions: +let mut map = HashMap::new(); +map.insert("foo", do_interesting_stuff); +map.insert("bar", other_stuff); +map.insert("baz", id); +``` + +### Using `id` as a no-op function in a conditional + +This reasoning also applies to simpler yes/no dispatch as below: + +```rust +let mapper = if condition { some_manipulation } else { id }; + +// do more interesting stuff inbetween.. + +do_stuff(42); +``` + +### Using `id` to concatenate an iterator of iterators + +Given the law `join = (>>= id)`, we use the identity function to perform +a monadic join on iterators in this example. + +```rust +let vec_vec = vec![vec![1, 3, 4], vec![5, 6]]; +let iter_iter = vec_vec.into_iter().map(Vec::into_iter); +let concatenated = iter_iter.flat_map(id).collect::>(); +assert_eq!(vec![1, 3, 4, 5, 6], concatenated); +``` + +### Using `id` to keep the `Some` variants of an iterator of `Option` + +We can keep all the maybe variants by simply `iter.filter_map(id)`. + +```rust +let iter = vec![Some(1), None, Some(3)].into_iter(); +let filtered = iter.filter_map(id).collect::>(); +assert_eq!(vec![1, 3], filtered); +``` + +### To be clear that you intended to use an identity conversion + +If you instead use a closure as in `|x| x` when you need an +identity conversion, it is less clear that this was intentional. +With `id`, this intent becomes clearer. + +## The `drop` function as a precedent + +The `drop` function in `core::mem` is defined as `pub fn drop(_x: T) { }`. +The same effect can be achieved by writing `{ _x; }`. This presents us +with a precendent that such trivial functions are considered useful and +includable inside the standard library even tho they can be written easily +inside a user's crate. + +## Avoiding repetition in user crates + +Here are a few examples of the identity function being defined and used: + ++ https://docs.rs/functils/0.0.2/functils/fn.identity.html ++ https://docs.rs/tool/0.2.0/tool/fn.id.html ++ https://github.com/hephex/api/blob/ef67b209cd88d0af40af10b4a9f3e0e61a5924da/src/lib.rs + +There's a smattering of more examples. To reduce duplication, it +should be provided in the standard library as a common place it is defined. + +## Precedent from other languages + +There are other languages that include an identity function in +their standard libraries, among these are: + ++ [Haskell](http://hackage.haskell.org/package/base-4.10.1.0/docs/Prelude.html#v:id), which also exports this to the prelude. ++ [Scala](https://www.scala-lang.org/api/current/scala/Predef$.html#identity[A](x:A):A), which also exports this to the prelude. ++ [Java](https://docs.oracle.com/javase/8/docs/api/java/util/function/Function.html#identity--), which is a widely used language. ++ [Idris](https://www.idris-lang.org/docs/1.0/prelude_doc/docs/Prelude.Basics.html), which also exports this to the prelude. ++ [Ruby](http://ruby-doc.org/core-2.5.0/Object.html#method-i-itself), which exports it to what amounts to the top type. ++ [Racket](http://docs.racket-lang.org/reference/values.html) ++ [Julia](https://docs.julialang.org/en/release-0.4/stdlib/base/#Base.identity) ++ [R](https://stat.ethz.ch/R-manual/R-devel/library/base/html/identity.html) ++ [F#](https://msdn.microsoft.com/en-us/visualfsharpdocs/conceptual/operators.id%5B%27t%5D-function-%5Bfsharp%5D) ++ [Clojure](https://clojuredocs.org/clojure.core/identity) ++ [Agda](http://www.cse.chalmers.se/~nad/repos/lib/src/Function.agda) ++ [Elm](http://package.elm-lang.org/packages/elm-lang/core/latest/Basics#identity) + +## The case for inclusion in the prelude + +Let's compare the effort required, assuming that each letter +typed has a uniform cost wrt. effort. + +```rust +use std::convert::id; iter.filter_map(id) + +fn id(x: T) -> T { x } iter.filter_map(id) + +iter.filter_map(::std::convert::id) + +iter.filter_map(id) +``` + +Comparing the length of these lines, we see that there's not much difference in +length when defining the function yourself or when importing or using an absolute +path. But the prelude-using variant is considerably shorter. To encourage the +use of the function, exporting to the prelude is therefore a good idea. + +In addition, there's an argument to be made from similarity to other things in +`core::convert` as well as `drop` all of which are in the prelude. This is +especially relevant in the case of `drop` which is also a trivial function. + +# Guide-level explanation +[guide-level-explanation]: #guide-level-explanation + +An identity function is a mapping of one type onto itself such that the output +is the same as the input. In other words, a function `id : T -> T` for some +type `T` defined as `id(x) = x`. This RFC adds such a function for all types +in Rust into libcore at the module `core::convert` and defines it as: + +```rust +pub fn id(x: T) -> T { x } +``` + +This function is also re-exported to `std::convert::id` as well as +the prelude of both libcore and libstd. + +It is important to note that the input `x` passed to the function is +moved since Rust uses move semantics by default. + +# Reference-level explanation +[reference-level-explanation]: #reference-level-explanation + +An identity function defined as `pub fn id(x: T) -> T { x }` exists in +`core::convert::id`. The function is also re-exported to `std::convert::id` +as well as the prelude of both libcore and libstd. + +Note that the identity function is not always equivalent to a closure +such as `|x| x` since the closure may coerce `x` into a different type +while the identity function never changes the type. + +# Drawbacks +[drawbacks]: #drawbacks + +It is already possible to do this in user code by: + ++ using an identity closure: `|x| x`. ++ writing the identity function as defined in the RFC yourself. + +These are contrasted with the [motivation] for including the function +in the standard library. + +# Rationale and alternatives +[alternatives]: #alternatives + +The rationale for including this in `convert` and not `mem` is that the +former generally deals with conversions, and identity conversion" is a used +phrase. Meanwhile, `mem` does not relate to `identity` other than that both +deal with move semantics. Therefore, `convert` is the better choice. Including +it in `mem` is still an alternative, but as explained, it isn't fitting. + +The rationale for including this in the prelude has been previously +explained in the [motivation] section. It is an alternative to not do that. +If the function is not in the prelude, the utility is so low that it may +be a better idea to not add the function at all. + +Naming the function `identity` instead of `id` is a possibility. +However, to make the `id` function more appetizing than using a `|x| x`, it is +preferrable for the identity function to have a shorter but still clear name. + +# Unresolved questions +[unresolved]: #unresolved-questions + +There are no unresolved questions. \ No newline at end of file From 32741df048adb9bcd5ec34d1890827819d7d4a6a Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 19 Jan 2018 18:39:54 +0100 Subject: [PATCH 2/7] rfc, convert_id: stylistic/linguistic improvements --- text/0000-convert-id.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/text/0000-convert-id.md b/text/0000-convert-id.md index e0cee24a1f6..1c2a40dd584 100644 --- a/text/0000-convert-id.md +++ b/text/0000-convert-id.md @@ -50,8 +50,9 @@ do_stuff(42); ### Using `id` to concatenate an iterator of iterators -Given the law `join = (>>= id)`, we use the identity function to perform -a monadic join on iterators in this example. +We use the identity function to perform a monadic join on iterators, in the +example below. In other words we are concatenating an iterator of iterators +into a single iterator, ```rust let vec_vec = vec![vec![1, 3, 4], vec![5, 6]]; @@ -81,7 +82,7 @@ With `id`, this intent becomes clearer. The `drop` function in `core::mem` is defined as `pub fn drop(_x: T) { }`. The same effect can be achieved by writing `{ _x; }`. This presents us with a precendent that such trivial functions are considered useful and -includable inside the standard library even tho they can be written easily +includable inside the standard library even though they can be written easily inside a user's crate. ## Avoiding repetition in user crates From bd36bbb2a01f8a3b78d6ee239fbaafb59b1a5634 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 19 Jan 2018 19:38:16 +0100 Subject: [PATCH 3/7] rfc, convert_id: s/id/identity by popular demand --- text/0000-convert-id.md | 60 +++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/text/0000-convert-id.md b/text/0000-convert-id.md index 1c2a40dd584..e61973f557e 100644 --- a/text/0000-convert-id.md +++ b/text/0000-convert-id.md @@ -1,4 +1,4 @@ -- Feature Name: convert_id +- Feature Name: convert_identity - Start Date: 2018-01-19 - RFC PR: (leave this empty) - Rust Issue: (leave this empty) @@ -6,8 +6,9 @@ # Summary [summary]: #summary -Adds an identity function `pub fn id(x: T) -> T { x }` as `core::convert::id`. -The function is also re-exported to `std::convert::id` as well as the prelude of +Adds an identity function `pub fn identity(x: T) -> T { x }` as +`core::convert::identity`. The function is also re-exported to +`std::convert::identity` as well as the prelude of both libcore and libstd. # Motivation @@ -18,7 +19,7 @@ both libcore and libstd. While it might seem strange to have a function that just returns back the input, there are some cases where the function is useful. -### Using `id` to do nothing among a collection of mappers +### Using `identity` to do nothing among a collection of mappers When you have collections such as maps or arrays of mapping functions like below and you watch to dispatch to those you sometimes need the identity @@ -33,22 +34,22 @@ fn do_interesting_stuff(x: u32) -> u32 { .. } let mut map = HashMap::new(); map.insert("foo", do_interesting_stuff); map.insert("bar", other_stuff); -map.insert("baz", id); +map.insert("baz", identity); ``` -### Using `id` as a no-op function in a conditional +### Using `identity` as a no-op function in a conditional This reasoning also applies to simpler yes/no dispatch as below: ```rust -let mapper = if condition { some_manipulation } else { id }; +let mapper = if condition { some_manipulation } else { identity }; // do more interesting stuff inbetween.. do_stuff(42); ``` -### Using `id` to concatenate an iterator of iterators +### Using `identity` to concatenate an iterator of iterators We use the identity function to perform a monadic join on iterators, in the example below. In other words we are concatenating an iterator of iterators @@ -57,17 +58,17 @@ into a single iterator, ```rust let vec_vec = vec![vec![1, 3, 4], vec![5, 6]]; let iter_iter = vec_vec.into_iter().map(Vec::into_iter); -let concatenated = iter_iter.flat_map(id).collect::>(); +let concatenated = iter_iter.flat_map(identity).collect::>(); assert_eq!(vec![1, 3, 4, 5, 6], concatenated); ``` -### Using `id` to keep the `Some` variants of an iterator of `Option` +### Using `identity` to keep the `Some` variants of an iterator of `Option` -We can keep all the maybe variants by simply `iter.filter_map(id)`. +We can keep all the maybe variants by simply `iter.filter_map(identity)`. ```rust let iter = vec![Some(1), None, Some(3)].into_iter(); -let filtered = iter.filter_map(id).collect::>(); +let filtered = iter.filter_map(identity).collect::>(); assert_eq!(vec![1, 3], filtered); ``` @@ -75,7 +76,7 @@ assert_eq!(vec![1, 3], filtered); If you instead use a closure as in `|x| x` when you need an identity conversion, it is less clear that this was intentional. -With `id`, this intent becomes clearer. +With `identity`, this intent becomes clearer. ## The `drop` function as a precedent @@ -120,13 +121,13 @@ Let's compare the effort required, assuming that each letter typed has a uniform cost wrt. effort. ```rust -use std::convert::id; iter.filter_map(id) +use std::convert::identity; iter.filter_map(identity) -fn id(x: T) -> T { x } iter.filter_map(id) +fn identity(x: T) -> T { x } iter.filter_map(identity) -iter.filter_map(::std::convert::id) +iter.filter_map(::std::convert::identity) -iter.filter_map(id) +iter.filter_map(identity) ``` Comparing the length of these lines, we see that there's not much difference in @@ -142,15 +143,16 @@ especially relevant in the case of `drop` which is also a trivial function. [guide-level-explanation]: #guide-level-explanation An identity function is a mapping of one type onto itself such that the output -is the same as the input. In other words, a function `id : T -> T` for some -type `T` defined as `id(x) = x`. This RFC adds such a function for all types -in Rust into libcore at the module `core::convert` and defines it as: +is the same as the input. In other words, a function `identity : T -> T` for +some type `T` defined as `identity(x) = x`. This RFC adds such a function for +all `Sized` types in Rust into libcore at the module `core::convert` and +defines it as: ```rust -pub fn id(x: T) -> T { x } +pub fn identity(x: T) -> T { x } ``` -This function is also re-exported to `std::convert::id` as well as +This function is also re-exported to `std::convert::identity` as well as the prelude of both libcore and libstd. It is important to note that the input `x` passed to the function is @@ -159,9 +161,9 @@ moved since Rust uses move semantics by default. # Reference-level explanation [reference-level-explanation]: #reference-level-explanation -An identity function defined as `pub fn id(x: T) -> T { x }` exists in -`core::convert::id`. The function is also re-exported to `std::convert::id` -as well as the prelude of both libcore and libstd. +An identity function defined as `pub fn identity(x: T) -> T { x }` exists as +`core::convert::identity`. The function is also re-exported as +`std::convert::identity` as well as the prelude of both libcore and libstd. Note that the identity function is not always equivalent to a closure such as `|x| x` since the closure may coerce `x` into a different type @@ -173,7 +175,7 @@ while the identity function never changes the type. It is already possible to do this in user code by: + using an identity closure: `|x| x`. -+ writing the identity function as defined in the RFC yourself. ++ writing the `identity` function as defined in the RFC yourself. These are contrasted with the [motivation] for including the function in the standard library. @@ -192,9 +194,9 @@ explained in the [motivation] section. It is an alternative to not do that. If the function is not in the prelude, the utility is so low that it may be a better idea to not add the function at all. -Naming the function `identity` instead of `id` is a possibility. -However, to make the `id` function more appetizing than using a `|x| x`, it is -preferrable for the identity function to have a shorter but still clear name. +Naming the function `id` instead of `identity` is a possibility. +This name is however ambiguous with *"identifier"* and less clear +wherefore `identifier` was opted for. # Unresolved questions [unresolved]: #unresolved-questions From 1cfc8fd54eae9fefb6f5c2779e2b6b7f525173a9 Mon Sep 17 00:00:00 2001 From: Mazdak Date: Sat, 20 Jan 2018 20:43:52 +0100 Subject: [PATCH 4/7] rfc, convert_id: remove references to 'monad' as requested by @Manishearth --- text/0000-convert-id.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/text/0000-convert-id.md b/text/0000-convert-id.md index e61973f557e..597044f3cdf 100644 --- a/text/0000-convert-id.md +++ b/text/0000-convert-id.md @@ -51,9 +51,8 @@ do_stuff(42); ### Using `identity` to concatenate an iterator of iterators -We use the identity function to perform a monadic join on iterators, in the -example below. In other words we are concatenating an iterator of iterators -into a single iterator, +We can use the identity function to concatenate an iterator of iterators +into a single iterator. ```rust let vec_vec = vec![vec![1, 3, 4], vec![5, 6]]; From 1c8c20c0bc386fbcd42a19c7ae8141d50dcf1ed9 Mon Sep 17 00:00:00 2001 From: Mazdak Date: Sat, 20 Jan 2018 21:22:36 +0100 Subject: [PATCH 5/7] rfc, convert_id: made the function const as it should be. --- text/0000-convert-id.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/text/0000-convert-id.md b/text/0000-convert-id.md index 597044f3cdf..360d5646102 100644 --- a/text/0000-convert-id.md +++ b/text/0000-convert-id.md @@ -6,7 +6,7 @@ # Summary [summary]: #summary -Adds an identity function `pub fn identity(x: T) -> T { x }` as +Adds an identity function `pub const fn identity(x: T) -> T { x }` as `core::convert::identity`. The function is also re-exported to `std::convert::identity` as well as the prelude of both libcore and libstd. @@ -148,7 +148,7 @@ all `Sized` types in Rust into libcore at the module `core::convert` and defines it as: ```rust -pub fn identity(x: T) -> T { x } +pub const fn identity(x: T) -> T { x } ``` This function is also re-exported to `std::convert::identity` as well as @@ -160,8 +160,8 @@ moved since Rust uses move semantics by default. # Reference-level explanation [reference-level-explanation]: #reference-level-explanation -An identity function defined as `pub fn identity(x: T) -> T { x }` exists as -`core::convert::identity`. The function is also re-exported as +An identity function defined as `pub const fn identity(x: T) -> T { x }` +exists as `core::convert::identity`. The function is also re-exported as `std::convert::identity` as well as the prelude of both libcore and libstd. Note that the identity function is not always equivalent to a closure From 088860d280385c10d7b87e11d4af3ec732c83c6e Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Thu, 9 Aug 2018 01:20:38 +0200 Subject: [PATCH 6/7] rfc, convert-id: move prelude inclusion to possible-future-work. --- text/0000-convert-id.md | 88 ++++++++++++++++++++++------------------- 1 file changed, 48 insertions(+), 40 deletions(-) diff --git a/text/0000-convert-id.md b/text/0000-convert-id.md index 360d5646102..9bf0586224f 100644 --- a/text/0000-convert-id.md +++ b/text/0000-convert-id.md @@ -1,4 +1,4 @@ -- Feature Name: convert_identity +- Feature Name: `convert_identity` - Start Date: 2018-01-19 - RFC PR: (leave this empty) - Rust Issue: (leave this empty) @@ -6,10 +6,9 @@ # Summary [summary]: #summary -Adds an identity function `pub const fn identity(x: T) -> T { x }` as -`core::convert::identity`. The function is also re-exported to -`std::convert::identity` as well as the prelude of -both libcore and libstd. +Adds an identity function `pub const fn identity(x: T) -> T { x }` +as `core::convert::identity`. The function is also re-exported to +`std::convert::identity`. # Motivation [motivation]: #motivation @@ -61,6 +60,10 @@ let concatenated = iter_iter.flat_map(identity).collect::>(); assert_eq!(vec![1, 3, 4, 5, 6], concatenated); ``` +While the standard library has recently added `Iterator::flatten`, +which you should use instead, to achieve the same semantics, similar situations +are likely in the wild and the `identity` function can be used in those cases. + ### Using `identity` to keep the `Some` variants of an iterator of `Option` We can keep all the maybe variants by simply `iter.filter_map(identity)`. @@ -93,8 +96,8 @@ Here are a few examples of the identity function being defined and used: + https://docs.rs/tool/0.2.0/tool/fn.id.html + https://github.com/hephex/api/blob/ef67b209cd88d0af40af10b4a9f3e0e61a5924da/src/lib.rs -There's a smattering of more examples. To reduce duplication, it -should be provided in the standard library as a common place it is defined. +There's a smattering of more examples. To reduce duplication, +it should be provided in the standard library as a common place it is defined. ## Precedent from other languages @@ -114,30 +117,6 @@ their standard libraries, among these are: + [Agda](http://www.cse.chalmers.se/~nad/repos/lib/src/Function.agda) + [Elm](http://package.elm-lang.org/packages/elm-lang/core/latest/Basics#identity) -## The case for inclusion in the prelude - -Let's compare the effort required, assuming that each letter -typed has a uniform cost wrt. effort. - -```rust -use std::convert::identity; iter.filter_map(identity) - -fn identity(x: T) -> T { x } iter.filter_map(identity) - -iter.filter_map(::std::convert::identity) - -iter.filter_map(identity) -``` - -Comparing the length of these lines, we see that there's not much difference in -length when defining the function yourself or when importing or using an absolute -path. But the prelude-using variant is considerably shorter. To encourage the -use of the function, exporting to the prelude is therefore a good idea. - -In addition, there's an argument to be made from similarity to other things in -`core::convert` as well as `drop` all of which are in the prelude. This is -especially relevant in the case of `drop` which is also a trivial function. - # Guide-level explanation [guide-level-explanation]: #guide-level-explanation @@ -151,8 +130,7 @@ defines it as: pub const fn identity(x: T) -> T { x } ``` -This function is also re-exported to `std::convert::identity` as well as -the prelude of both libcore and libstd. +This function is also re-exported to `std::convert::identity`. It is important to note that the input `x` passed to the function is moved since Rust uses move semantics by default. @@ -162,7 +140,7 @@ moved since Rust uses move semantics by default. An identity function defined as `pub const fn identity(x: T) -> T { x }` exists as `core::convert::identity`. The function is also re-exported as -`std::convert::identity` as well as the prelude of both libcore and libstd. +`std::convert::identity`- Note that the identity function is not always equivalent to a closure such as `|x| x` since the closure may coerce `x` into a different type @@ -188,11 +166,6 @@ phrase. Meanwhile, `mem` does not relate to `identity` other than that both deal with move semantics. Therefore, `convert` is the better choice. Including it in `mem` is still an alternative, but as explained, it isn't fitting. -The rationale for including this in the prelude has been previously -explained in the [motivation] section. It is an alternative to not do that. -If the function is not in the prelude, the utility is so low that it may -be a better idea to not add the function at all. - Naming the function `id` instead of `identity` is a possibility. This name is however ambiguous with *"identifier"* and less clear wherefore `identifier` was opted for. @@ -200,4 +173,39 @@ wherefore `identifier` was opted for. # Unresolved questions [unresolved]: #unresolved-questions -There are no unresolved questions. \ No newline at end of file +There are no unresolved questions. + +# Possible future work + +A previous iteration of this RFC proposed that the `identity` function +should be added to prelude of both libcore and libstd. +However, the library team decided that for the time being, it was not sold on +this inclusion. As we gain usage experience with using this function, +it is possible to revisit this in the future if the team chances its mind. + +The section below details, for posterity, +the argument for inclusion that was previously in the [motivation]. + +## The case for inclusion in the prelude + +Let's compare the effort required, assuming that each letter +typed has a uniform cost with respect to effort. + +```rust +use std::convert::identity; iter.filter_map(identity) + +fn identity(x: T) -> T { x } iter.filter_map(identity) + +iter.filter_map(::std::convert::identity) + +iter.filter_map(identity) +``` + +Comparing the length of these lines, we see that there's not much difference in +length when defining the function yourself or when importing or using an absolute +path. But the prelude-using variant is considerably shorter. To encourage the +use of the function, exporting to the prelude is therefore a good idea. + +In addition, there's an argument to be made from similarity to other things in +`core::convert` as well as `drop` all of which are in the prelude. This is +especially relevant in the case of `drop` which is also a trivial function. From ca0e0635b2a2df4fa0d61c28172ffce11cb35991 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 19 Aug 2018 18:18:27 +0200 Subject: [PATCH 7/7] RFC 2306 --- text/{0000-convert-id.md => 2306-convert-id.md} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename text/{0000-convert-id.md => 2306-convert-id.md} (98%) diff --git a/text/0000-convert-id.md b/text/2306-convert-id.md similarity index 98% rename from text/0000-convert-id.md rename to text/2306-convert-id.md index 9bf0586224f..60592314f8e 100644 --- a/text/0000-convert-id.md +++ b/text/2306-convert-id.md @@ -1,7 +1,7 @@ - Feature Name: `convert_identity` - Start Date: 2018-01-19 -- RFC PR: (leave this empty) -- Rust Issue: (leave this empty) +- RFC PR: [rust-lang/rfcs#2306](https://github.com/rust-lang/rfcs/pull/2306) +- Rust Issue: [rust-lang/rust#53500](https://github.com/rust-lang/rust/issues/53500) # Summary [summary]: #summary