summaryrefslogtreecommitdiffstats
path: root/src/test/ui/generic-associated-types/streaming_iterator.rs
blob: 408b8dc99eb4ebeb8ab2b0ce5a9267bb5c4d4a08 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// run-pass

use std::fmt::Display;

trait StreamingIterator {
    type Item<'a> where Self: 'a;
    // Applying the lifetime parameter `'a` to `Self::Item` inside the trait.
    fn next<'a>(&'a mut self) -> Option<Self::Item<'a>>;
}

struct Foo<T: StreamingIterator + 'static> {
    // Applying a concrete lifetime to the constructor outside the trait.
    bar: <T as StreamingIterator>::Item<'static>,
}

// Users can bound parameters by the type constructed by that trait's associated type constructor
// of a trait using HRTB. Both type equality bounds and trait bounds of this kind are valid:
//FIXME(#44265): This next line should parse and be valid
//fn foo<T: for<'a> StreamingIterator<Item<'a>=&'a [i32]>>(_iter: T) { /* ... */ }
fn _foo<T>(_iter: T) where T: StreamingIterator, for<'a> T::Item<'a>: Display { /* ... */ }

// Full example of enumerate iterator

#[must_use = "iterators are lazy and do nothing unless consumed"]
struct StreamEnumerate<I> {
    iter: I,
    count: usize,
}

impl<I: StreamingIterator> StreamingIterator for StreamEnumerate<I> {
    type Item<'a> = (usize, I::Item<'a>) where Self: 'a;
    fn next<'a>(&'a mut self) -> Option<Self::Item<'a>> {
        match self.iter.next() {
            None => None,
            Some(val) => {
                let r = Some((self.count, val));
                self.count += 1;
                r
            }
        }
    }
}

impl<I: Iterator> StreamingIterator for I {
    type Item<'a> = <I as Iterator>::Item where Self: 'a;
    fn next(&mut self) -> Option<<I as StreamingIterator>::Item<'_>> {
        Iterator::next(self)
    }
}

impl<I> StreamEnumerate<I> {
    pub fn new(iter: I) -> Self {
        StreamEnumerate {
            count: 0,
            iter,
        }
    }
}

fn test_stream_enumerate() {
    let v = vec!["a", "b", "c"];
    let mut se = StreamEnumerate::new(v.iter());
    while let Some(item) = se.next() {
        assert_eq!(v[item.0], *item.1);
    }
    let x = Foo::<std::slice::Iter<'static, u32>> {
        bar: &0u32,
    };
    assert_eq!(*x.bar, 0u32);
}

fn main() {
    test_stream_enumerate();
}