mirror of
https://github.com/rust-lang/rust
synced 2024-09-21 09:22:41 +00:00
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
This commit is contained in:
commit
341e858bd8
|
@ -576,6 +576,10 @@ extern fn panic_fmt(args: &core::fmt::Arguments,
|
|||
#[lang = "eh_personality"] extern fn eh_personality() {}
|
||||
# #[start] fn start(argc: isize, argv: *const *const u8) -> isize { 0 }
|
||||
# fn main() {}
|
||||
# mod std { // for-loops
|
||||
# pub use core::iter;
|
||||
# pub use core::option;
|
||||
# }
|
||||
```
|
||||
|
||||
Note that there is one extra lang item here which differs from the examples
|
||||
|
|
|
@ -153,7 +153,7 @@
|
|||
use core::prelude::*;
|
||||
|
||||
use core::default::Default;
|
||||
use core::iter::FromIterator;
|
||||
use core::iter::{FromIterator, IntoIterator};
|
||||
use core::mem::{zeroed, replace, swap};
|
||||
use core::ptr;
|
||||
|
||||
|
@ -655,6 +655,22 @@ fn from_iter<Iter: Iterator<Item=T>>(iter: Iter) -> BinaryHeap<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Ord> IntoIterator for BinaryHeap<T> {
|
||||
type Iter = IntoIter<T>;
|
||||
|
||||
fn into_iter(self) -> IntoIter<T> {
|
||||
self.into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> IntoIterator for &'a BinaryHeap<T> where T: Ord {
|
||||
type Iter = Iter<'a, T>;
|
||||
|
||||
fn into_iter(self) -> Iter<'a, T> {
|
||||
self.iter()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: Ord> Extend<T> for BinaryHeap<T> {
|
||||
fn extend<Iter: Iterator<Item=T>>(&mut self, mut iter: Iter) {
|
||||
|
|
|
@ -89,7 +89,7 @@
|
|||
use core::hash;
|
||||
use core::iter::RandomAccessIterator;
|
||||
use core::iter::{Chain, Enumerate, Repeat, Skip, Take, repeat, Cloned};
|
||||
use core::iter::{self, FromIterator};
|
||||
use core::iter::{self, FromIterator, IntoIterator};
|
||||
use core::num::Int;
|
||||
use core::ops::Index;
|
||||
use core::slice;
|
||||
|
@ -1070,6 +1070,14 @@ fn idx(&mut self, index: uint) -> Option<bool> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoIterator for &'a Bitv {
|
||||
type Iter = Iter<'a>;
|
||||
|
||||
fn into_iter(self) -> Iter<'a> {
|
||||
self.iter()
|
||||
}
|
||||
}
|
||||
|
||||
/// An implementation of a set using a bit vector as an underlying
|
||||
/// representation for holding unsigned numerical elements.
|
||||
///
|
||||
|
@ -1873,6 +1881,13 @@ impl<'a> Iterator for SymmetricDifference<'a> {
|
|||
#[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.0.size_hint() }
|
||||
}
|
||||
|
||||
impl<'a> IntoIterator for &'a BitvSet {
|
||||
type Iter = SetIter<'a>;
|
||||
|
||||
fn into_iter(self) -> SetIter<'a> {
|
||||
self.iter()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
use core::default::Default;
|
||||
use core::fmt::Debug;
|
||||
use core::hash::{Hash, Hasher};
|
||||
use core::iter::{Map, FromIterator};
|
||||
use core::iter::{Map, FromIterator, IntoIterator};
|
||||
use core::ops::{Index, IndexMut};
|
||||
use core::{iter, fmt, mem};
|
||||
use Bound::{self, Included, Excluded, Unbounded};
|
||||
|
@ -478,6 +478,30 @@ pub fn remove<Q: ?Sized>(&mut self, key: &Q) -> Option<V> where Q: BorrowFrom<K>
|
|||
}
|
||||
}
|
||||
|
||||
impl<K, V> IntoIterator for BTreeMap<K, V> {
|
||||
type Iter = IntoIter<K, V>;
|
||||
|
||||
fn into_iter(self) -> IntoIter<K, V> {
|
||||
self.into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, K, V> IntoIterator for &'a BTreeMap<K, V> {
|
||||
type Iter = Iter<'a, K, V>;
|
||||
|
||||
fn into_iter(self) -> Iter<'a, K, V> {
|
||||
self.iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, K, V> IntoIterator for &'a mut BTreeMap<K, V> {
|
||||
type Iter = IterMut<'a, K, V>;
|
||||
|
||||
fn into_iter(mut self) -> IterMut<'a, K, V> {
|
||||
self.iter_mut()
|
||||
}
|
||||
}
|
||||
|
||||
/// A helper enum useful for deciding whether to continue a loop since we can't
|
||||
/// return from a closure
|
||||
enum Continuation<A, B> {
|
||||
|
|
|
@ -271,7 +271,7 @@ fn next_back(&mut self) -> Option<T> {
|
|||
#[unsafe_destructor]
|
||||
impl<T> Drop for RawItems<T> {
|
||||
fn drop(&mut self) {
|
||||
for _ in *self {}
|
||||
for _ in self.by_ref() {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1374,9 +1374,9 @@ impl<K, V> Drop for MoveTraversalImpl<K, V> {
|
|||
fn drop(&mut self) {
|
||||
// We need to cleanup the stored values manually, as the RawItems destructor would run
|
||||
// after our deallocation.
|
||||
for _ in self.keys {}
|
||||
for _ in self.vals {}
|
||||
for _ in self.edges {}
|
||||
for _ in self.keys.by_ref() {}
|
||||
for _ in self.vals.by_ref() {}
|
||||
for _ in self.edges.by_ref() {}
|
||||
|
||||
let (alignment, size) =
|
||||
calculate_allocation_generic::<K, V>(self.capacity, self.is_leaf);
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
use core::default::Default;
|
||||
use core::fmt::Debug;
|
||||
use core::fmt;
|
||||
use core::iter::{Peekable, Map, FromIterator};
|
||||
use core::iter::{Peekable, Map, FromIterator, IntoIterator};
|
||||
use core::ops::{BitOr, BitAnd, BitXor, Sub};
|
||||
|
||||
use btree_map::{BTreeMap, Keys};
|
||||
|
@ -480,6 +480,22 @@ fn from_iter<Iter: Iterator<Item=T>>(iter: Iter) -> BTreeSet<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> IntoIterator for BTreeSet<T> {
|
||||
type Iter = IntoIter<T>;
|
||||
|
||||
fn into_iter(self) -> IntoIter<T> {
|
||||
self.into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> IntoIterator for &'a BTreeSet<T> {
|
||||
type Iter = Iter<'a, T>;
|
||||
|
||||
fn into_iter(self) -> Iter<'a, T> {
|
||||
self.iter()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: Ord> Extend<T> for BTreeSet<T> {
|
||||
#[inline]
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
use core::default::Default;
|
||||
use core::fmt;
|
||||
use core::hash::{Writer, Hasher, Hash};
|
||||
use core::iter::{self, FromIterator};
|
||||
use core::iter::{self, FromIterator, IntoIterator};
|
||||
use core::mem;
|
||||
use core::ptr;
|
||||
|
||||
|
@ -830,6 +830,30 @@ fn from_iter<T: Iterator<Item=A>>(iterator: T) -> DList<A> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> IntoIterator for DList<T> {
|
||||
type Iter = IntoIter<T>;
|
||||
|
||||
fn into_iter(self) -> IntoIter<T> {
|
||||
self.into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> IntoIterator for &'a DList<T> {
|
||||
type Iter = Iter<'a, T>;
|
||||
|
||||
fn into_iter(self) -> Iter<'a, T> {
|
||||
self.iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> IntoIterator for &'a mut DList<T> {
|
||||
type Iter = IterMut<'a, T>;
|
||||
|
||||
fn into_iter(mut self) -> IterMut<'a, T> {
|
||||
self.iter_mut()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A> Extend<A> for DList<A> {
|
||||
fn extend<T: Iterator<Item=A>>(&mut self, mut iterator: T) {
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
use core::prelude::*;
|
||||
use core::fmt;
|
||||
use core::num::Int;
|
||||
use core::iter::FromIterator;
|
||||
use core::iter::{FromIterator, IntoIterator};
|
||||
use core::ops::{Sub, BitOr, BitAnd, BitXor};
|
||||
|
||||
// FIXME(contentions): implement union family of methods? (general design may be wrong here)
|
||||
|
@ -256,6 +256,14 @@ fn from_iter<I:Iterator<Item=E>>(iterator: I) -> EnumSet<E> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, E> IntoIterator for &'a EnumSet<E> where E: CLike {
|
||||
type Iter = Iter<E>;
|
||||
|
||||
fn into_iter(self) -> Iter<E> {
|
||||
self.iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<E:CLike> Extend<E> for EnumSet<E> {
|
||||
fn extend<I: Iterator<Item=E>>(&mut self, mut iterator: I) {
|
||||
for element in iterator {
|
||||
|
|
|
@ -34,6 +34,8 @@
|
|||
#![feature(unicode)]
|
||||
#![feature(hash)]
|
||||
#![cfg_attr(test, feature(test))]
|
||||
// NOTE(stage0): remove after a snapshot
|
||||
#![cfg_attr(not(stage0), allow(unused_mut))]
|
||||
|
||||
#[macro_use]
|
||||
extern crate core;
|
||||
|
@ -114,6 +116,8 @@ mod std {
|
|||
pub use core::marker; // derive(Copy)
|
||||
pub use core::hash; // derive(Hash)
|
||||
pub use core::ops; // RangeFull
|
||||
// for-loops
|
||||
pub use core::iter;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
use core::cmp::Ordering;
|
||||
use core::default::Default;
|
||||
use core::fmt;
|
||||
use core::iter::{self, repeat, FromIterator, RandomAccessIterator};
|
||||
use core::iter::{self, repeat, FromIterator, IntoIterator, RandomAccessIterator};
|
||||
use core::marker;
|
||||
use core::mem;
|
||||
use core::num::{Int, UnsignedInt};
|
||||
|
@ -1510,7 +1510,7 @@ pub struct Drain<'a, T: 'a> {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a, T: 'a> Drop for Drain<'a, T> {
|
||||
fn drop(&mut self) {
|
||||
for _ in *self {}
|
||||
for _ in self.by_ref() {}
|
||||
self.inner.head = 0;
|
||||
self.inner.tail = 0;
|
||||
}
|
||||
|
@ -1609,6 +1609,30 @@ fn from_iter<T: Iterator<Item=A>>(iterator: T) -> RingBuf<A> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> IntoIterator for RingBuf<T> {
|
||||
type Iter = IntoIter<T>;
|
||||
|
||||
fn into_iter(self) -> IntoIter<T> {
|
||||
self.into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> IntoIterator for &'a RingBuf<T> {
|
||||
type Iter = Iter<'a, T>;
|
||||
|
||||
fn into_iter(self) -> Iter<'a, T> {
|
||||
self.iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> IntoIterator for &'a mut RingBuf<T> {
|
||||
type Iter = IterMut<'a, T>;
|
||||
|
||||
fn into_iter(mut self) -> IterMut<'a, T> {
|
||||
self.iter_mut()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A> Extend<A> for RingBuf<A> {
|
||||
fn extend<T: Iterator<Item=A>>(&mut self, mut iterator: T) {
|
||||
|
|
|
@ -1958,7 +1958,7 @@ fn test_permutations() {
|
|||
let mut amt = 0;
|
||||
let mut it = v.permutations();
|
||||
let (min_size, max_opt) = it.size_hint();
|
||||
for _perm in it {
|
||||
for _perm in it.by_ref() {
|
||||
amt += 1;
|
||||
}
|
||||
assert_eq!(amt, it.swaps.swaps_made);
|
||||
|
|
|
@ -199,7 +199,7 @@ fn next(&mut self) -> Option<char> {
|
|||
}
|
||||
|
||||
if !self.sorted {
|
||||
for ch in self.iter {
|
||||
for ch in self.iter.by_ref() {
|
||||
let buffer = &mut self.buffer;
|
||||
let sorted = &mut self.sorted;
|
||||
{
|
||||
|
@ -279,7 +279,7 @@ fn next(&mut self) -> Option<char> {
|
|||
loop {
|
||||
match self.state {
|
||||
Composing => {
|
||||
for ch in self.iter {
|
||||
for ch in self.iter.by_ref() {
|
||||
let ch_class = unicode::char::canonical_combining_class(ch);
|
||||
if self.composee.is_none() {
|
||||
if ch_class != 0 {
|
||||
|
@ -2154,7 +2154,7 @@ fn test_iterator_clone() {
|
|||
let s = "ศไทย中华Việt Nam";
|
||||
let mut it = s.chars();
|
||||
it.next();
|
||||
assert!(it.zip(it.clone()).all(|(x,y)| x == y));
|
||||
assert!(it.clone().zip(it).all(|(x,y)| x == y));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
use core::default::Default;
|
||||
use core::fmt;
|
||||
use core::hash::{self, Hash};
|
||||
use core::iter::{repeat, FromIterator};
|
||||
use core::iter::{repeat, FromIterator, IntoIterator};
|
||||
use core::marker::{ContravariantLifetime, InvariantType};
|
||||
use core::mem;
|
||||
use core::nonzero::NonZero;
|
||||
|
@ -65,6 +65,7 @@
|
|||
use core::ops;
|
||||
use core::ptr;
|
||||
use core::raw::Slice as RawSlice;
|
||||
use core::slice;
|
||||
use core::uint;
|
||||
|
||||
/// A growable list type, written `Vec<T>` but pronounced 'vector.'
|
||||
|
@ -1404,6 +1405,30 @@ fn from_iter<I:Iterator<Item=T>>(mut iterator: I) -> Vec<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> IntoIterator for Vec<T> {
|
||||
type Iter = IntoIter<T>;
|
||||
|
||||
fn into_iter(self) -> IntoIter<T> {
|
||||
self.into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> IntoIterator for &'a Vec<T> {
|
||||
type Iter = slice::Iter<'a, T>;
|
||||
|
||||
fn into_iter(self) -> slice::Iter<'a, T> {
|
||||
self.iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> IntoIterator for &'a mut Vec<T> {
|
||||
type Iter = slice::IterMut<'a, T>;
|
||||
|
||||
fn into_iter(mut self) -> slice::IterMut<'a, T> {
|
||||
self.iter_mut()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "collections", reason = "waiting on Extend stability")]
|
||||
impl<T> Extend<T> for Vec<T> {
|
||||
#[inline]
|
||||
|
@ -1623,7 +1648,7 @@ impl<T> IntoIter<T> {
|
|||
#[unstable(feature = "collections")]
|
||||
pub fn into_inner(mut self) -> Vec<T> {
|
||||
unsafe {
|
||||
for _x in self { }
|
||||
for _x in self.by_ref() { }
|
||||
let IntoIter { allocation, cap, ptr: _ptr, end: _end } = self;
|
||||
mem::forget(self);
|
||||
Vec { ptr: NonZero::new(allocation), cap: cap, len: 0 }
|
||||
|
@ -1701,7 +1726,7 @@ impl<T> Drop for IntoIter<T> {
|
|||
fn drop(&mut self) {
|
||||
// destroy the remaining elements
|
||||
if self.cap != 0 {
|
||||
for _x in *self {}
|
||||
for _x in self.by_ref() {}
|
||||
unsafe {
|
||||
dealloc(self.allocation, self.cap);
|
||||
}
|
||||
|
@ -1791,7 +1816,7 @@ fn drop(&mut self) {
|
|||
// so we can use #[unsafe_no_drop_flag].
|
||||
|
||||
// destroy the remaining elements
|
||||
for _x in *self {}
|
||||
for _x in self.by_ref() {}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
use core::default::Default;
|
||||
use core::fmt;
|
||||
use core::hash::{Hash, Writer, Hasher};
|
||||
use core::iter::{Enumerate, FilterMap, Map, FromIterator};
|
||||
use core::iter::{Enumerate, FilterMap, Map, FromIterator, IntoIterator};
|
||||
use core::iter;
|
||||
use core::mem::replace;
|
||||
use core::ops::{Index, IndexMut};
|
||||
|
@ -536,6 +536,30 @@ fn from_iter<Iter: Iterator<Item=(uint, V)>>(iter: Iter) -> VecMap<V> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> IntoIterator for VecMap<T> {
|
||||
type Iter = IntoIter<T>;
|
||||
|
||||
fn into_iter(self) -> IntoIter<T> {
|
||||
self.into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> IntoIterator for &'a VecMap<T> {
|
||||
type Iter = Iter<'a, T>;
|
||||
|
||||
fn into_iter(self) -> Iter<'a, T> {
|
||||
self.iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> IntoIterator for &'a mut VecMap<T> {
|
||||
type Iter = IterMut<'a, T>;
|
||||
|
||||
fn into_iter(mut self) -> IterMut<'a, T> {
|
||||
self.iter_mut()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<V> Extend<(uint, V)> for VecMap<V> {
|
||||
fn extend<Iter: Iterator<Item=(uint, V)>>(&mut self, mut iter: Iter) {
|
||||
|
|
|
@ -18,12 +18,14 @@
|
|||
use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
|
||||
use fmt;
|
||||
use hash::{Hash, Hasher, self};
|
||||
use iter::IntoIterator;
|
||||
use marker::Copy;
|
||||
#[cfg(stage0)]
|
||||
use ops::{Deref, FullRange};
|
||||
#[cfg(not(stage0))]
|
||||
use ops::Deref;
|
||||
use option::Option;
|
||||
use slice::{Iter, IterMut, SliceExt};
|
||||
|
||||
// macro for implementing n-ary tuple functions and operations
|
||||
macro_rules! array_impls {
|
||||
|
@ -49,6 +51,22 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, T> IntoIterator for &'a [T; $N] {
|
||||
type Iter = Iter<'a, T>;
|
||||
|
||||
fn into_iter(self) -> Iter<'a, T> {
|
||||
self.iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> IntoIterator for &'a mut [T; $N] {
|
||||
type Iter = IterMut<'a, T>;
|
||||
|
||||
fn into_iter(self) -> IterMut<'a, T> {
|
||||
self.iter_mut()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A, B> PartialEq<[B; $N]> for [A; $N] where A: PartialEq<B> {
|
||||
#[inline]
|
||||
|
|
|
@ -122,6 +122,22 @@ pub trait FromIterator<A> {
|
|||
fn from_iter<T: Iterator<Item=A>>(iterator: T) -> Self;
|
||||
}
|
||||
|
||||
/// Conversion into an `Iterator`
|
||||
pub trait IntoIterator {
|
||||
type Iter: Iterator;
|
||||
|
||||
/// Consumes `Self` and returns an iterator over it
|
||||
fn into_iter(self) -> Self::Iter;
|
||||
}
|
||||
|
||||
impl<I> IntoIterator for I where I: Iterator {
|
||||
type Iter = I;
|
||||
|
||||
fn into_iter(self) -> I {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// A type growable from an `Iterator` implementation
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait Extend<A> {
|
||||
|
@ -178,7 +194,7 @@ fn last(mut self) -> Option<Self::Item> {
|
|||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn nth(&mut self, mut n: usize) -> Option<Self::Item> {
|
||||
for x in *self {
|
||||
for x in self.by_ref() {
|
||||
if n == 0 { return Some(x) }
|
||||
n -= 1;
|
||||
}
|
||||
|
@ -475,7 +491,7 @@ fn flat_map<B, U, F>(self, f: F) -> FlatMap<Self::Item, B, Self, U, F> where
|
|||
/// fn process<U: Iterator<Item=isize>>(it: U) -> isize {
|
||||
/// let mut it = it.fuse();
|
||||
/// let mut sum = 0;
|
||||
/// for x in it {
|
||||
/// for x in it.by_ref() {
|
||||
/// if x > 5 {
|
||||
/// break;
|
||||
/// }
|
||||
|
@ -643,7 +659,7 @@ fn all<F>(mut self, mut f: F) -> bool where F: FnMut(Self::Item) -> bool {
|
|||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn any<F>(&mut self, mut f: F) -> bool where F: FnMut(Self::Item) -> bool {
|
||||
for x in *self { if f(x) { return true; } }
|
||||
for x in self.by_ref() { if f(x) { return true; } }
|
||||
false
|
||||
}
|
||||
|
||||
|
@ -663,7 +679,7 @@ fn any<F>(&mut self, mut f: F) -> bool where F: FnMut(Self::Item) -> bool {
|
|||
fn find<P>(&mut self, mut predicate: P) -> Option<Self::Item> where
|
||||
P: FnMut(&Self::Item) -> bool,
|
||||
{
|
||||
for x in *self {
|
||||
for x in self.by_ref() {
|
||||
if predicate(&x) { return Some(x) }
|
||||
}
|
||||
None
|
||||
|
@ -686,7 +702,7 @@ fn position<P>(&mut self, mut predicate: P) -> Option<usize> where
|
|||
P: FnMut(Self::Item) -> bool,
|
||||
{
|
||||
let mut i = 0;
|
||||
for x in *self {
|
||||
for x in self.by_ref() {
|
||||
if predicate(x) {
|
||||
return Some(i);
|
||||
}
|
||||
|
@ -1312,7 +1328,7 @@ impl<T, D, I> ExactSizeIterator for Cloned<I> where
|
|||
{}
|
||||
|
||||
/// An iterator that repeats endlessly
|
||||
#[derive(Clone, Copy)]
|
||||
#[derive(Clone)]
|
||||
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Cycle<I> {
|
||||
|
@ -1647,7 +1663,7 @@ impl<A, I, P> Iterator for Filter<A, I, P> where I: Iterator<Item=A>, P: FnMut(&
|
|||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<A> {
|
||||
for x in self.iter {
|
||||
for x in self.iter.by_ref() {
|
||||
if (self.predicate)(&x) {
|
||||
return Some(x);
|
||||
} else {
|
||||
|
@ -1711,7 +1727,7 @@ impl<A, B, I, F> Iterator for FilterMap<A, B, I, F> where
|
|||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<B> {
|
||||
for x in self.iter {
|
||||
for x in self.iter.by_ref() {
|
||||
match (self.f)(x) {
|
||||
Some(y) => return Some(y),
|
||||
None => ()
|
||||
|
@ -1810,7 +1826,6 @@ fn idx(&mut self, index: usize) -> Option<(usize, <I as Iterator>::Item)> {
|
|||
/// An iterator with a `peek()` that returns an optional reference to the next element.
|
||||
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[derive(Copy)]
|
||||
pub struct Peekable<T, I> where I: Iterator<Item=T> {
|
||||
iter: I,
|
||||
peeked: Option<T>,
|
||||
|
@ -1897,7 +1912,7 @@ impl<A, I, P> Iterator for SkipWhile<A, I, P> where I: Iterator<Item=A>, P: FnMu
|
|||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<A> {
|
||||
for x in self.iter {
|
||||
for x in self.iter.by_ref() {
|
||||
if self.flag || !(self.predicate)(&x) {
|
||||
self.flag = true;
|
||||
return Some(x);
|
||||
|
@ -2190,7 +2205,7 @@ impl<A, B, I, U, F> Iterator for FlatMap<A, B, I, U, F> where
|
|||
fn next(&mut self) -> Option<B> {
|
||||
loop {
|
||||
for inner in self.frontiter.iter_mut() {
|
||||
for x in *inner {
|
||||
for x in inner.by_ref() {
|
||||
return Some(x)
|
||||
}
|
||||
}
|
||||
|
@ -2484,7 +2499,7 @@ fn size_hint(&self) -> (usize, Option<usize>) {
|
|||
|
||||
/// An infinite iterator starting at `start` and advancing by `step` with each
|
||||
/// iteration
|
||||
#[derive(Clone, Copy)]
|
||||
#[derive(Clone)]
|
||||
#[unstable(feature = "core",
|
||||
reason = "may be renamed or replaced by range notation adapaters")]
|
||||
pub struct Counter<A> {
|
||||
|
@ -2520,7 +2535,7 @@ fn size_hint(&self) -> (usize, Option<usize>) {
|
|||
}
|
||||
|
||||
/// An iterator over the range [start, stop)
|
||||
#[derive(Clone, Copy)]
|
||||
#[derive(Clone)]
|
||||
#[unstable(feature = "core",
|
||||
reason = "will be replaced by range notation")]
|
||||
pub struct Range<A> {
|
||||
|
|
|
@ -65,6 +65,8 @@
|
|||
#![allow(unknown_features)] #![feature(int_uint)]
|
||||
#![feature(on_unimplemented)]
|
||||
#![deny(missing_docs)]
|
||||
// NOTE(stage0) remove cfg_attr after a snapshot
|
||||
#![cfg_attr(not(stage0), allow(unused_mut))]
|
||||
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
|
@ -158,4 +160,6 @@ mod std {
|
|||
pub use marker;
|
||||
pub use ops;
|
||||
pub use option;
|
||||
// for-loops
|
||||
pub use iter;
|
||||
}
|
||||
|
|
|
@ -1524,7 +1524,7 @@ fn from_str_radix(src: &str, radix: uint) -> Option<$T> {
|
|||
let mut exp_info = None::<(char, uint)>;
|
||||
|
||||
// Parse the integer part of the significand
|
||||
for (i, c) in cs {
|
||||
for (i, c) in cs.by_ref() {
|
||||
match c.to_digit(radix) {
|
||||
Some(digit) => {
|
||||
// shift significand one digit left
|
||||
|
@ -1572,7 +1572,7 @@ fn from_str_radix(src: &str, radix: uint) -> Option<$T> {
|
|||
// part of the significand
|
||||
if exp_info.is_none() {
|
||||
let mut power = 1.0;
|
||||
for (i, c) in cs {
|
||||
for (i, c) in cs.by_ref() {
|
||||
match c.to_digit(radix) {
|
||||
Some(digit) => {
|
||||
// Decrease power one order of magnitude
|
||||
|
|
|
@ -41,7 +41,6 @@
|
|||
use cmp;
|
||||
use default::Default;
|
||||
use iter::*;
|
||||
use marker::Copy;
|
||||
use num::Int;
|
||||
use ops::{FnMut, self, Index};
|
||||
#[cfg(stage0)]
|
||||
|
@ -637,6 +636,22 @@ fn default() -> &'a [T] { &[] }
|
|||
// Iterators
|
||||
//
|
||||
|
||||
impl<'a, T> IntoIterator for &'a [T] {
|
||||
type Iter = Iter<'a, T>;
|
||||
|
||||
fn into_iter(self) -> Iter<'a, T> {
|
||||
self.iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> IntoIterator for &'a mut [T] {
|
||||
type Iter = IterMut<'a, T>;
|
||||
|
||||
fn into_iter(self) -> IterMut<'a, T> {
|
||||
self.iter_mut()
|
||||
}
|
||||
}
|
||||
|
||||
// The shared definition of the `Iter` and `IterMut` iterators
|
||||
macro_rules! iterator {
|
||||
(struct $name:ident -> $ptr:ty, $elem:ty) => {
|
||||
|
@ -784,8 +799,6 @@ pub fn as_slice(&self) -> &'a [T] {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a,T> Copy for Iter<'a,T> {}
|
||||
|
||||
iterator!{struct Iter -> *const T, &'a T}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
@ -793,7 +806,7 @@ impl<'a, T> ExactSizeIterator for Iter<'a, T> {}
|
|||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a, T> Clone for Iter<'a, T> {
|
||||
fn clone(&self) -> Iter<'a, T> { *self }
|
||||
fn clone(&self) -> Iter<'a, T> { Iter { ptr: self.ptr, end: self.end, marker: self.marker } }
|
||||
}
|
||||
|
||||
#[unstable(feature = "core", reason = "trait is experimental")]
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
use self::Searcher::{Naive, TwoWay, TwoWayLong};
|
||||
|
||||
use clone::Clone;
|
||||
use cmp::{self, Eq};
|
||||
use default::Default;
|
||||
use error::Error;
|
||||
|
@ -279,7 +280,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|||
/// Iterator for the char (representing *Unicode Scalar Values*) of a string
|
||||
///
|
||||
/// Created with the method `.chars()`.
|
||||
#[derive(Clone, Copy)]
|
||||
#[derive(Clone)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Chars<'a> {
|
||||
iter: slice::Iter<'a, u8>
|
||||
|
@ -1007,11 +1008,11 @@ fn run_utf8_validation_iterator(iter: &mut slice::Iter<u8>)
|
|||
let whole = iter.as_slice();
|
||||
loop {
|
||||
// save the current thing we're pointing at.
|
||||
let old = *iter;
|
||||
let old = iter.clone();
|
||||
|
||||
// restore the iterator we had at the start of this codepoint.
|
||||
macro_rules! err { () => {{
|
||||
*iter = old;
|
||||
*iter = old.clone();
|
||||
return Err(Utf8Error::InvalidByte(whole.len() - iter.as_slice().len()))
|
||||
}}}
|
||||
|
||||
|
|
|
@ -366,32 +366,32 @@ fn test_iterator_size_hint() {
|
|||
let vi = v.iter();
|
||||
|
||||
assert_eq!(c.size_hint(), (uint::MAX, None));
|
||||
assert_eq!(vi.size_hint(), (10, Some(10)));
|
||||
assert_eq!(vi.clone().size_hint(), (10, Some(10)));
|
||||
|
||||
assert_eq!(c.take(5).size_hint(), (5, Some(5)));
|
||||
assert_eq!(c.skip(5).size_hint().1, None);
|
||||
assert_eq!(c.take_while(|_| false).size_hint(), (0, None));
|
||||
assert_eq!(c.skip_while(|_| false).size_hint(), (0, None));
|
||||
assert_eq!(c.enumerate().size_hint(), (uint::MAX, None));
|
||||
assert_eq!(c.chain(vi.map(|&i| i)).size_hint(), (uint::MAX, None));
|
||||
assert_eq!(c.zip(vi).size_hint(), (10, Some(10)));
|
||||
assert_eq!(c.scan(0i, |_,_| Some(0i)).size_hint(), (0, None));
|
||||
assert_eq!(c.filter(|_| false).size_hint(), (0, None));
|
||||
assert_eq!(c.map(|_| 0i).size_hint(), (uint::MAX, None));
|
||||
assert_eq!(c.clone().take(5).size_hint(), (5, Some(5)));
|
||||
assert_eq!(c.clone().skip(5).size_hint().1, None);
|
||||
assert_eq!(c.clone().take_while(|_| false).size_hint(), (0, None));
|
||||
assert_eq!(c.clone().skip_while(|_| false).size_hint(), (0, None));
|
||||
assert_eq!(c.clone().enumerate().size_hint(), (uint::MAX, None));
|
||||
assert_eq!(c.clone().chain(vi.clone().map(|&i| i)).size_hint(), (uint::MAX, None));
|
||||
assert_eq!(c.clone().zip(vi.clone()).size_hint(), (10, Some(10)));
|
||||
assert_eq!(c.clone().scan(0i, |_,_| Some(0i)).size_hint(), (0, None));
|
||||
assert_eq!(c.clone().filter(|_| false).size_hint(), (0, None));
|
||||
assert_eq!(c.clone().map(|_| 0i).size_hint(), (uint::MAX, None));
|
||||
assert_eq!(c.filter_map(|_| Some(0i)).size_hint(), (0, None));
|
||||
|
||||
assert_eq!(vi.take(5).size_hint(), (5, Some(5)));
|
||||
assert_eq!(vi.take(12).size_hint(), (10, Some(10)));
|
||||
assert_eq!(vi.skip(3).size_hint(), (7, Some(7)));
|
||||
assert_eq!(vi.skip(12).size_hint(), (0, Some(0)));
|
||||
assert_eq!(vi.take_while(|_| false).size_hint(), (0, Some(10)));
|
||||
assert_eq!(vi.skip_while(|_| false).size_hint(), (0, Some(10)));
|
||||
assert_eq!(vi.enumerate().size_hint(), (10, Some(10)));
|
||||
assert_eq!(vi.chain(v2.iter()).size_hint(), (13, Some(13)));
|
||||
assert_eq!(vi.zip(v2.iter()).size_hint(), (3, Some(3)));
|
||||
assert_eq!(vi.scan(0i, |_,_| Some(0i)).size_hint(), (0, Some(10)));
|
||||
assert_eq!(vi.filter(|_| false).size_hint(), (0, Some(10)));
|
||||
assert_eq!(vi.map(|&i| i+1).size_hint(), (10, Some(10)));
|
||||
assert_eq!(vi.clone().take(5).size_hint(), (5, Some(5)));
|
||||
assert_eq!(vi.clone().take(12).size_hint(), (10, Some(10)));
|
||||
assert_eq!(vi.clone().skip(3).size_hint(), (7, Some(7)));
|
||||
assert_eq!(vi.clone().skip(12).size_hint(), (0, Some(0)));
|
||||
assert_eq!(vi.clone().take_while(|_| false).size_hint(), (0, Some(10)));
|
||||
assert_eq!(vi.clone().skip_while(|_| false).size_hint(), (0, Some(10)));
|
||||
assert_eq!(vi.clone().enumerate().size_hint(), (10, Some(10)));
|
||||
assert_eq!(vi.clone().chain(v2.iter()).size_hint(), (13, Some(13)));
|
||||
assert_eq!(vi.clone().zip(v2.iter()).size_hint(), (3, Some(3)));
|
||||
assert_eq!(vi.clone().scan(0i, |_,_| Some(0i)).size_hint(), (0, Some(10)));
|
||||
assert_eq!(vi.clone().filter(|_| false).size_hint(), (0, Some(10)));
|
||||
assert_eq!(vi.clone().map(|&i| i+1).size_hint(), (10, Some(10)));
|
||||
assert_eq!(vi.filter_map(|_| Some(0i)).size_hint(), (0, Some(10)));
|
||||
}
|
||||
|
||||
|
@ -904,7 +904,7 @@ fn bench_multiple_take(b: &mut Bencher) {
|
|||
b.iter(|| {
|
||||
let n = it.next().unwrap();
|
||||
for _ in 0u..n {
|
||||
it.take(it.next().unwrap()).all(|_| true);
|
||||
it.clone().take(it.next().unwrap()).all(|_| true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -498,6 +498,8 @@ mod std {
|
|||
pub use core::{option, fmt}; // panic!()
|
||||
pub use core::clone; // derive Clone
|
||||
pub use core::marker;
|
||||
// for-loops
|
||||
pub use core::iter;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -41,6 +41,8 @@
|
|||
#![feature(unicode)]
|
||||
#![feature(hash)]
|
||||
#![cfg_attr(test, feature(test))]
|
||||
// NOTE(stage0) remove cfg_attr after a snapshot
|
||||
#![cfg_attr(not(stage0), allow(unused_mut))]
|
||||
|
||||
extern crate arena;
|
||||
extern crate flate;
|
||||
|
|
|
@ -1163,6 +1163,7 @@ fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
|
|||
ast::MatchSource::Normal => (head, "`match` head expression", true),
|
||||
ast::MatchSource::IfLetDesugar { .. } => (head, "`if let` head expression", true),
|
||||
ast::MatchSource::WhileLetDesugar => (head, "`while let` head expression", true),
|
||||
ast::MatchSource::ForLoopDesugar => (head, "`for` head expression", true),
|
||||
},
|
||||
ast::ExprRet(Some(ref value)) => (value, "`return` value", false),
|
||||
ast::ExprAssign(_, ref value) => (value, "assigned value", false),
|
||||
|
|
|
@ -263,43 +263,8 @@ fn expr(&mut self, expr: &ast::Expr, pred: CFGIndex) -> CFGIndex {
|
|||
self.tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet");
|
||||
}
|
||||
|
||||
ast::ExprForLoop(ref pat, ref head, ref body, _) => {
|
||||
//
|
||||
// [pred]
|
||||
// |
|
||||
// v 1
|
||||
// [head]
|
||||
// |
|
||||
// v 2
|
||||
// [loopback] <--+ 7
|
||||
// | |
|
||||
// v 3 |
|
||||
// +------[cond] |
|
||||
// | | |
|
||||
// | v 5 |
|
||||
// | [pat] |
|
||||
// | | |
|
||||
// | v 6 |
|
||||
// v 4 [body] -----+
|
||||
// [expr]
|
||||
//
|
||||
// Note that `break` and `continue` statements
|
||||
// may cause additional edges.
|
||||
|
||||
let head = self.expr(&**head, pred); // 1
|
||||
let loopback = self.add_dummy_node(&[head]); // 2
|
||||
let cond = self.add_dummy_node(&[loopback]); // 3
|
||||
let expr_exit = self.add_node(expr.id, &[cond]); // 4
|
||||
self.loop_scopes.push(LoopScope {
|
||||
loop_id: expr.id,
|
||||
continue_index: loopback,
|
||||
break_index: expr_exit,
|
||||
});
|
||||
let pat = self.pat(&**pat, cond); // 5
|
||||
let body = self.block(&**body, pat); // 6
|
||||
self.add_contained_edge(body, loopback); // 7
|
||||
self.loop_scopes.pop();
|
||||
expr_exit
|
||||
ast::ExprForLoop(..) => {
|
||||
self.tcx.sess.span_bug(expr.span, "non-desugared ExprForLoop");
|
||||
}
|
||||
|
||||
ast::ExprLoop(ref body, _) => {
|
||||
|
|
|
@ -45,10 +45,6 @@ fn visit_expr(&mut self, e: &ast::Expr) {
|
|||
ast::ExprLoop(ref b, _) => {
|
||||
self.with_context(Loop, |v| v.visit_block(&**b));
|
||||
}
|
||||
ast::ExprForLoop(_, ref e, ref b, _) => {
|
||||
self.visit_expr(&**e);
|
||||
self.with_context(Loop, |v| v.visit_block(&**b));
|
||||
}
|
||||
ast::ExprClosure(_, _, _, ref b) => {
|
||||
self.with_context(Closure, |v| v.visit_block(&**b));
|
||||
}
|
||||
|
|
|
@ -221,21 +221,8 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &ast::Expr) {
|
|||
.flat_map(|arm| arm.0.iter())
|
||||
.map(|pat| vec![&**pat])
|
||||
.collect();
|
||||
check_exhaustive(cx, ex.span, &matrix);
|
||||
check_exhaustive(cx, ex.span, &matrix, source);
|
||||
},
|
||||
ast::ExprForLoop(ref pat, _, _, _) => {
|
||||
let mut static_inliner = StaticInliner::new(cx.tcx);
|
||||
is_refutable(cx, &*static_inliner.fold_pat((*pat).clone()), |uncovered_pat| {
|
||||
span_err!(cx.tcx.sess, pat.span, E0297,
|
||||
"refutable pattern in `for` loop binding: \
|
||||
`{}` not covered",
|
||||
pat_to_string(uncovered_pat));
|
||||
});
|
||||
|
||||
// Check legality of move bindings.
|
||||
check_legality_of_move_bindings(cx, false, slice::ref_slice(pat));
|
||||
check_legality_of_bindings_in_at_patterns(cx, &**pat);
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
@ -327,6 +314,14 @@ fn check_arms(cx: &MatchCheckCtxt,
|
|||
span_err!(cx.tcx.sess, span, E0165, "irrefutable while-let pattern");
|
||||
},
|
||||
|
||||
ast::MatchSource::ForLoopDesugar => {
|
||||
// this is a bug, because on `match iter.next()` we cover
|
||||
// `Some(<head>)` and `None`. It's impossible to have an unreachable
|
||||
// pattern
|
||||
// (see libsyntax/ext/expand.rs for the full expansion of a for loop)
|
||||
cx.tcx.sess.span_bug(pat.span, "unreachable for-loop pattern")
|
||||
},
|
||||
|
||||
ast::MatchSource::Normal => {
|
||||
span_err!(cx.tcx.sess, pat.span, E0001, "unreachable pattern")
|
||||
},
|
||||
|
@ -351,7 +346,7 @@ fn raw_pat<'a>(p: &'a Pat) -> &'a Pat {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, matrix: &Matrix) {
|
||||
fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, matrix: &Matrix, source: ast::MatchSource) {
|
||||
match is_useful(cx, matrix, &[DUMMY_WILD_PAT], ConstructWitness) {
|
||||
UsefulWithWitness(pats) => {
|
||||
let witness = match &pats[] {
|
||||
|
@ -359,10 +354,29 @@ fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, matrix: &Matrix) {
|
|||
[] => DUMMY_WILD_PAT,
|
||||
_ => unreachable!()
|
||||
};
|
||||
match source {
|
||||
ast::MatchSource::ForLoopDesugar => {
|
||||
// `witness` has the form `Some(<head>)`, peel off the `Some`
|
||||
let witness = match witness.node {
|
||||
ast::PatEnum(_, Some(ref pats)) => match &pats[] {
|
||||
[ref pat] => &**pat,
|
||||
_ => unreachable!(),
|
||||
},
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
span_err!(cx.tcx.sess, sp, E0297,
|
||||
"refutable pattern in `for` loop binding: \
|
||||
`{}` not covered",
|
||||
pat_to_string(witness));
|
||||
},
|
||||
_ => {
|
||||
span_err!(cx.tcx.sess, sp, E0004,
|
||||
"non-exhaustive patterns: `{}` not covered",
|
||||
pat_to_string(witness)
|
||||
);
|
||||
},
|
||||
}
|
||||
}
|
||||
NotUseful => {
|
||||
// This is good, wildcard pattern isn't reachable
|
||||
|
|
|
@ -537,22 +537,8 @@ pub fn walk_expr(&mut self, expr: &ast::Expr) {
|
|||
self.tcx().sess.span_bug(expr.span, "non-desugared ExprWhileLet");
|
||||
}
|
||||
|
||||
ast::ExprForLoop(ref pat, ref head, ref blk, _) => {
|
||||
// The pattern lives as long as the block.
|
||||
debug!("walk_expr for loop case: blk id={}", blk.id);
|
||||
self.consume_expr(&**head);
|
||||
|
||||
// Fetch the type of the value that the iteration yields to
|
||||
// produce the pattern's categorized mutable type.
|
||||
let pattern_type = return_if_err!(self.typer.node_ty(pat.id));
|
||||
let blk_scope = region::CodeExtent::from_node_id(blk.id);
|
||||
let pat_cmt = self.mc.cat_rvalue(pat.id,
|
||||
pat.span,
|
||||
ty::ReScope(blk_scope),
|
||||
pattern_type);
|
||||
self.walk_irrefutable_pat(pat_cmt, &**pat);
|
||||
|
||||
self.walk_block(&**blk);
|
||||
ast::ExprForLoop(..) => {
|
||||
self.tcx().sess.span_bug(expr.span, "non-desugared ExprForLoop");
|
||||
}
|
||||
|
||||
ast::ExprUnary(op, ref lhs) => {
|
||||
|
|
|
@ -325,8 +325,6 @@ pub fn collect_language_items(krate: &ast::Crate,
|
|||
|
||||
NonZeroItem, "non_zero", non_zero;
|
||||
|
||||
IteratorItem, "iterator", iterator;
|
||||
|
||||
StackExhaustedLangItem, "stack_exhausted", stack_exhausted;
|
||||
|
||||
DebugTraitLangItem, "debug_trait", debug_trait;
|
||||
|
|
|
@ -135,8 +135,6 @@ enum LoopKind<'a> {
|
|||
LoopLoop,
|
||||
/// A `while` loop, with the given expression as condition.
|
||||
WhileLoop(&'a Expr),
|
||||
/// A `for` loop, with the given pattern to bind.
|
||||
ForLoop(&'a ast::Pat),
|
||||
}
|
||||
|
||||
#[derive(Copy, PartialEq)]
|
||||
|
@ -490,19 +488,8 @@ fn visit_expr(ir: &mut IrMaps, expr: &Expr) {
|
|||
ast::ExprWhileLet(..) => {
|
||||
ir.tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet");
|
||||
}
|
||||
ast::ExprForLoop(ref pat, _, _, _) => {
|
||||
pat_util::pat_bindings(&ir.tcx.def_map, &**pat, |bm, p_id, sp, path1| {
|
||||
debug!("adding local variable {} from for loop with bm {:?}",
|
||||
p_id, bm);
|
||||
let name = path1.node;
|
||||
ir.add_live_node_for_node(p_id, VarDefNode(sp));
|
||||
ir.add_variable(Local(LocalInfo {
|
||||
id: p_id,
|
||||
ident: name
|
||||
}));
|
||||
});
|
||||
ir.add_live_node_for_node(expr.id, ExprNode(expr.span));
|
||||
visit::walk_expr(ir, expr);
|
||||
ast::ExprForLoop(..) => {
|
||||
ir.tcx.sess.span_bug(expr.span, "non-desugared ExprForLoop");
|
||||
}
|
||||
ast::ExprBinary(op, _, _) if ast_util::lazy_binop(op.node) => {
|
||||
ir.add_live_node_for_node(expr.id, ExprNode(expr.span));
|
||||
|
@ -1034,9 +1021,8 @@ fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode)
|
|||
self.ir.tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet");
|
||||
}
|
||||
|
||||
ast::ExprForLoop(ref pat, ref head, ref blk, _) => {
|
||||
let ln = self.propagate_through_loop(expr, ForLoop(&**pat), &**blk, succ);
|
||||
self.propagate_through_expr(&**head, ln)
|
||||
ast::ExprForLoop(..) => {
|
||||
self.ir.tcx.sess.span_bug(expr.span, "non-desugared ExprForLoop");
|
||||
}
|
||||
|
||||
// Note that labels have been resolved, so we don't need to look
|
||||
|
@ -1373,7 +1359,6 @@ fn propagate_through_loop(&mut self,
|
|||
|
||||
let cond_ln = match kind {
|
||||
LoopLoop => ln,
|
||||
ForLoop(ref pat) => self.define_bindings_in_pat(*pat, ln),
|
||||
WhileLoop(ref cond) => self.propagate_through_expr(&**cond, ln),
|
||||
};
|
||||
let body_ln = self.with_loop_nodes(expr.id, succ, ln, |this| {
|
||||
|
@ -1386,9 +1371,6 @@ fn propagate_through_loop(&mut self,
|
|||
|
||||
let new_cond_ln = match kind {
|
||||
LoopLoop => ln,
|
||||
ForLoop(ref pat) => {
|
||||
self.define_bindings_in_pat(*pat, ln)
|
||||
}
|
||||
WhileLoop(ref cond) => {
|
||||
self.propagate_through_expr(&**cond, ln)
|
||||
}
|
||||
|
@ -1476,14 +1458,6 @@ fn check_expr(this: &mut Liveness, expr: &Expr) {
|
|||
visit::walk_expr(this, expr);
|
||||
}
|
||||
|
||||
ast::ExprForLoop(ref pat, _, _, _) => {
|
||||
this.pat_bindings(&**pat, |this, ln, var, sp, id| {
|
||||
this.warn_about_unused(sp, id, ln, var);
|
||||
});
|
||||
|
||||
visit::walk_expr(this, expr);
|
||||
}
|
||||
|
||||
// no correctness conditions related to liveness
|
||||
ast::ExprCall(..) | ast::ExprMethodCall(..) | ast::ExprIf(..) |
|
||||
ast::ExprMatch(..) | ast::ExprWhile(..) | ast::ExprLoop(..) |
|
||||
|
@ -1503,6 +1477,9 @@ fn check_expr(this: &mut Liveness, expr: &Expr) {
|
|||
ast::ExprWhileLet(..) => {
|
||||
this.ir.tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet");
|
||||
}
|
||||
ast::ExprForLoop(..) => {
|
||||
this.ir.tcx.sess.span_bug(expr.span, "non-desugared ExprForLoop");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -536,8 +536,7 @@ pub fn cat_expr_unadjusted(&self, expr: &ast::Expr) -> McResult<cmt<'tcx>> {
|
|||
ast::ExprBlock(..) | ast::ExprLoop(..) | ast::ExprMatch(..) |
|
||||
ast::ExprLit(..) | ast::ExprBreak(..) | ast::ExprMac(..) |
|
||||
ast::ExprAgain(..) | ast::ExprStruct(..) | ast::ExprRepeat(..) |
|
||||
ast::ExprInlineAsm(..) | ast::ExprBox(..) |
|
||||
ast::ExprForLoop(..) => {
|
||||
ast::ExprInlineAsm(..) | ast::ExprBox(..) => {
|
||||
Ok(self.cat_rvalue_node(expr.id(), expr.span(), expr_ty))
|
||||
}
|
||||
|
||||
|
@ -547,6 +546,9 @@ pub fn cat_expr_unadjusted(&self, expr: &ast::Expr) -> McResult<cmt<'tcx>> {
|
|||
ast::ExprWhileLet(..) => {
|
||||
self.tcx().sess.span_bug(expr.span, "non-desugared ExprWhileLet");
|
||||
}
|
||||
ast::ExprForLoop(..) => {
|
||||
self.tcx().sess.span_bug(expr.span, "non-desugared ExprForLoop");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -701,14 +701,6 @@ fn resolve_expr(visitor: &mut RegionResolutionVisitor, expr: &ast::Expr) {
|
|||
terminating(body.id);
|
||||
}
|
||||
|
||||
ast::ExprForLoop(ref _pat, ref _head, ref body, _) => {
|
||||
terminating(body.id);
|
||||
|
||||
// The variable parent of everything inside (most importantly, the
|
||||
// pattern) is the body.
|
||||
visitor.cx.var_parent = InnermostDeclaringBlock::Block(body.id);
|
||||
}
|
||||
|
||||
ast::ExprMatch(..) => {
|
||||
visitor.cx.var_parent = InnermostDeclaringBlock::Match(expr.id);
|
||||
}
|
||||
|
|
|
@ -4493,9 +4493,6 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
|
|||
// the index method invoked for `a[i]` always yields an `&T`
|
||||
ast::ExprIndex(..) => LvalueExpr,
|
||||
|
||||
// `for` loops are statements
|
||||
ast::ExprForLoop(..) => RvalueStmtExpr,
|
||||
|
||||
// in the general case, result could be any type, use DPS
|
||||
_ => RvalueDpsExpr
|
||||
};
|
||||
|
@ -4582,6 +4579,10 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
|
|||
tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet");
|
||||
}
|
||||
|
||||
ast::ExprForLoop(..) => {
|
||||
tcx.sess.span_bug(expr.span, "non-desugared ExprForLoop");
|
||||
}
|
||||
|
||||
ast::ExprLit(ref lit) if lit_is_str(&**lit) => {
|
||||
RvalueDpsExpr
|
||||
}
|
||||
|
@ -4619,8 +4620,7 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
|
|||
ast::ExprLoop(..) |
|
||||
ast::ExprAssign(..) |
|
||||
ast::ExprInlineAsm(..) |
|
||||
ast::ExprAssignOp(..) |
|
||||
ast::ExprForLoop(..) => {
|
||||
ast::ExprAssignOp(..) => {
|
||||
RvalueStmtExpr
|
||||
}
|
||||
|
||||
|
|
|
@ -96,7 +96,7 @@ fn visit_expr(&mut self, e: &ast::Expr) {
|
|||
match e.node {
|
||||
// Skip inner loops, since a break in the inner loop isn't a
|
||||
// break inside the outer loop
|
||||
ast::ExprLoop(..) | ast::ExprWhile(..) | ast::ExprForLoop(..) => {}
|
||||
ast::ExprLoop(..) | ast::ExprWhile(..) => {}
|
||||
_ => visit::walk_expr(self, e)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -100,6 +100,7 @@ pub fn explain_region_and_span(cx: &ctxt, region: ty::Region)
|
|||
ast::ExprMethodCall(..) => "method call",
|
||||
ast::ExprMatch(_, _, ast::MatchSource::IfLetDesugar { .. }) => "if let",
|
||||
ast::ExprMatch(_, _, ast::MatchSource::WhileLetDesugar) => "while let",
|
||||
ast::ExprMatch(_, _, ast::MatchSource::ForLoopDesugar) => "for",
|
||||
ast::ExprMatch(..) => "match",
|
||||
_ => "expression",
|
||||
},
|
||||
|
|
|
@ -252,7 +252,6 @@ pub enum SawExprComponent<'a> {
|
|||
SawExprStruct,
|
||||
SawExprRepeat,
|
||||
SawExprParen,
|
||||
SawExprForLoop,
|
||||
}
|
||||
|
||||
fn saw_expr<'a>(node: &'a Expr_) -> SawExprComponent<'a> {
|
||||
|
@ -288,9 +287,9 @@ fn saw_expr<'a>(node: &'a Expr_) -> SawExprComponent<'a> {
|
|||
ExprStruct(..) => SawExprStruct,
|
||||
ExprRepeat(..) => SawExprRepeat,
|
||||
ExprParen(..) => SawExprParen,
|
||||
ExprForLoop(..) => SawExprForLoop,
|
||||
|
||||
// just syntactic artifacts, expanded away by time of SVH.
|
||||
ExprForLoop(..) => unreachable!(),
|
||||
ExprIfLet(..) => unreachable!(),
|
||||
ExprWhileLet(..) => unreachable!(),
|
||||
ExprMac(..) => unreachable!(),
|
||||
|
|
|
@ -68,7 +68,7 @@
|
|||
|
||||
use syntax::ast::{Arm, BindByRef, BindByValue, BindingMode, Block, Crate, CrateNum};
|
||||
use syntax::ast::{DefId, Expr, ExprAgain, ExprBreak, ExprField};
|
||||
use syntax::ast::{ExprClosure, ExprForLoop, ExprLoop, ExprWhile, ExprMethodCall};
|
||||
use syntax::ast::{ExprClosure, ExprLoop, ExprWhile, ExprMethodCall};
|
||||
use syntax::ast::{ExprPath, ExprQPath, ExprStruct, FnDecl};
|
||||
use syntax::ast::{ForeignItemFn, ForeignItemStatic, Generics};
|
||||
use syntax::ast::{Ident, ImplItem, Item, ItemConst, ItemEnum, ItemExternCrate};
|
||||
|
@ -4562,39 +4562,6 @@ fn resolve_expr(&mut self, expr: &Expr) {
|
|||
})
|
||||
}
|
||||
|
||||
ExprForLoop(ref pattern, ref head, ref body, optional_label) => {
|
||||
self.resolve_expr(&**head);
|
||||
|
||||
self.value_ribs.push(Rib::new(NormalRibKind));
|
||||
|
||||
self.resolve_pattern(&**pattern,
|
||||
LocalIrrefutableMode,
|
||||
&mut HashMap::new());
|
||||
|
||||
match optional_label {
|
||||
None => {}
|
||||
Some(label) => {
|
||||
self.label_ribs
|
||||
.push(Rib::new(NormalRibKind));
|
||||
let def_like = DlDef(DefLabel(expr.id));
|
||||
|
||||
{
|
||||
let rib = self.label_ribs.last_mut().unwrap();
|
||||
let renamed = mtwt::resolve(label);
|
||||
rib.bindings.insert(renamed, def_like);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.resolve_block(&**body);
|
||||
|
||||
if optional_label.is_some() {
|
||||
drop(self.label_ribs.pop())
|
||||
}
|
||||
|
||||
self.value_ribs.pop();
|
||||
}
|
||||
|
||||
ExprBreak(Some(label)) | ExprAgain(Some(label)) => {
|
||||
let renamed = mtwt::resolve(label);
|
||||
match self.search_label(renamed) {
|
||||
|
|
|
@ -41,6 +41,8 @@
|
|||
#![feature(std_misc)]
|
||||
#![feature(unicode)]
|
||||
#![feature(hash)]
|
||||
// NOTE(stage0) remove cfg_attr after a snapshot
|
||||
#![cfg_attr(not(stage0), allow(unused_mut))]
|
||||
|
||||
extern crate arena;
|
||||
extern crate flate;
|
||||
|
|
|
@ -1537,31 +1537,6 @@ pub fn store_arg<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
|
|||
}
|
||||
}
|
||||
|
||||
/// Generates code for the pattern binding in a `for` loop like
|
||||
/// `for <pat> in <expr> { ... }`.
|
||||
pub fn store_for_loop_binding<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
pat: &ast::Pat,
|
||||
llvalue: ValueRef,
|
||||
body_scope: cleanup::ScopeId)
|
||||
-> Block<'blk, 'tcx> {
|
||||
let _icx = push_ctxt("match::store_for_loop_binding");
|
||||
|
||||
if simple_identifier(&*pat).is_some() &&
|
||||
bcx.sess().opts.debuginfo != FullDebugInfo {
|
||||
// Generate nicer LLVM for the common case of a `for` loop pattern
|
||||
// like `for x in blahblah { ... }`.
|
||||
let binding_type = node_id_type(bcx, pat.id);
|
||||
bcx.fcx.lllocals.borrow_mut().insert(pat.id,
|
||||
Datum::new(llvalue,
|
||||
binding_type,
|
||||
Lvalue));
|
||||
return bcx
|
||||
}
|
||||
|
||||
// General path. Copy out the values that are used in the pattern.
|
||||
bind_irrefutable_pat(bcx, pat, llvalue, body_scope)
|
||||
}
|
||||
|
||||
fn mk_binding_alloca<'blk, 'tcx, A, F>(bcx: Block<'blk, 'tcx>,
|
||||
p_id: ast::NodeId,
|
||||
ident: &ast::Ident,
|
||||
|
|
|
@ -11,8 +11,6 @@
|
|||
use llvm::ValueRef;
|
||||
use middle::def;
|
||||
use middle::lang_items::{PanicFnLangItem, PanicBoundsCheckFnLangItem};
|
||||
use trans::_match;
|
||||
use trans::adt;
|
||||
use trans::base::*;
|
||||
use trans::build::*;
|
||||
use trans::callee;
|
||||
|
@ -20,17 +18,12 @@
|
|||
use trans::cleanup;
|
||||
use trans::common::*;
|
||||
use trans::consts;
|
||||
use trans::datum;
|
||||
use trans::debuginfo;
|
||||
use trans::debuginfo::{DebugLoc, ToDebugLoc};
|
||||
use trans::expr;
|
||||
use trans::meth;
|
||||
use trans::type_::Type;
|
||||
use trans;
|
||||
use middle::ty;
|
||||
use middle::ty::MethodCall;
|
||||
use util::ppaux::Repr;
|
||||
use util::ppaux;
|
||||
|
||||
use syntax::ast;
|
||||
use syntax::ast::Ident;
|
||||
|
@ -259,135 +252,6 @@ pub fn trans_while<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
|||
return next_bcx_in;
|
||||
}
|
||||
|
||||
/// Translates a `for` loop.
|
||||
pub fn trans_for<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
|
||||
loop_info: NodeIdAndSpan,
|
||||
pat: &ast::Pat,
|
||||
head: &ast::Expr,
|
||||
body: &ast::Block)
|
||||
-> Block<'blk, 'tcx>
|
||||
{
|
||||
let _icx = push_ctxt("trans_for");
|
||||
|
||||
// bcx
|
||||
// |
|
||||
// loopback_bcx_in <-------+
|
||||
// | |
|
||||
// loopback_bcx_out |
|
||||
// | | |
|
||||
// | body_bcx_in |
|
||||
// cleanup_blk | |
|
||||
// | body_bcx_out --+
|
||||
// next_bcx_in
|
||||
|
||||
// Codegen the head to create the iterator value.
|
||||
let iterator_datum =
|
||||
unpack_datum!(bcx, expr::trans_to_lvalue(bcx, head, "for_head"));
|
||||
let iterator_type = node_id_type(bcx, head.id);
|
||||
debug!("iterator type is {}, datum type is {}",
|
||||
ppaux::ty_to_string(bcx.tcx(), iterator_type),
|
||||
ppaux::ty_to_string(bcx.tcx(), iterator_datum.ty));
|
||||
|
||||
let lliterator = load_ty(bcx, iterator_datum.val, iterator_datum.ty);
|
||||
|
||||
// Create our basic blocks and set up our loop cleanups.
|
||||
let next_bcx_in = bcx.fcx.new_id_block("for_exit", loop_info.id);
|
||||
let loopback_bcx_in = bcx.fcx.new_id_block("for_loopback", head.id);
|
||||
let body_bcx_in = bcx.fcx.new_id_block("for_body", body.id);
|
||||
bcx.fcx.push_loop_cleanup_scope(loop_info.id,
|
||||
[next_bcx_in, loopback_bcx_in]);
|
||||
Br(bcx, loopback_bcx_in.llbb, DebugLoc::None);
|
||||
let cleanup_llbb = bcx.fcx.normal_exit_block(loop_info.id,
|
||||
cleanup::EXIT_BREAK);
|
||||
|
||||
// Set up the method call (to `.next()`).
|
||||
let method_call = MethodCall::expr(loop_info.id);
|
||||
let method_type = (*loopback_bcx_in.tcx()
|
||||
.method_map
|
||||
.borrow())[method_call]
|
||||
.ty;
|
||||
let method_type = monomorphize_type(loopback_bcx_in, method_type);
|
||||
let method_result_type =
|
||||
ty::assert_no_late_bound_regions( // LB regions are instantiated in invoked methods
|
||||
loopback_bcx_in.tcx(), &ty::ty_fn_ret(method_type)).unwrap();
|
||||
let option_cleanup_scope = body_bcx_in.fcx.push_custom_cleanup_scope();
|
||||
let option_cleanup_scope_id = cleanup::CustomScope(option_cleanup_scope);
|
||||
|
||||
// Compile the method call (to `.next()`).
|
||||
let mut loopback_bcx_out = loopback_bcx_in;
|
||||
let option_datum =
|
||||
unpack_datum!(loopback_bcx_out,
|
||||
datum::lvalue_scratch_datum(loopback_bcx_out,
|
||||
method_result_type,
|
||||
"loop_option",
|
||||
false,
|
||||
option_cleanup_scope_id,
|
||||
(),
|
||||
|(), bcx, lloption| {
|
||||
let Result {
|
||||
bcx,
|
||||
val: _
|
||||
} = callee::trans_call_inner(bcx,
|
||||
Some(loop_info),
|
||||
method_type,
|
||||
|bcx, arg_cleanup_scope| {
|
||||
meth::trans_method_callee(
|
||||
bcx,
|
||||
method_call,
|
||||
None,
|
||||
arg_cleanup_scope)
|
||||
},
|
||||
callee::ArgVals(&[lliterator]),
|
||||
Some(expr::SaveIn(lloption)));
|
||||
bcx
|
||||
}));
|
||||
|
||||
// Check the discriminant; if the `None` case, exit the loop.
|
||||
let option_representation = adt::represent_type(loopback_bcx_out.ccx(),
|
||||
method_result_type);
|
||||
let lldiscriminant = adt::trans_get_discr(loopback_bcx_out,
|
||||
&*option_representation,
|
||||
option_datum.val,
|
||||
None);
|
||||
let i1_type = Type::i1(loopback_bcx_out.ccx());
|
||||
let llcondition = Trunc(loopback_bcx_out, lldiscriminant, i1_type);
|
||||
CondBr(loopback_bcx_out, llcondition, body_bcx_in.llbb, cleanup_llbb, DebugLoc::None);
|
||||
|
||||
// Now we're in the body. Unpack the `Option` value into the programmer-
|
||||
// supplied pattern.
|
||||
let llpayload = adt::trans_field_ptr(body_bcx_in,
|
||||
&*option_representation,
|
||||
option_datum.val,
|
||||
1,
|
||||
0);
|
||||
let binding_cleanup_scope = body_bcx_in.fcx.push_custom_cleanup_scope();
|
||||
let binding_cleanup_scope_id =
|
||||
cleanup::CustomScope(binding_cleanup_scope);
|
||||
let mut body_bcx_out =
|
||||
_match::store_for_loop_binding(body_bcx_in,
|
||||
pat,
|
||||
llpayload,
|
||||
binding_cleanup_scope_id);
|
||||
|
||||
debuginfo::create_for_loop_var_metadata(body_bcx_in, pat);
|
||||
|
||||
// Codegen the body.
|
||||
body_bcx_out = trans_block(body_bcx_out, body, expr::Ignore);
|
||||
body_bcx_out =
|
||||
body_bcx_out.fcx
|
||||
.pop_and_trans_custom_cleanup_scope(body_bcx_out,
|
||||
binding_cleanup_scope);
|
||||
body_bcx_out =
|
||||
body_bcx_out.fcx
|
||||
.pop_and_trans_custom_cleanup_scope(body_bcx_out,
|
||||
option_cleanup_scope);
|
||||
Br(body_bcx_out, loopback_bcx_in.llbb, DebugLoc::None);
|
||||
|
||||
// Codegen cleanups and leave.
|
||||
next_bcx_in.fcx.pop_loop_cleanup_scope(loop_info.id);
|
||||
next_bcx_in
|
||||
}
|
||||
|
||||
pub fn trans_loop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
loop_expr: &ast::Expr,
|
||||
body: &ast::Block)
|
||||
|
|
|
@ -1053,48 +1053,6 @@ pub fn create_argument_metadata(bcx: Block, arg: &ast::Arg) {
|
|||
})
|
||||
}
|
||||
|
||||
/// Creates debug information for the given for-loop variable.
|
||||
///
|
||||
/// This function assumes that there's a datum for each pattern component of the
|
||||
/// loop variable in `bcx.fcx.lllocals`.
|
||||
/// Adds the created metadata nodes directly to the crate's IR.
|
||||
pub fn create_for_loop_var_metadata(bcx: Block, pat: &ast::Pat) {
|
||||
if bcx.unreachable.get() ||
|
||||
fn_should_be_ignored(bcx.fcx) ||
|
||||
bcx.sess().opts.debuginfo != FullDebugInfo {
|
||||
return;
|
||||
}
|
||||
|
||||
let def_map = &bcx.tcx().def_map;
|
||||
let locals = bcx.fcx.lllocals.borrow();
|
||||
|
||||
pat_util::pat_bindings(def_map, pat, |_, node_id, span, var_ident| {
|
||||
let datum = match locals.get(&node_id) {
|
||||
Some(datum) => datum,
|
||||
None => {
|
||||
bcx.sess().span_bug(span,
|
||||
format!("no entry in lllocals table for {}",
|
||||
node_id).as_slice());
|
||||
}
|
||||
};
|
||||
|
||||
if unsafe { llvm::LLVMIsAAllocaInst(datum.val) } == ptr::null_mut() {
|
||||
bcx.sess().span_bug(span, "debuginfo::create_for_loop_var_metadata() - \
|
||||
Referenced variable location is not an alloca!");
|
||||
}
|
||||
|
||||
let scope_metadata = scope_metadata(bcx.fcx, node_id, span);
|
||||
|
||||
declare_local(bcx,
|
||||
var_ident.node,
|
||||
datum.ty,
|
||||
scope_metadata,
|
||||
DirectVariable { alloca: datum.val },
|
||||
LocalVariable,
|
||||
span);
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_cleanup_debug_loc_for_ast_node<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||
node_id: ast::NodeId,
|
||||
node_span: Span,
|
||||
|
@ -3627,24 +3585,9 @@ fn walk_expr(cx: &CrateContext,
|
|||
Found unexpanded while-let.");
|
||||
}
|
||||
|
||||
ast::ExprForLoop(ref pattern, ref head, ref body, _) => {
|
||||
walk_expr(cx, &**head, scope_stack, scope_map);
|
||||
|
||||
with_new_scope(cx,
|
||||
exp.span,
|
||||
scope_stack,
|
||||
scope_map,
|
||||
|cx, scope_stack, scope_map| {
|
||||
scope_map.insert(exp.id,
|
||||
scope_stack.last()
|
||||
.unwrap()
|
||||
.scope_metadata);
|
||||
walk_pattern(cx,
|
||||
&**pattern,
|
||||
scope_stack,
|
||||
scope_map);
|
||||
walk_block(cx, &**body, scope_stack, scope_map);
|
||||
})
|
||||
ast::ExprForLoop(..) => {
|
||||
cx.sess().span_bug(exp.span, "debuginfo::create_scope_map() - \
|
||||
Found unexpanded for loop.");
|
||||
}
|
||||
|
||||
ast::ExprMac(_) => {
|
||||
|
|
|
@ -927,13 +927,6 @@ fn trans_rvalue_stmt_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
|||
ast::ExprWhile(ref cond, ref body, _) => {
|
||||
controlflow::trans_while(bcx, expr, &**cond, &**body)
|
||||
}
|
||||
ast::ExprForLoop(ref pat, ref head, ref body, _) => {
|
||||
controlflow::trans_for(bcx,
|
||||
expr_info(expr),
|
||||
&**pat,
|
||||
&**head,
|
||||
&**body)
|
||||
}
|
||||
ast::ExprLoop(ref body, _) => {
|
||||
controlflow::trans_loop(bcx, expr, &**body)
|
||||
}
|
||||
|
|
|
@ -87,7 +87,6 @@
|
|||
use fmt_macros::{Parser, Piece, Position};
|
||||
use middle::{const_eval, def};
|
||||
use middle::infer;
|
||||
use middle::lang_items::IteratorItem;
|
||||
use middle::mem_categorization as mc;
|
||||
use middle::mem_categorization::McResult;
|
||||
use middle::pat_util::{self, pat_id_map};
|
||||
|
@ -2140,92 +2139,6 @@ fn try_index_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
|||
})
|
||||
}
|
||||
|
||||
/// Given the head of a `for` expression, looks up the `next` method in the
|
||||
/// `Iterator` trait. Panics if the expression does not implement `next`.
|
||||
///
|
||||
/// The return type of this function represents the concrete element type
|
||||
/// `A` in the type `Iterator<A>` that the method returns.
|
||||
fn lookup_method_for_for_loop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
iterator_expr: &ast::Expr,
|
||||
loop_id: ast::NodeId)
|
||||
-> Ty<'tcx> {
|
||||
let trait_did = match fcx.tcx().lang_items.require(IteratorItem) {
|
||||
Ok(trait_did) => trait_did,
|
||||
Err(ref err_string) => {
|
||||
span_err!(fcx.tcx().sess, iterator_expr.span, E0233,
|
||||
"{}", &err_string[]);
|
||||
return fcx.tcx().types.err
|
||||
}
|
||||
};
|
||||
|
||||
let expr_type = fcx.expr_ty(&*iterator_expr);
|
||||
let method = method::lookup_in_trait(fcx,
|
||||
iterator_expr.span,
|
||||
Some(&*iterator_expr),
|
||||
token::intern("next"),
|
||||
trait_did,
|
||||
expr_type,
|
||||
None);
|
||||
|
||||
// Regardless of whether the lookup succeeds, check the method arguments
|
||||
// so that we have *some* type for each argument.
|
||||
let method_type = match method {
|
||||
Some(ref method) => method.ty,
|
||||
None => {
|
||||
let true_expr_type = fcx.infcx().resolve_type_vars_if_possible(&expr_type);
|
||||
|
||||
if !ty::type_is_error(true_expr_type) {
|
||||
let ty_string = fcx.infcx().ty_to_string(true_expr_type);
|
||||
span_err!(fcx.tcx().sess, iterator_expr.span, E0234,
|
||||
"`for` loop expression has type `{}` which does \
|
||||
not implement the `Iterator` trait; \
|
||||
maybe try .iter()", ty_string);
|
||||
}
|
||||
fcx.tcx().types.err
|
||||
}
|
||||
};
|
||||
let return_type = check_method_argument_types(fcx,
|
||||
iterator_expr.span,
|
||||
method_type,
|
||||
iterator_expr,
|
||||
&[],
|
||||
AutorefArgs::No,
|
||||
DontTupleArguments,
|
||||
NoExpectation);
|
||||
|
||||
match method {
|
||||
Some(method) => {
|
||||
fcx.inh.method_map.borrow_mut().insert(MethodCall::expr(loop_id),
|
||||
method);
|
||||
|
||||
// We expect the return type to be `Option` or something like it.
|
||||
// Grab the first parameter of its type substitution.
|
||||
let return_type = match return_type {
|
||||
ty::FnConverging(return_type) =>
|
||||
structurally_resolved_type(fcx, iterator_expr.span, return_type),
|
||||
ty::FnDiverging => fcx.tcx().types.err
|
||||
};
|
||||
match return_type.sty {
|
||||
ty::ty_enum(_, ref substs)
|
||||
if !substs.types.is_empty_in(subst::TypeSpace) => {
|
||||
*substs.types.get(subst::TypeSpace, 0)
|
||||
}
|
||||
ty::ty_err => {
|
||||
fcx.tcx().types.err
|
||||
}
|
||||
_ => {
|
||||
span_err!(fcx.tcx().sess, iterator_expr.span, E0239,
|
||||
"`next` method of the `Iterator` \
|
||||
trait has an unexpected type `{}`",
|
||||
fcx.infcx().ty_to_string(return_type));
|
||||
fcx.tcx().types.err
|
||||
}
|
||||
}
|
||||
}
|
||||
None => fcx.tcx().types.err
|
||||
}
|
||||
}
|
||||
|
||||
fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
sp: Span,
|
||||
method_fn_ty: Ty<'tcx>,
|
||||
|
@ -3762,22 +3675,8 @@ fn check_struct_fields_on_error(fcx: &FnCtxt,
|
|||
ast::ExprWhileLet(..) => {
|
||||
tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet");
|
||||
}
|
||||
ast::ExprForLoop(ref pat, ref head, ref block, _) => {
|
||||
check_expr(fcx, &**head);
|
||||
let typ = lookup_method_for_for_loop(fcx, &**head, expr.id);
|
||||
vtable::select_new_fcx_obligations(fcx);
|
||||
|
||||
debug!("ExprForLoop each item has type {}",
|
||||
fcx.infcx().resolve_type_vars_if_possible(&typ).repr(fcx.tcx()));
|
||||
|
||||
let pcx = pat_ctxt {
|
||||
fcx: fcx,
|
||||
map: pat_id_map(&tcx.def_map, &**pat),
|
||||
};
|
||||
_match::check_pat(&pcx, &**pat, typ);
|
||||
|
||||
check_block_no_value(fcx, &**block);
|
||||
fcx.write_nil(id);
|
||||
ast::ExprForLoop(..) => {
|
||||
tcx.sess.span_bug(expr.span, "non-desugared ExprForLoop");
|
||||
}
|
||||
ast::ExprLoop(ref body, _) => {
|
||||
check_block_no_value(fcx, &**body);
|
||||
|
|
|
@ -658,30 +658,6 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
|
|||
rcx.set_repeating_scope(repeating_scope);
|
||||
}
|
||||
|
||||
ast::ExprForLoop(ref pat, ref head, ref body, _) => {
|
||||
constrain_bindings_in_pat(&**pat, rcx);
|
||||
|
||||
{
|
||||
let mc = mc::MemCategorizationContext::new(rcx.fcx);
|
||||
let pat_ty = rcx.resolve_node_type(pat.id);
|
||||
let pat_cmt = mc.cat_rvalue(pat.id,
|
||||
pat.span,
|
||||
ty::ReScope(CodeExtent::from_node_id(body.id)),
|
||||
pat_ty);
|
||||
link_pattern(rcx, mc, pat_cmt, &**pat);
|
||||
}
|
||||
|
||||
rcx.visit_expr(&**head);
|
||||
type_of_node_must_outlive(rcx,
|
||||
infer::AddrOf(expr.span),
|
||||
head.id,
|
||||
ty::ReScope(CodeExtent::from_node_id(expr.id)));
|
||||
|
||||
let repeating_scope = rcx.set_repeating_scope(body.id);
|
||||
rcx.visit_block(&**body);
|
||||
rcx.set_repeating_scope(repeating_scope);
|
||||
}
|
||||
|
||||
_ => {
|
||||
visit::walk_expr(rcx, expr);
|
||||
}
|
||||
|
|
|
@ -84,6 +84,8 @@
|
|||
#![feature(core)]
|
||||
#![feature(rustc_private)]
|
||||
#![feature(std_misc)]
|
||||
// NOTE(stage0) remove cfg_attr after a snapshot
|
||||
#![cfg_attr(not(stage0), allow(unused_mut))]
|
||||
|
||||
#[macro_use] extern crate log;
|
||||
#[macro_use] extern crate syntax;
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
#![feature(test)]
|
||||
#![feature(unicode)]
|
||||
#![feature(hash)]
|
||||
// NOTE(stage0) remove cfg_attr after a snapshot
|
||||
#![cfg_attr(not(stage0), allow(unused_mut))]
|
||||
|
||||
extern crate arena;
|
||||
extern crate getopts;
|
||||
|
|
|
@ -1772,7 +1772,7 @@ fn test_move_iter_drops() {
|
|||
}
|
||||
});
|
||||
|
||||
for _ in half {}
|
||||
for _ in half.by_ref() {}
|
||||
|
||||
DROP_VECTOR.with(|v| {
|
||||
let nk = (0u..100).filter(|&i| {
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
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 @@ fn len(&self) -> usize { self.table.size() }
|
|||
#[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() {}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -557,7 +557,7 @@ fn comp_requires_verbatim(s: &str) -> bool {
|
|||
}
|
||||
(Some(a), Some(_)) => {
|
||||
comps.push("..");
|
||||
for _ in itb {
|
||||
for _ in itb.by_ref() {
|
||||
comps.push("..");
|
||||
}
|
||||
comps.push(a);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -788,6 +788,7 @@ pub enum MatchSource {
|
|||
Normal,
|
||||
IfLetDesugar { contains_else_clause: bool },
|
||||
WhileLetDesugar,
|
||||
ForLoopDesugar,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
|
||||
|
|
|
@ -225,11 +225,101 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
|
|||
fld.cx.expr(span, ast::ExprLoop(loop_block, opt_ident))
|
||||
}
|
||||
|
||||
// Desugar ExprForLoop
|
||||
// From: `[opt_ident]: for <pat> in <head> <body>`
|
||||
ast::ExprForLoop(pat, head, body, opt_ident) => {
|
||||
let pat = fld.fold_pat(pat);
|
||||
// to:
|
||||
//
|
||||
// match ::std::iter::IntoIterator::into_iter(<head>) {
|
||||
// mut iter => {
|
||||
// [opt_ident]: loop {
|
||||
// match ::std::iter::Iterator::next(&mut iter) {
|
||||
// ::std::option::Option::Some(<pat>) => <body>,
|
||||
// ::std::option::Option::None => break
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// expand <head>
|
||||
let head = fld.fold_expr(head);
|
||||
let (body, opt_ident) = expand_loop_block(body, opt_ident, fld);
|
||||
fld.cx.expr(span, ast::ExprForLoop(pat, head, body, opt_ident))
|
||||
|
||||
// create an hygienic ident
|
||||
let iter = {
|
||||
let ident = fld.cx.ident_of("iter");
|
||||
let new_ident = fresh_name(&ident);
|
||||
let rename = (ident, new_ident);
|
||||
let mut rename_list = vec![rename];
|
||||
let mut rename_fld = IdentRenamer{ renames: &mut rename_list };
|
||||
|
||||
rename_fld.fold_ident(ident)
|
||||
};
|
||||
|
||||
let pat_span = pat.span;
|
||||
// `:;std::option::Option::Some(<pat>) => <body>`
|
||||
let pat_arm = {
|
||||
let body_expr = fld.cx.expr_block(body);
|
||||
let some_pat = fld.cx.pat_some(pat_span, pat);
|
||||
|
||||
fld.cx.arm(pat_span, vec![some_pat], body_expr)
|
||||
};
|
||||
|
||||
// `::std::option::Option::None => break`
|
||||
let break_arm = {
|
||||
let break_expr = fld.cx.expr_break(span);
|
||||
|
||||
fld.cx.arm(span, vec![fld.cx.pat_none(span)], break_expr)
|
||||
};
|
||||
|
||||
// `match ::std::iter::Iterator::next(&mut iter) { ... }`
|
||||
let match_expr = {
|
||||
let next_path = {
|
||||
let strs = vec![
|
||||
fld.cx.ident_of("std"),
|
||||
fld.cx.ident_of("iter"),
|
||||
fld.cx.ident_of("Iterator"),
|
||||
fld.cx.ident_of("next"),
|
||||
];
|
||||
|
||||
fld.cx.path_global(span, strs)
|
||||
};
|
||||
let ref_mut_iter = fld.cx.expr_mut_addr_of(span, fld.cx.expr_ident(span, iter));
|
||||
let next_expr =
|
||||
fld.cx.expr_call(span, fld.cx.expr_path(next_path), vec![ref_mut_iter]);
|
||||
let arms = vec![pat_arm, break_arm];
|
||||
|
||||
fld.cx.expr(pat_span,
|
||||
ast::ExprMatch(next_expr, arms, ast::MatchSource::ForLoopDesugar))
|
||||
};
|
||||
|
||||
// `[opt_ident]: loop { ... }`
|
||||
let loop_block = fld.cx.block_expr(match_expr);
|
||||
let (loop_block, opt_ident) = expand_loop_block(loop_block, opt_ident, fld);
|
||||
let loop_expr = fld.cx.expr(span, ast::ExprLoop(loop_block, opt_ident));
|
||||
|
||||
// `mut iter => { ... }`
|
||||
let iter_arm = {
|
||||
let iter_pat =
|
||||
fld.cx.pat_ident_binding_mode(span, iter, ast::BindByValue(ast::MutMutable));
|
||||
fld.cx.arm(span, vec![iter_pat], loop_expr)
|
||||
};
|
||||
|
||||
// `match ::std::iter::IntoIterator::into_iter(<head>) { ... }`
|
||||
let into_iter_expr = {
|
||||
let into_iter_path = {
|
||||
let strs = vec![
|
||||
fld.cx.ident_of("std"),
|
||||
fld.cx.ident_of("iter"),
|
||||
fld.cx.ident_of("IntoIterator"),
|
||||
fld.cx.ident_of("into_iter"),
|
||||
];
|
||||
|
||||
fld.cx.path_global(span, strs)
|
||||
};
|
||||
|
||||
fld.cx.expr_call(span, fld.cx.expr_path(into_iter_path), vec![head])
|
||||
};
|
||||
fld.cx.expr_match(span, into_iter_expr, vec![iter_arm])
|
||||
}
|
||||
|
||||
ast::ExprClosure(capture_clause, opt_kind, fn_decl, block) => {
|
||||
|
|
|
@ -39,6 +39,8 @@
|
|||
#![feature(rustc_private)]
|
||||
#![feature(std_misc)]
|
||||
#![feature(unicode)]
|
||||
// NOTE(stage0) remove cfg_attr after a snapshot
|
||||
#![cfg_attr(not(stage0), allow(unused_mut))]
|
||||
|
||||
extern crate arena;
|
||||
extern crate fmt_macros;
|
||||
|
|
|
@ -44,6 +44,8 @@
|
|||
#![feature(rustc_private)]
|
||||
#![feature(std_misc)]
|
||||
#![feature(hash)]
|
||||
// NOTE(stage0): remove cfg_attr after a snapshot
|
||||
#![cfg_attr(not(stage0), allow(unused_mut))]
|
||||
|
||||
extern crate getopts;
|
||||
extern crate serialize;
|
||||
|
|
|
@ -84,4 +84,7 @@ mod std {
|
|||
pub use core::cmp;
|
||||
pub use core::fmt;
|
||||
pub use core::marker;
|
||||
// for-loops
|
||||
pub use core::iter;
|
||||
pub use core::option;
|
||||
}
|
||||
|
|
|
@ -447,7 +447,7 @@ fn next(&mut self) -> Option<Utf16Item> {
|
|||
Some(Utf16Item::LoneSurrogate(u))
|
||||
} else {
|
||||
// preserve state for rewinding.
|
||||
let old = self.iter;
|
||||
let old = self.iter.clone();
|
||||
|
||||
let u2 = match self.iter.next() {
|
||||
Some(u2) => *u2,
|
||||
|
@ -457,7 +457,7 @@ fn next(&mut self) -> Option<Utf16Item> {
|
|||
if u2 < 0xDC00 || u2 > 0xDFFF {
|
||||
// not a trailing surrogate so we're not a valid
|
||||
// surrogate pair, so rewind to redecode u2 next time.
|
||||
self.iter = old;
|
||||
self.iter = old.clone();
|
||||
return Some(Utf16Item::LoneSurrogate(u))
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
impl<H> TreeBuilder<H> {
|
||||
pub fn process_token(&mut self) {
|
||||
match self {
|
||||
_ => for _y in *self {}
|
||||
_ => for _y in self.by_ref() {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,10 @@ pub fn main() {
|
|||
x: 1,
|
||||
y: 2,
|
||||
};
|
||||
for x in bogus { //~ ERROR has type `MyStruct` which does not implement the `Iterator` trait
|
||||
for x in bogus { //~ ERROR `core::iter::Iterator` is not implemented for the type `MyStruct`
|
||||
//~^ ERROR
|
||||
//~^^ ERROR
|
||||
// FIXME(#21528) not fulfilled obligation error should be reported once, not thrice
|
||||
drop(x);
|
||||
}
|
||||
}
|
||||
|
|
20
src/test/compile-fail/for-loop-hygiene.rs
Normal file
20
src/test/compile-fail/for-loop-hygiene.rs
Normal file
|
@ -0,0 +1,20 @@
|
|||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// for-loops are expanded in the front end, and use an `iter` ident in their expansion. Check that
|
||||
// `iter` is not accessible inside the for loop.
|
||||
|
||||
#![allow(unstable)]
|
||||
|
||||
fn main() {
|
||||
for _ in 0..10 {
|
||||
iter.next(); //~ error: unresolved name `iter`
|
||||
}
|
||||
}
|
|
@ -8,7 +8,6 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
|
||||
fn main() {
|
||||
for
|
||||
&1is //~ ERROR refutable pattern in `for` loop binding
|
||||
|
|
|
@ -32,7 +32,7 @@ fn zomg() {
|
|||
|
||||
fn iterate<N: Node, G: Graph<N>>(graph: &G) {
|
||||
for node in graph.iter() { //~ ERROR does not implement any method in scope named
|
||||
node.zomg();
|
||||
node.zomg(); //~ error: the type of this value must be known in this context
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
// except according to those terms.
|
||||
|
||||
#![deny(unused_variables)]
|
||||
#![feature(core)]
|
||||
|
||||
fn main() {
|
||||
for _ in 1is..101 {
|
||||
|
|
19
src/test/compile-fail/issue-20605.rs
Normal file
19
src/test/compile-fail/issue-20605.rs
Normal file
|
@ -0,0 +1,19 @@
|
|||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
fn changer<'a>(mut things: Box<Iterator<Item=&'a mut u8>>) {
|
||||
for item in *things { *item = 0 }
|
||||
//~^ ERROR the trait `core::marker::Sized` is not implemented for the type `core::iter::Iterator
|
||||
//~^^ ERROR
|
||||
//~^^^ ERROR
|
||||
// FIXME(#21528) error should be reported once, not thrice
|
||||
}
|
||||
|
||||
fn main() {}
|
|
@ -11,6 +11,7 @@
|
|||
#![deny(unreachable_code)]
|
||||
#![allow(unused_variables)]
|
||||
#![allow(dead_code)]
|
||||
#![feature(core)]
|
||||
|
||||
fn fail_len(v: Vec<isize> ) -> usize {
|
||||
let mut i = 3;
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#![deny(unused_variables)]
|
||||
#![deny(unused_assignments)]
|
||||
#![allow(dead_code, non_camel_case_types)]
|
||||
#![feature(core)]
|
||||
#![feature(os)]
|
||||
|
||||
fn f1(x: isize) {
|
||||
|
|
|
@ -17,7 +17,10 @@ pub fn main() {
|
|||
|
||||
// Float => does not implement iterator.
|
||||
for i in 0f32..42f32 {}
|
||||
//~^ ERROR `for` loop expression has type `core::ops::Range<f32>` which does not implement
|
||||
//~^ ERROR `core::iter::Iterator` is not implemented for the type `core::ops::Range<f32>`
|
||||
//~^^ ERROR
|
||||
//~^^^ ERROR
|
||||
// FIXME(#21528) not fulfilled obligation error should be reported once, not thrice
|
||||
|
||||
// Unsized type.
|
||||
let arr: &[_] = &[1us, 2, 3];
|
||||
|
|
27
src/test/run-pass/for-loop-into-iterator.rs
Normal file
27
src/test/run-pass/for-loop-into-iterator.rs
Normal file
|
@ -0,0 +1,27 @@
|
|||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Test that for loops can do what RFC #235 claims
|
||||
|
||||
fn main() {
|
||||
let mut v = vec![1];
|
||||
|
||||
for x in &v {
|
||||
assert_eq!(x, &1);
|
||||
}
|
||||
|
||||
for x in &mut v {
|
||||
assert_eq!(x, &mut 1);
|
||||
}
|
||||
|
||||
for x in v {
|
||||
assert_eq!(x, 1);
|
||||
}
|
||||
}
|
|
@ -27,7 +27,7 @@ pub fn main() {
|
|||
|
||||
let mut i = h.iter();
|
||||
|
||||
for (&k,&v) in i {
|
||||
for (&k,&v) in i.by_ref() {
|
||||
x += k;
|
||||
y += v;
|
||||
break;
|
||||
|
|
20
src/test/run-pass/issue-21655.rs
Normal file
20
src/test/run-pass/issue-21655.rs
Normal file
|
@ -0,0 +1,20 @@
|
|||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
fn test(it: &mut Iterator<Item=i32>) {
|
||||
for x in it {
|
||||
assert_eq!(x, 1)
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let v = vec![1];
|
||||
test(&mut v.into_iter())
|
||||
}
|
Loading…
Reference in a new issue