diff options
| author | Alex Crichton <alex@alexcrichton.com> | 2015-01-30 12:02:44 -0800 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2015-01-30 12:02:44 -0800 |
| commit | 341e858bd882061b823dac236fd718d473f8ab2e (patch) | |
| tree | 2e6d18523dcd67f28fe0a527f02102072ce14996 /src/libstd | |
| parent | 1a51eb9cca3ae5f815825096de4dfbdc9267f735 (diff) | |
| parent | b9a9030ed68f135e116e9a5d32663e00b897cf4f (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.rs | 2 | ||||
| -rw-r--r-- | src/libstd/collections/hash/table.rs | 4 | ||||
| -rw-r--r-- | src/libstd/lib.rs | 4 | ||||
| -rw-r--r-- | src/libstd/path/windows.rs | 2 | ||||
| -rw-r--r-- | src/libstd/sys/common/backtrace.rs | 2 |
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 { |
