From e25ddad2f64e5796dcc6d2f1686d1ea55cee8d43 Mon Sep 17 00:00:00 2001
From: Peter Jaszkowiak
Date: Mon, 29 Apr 2024 23:22:16 -0600
Subject: [PATCH] minor changes of wording, layout, and clarification
---
text/3550-new-range.md | 51 +++++++++++++++++++++---------------------
1 file changed, 26 insertions(+), 25 deletions(-)
diff --git a/text/3550-new-range.md b/text/3550-new-range.md
index a29f88e71..00d6936d6 100644
--- a/text/3550-new-range.md
+++ b/text/3550-new-range.md
@@ -109,7 +109,7 @@ for n in (0..5).rev() { ... } // No changes necessary
for n in (0..5).map(|x| x * 2) { ... } // No changes necessary
```
-In other cases, `cargo fix --edition 2024` will insert `.into_iter()` as necessary:
+In other cases, `cargo fix --edition` will insert `.into_iter()` as necessary:
```rust
pub fn takes_iter(range: impl Iterator) { ... }
@@ -119,6 +119,19 @@ takes_iter((0..5).into_iter()); // Add `.into_iter()`
(0..5).for_each(...);
// After
(0..5).into_iter().for_each(...); // Add `.into_iter()`
+
+// Before
+let mut range = 0..5;
+assert_eq!(range.next(), Some(0));
+range.for_each(|n| {
+ // n = 1, 2, 3, 4
+});
+// After
+let mut range = (0..5).into_iter();
+assert_eq!(range.next(), Some(0));
+range.for_each(|n| {
+ // n = 1, 2, 3, 4
+});
```
Or fall back to converting to the legacy types:
@@ -132,9 +145,11 @@ pub fn takes_range(range: std::range::legacy::Range) { ... }
takes_range((0..5).into());
```
-#### Libraries
+## Migrating Libraries
-To reduce the need for the above conversions, we recommend making the following changes to libraries:
+Some libraries have range types in their public interface. To use the new range types with such a library, users will need to add explicit conversions.
+
+To reduce the burden of explicit conversions, libraries should make the following backwards-compatible changes:
- Change any function parameters from legacy `Range*` types to `impl Into`
Or if applicable, `impl RangeBounds<_>`
@@ -181,25 +196,7 @@ where Range: IntoIterator
}
```
-- When the range is treated as mutable iterator, call `.into_iter()` before using it
-
-```rust
-// Before
-let mut range = 0..5;
-assert_eq!(range.next(), Some(0));
-range.for_each(|n| {
- // n = 1, 2, 3, 4
-});
-
-// After
-let mut range = (0..5).into_iter();
-assert_eq!(range.next(), Some(0));
-range.for_each(|n| {
- // n = 1, 2, 3, 4
-});
-```
-
-- When ranges are used with `std::ops::Index`, add impls for the new range types
+- When your library implements a trait involving ranges, such as `std::ops::Index`, add impls for the new range types
```rust
// Before
@@ -212,6 +209,10 @@ impl Index> for Bar { ... }
impl Index> for Bar { ... }
```
+**Note**
+- These changes to libraries should happen when _users_ of a given library transition to the new edition
+- These changes do not require the library itself to transition to the new edition
+
## Diagnostics
There is a substantial amount of educational material in the wild which assumes the the range types implement `Iterator`. If a user references this outdated material, it is important that compiler errors guide them to the new solution.
@@ -415,7 +416,7 @@ impl Range {
This change has the potential to cause a significant amount of churn in the ecosystem. There are two main sources of churn:
- where ranges are assumed to be `Iterator`
-- when `Index>` is implemented directly
+- trait impls involving ranges, such as `Index>`
Changes will be required to support the new range types, even on older editions. See the [migrating section](#migrating) for specifics.
@@ -535,7 +536,7 @@ We leave the following items to be decided by the **libs-api** team after this p
- The set of inherent methods copied from `Iterator` present on the new range types
- The exact module paths and type names
+ Should the new types live at `std::ops::range::` instead?
- + `IterRange`, `IterRangeInclusive` or just `Iter`, `IterInclusive`?
+ + `IterRange`, `IterRangeInclusive` or just `Iter`, `IterInclusive`? Or `RangeIter`, `RangeInclusiveIter`, ...?
- Should other range-related items (like `RangeBounds`) also be moved under the `range` module?
- Should `RangeFrom` even implement `IntoIterator`, or should it require an explicit `.iter()` call? Using it as an iterator [can be a footgun](https://github.com/rust-lang/libs-team/issues/304), usually people want `start..=MAX` instead. Also, it is inconsistent with `RangeTo`, which doesn't implement `IntoIterator` either.
- Should there be a way to get an iterator that modifies the range in place, rather than taking the range by value? That would allow things like `range.by_ref().next()`.
@@ -549,7 +550,7 @@ impl From> for RangeInclusive {
# Future possibilities
[future-possibilities]: #future-possibilities
-- Hide or deprecate range-related items directly under `ops`, without breaking existing links or triggering deprecation warnings on previous editions.
+- Hide or deprecate range-related items directly under `ops` (without breaking existing links or triggering deprecation warnings on previous editions).
- `RangeTo(Inclusive)::rev()` that returns an iterator?
- `IterRangeInclusive` can be optimized to take advantage of the case where the bounds don't occupy the full domain of the index type: