]> git.proxmox.com Git - rustc.git/blame - src/test/ui/hrtb/issue-30786.rs
New upstream version 1.63.0+dfsg1
[rustc.git] / src / test / ui / hrtb / issue-30786.rs
CommitLineData
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 9pub trait Stream {
416331ca
XL
10 type Item;
11 fn next(self) -> Option<Self::Item>;
12}
13
14// Example stream
15pub struct Repeat(u64);
16
17impl<'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
24pub struct Map<S, F> {
25 stream: S,
26 func: F,
27}
28
29impl<'a, A, F, T> Stream for &'a mut Map<A, F>
f035d41b
XL
30where
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
43pub struct Filter<S, F> {
44 stream: S,
45 func: F,
46}
47
48impl<'a, A, F, T> Stream for &'a mut Filter<A, F>
f035d41b
XL
49where
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
64pub trait StreamExt
65where
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 96impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
416331ca 97
f035d41b
XL
98fn identity<T>(x: &T) -> &T {
99 x
100}
101
102fn 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
122fn 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
134fn main() {}