]>
Commit | Line | Data |
---|---|---|
416331ca XL |
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 | ||
f035d41b | 9 | pub trait Stream { |
416331ca XL |
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> | |
f035d41b XL |
30 | where |
31 | &'a mut A: Stream, | |
32 | F: FnMut(<&'a mut A as Stream>::Item) -> T, | |
416331ca XL |
33 | { |
34 | type Item = T; | |
35 | fn next(self) -> Option<T> { | |
36 | match self.stream.next() { | |
37 | Some(item) => Some((self.func)(item)), | |
38 | None => None, | |
39 | } | |
40 | } | |
41 | } | |
42 | ||
43 | pub struct Filter<S, F> { | |
44 | stream: S, | |
45 | func: F, | |
46 | } | |
47 | ||
48 | impl<'a, A, F, T> Stream for &'a mut Filter<A, F> | |
f035d41b XL |
49 | where |
50 | for<'b> &'b mut A: Stream<Item = T>, // <---- BAD | |
51 | F: FnMut(&T) -> bool, | |
416331ca XL |
52 | { |
53 | type Item = <&'a mut A as Stream>::Item; | |
54 | fn next(self) -> Option<Self::Item> { | |
55 | while let Some(item) = self.stream.next() { | |
56 | if (self.func)(&item) { | |
57 | return Some(item); | |
58 | } | |
59 | } | |
60 | None | |
61 | } | |
62 | } | |
63 | ||
f035d41b XL |
64 | pub trait StreamExt |
65 | where | |
66 | for<'b> &'b mut Self: Stream, | |
67 | { | |
68 | fn mapx<F>(self, func: F) -> Map<Self, F> | |
69 | where | |
70 | Self: Sized, | |
71 | for<'a> &'a mut Map<Self, F>: Stream, | |
416331ca | 72 | { |
f035d41b | 73 | Map { func: func, stream: self } |
416331ca XL |
74 | } |
75 | ||
f035d41b XL |
76 | fn filterx<F>(self, func: F) -> Filter<Self, F> |
77 | where | |
78 | Self: Sized, | |
79 | for<'a> &'a mut Filter<Self, F>: Stream, | |
416331ca | 80 | { |
f035d41b | 81 | Filter { func: func, stream: self } |
416331ca XL |
82 | } |
83 | ||
f035d41b XL |
84 | fn countx(mut self) -> usize |
85 | where | |
86 | Self: Sized, | |
416331ca XL |
87 | { |
88 | let mut count = 0; | |
89 | while let Some(_) = self.next() { | |
90 | count += 1; | |
91 | } | |
92 | count | |
93 | } | |
94 | } | |
95 | ||
f035d41b | 96 | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {} |
416331ca | 97 | |
f035d41b XL |
98 | fn identity<T>(x: &T) -> &T { |
99 | x | |
100 | } | |
101 | ||
102 | fn variant1() { | |
416331ca | 103 | let source = Repeat(10); |
f035d41b XL |
104 | |
105 | // Here, the call to `mapx` returns a type `T` to which `StreamExt` | |
106 | // is not applicable, because `for<'b> &'b mut T: Stream`) doesn't hold. | |
107 | // | |
108 | // More concretely, the type `T` is `Map<Repeat, Closure>`, and | |
109 | // the where clause doesn't hold because the signature of the | |
110 | // closure gets inferred to a signature like `|&'_ Stream| -> &'_` | |
111 | // for some specific `'_`, rather than a more generic | |
112 | // signature. | |
113 | // | |
114 | // Why *exactly* we opt for this signature is a bit unclear to me, | |
115 | // we deduce it somehow from a reuqirement that `Map: Stream` I | |
116 | // guess. | |
117 | let map = source.mapx(|x: &_| x); | |
118 | let filter = map.filterx(|x: &_| true); | |
923072b8 | 119 | //~^ ERROR the method |
416331ca | 120 | } |
f035d41b XL |
121 | |
122 | fn variant2() { | |
123 | let source = Repeat(10); | |
124 | ||
125 | // Here, we use a function, which is not subject to the vagaries | |
126 | // of closure signature inference. In this case, we get the error | |
127 | // on `countx` as, I think, the test originally expected. | |
128 | let map = source.mapx(identity); | |
129 | let filter = map.filterx(|x: &_| true); | |
130 | let count = filter.countx(); | |
923072b8 | 131 | //~^ ERROR the method |
f035d41b XL |
132 | } |
133 | ||
134 | fn main() {} |