]> git.lizzy.rs Git - rust.git/blob - src/test/ui/hrtb/issue-30786.rs
c656f8430653629be8124a5b4114d9276921454a
[rust.git] / src / test / ui / hrtb / issue-30786.rs
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
19 pub trait Stream { //[migrate]~ NOTE trait `Stream` defined here
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);
109     //[nll]~^ ERROR higher-ranked subtype error
110     //[migrate]~^^ ERROR implementation of `Stream` is not general enough
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
113     //[migrate]~| NOTE  implementation of `Stream` is not general enough
114     let filter = map.filter(|x: &_| true);
115     //[nll]~^ ERROR higher-ranked subtype error
116     //[nll]~| ERROR higher-ranked subtype error
117     //[nll]~| ERROR higher-ranked subtype error
118     //[nll]~| ERROR higher-ranked subtype error
119     let count = filter.count(); // Assert that we still have a valid stream.
120     //[nll]~^ ERROR higher-ranked subtype error
121     //[nll]~| ERROR higher-ranked subtype error
122     //[nll]~| ERROR higher-ranked subtype error
123     //[nll]~| ERROR higher-ranked subtype error
124 }