Hi,

I've been struggling for a few days with a borrow checker problem and been unable to figure out what the Problem is. The actual code I'm working on is about computations on graphs, but for a minimalish example I've used some simple integer computations.

``````trait IteratorProducer<T> {
fn iterator<'a>(&'a self) -> Box<dyn Iterator<Item = T> + 'a>;
// Default implementation. Actual trait impls might have a more
// efficient way to implement this.
fn transformed<'a>(&'a self) -> Box<dyn Iterator<Item = T> + 'a> {
Box::new(self
.iterator()
// Here rustc complains that i has insufficent lifetime. Why?
.map(|i| self.transform(i)))
}
fn transform(&self, x: T) -> T;
}

struct RangeIterator {}

impl IteratorProducer<i32> for RangeIterator {
fn iterator<'a>(&'a self) -> Box<dyn Iterator<Item = i32> + 'a> {
Box::new(1..10)
}
fn transform(&self, x: i32) -> i32 {
x + 1
}
}

#[test]
fn test_it() {
let ri = RangeIterator {};
let bi: Box<dyn IteratorProducer<_>> = Box::new(ri);

let values: Vec<_> = bi.iterator().collect();
let larger_values: Vec<_> = bi.transformed().collect();
dbg!(values);
dbg!(larger_values);
}

``````

rustc's opinion, with a tip that didn't work:

``````error[E0309]: the parameter type `T` may not live long enough
--> tests/borrow.rs:6:9
|
6 | /         Box::new(self
7 | |             .iterator()
8 | |             // Here rustc complains that i has insufficent lifetime. Why?
9 | |             .map(|i| self.transform(i)))
| |________________________________________^ ...so that the type `T` will meet its required lifetime bounds
|
|
1 | trait IteratorProducer<T: 'a> {
``````

Hints about what is going on here would be appreciated.

I think you need to add a `where T: 'a` clause to the `iterator()` and `transformed()` methods so the lifetime of the`T` being yielded isn't shorter than the `&'a self` reference.

``````trait IteratorProducer<T> {
fn iterator<'a>(&'a self) -> Box<dyn Iterator<Item = T> + 'a>
where
T: 'a;

// Default implementation. Actual trait impls might have a more
// efficient way to implement this.
fn transformed<'a>(&'a self) -> Box<dyn Iterator<Item = T> + 'a>
where
T: 'a,
{
Box::new(
self.iterator()
// Here rustc complains that i has insufficent lifetime. Why?
.map(|i| self.transform(i)),
)
}

fn transform(&self, x: T) -> T;
}

struct RangeIterator {}

impl IteratorProducer<i32> for RangeIterator {
fn iterator<'a>(&'a self) -> Box<dyn Iterator<Item = i32> + 'a>
where
i32: 'a,
{
Box::new(1..10)
}
fn transform(&self, x: i32) -> i32 {
x + 1
}
}

#[test]
fn test_it() {
let ri = RangeIterator {};
let bi: Box<dyn IteratorProducer<_>> = Box::new(ri);

let values: Vec<_> = bi.iterator().collect();
let larger_values: Vec<_> = bi.transformed().collect();
dbg!(values);
dbg!(larger_values);
}
``````

(playground)

3 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.