|  | 
|  | 1 | +// rust-lang/rust#30786: the use of `for<'b> &'b mut A: Stream<Item=T` | 
|  | 2 | +// should act as assertion that item does not borrow from its stream; | 
|  | 3 | +// but an earlier buggy rustc allowed `.map(|x: &_| x)` which does | 
|  | 4 | +// have such an item. | 
|  | 5 | +// | 
|  | 6 | +// This tests double-checks that we do not allow such behavior to leak | 
|  | 7 | +// through again. | 
|  | 8 | + | 
|  | 9 | +pub trait Stream { | 
|  | 10 | +    type Item; | 
|  | 11 | +    fn next(self) -> Option<Self::Item>; | 
|  | 12 | +} | 
|  | 13 | + | 
|  | 14 | +// Example stream | 
|  | 15 | +pub struct Repeat(u64); | 
|  | 16 | + | 
|  | 17 | +impl<'a> Stream for &'a mut Repeat { | 
|  | 18 | +    type Item = &'a u64; | 
|  | 19 | +    fn next(self) -> Option<Self::Item> { | 
|  | 20 | +        Some(&self.0) | 
|  | 21 | +    } | 
|  | 22 | +} | 
|  | 23 | + | 
|  | 24 | +pub struct Map<S, F> { | 
|  | 25 | +    stream: S, | 
|  | 26 | +    func: F, | 
|  | 27 | +} | 
|  | 28 | + | 
|  | 29 | +impl<'a, A, F, T> Stream for &'a mut Map<A, F> | 
|  | 30 | +where &'a mut A: Stream, | 
|  | 31 | +      F: FnMut(<&'a mut A as Stream>::Item) -> T, | 
|  | 32 | +{ | 
|  | 33 | +    type Item = T; | 
|  | 34 | +    fn next(self) -> Option<T> { | 
|  | 35 | +        match self.stream.next() { | 
|  | 36 | +            Some(item) => Some((self.func)(item)), | 
|  | 37 | +            None => None, | 
|  | 38 | +        } | 
|  | 39 | +    } | 
|  | 40 | +} | 
|  | 41 | + | 
|  | 42 | +pub struct Filter<S, F> { | 
|  | 43 | +    stream: S, | 
|  | 44 | +    func: F, | 
|  | 45 | +} | 
|  | 46 | + | 
|  | 47 | +impl<'a, A, F, T> Stream for &'a mut Filter<A, F> | 
|  | 48 | +where for<'b> &'b mut A: Stream<Item=T>, // <---- BAD | 
|  | 49 | +      F: FnMut(&T) -> bool, | 
|  | 50 | +{ | 
|  | 51 | +    type Item = <&'a mut A as Stream>::Item; | 
|  | 52 | +    fn next(self) -> Option<Self::Item> { | 
|  | 53 | +        while let Some(item) = self.stream.next() { | 
|  | 54 | +            if (self.func)(&item) { | 
|  | 55 | +                return Some(item); | 
|  | 56 | +            } | 
|  | 57 | +        } | 
|  | 58 | +        None | 
|  | 59 | +    } | 
|  | 60 | +} | 
|  | 61 | + | 
|  | 62 | +pub trait StreamExt where for<'b> &'b mut Self: Stream { | 
|  | 63 | +    fn map<F>(self, func: F) -> Map<Self, F> | 
|  | 64 | +    where Self: Sized, | 
|  | 65 | +    for<'a> &'a mut Map<Self, F>: Stream, | 
|  | 66 | +    { | 
|  | 67 | +        Map { | 
|  | 68 | +            func: func, | 
|  | 69 | +            stream: self, | 
|  | 70 | +        } | 
|  | 71 | +    } | 
|  | 72 | + | 
|  | 73 | +    fn filter<F>(self, func: F) -> Filter<Self, F> | 
|  | 74 | +    where Self: Sized, | 
|  | 75 | +    for<'a> &'a mut Filter<Self, F>: Stream, | 
|  | 76 | +    { | 
|  | 77 | +        Filter { | 
|  | 78 | +            func: func, | 
|  | 79 | +            stream: self, | 
|  | 80 | +        } | 
|  | 81 | +    } | 
|  | 82 | + | 
|  | 83 | +    fn count(mut self) -> usize | 
|  | 84 | +    where Self: Sized, | 
|  | 85 | +    { | 
|  | 86 | +        let mut count = 0; | 
|  | 87 | +        while let Some(_) = self.next() { | 
|  | 88 | +            count += 1; | 
|  | 89 | +        } | 
|  | 90 | +        count | 
|  | 91 | +    } | 
|  | 92 | +} | 
|  | 93 | + | 
|  | 94 | +impl<T> StreamExt for T where for<'a> &'a mut T: Stream { } | 
|  | 95 | + | 
|  | 96 | +fn main() { | 
|  | 97 | +    let source = Repeat(10); | 
|  | 98 | +    let map = source.map(|x: &_| x); | 
|  | 99 | +    //~^ ERROR implementation of `Stream` is not general enough | 
|  | 100 | +    //~| NOTE  `Stream` would have to be implemented for the type `&'0 mut Map | 
|  | 101 | +    //~| NOTE  but `Stream` is actually implemented for the type `&'1 | 
|  | 102 | + | 
|  | 103 | +    let filter = map.filter(|x: &_| true); | 
|  | 104 | +    let count = filter.count(); // Assert that we still have a valid stream. | 
|  | 105 | +} | 
0 commit comments