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