about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2015-01-30 12:02:44 -0800
committerAlex Crichton <alex@alexcrichton.com>2015-01-30 12:02:44 -0800
commit341e858bd882061b823dac236fd718d473f8ab2e (patch)
tree2e6d18523dcd67f28fe0a527f02102072ce14996 /src/libstd
parent1a51eb9cca3ae5f815825096de4dfbdc9267f735 (diff)
parentb9a9030ed68f135e116e9a5d32663e00b897cf4f (diff)
rollup merge of #20790: japaric/for-loops
As per [RFC #235][rfc], you can now do:

[rfc]: https://github.com/rust-lang/rfcs/blob/master/text/0235-collections-conventions.md#intoiterator-and-iterable

``` rust
let mut v = vec![1];

// iterate over immutable references
for x in &v {
    assert_eq!(x, &1);
}

// iterate over mutable references
for x in &mut v {
    assert_eq!(x, &mut 1);
}

// iterate over values, this consumes `v`
for x in v {
    assert_eq!(x, 1);
}
```

[breaking-change]s

For loops now "consume" (move) the iterator, this breaks iterating over mutable references to iterators, and also breaks multiple iterations over the same iterator:

``` rust
fn foo(mut it: &mut Iter) {  // `Iter` implements `Iterator`
    for x in it { .. }  //~ error: `&mut Iter` doesn't implement Iterator
}

fn bar() {
    for x in it { .. }  //~ note: `it` moved here
    for x in it { .. }  //~ error: `it` has been moved
}
```

Both cases can be fixed using the `by_ref()` adapter to create an iterator from the mutable reference:

``` rust
fn foo(mut it: &mut Iter) {
    for x in it.by_ref() { .. }
}

fn bar() {
    for x in it.by_ref() { .. }
    for x in it { .. }
}
```

This PR also makes iterator non-implicitly copyable, as this was source of subtle bugs in the libraries. You can still use `clone()` to explictly copy the iterator.

Finally, since the for loops are implemented in the frontend and use global paths to `IntoIterator`, `Iterator` and `Option` variants, users of the `core` crate will have to use add an `std` module to the root of their crate to be able to use for loops:

``` rust
#![no_std]

extern crate core;

fn main() {
    for x in 0..10 {}
}

#[doc(hidden)]
mod std {
    // these imports are needed to use for-loops
    pub use core::iter;
    pub use core::option;
}
```

---

r? @nikomatsakis @aturon
cc #18424
closes #18045
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/collections/hash/map.rs2
-rw-r--r--src/libstd/collections/hash/table.rs4
-rw-r--r--src/libstd/lib.rs4
-rw-r--r--src/libstd/path/windows.rs2
-rw-r--r--src/libstd/sys/common/backtrace.rs2
5 files changed, 9 insertions, 5 deletions
diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs
index a291ec16a62..b1c1dd1a9f6 100644
--- a/src/libstd/collections/hash/map.rs
+++ b/src/libstd/collections/hash/map.rs
@@ -1772,7 +1772,7 @@ mod test_map {
                 }
             });
 
-            for _ in half {}
+            for _ in half.by_ref() {}
 
             DROP_VECTOR.with(|v| {
                 let nk = (0u..100).filter(|&i| {
diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs
index 9e6a45d8bf0..141c51d8363 100644
--- a/src/libstd/collections/hash/table.rs
+++ b/src/libstd/collections/hash/table.rs
@@ -15,7 +15,7 @@ use self::BucketState::*;
 use clone::Clone;
 use cmp;
 use hash::{Hash, Hasher};
-use iter::{Iterator, ExactSizeIterator, count};
+use iter::{Iterator, IteratorExt, ExactSizeIterator, count};
 use marker::{Copy, Sized, self};
 use mem::{min_align_of, size_of};
 use mem;
@@ -921,7 +921,7 @@ impl<'a, K, V> ExactSizeIterator for Drain<'a, K, V> {
 #[unsafe_destructor]
 impl<'a, K: 'a, V: 'a> Drop for Drain<'a, K, V> {
     fn drop(&mut self) {
-        for _ in *self {}
+        for _ in self.by_ref() {}
     }
 }
 
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index a016ba8fb0c..54e2eaf16ee 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -123,6 +123,8 @@
 #![feature(rand)]
 #![feature(hash)]
 #![cfg_attr(test, feature(test))]
+// NOTE(stage0): remove cfg_attr after a snapshot
+#![cfg_attr(not(stage0), allow(unused_mut))]
 
 // Don't link to std. We are std.
 #![no_std]
@@ -310,4 +312,6 @@ mod std {
     pub use slice;
 
     pub use boxed; // used for vec![]
+    // for-loops
+    pub use iter;
 }
diff --git a/src/libstd/path/windows.rs b/src/libstd/path/windows.rs
index 88db27013ac..98e0320cd14 100644
--- a/src/libstd/path/windows.rs
+++ b/src/libstd/path/windows.rs
@@ -557,7 +557,7 @@ impl GenericPath for Path {
                     }
                     (Some(a), Some(_)) => {
                         comps.push("..");
-                        for _ in itb {
+                        for _ in itb.by_ref() {
                             comps.push("..");
                         }
                         comps.push(a);
diff --git a/src/libstd/sys/common/backtrace.rs b/src/libstd/sys/common/backtrace.rs
index c3e12586829..a71676c6bf2 100644
--- a/src/libstd/sys/common/backtrace.rs
+++ b/src/libstd/sys/common/backtrace.rs
@@ -54,7 +54,7 @@ pub fn demangle(writer: &mut Writer, s: &str) -> IoResult<()> {
         let mut chars = inner.chars();
         while valid {
             let mut i = 0;
-            for c in chars {
+            for c in chars.by_ref() {
                 if c.is_numeric() {
                     i = i * 10 + c as uint - '0' as uint;
                 } else {