Skip to content

Commit 27d18fb

Browse files
committed
core: add #[must_use] attributes to iterator adaptor structs.
It can be a little unintuitive that something like `v.iter().map(|x| println!("{}", x));` does nothing: the majority of the iterator adaptors are lazy and do not execute anything until something calls `next`, e.g. a `for` loop, `collect`, `fold`, etc. The majority of such errors can be seen by someone writing something like the above, i.e. just calling an iterator adaptor and doing nothing with it (and doing this is certainly useless), so we can co-opt the `must_use` lint, using the message functionality to give a hint to the reason why. Fixes #14666.
1 parent b9e35a1 commit 27d18fb

File tree

1 file changed

+18
-1
lines changed

1 file changed

+18
-1
lines changed

src/libcore/iter.rs

+18-1
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,7 @@ impl<A, B, T: ExactSize<A>, U: ExactSize<B>> ExactSize<(A, B)> for Zip<T, U> {}
750750

751751
/// An double-ended iterator with the direction inverted
752752
#[deriving(Clone)]
753+
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
753754
pub struct Rev<T> {
754755
iter: T
755756
}
@@ -778,6 +779,7 @@ impl<A, T: DoubleEndedIterator<A> + RandomAccessIterator<A>> RandomAccessIterato
778779
}
779780

780781
/// A mutable reference to an iterator
782+
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
781783
pub struct ByRef<'a, T> {
782784
iter: &'a mut T
783785
}
@@ -1038,6 +1040,7 @@ impl<A, T: Clone + Iterator<A>> CloneableIterator for T {
10381040

10391041
/// An iterator that repeats endlessly
10401042
#[deriving(Clone)]
1043+
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
10411044
pub struct Cycle<T> {
10421045
orig: T,
10431046
iter: T,
@@ -1089,6 +1092,7 @@ impl<A, T: Clone + RandomAccessIterator<A>> RandomAccessIterator<A> for Cycle<T>
10891092

10901093
/// An iterator which strings two iterators together
10911094
#[deriving(Clone)]
1095+
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
10921096
pub struct Chain<T, U> {
10931097
a: T,
10941098
b: U,
@@ -1158,6 +1162,7 @@ for Chain<T, U> {
11581162

11591163
/// An iterator which iterates two other iterators simultaneously
11601164
#[deriving(Clone)]
1165+
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
11611166
pub struct Zip<T, U> {
11621167
a: T,
11631168
b: U
@@ -1236,6 +1241,7 @@ RandomAccessIterator<(A, B)> for Zip<T, U> {
12361241
}
12371242

12381243
/// An iterator which maps the values of `iter` with `f`
1244+
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
12391245
pub struct Map<'a, A, B, T> {
12401246
iter: T,
12411247
f: |A|: 'a -> B
@@ -1286,6 +1292,7 @@ impl<'a, A, B, T: RandomAccessIterator<A>> RandomAccessIterator<B> for Map<'a, A
12861292
}
12871293

12881294
/// An iterator which filters the elements of `iter` with `predicate`
1295+
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
12891296
pub struct Filter<'a, A, T> {
12901297
iter: T,
12911298
predicate: |&A|: 'a -> bool
@@ -1330,6 +1337,7 @@ impl<'a, A, T: DoubleEndedIterator<A>> DoubleEndedIterator<A> for Filter<'a, A,
13301337
}
13311338

13321339
/// An iterator which uses `f` to both filter and map elements from `iter`
1340+
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
13331341
pub struct FilterMap<'a, A, B, T> {
13341342
iter: T,
13351343
f: |A|: 'a -> Option<B>
@@ -1374,6 +1382,7 @@ for FilterMap<'a, A, B, T> {
13741382

13751383
/// An iterator which yields the current count and the element during iteration
13761384
#[deriving(Clone)]
1385+
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
13771386
pub struct Enumerate<T> {
13781387
iter: T,
13791388
count: uint
@@ -1428,6 +1437,7 @@ impl<A, T: RandomAccessIterator<A>> RandomAccessIterator<(uint, A)> for Enumerat
14281437
}
14291438

14301439
/// An iterator with a `peek()` that returns an optional reference to the next element.
1440+
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
14311441
pub struct Peekable<A, T> {
14321442
iter: T,
14331443
peeked: Option<A>,
@@ -1478,6 +1488,7 @@ impl<'a, A, T: Iterator<A>> Peekable<A, T> {
14781488
}
14791489

14801490
/// An iterator which rejects elements while `predicate` is true
1491+
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
14811492
pub struct SkipWhile<'a, A, T> {
14821493
iter: T,
14831494
flag: bool,
@@ -1516,6 +1527,7 @@ impl<'a, A, T: Iterator<A>> Iterator<A> for SkipWhile<'a, A, T> {
15161527
}
15171528

15181529
/// An iterator which only accepts elements while `predicate` is true
1530+
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
15191531
pub struct TakeWhile<'a, A, T> {
15201532
iter: T,
15211533
flag: bool,
@@ -1551,6 +1563,7 @@ impl<'a, A, T: Iterator<A>> Iterator<A> for TakeWhile<'a, A, T> {
15511563

15521564
/// An iterator which skips over `n` elements of `iter`.
15531565
#[deriving(Clone)]
1566+
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
15541567
pub struct Skip<T> {
15551568
iter: T,
15561569
n: uint
@@ -1615,6 +1628,7 @@ impl<A, T: RandomAccessIterator<A>> RandomAccessIterator<A> for Skip<T> {
16151628

16161629
/// An iterator which only iterates over the first `n` iterations of `iter`.
16171630
#[deriving(Clone)]
1631+
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
16181632
pub struct Take<T> {
16191633
iter: T,
16201634
n: uint
@@ -1664,6 +1678,7 @@ impl<A, T: RandomAccessIterator<A>> RandomAccessIterator<A> for Take<T> {
16641678

16651679

16661680
/// An iterator to maintain state while iterating another iterator
1681+
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
16671682
pub struct Scan<'a, A, B, T, St> {
16681683
iter: T,
16691684
f: |&mut St, A|: 'a -> Option<B>,
@@ -1688,6 +1703,7 @@ impl<'a, A, B, T: Iterator<A>, St> Iterator<B> for Scan<'a, A, B, T, St> {
16881703
/// An iterator that maps each element to an iterator,
16891704
/// and yields the elements of the produced iterators
16901705
///
1706+
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
16911707
pub struct FlatMap<'a, A, T, U> {
16921708
iter: T,
16931709
f: |A|: 'a -> U,
@@ -1747,6 +1763,7 @@ impl<'a,
17471763
/// An iterator that yields `None` forever after the underlying iterator
17481764
/// yields `None` once.
17491765
#[deriving(Clone)]
1766+
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
17501767
pub struct Fuse<T> {
17511768
iter: T,
17521769
done: bool
@@ -1819,6 +1836,7 @@ impl<T> Fuse<T> {
18191836

18201837
/// An iterator that calls a function with a reference to each
18211838
/// element before yielding it.
1839+
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
18221840
pub struct Inspect<'a, A, T> {
18231841
iter: T,
18241842
f: |&A|: 'a
@@ -2298,4 +2316,3 @@ pub mod order {
22982316
}
22992317
}
23002318
}
2301-

0 commit comments

Comments
 (0)