Skip to content

Commit e3aae61

Browse files
committed
add filtering lending iterator known-bug
1 parent d6dc363 commit e3aae61

File tree

2 files changed

+70
-0
lines changed

2 files changed

+70
-0
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error[E0499]: cannot borrow `self.iter` as mutable more than once at a time
2+
--> $DIR/filtering-lending-iterator-issue-92985.rs:49:32
3+
|
4+
LL | fn next(&mut self) -> Option<I::Item<'_>> {
5+
| - let's call the lifetime of this reference `'1`
6+
LL | while let Some(item) = self.iter.next() {
7+
| ^^^^^^^^^ `self.iter` was mutably borrowed here in the previous iteration of the loop
8+
LL | if (self.predicate)(&item) {
9+
LL | return Some(item);
10+
| ---------- returning this value requires that `self.iter` is borrowed for `'1`
11+
12+
error: aborting due to 1 previous error
13+
14+
For more information about this error, try `rustc --explain E0499`.
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#![crate_type = "lib"]
2+
3+
// This test is an example of a filtering lending iterator with GATs from #92985 (that is similar to
4+
// NLL problem case #3) to ensure it "works" with the polonius alpha analysis as with the datalog
5+
// implementation.
6+
//
7+
// The polonius analysis only changes how the `Filter::next` function is borrowcked, not the bounds
8+
// on the predicate from using the GAT. So even if the #92985 limitation is removed, the unrelated
9+
// 'static limitation on the predicate argument is still there, and the pattern is still impractical
10+
// to use in the real world.
11+
12+
//@ ignore-compare-mode-polonius (explicit revisions)
13+
//@ revisions: nll polonius legacy
14+
//@ [nll] known-bug: #92985
15+
//@ [polonius] check-pass
16+
//@ [polonius] compile-flags: -Z polonius=next
17+
//@ [legacy] check-pass
18+
//@ [legacy] compile-flags: -Z polonius=legacy
19+
20+
trait LendingIterator {
21+
type Item<'a>
22+
where
23+
Self: 'a;
24+
fn next(&mut self) -> Option<Self::Item<'_>>;
25+
26+
fn filter<P>(self, predicate: P) -> Filter<Self, P>
27+
where
28+
Self: Sized,
29+
P: FnMut(&Self::Item<'_>) -> bool,
30+
{
31+
Filter { iter: self, predicate }
32+
}
33+
}
34+
35+
pub struct Filter<I, P> {
36+
iter: I,
37+
predicate: P,
38+
}
39+
impl<I: LendingIterator, P> LendingIterator for Filter<I, P>
40+
where
41+
P: FnMut(&I::Item<'_>) -> bool,
42+
{
43+
type Item<'a>
44+
= I::Item<'a>
45+
where
46+
Self: 'a;
47+
48+
fn next(&mut self) -> Option<I::Item<'_>> {
49+
while let Some(item) = self.iter.next() {
50+
if (self.predicate)(&item) {
51+
return Some(item);
52+
}
53+
}
54+
return None;
55+
}
56+
}

0 commit comments

Comments
 (0)