]>
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 | ||
9 | // revisions: migrate nll | |
10 | ||
11 | // Since we are testing nll (and migration) explicitly as a separate | |
12 | // revisions, don't worry about the --compare-mode=nll on this test. | |
13 | ||
14 | // ignore-compare-mode-nll | |
15 | // ignore-compare-mode-polonius | |
16 | ||
17 | //[nll]compile-flags: -Z borrowck=mir | |
18 | ||
e1599b0c | 19 | pub trait Stream { //[migrate]~ NOTE trait `Stream` defined here |
416331ca XL |
20 | type Item; |
21 | fn next(self) -> Option<Self::Item>; | |
22 | } | |
23 | ||
24 | // Example stream | |
25 | pub struct Repeat(u64); | |
26 | ||
27 | impl<'a> Stream for &'a mut Repeat { | |
28 | type Item = &'a u64; | |
29 | fn next(self) -> Option<Self::Item> { | |
30 | Some(&self.0) | |
31 | } | |
32 | } | |
33 | ||
34 | pub struct Map<S, F> { | |
35 | stream: S, | |
36 | func: F, | |
37 | } | |
38 | ||
39 | impl<'a, A, F, T> Stream for &'a mut Map<A, F> | |
40 | where &'a mut A: Stream, | |
41 | F: FnMut(<&'a mut A as Stream>::Item) -> T, | |
42 | { | |
43 | type Item = T; | |
44 | fn next(self) -> Option<T> { | |
45 | match self.stream.next() { | |
46 | Some(item) => Some((self.func)(item)), | |
47 | None => None, | |
48 | } | |
49 | } | |
50 | } | |
51 | ||
52 | pub struct Filter<S, F> { | |
53 | stream: S, | |
54 | func: F, | |
55 | } | |
56 | ||
57 | impl<'a, A, F, T> Stream for &'a mut Filter<A, F> | |
58 | where for<'b> &'b mut A: Stream<Item=T>, // <---- BAD | |
59 | F: FnMut(&T) -> bool, | |
60 | { | |
61 | type Item = <&'a mut A as Stream>::Item; | |
62 | fn next(self) -> Option<Self::Item> { | |
63 | while let Some(item) = self.stream.next() { | |
64 | if (self.func)(&item) { | |
65 | return Some(item); | |
66 | } | |
67 | } | |
68 | None | |
69 | } | |
70 | } | |
71 | ||
72 | pub trait StreamExt where for<'b> &'b mut Self: Stream { | |
73 | fn map<F>(self, func: F) -> Map<Self, F> | |
74 | where Self: Sized, | |
75 | for<'a> &'a mut Map<Self, F>: Stream, | |
76 | { | |
77 | Map { | |
78 | func: func, | |
79 | stream: self, | |
80 | } | |
81 | } | |
82 | ||
83 | fn filter<F>(self, func: F) -> Filter<Self, F> | |
84 | where Self: Sized, | |
85 | for<'a> &'a mut Filter<Self, F>: Stream, | |
86 | { | |
87 | Filter { | |
88 | func: func, | |
89 | stream: self, | |
90 | } | |
91 | } | |
92 | ||
93 | fn count(mut self) -> usize | |
94 | where Self: Sized, | |
95 | { | |
96 | let mut count = 0; | |
97 | while let Some(_) = self.next() { | |
98 | count += 1; | |
99 | } | |
100 | count | |
101 | } | |
102 | } | |
103 | ||
104 | impl<T> StreamExt for T where for<'a> &'a mut T: Stream { } | |
105 | ||
106 | fn main() { | |
107 | let source = Repeat(10); | |
108 | let map = source.map(|x: &_| x); | |
e74abb32 XL |
109 | //[nll]~^ ERROR higher-ranked subtype error |
110 | //[migrate]~^^ ERROR implementation of `Stream` is not general enough | |
416331ca XL |
111 | //[migrate]~| NOTE `Stream` would have to be implemented for the type `&'0 mut Map |
112 | //[migrate]~| NOTE but `Stream` is actually implemented for the type `&'1 | |
e1599b0c | 113 | //[migrate]~| NOTE implementation of `Stream` is not general enough |
416331ca XL |
114 | let filter = map.filter(|x: &_| true); |
115 | //[nll]~^ ERROR higher-ranked subtype error | |
dfeec247 XL |
116 | //[nll]~| ERROR higher-ranked subtype error |
117 | //[nll]~| ERROR higher-ranked subtype error | |
118 | //[nll]~| ERROR higher-ranked subtype error | |
416331ca XL |
119 | let count = filter.count(); // Assert that we still have a valid stream. |
120 | //[nll]~^ ERROR higher-ranked subtype error | |
dfeec247 XL |
121 | //[nll]~| ERROR higher-ranked subtype error |
122 | //[nll]~| ERROR higher-ranked subtype error | |
123 | //[nll]~| ERROR higher-ranked subtype error | |
416331ca | 124 | } |