Explicit lifetime for Vec to slice conversation - rust

I want a callback on changes inside a list, so I created simple example:
struct Foo;
struct FooList {
list: Vec<Foo>,
on_change_cb: Vec<Box<FnMut(& mut [Foo])>>,
}
impl FooList {
/*
pub fn register_on_change_cb2<F>(&mut self, cb: F) where F: FnMut(&mut [Foo]) {
self.on_change_cb.push(Box::new(cb));
}*/
pub fn register_on_change_cb(&mut self, cb: Box<FnMut(&mut [Foo])>) {
self.on_change_cb.push(cb);
}
pub fn push(&mut self, foo: Foo) {
self.list.push(foo);
self.on_change();
}
fn on_change(&mut self) {
for cb in &mut self.on_change_cb {
cb(&mut self.list);
}
}
}
I don't give any explicit hint to the compiler about lifetimes here: Vec<Box<FnMut(& mut [Foo])>>, so what lifetimes will the compiler use here? If I change the code like this:
struct FooList<'a> {
list: Vec<Foo>,
on_change_cb: Vec<Box<FnMut(&'a mut [Foo])>>,
}
impl<'a> FooList<'a> {
I get a compile time error:
error[E0495]: cannot infer an appropriate lifetime for borrow
expression due to conflicting requirements
How can I explicitly set the lifetimes in some way such that the lifetime of & mut [Foo] for the callback is less than, but not equal to the lifetime of the whole FooList object?
I have commented register_on_change_cb2, I want to allow calling register_on_change_cb without usage of Box::new but failed. If you uncomment register_on_change_cb2, you get the error:
error[E0310]: the parameter type F may not live long enough
How can I fix this error without the requirement of a 'static lifetime for callback? I just want to call Box::new on my side.

I'm going to try to answer your questions 1 and 3, because question 2 is either redundant or orthogonal to the others, and I can't tell what you really want to achieve by it. Perhaps it deserves a question of its own.
If you have a function that takes a reference, but it doesn't need any lifetime information about the reference, it must be able to accept a reference of any lifetime. Here's the explicit syntax for that (this is what the compiler infers from the code you wrote):
on_change_cb: Vec<Box<for<'b> FnMut(&'b mut [Foo])>>,
This is called a higher ranked trait bound or HRTB for short. They're mostly useful for the Fn traits, which is why they exist.
If the type of on_change_cb is Vec<Box<FnMut(&mut [Foo])>>, which doesn't carry any lifetime information, then it must not contain any references (except 'static references). You need to say that the type implementing FnMut may also contain (non-'static) references, as long as they outlive some lifetime 'a:
struct FooList<'a> {
list: Vec<Foo>,
on_change_cb: Vec<Box<FnMut(&mut [Foo]) + 'a>>,
}
This reads something like: "For each FooList object, there is a lifetime 'a such that every callback in the FooList contains only references that live for at least 'a." This interpretation may make it easier to write the prototype for register_on_change_cb2: it takes a callback that also contains only references that live for at least 'a.
impl<'a> FooList<'a> {
pub fn register_on_change_cb2<F>(&mut self, cb: F)
where F: FnMut(&mut [Foo]) + 'a
{
self.on_change_cb.push(Box::new(cb));
}
(I think I have the variance of 'a correct now -- a previous version of this answer had it wrong.)
The 'a lifetime lets the compiler guarantee that you never put a callback in the Box (and therefore the Vec) unless it lasts at least as long as the FooList itself. This is important because closures can capture references to values in the enclosing scope, as in the following code (playground link):
let longlived = String::from("hello");
let mut list = FooList {
list: Vec::new(),
on_change_cb: Vec::new(),
};
list.register_on_change_cb2(|_| println!("{}", longlived)); // ok
let shortlived = String::from("hello");
list.register_on_change_cb2(|_| println!("{}", shortlived)); // `shortlived` does not live long enough
list.push(Foo);
In this example, you can't insert the closure that captures shortlived because it doesn't outlive the (inferred) lifetime 'a. But you can insert the closure that captures longlived, because the compiler can infer a lifetime 'a that satisfies both constraints:
'a must outlive list, because list is of type FooList<'a>.
longlived must outlive 'a, because |_| println!("{}", longlived), which borrows longlived, is bounded by 'a in the call to register_on_change_cb2.
If you want to say that the callbacks don't borrow anything by-reference, the 'a lifetime is unnecessary, and in that case you could just add the 'static bound that the compiler suggests:
pub fn register_on_change_cb2<F>(&mut self, cb: F)
where F: FnMut(&mut [Foo]) + 'static

Related

How can I make `Box<dyn Iterator>` peekable and avoid lifetime errors?

I have the following type definition:
pub struct UTF8Chars {
bytes: Peekable<Box<dyn Iterator<Item = u8>>>,
}
Now I'm wondering how to actually create an instance of this struct.
I've tried (and yes, this is inside a trait implementation if that is an important detail):
impl<'a> ToUTF8Chars for &'a str {
fn utf8_chars(self) -> UTF8Chars {
let bytes = Box::new(self.bytes()).peekable();
UTF8Chars { bytes }
}
}
That gives me the error:
expected struct `Peekable<Box<(dyn Iterator<Item = u8> + 'static)>>`
found struct `Peekable<Box<std::str::Bytes<'_>>>`
Playground
Forgive me if I try weird things, but I haven't gotten the hang of this intricate trait stuff yet. For all I know, rust-analyzer was telling me that Bytes in fact an impl Iterator<Item = u8>. So, next thing I tried was casting it first:
let bytes = Box::new(self.bytes()) as Box<dyn Iterator<Item = u8>>;
UTF8Chars { bytes: bytes.peekable() }
That sort of works, but now the borrow checker is complaining:
impl<'a> ToUTF8Chars for &'a str {
-- lifetime `'a` defined here
fn utf8_chars(self) -> UTF8Chars {
let bytes = Box::new(self.bytes()) as Box<dyn Iterator<Item = u8>>;
^^^^^^^^^^^^^^^^^^^^^^ cast requires that `'a` must outlive `'static`
I'm not exactly sure what is going out of scope here... as far as I know, I own the result from .bytes() (I also tried with an additional .clone() in case that assumption was incorrect), I own the Box, the Box is passed to Peekable, and finally Peekable is passed to UTF8Chars. What exactly is the issue here? Why do I somehow need to outlive static...?
I found this issue that seems similar, sadly no answer: Peekable of an Iterator in struct.
Why I want to do this?
Well, mainly because I don't really care, or am unable to care what exactly the underlying data is. I just need to know that I can .peek(), and .next(), etc. This is, because sometimes I want to assign different things to self.bytes. For example, Chain<...>, or Copied<...> instead of a simple vec::IntoIter<...>.
If there is an alternative approach to this, I'm happy to hear about it.
So, next thing I tried was casting it first:
let bytes = Box::new(self.bytes()) as Box<dyn Iterator<Item = u8>>;
This is the right thing to do in this situation, though I would write it with a type annotation on the let, instead of as.
let bytes: Box<dyn Iterator<Item = u8>> = Box::new(self.bytes());
In particular, there must be a point at which the unsizing coercion from Box<Bytes> to Box<dyn Iterator<Item = u8>> happens, and that point must be before the Box is contained in something else (because it actually produces a different Box, one with a vtable pointer added).
In some cases, just as _ (unspecified type) is sufficient to prompt the compiler into not immediately concluding that the type is the same as the incoming type.
I'm not exactly sure what is going out of scope here...
Every trait object (dyn) type has a lifetime, often implicit. This lifetime specifies how long instances of that type are guaranteed valid — or, from the opposite perspective, what references the trait object is allowed to borrow/contain.
When you don't specify that lifetime, and the trait object is in a Box, lifetime elision rules make that lifetime be 'static. That's why you have an error: you're trying to put a Bytes<'a> in a place where 'static is required.
In order to allow your boxed iterator to borrow, you must define the types and traits to have a lifetime.
use core::iter::Peekable;
pub struct UTF8Chars<'a> {
bytes: Peekable<Box<dyn Iterator<Item = u8> + 'a>>,
}
trait ToUTF8Chars<'a> {
fn utf8_chars(self) -> UTF8Chars<'a>;
}
impl<'a> ToUTF8Chars<'a> for &'a str {
fn utf8_chars(self) -> UTF8Chars<'a> {
let bytes: Box<dyn Iterator<Item = u8> + 'a> = Box::new(self.bytes());
UTF8Chars {
bytes: bytes.peekable(),
}
}
}
If you don't want to add a lifetime, then you must only use owning iterators (e.g. String::into_bytes(s).into_iter()). With the lifetime, you can use both owning and borrowing iterators.
The issue is that dyn Trait types are actually dyn Trait + 'static by default, which means they're not allowed to borrow any data. That's a problem for you because the iterator returned by calling bytes() on a &'a str borrows from that str and thus cannot outlive 'a. But 'a doesn't outlive 'static so you can't make a dyn Iterator + 'static from it.
As you might have guessed, the solution here is adding some more general lifetime bounds, first to the struct:
pub struct UTF8Chars<'a> {
// ^^^^ now generic over 'a
bytes: Peekable<Box<dyn Iterator<Item = u8> + 'a>>,
// ------------------------^^^^
// the iterator is now allowed to borrow data for 'a
}
Then to the trait:
trait ToUTF8Chars {
fn utf8_chars<'a>(self) -> UTF8Chars<'a> where Self: 'a;
// ^^^^ also generic over 'a ^^^^^^^^ self can borrow data for 'a
}
Depending on your exact use case, using a borrowed receiver might be nicer, though:
trait ToUTF8Chars {
fn utf8_chars<'a>(&'a self) -> UTF8Chars<'a>;
// ^^^^ just borrow `self` for 'a
}
I'm sure there's a cases where these two aren't the same (object safety, probably?) but I can't pin point a specific situation off the top of my head.
And finally the implementation:
impl<'b> ToUTF8Chars for &'b str {
fn utf8_chars<'a>(self) -> UTF8Chars<'a> where Self: 'a {
let bytes = Box::new(self.bytes()) as Box<dyn Iterator<Item = u8>>;
UTF8Chars { bytes: bytes.peekable() }
}
}
or
impl ToUTF8Chars for str {
fn utf8_chars<'a>(&'a str) -> UTF8Chars<'a> {
let bytes = Box::new(self.bytes()) as Box<dyn Iterator<Item = u8>>;
UTF8Chars { bytes: bytes.peekable() }
}
}
for the alternative version of ToUTF8Chars.

How to infer an appropriate lifetime for an implementation using lifetimes for structs and impl?

How do I resolve this error? What exactly am I telling the compiler when I use the "anonymous lifetime" in impl?
struct LineHandlerInfo<'a> {
label: &'a str,
match_literal: &'a str,
f: fn(&str) -> Option<&str>,
}
struct Game<'a> {
handlers: Vec<LineHandlerInfo<'a>>,
}
impl Game<'_> {
fn match_str<'a>(
&'a mut self,
label: &'a str,
match_literal: &'a str,
mut f: fn(&str) -> Option<&str>,
) {
let mut lh = LineHandlerInfo {
label,
match_literal,
f,
};
self.handlers.push(lh);
}
}
fn main() {
let mut g = Game {
handlers: Vec::new(),
};
g.match_str("echo hello", "hello", |s| {
println!("{}", s);
None
});
}
When I attempt to compile, I get the following error:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
--> src/main.rs:18:22
|
18 | let mut lh = LineHandlerInfo {
| ^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the lifetime 'a as defined on the method body at 12:18...
--> src/main.rs:12:18
|
12 | fn match_str<'a>(
| ^^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:19:13
|
19 | label,
| ^^^^^
note: but, the lifetime must be valid for the lifetime '_ as defined on the impl at 11:11...
--> src/main.rs:11:11
|
11 | impl Game<'_> {
| ^^
= note: ...so that the expression is assignable:
expected LineHandlerInfo<'_>
found LineHandlerInfo<'_>
How do I resolve this error and what exactly am I telling the compiler when I specify a lifetime on impl Game when I already have a lifetime on the struct?
How do I resolve this error and what exactly am I telling the compiler when I specify a lifetime on impl Game when I already have a lifetime on the struct?
I suspect your confusion stems from an incomplete understanding of the way in which lifetimes are declared and used in Rust.
Struct Lifetimes
In order to use a lifetime on a struct, you declare the lifetime inside the <> adjacent to the name of the struct you are declaring, and then refer to that lifetime inside the struct definition. Importantly, note that the lifetime declared there is scoped to the struct definition - it has no meaning outside.
For example (using the MRE that #Shepmaster provided):
struct Game<'a> {
handlers: Vec<&'a str>,
}
The struct Game contains a vector of references to strings, and the strings which are referenced must last at least as long as the Game struct.
Impl Lifetimes
When using a lifetime specifier on an impl block, you declare the lifetime inside the <> adjacent to the impl keyword, after which you may refer to the lifetime both in the struct being implemented, and inside the implementation itself, like this:
impl<'b> Game<'b> {
fn match_str(&mut self, label: &'b str) {
self.handlers.push(label);
}
}
Note that I am using an entirely different lifetime name here ('b) to illustrate that the the lifetime declaration on the struct is independent of the one on the impl block.
Breaking this down:
impl<'b>
This means that we are defining an implementation for a struct, and within that definition we will use the lifetime 'b
Game<'b> {
This means that the impl is for the struct Game with lifetime 'b - so any references to self inside this implementation are going to automatically have lifetime 'b as well.
fn match_str(&mut self, label: &'b str) {
Here we define the method match_str which takes an argument label. label is a string slice which also has the lifetime 'b - so it must last at least as long as the self that the method is called on.
In your original code, you had something like this:
impl Game<'_> {
fn match_str<'a>(&mut self, label: &'a str) {
...
}
}
This was telling the compiler:
That you are starting a new impl block that, and there are no lifetimes declared at impl level
That the implementation is for the struct Game; this struct has a lifetime parameter but we don't care about it and we are not going to tie it to any element of the implementation
We are defining a method match_str, and we are declaring a lifetime 'a which we can refer to in the rest of the function signature
We have an argument label which has the lifetime a, but we aren't relating this lifetime to anything else
More information:
Rust Book - Lifetime Annotations in Struct Definitions
Rust Book - Lifetime Annotations in Method Definitions
How do I resolve this error?
Remove the generic lifetime from the function, provide a name for the lifetime on the impl block instead of using the anonymous lifetime, then use the named lifetime in the function arguments. Remove the lifetime from &self:
impl<'a> Game<'a> {
fn match_str(&mut self, label: &'a str, match_literal: &'a str, f: fn(&str) -> Option<&str>) {
self.handlers.push(LineHandlerInfo {
label,
match_literal,
f,
});
}
}
See also:
Cannot borrow as mutable more than once at a time in one code - but can in another very similar
What exactly am I doing when I use the "anonymous lifetime" in impl?
You are effectively stating "I know there's a lifetime here, but I don't care about it". However, that's not true for your case; you do care about the lifetime that parameterizes the type because that's what your variables need to match.
See also:
'_, the anonymous lifetime in the Edition Guide
for a struct with a function pointer in it
This has nothing to do with function pointers. When encountering problems while programing, I recommend creating a minimal, reproducible example, stripping out things that don't make the error go away. This allows you to focus on exactly the problem at hand. For example, this reproduces the same error:
struct Game<'a> {
handlers: Vec<&'a str>,
}
impl Game<'_> {
fn match_str<'a>(&mut self, label: &'a str) {
self.handlers.push(label);
}
}

Confusing error in Rust with trait object lifetime

Can anyone tell what the problem is with the following code? The compiler is complaining about lifetimes, but the error message makes absolutely no sense. I've tried everything I could think of, but nothing seems to help.
use std::borrow::BorrowMut;
trait Trait<'a> {
fn accept(&mut self, &'a u8);
}
struct Impl<'a>{
myref: Option<&'a u8>,
}
impl<'a> Trait<'a> for Impl<'a> {
fn accept(&mut self, inp: &'a u8) { self.myref = Some(inp); }
}
fn new<'a>() -> Box<Trait<'a> + 'a> {
Box::new(Impl{myref: None})
}
fn user<'a>(obj: &mut Trait<'a>) {}
fn parent<'a>(x: &'a u8) {
let mut pool = new();
user(pool.borrow_mut());
}
The compiler error is
error: `pool` does not live long enough
--> src/wtf.rs:22:10
|
22 | user(pool.borrow_mut());
| ^^^^ does not live long enough
23 | }
| - borrowed value dropped before borrower
|
= note: values in a scope are dropped in the opposite order they are created
Which makes absolutely no sense. How is the borrower outliving anything? I'm not even using the borrowed value!
Ok, this does make sense, but it's hard to see due to lifetime elision. So, here's your code with all the lifetimes written out explicitly, and with irrelevant details culled:
use std::borrow::BorrowMut;
trait Trait<'a> {}
struct Impl<'a> {
myref: Option<&'a u8>,
}
impl<'a> Trait<'a> for Impl<'a> {}
fn new<'a>() -> Box<Trait<'a> + 'a> {
Box::new(Impl { myref: None })
}
fn user<'a, 'b>(obj: &'b mut (Trait<'a> + 'b)) {}
fn parent() {
/* 'i: */ let mut pool/*: Box<Trait<'x> + 'x>*/ = new();
/* 'j: */ let pool_ref/*: &'i mut Box<Trait<'x> + 'x>*/ = &mut pool;
/* BorrowMut<T>::borrow_mut<'d>(&'d mut Self) -> &'d mut T */
/* 'k: */ let pool_borrow/*: &'i mut (Trait<'x> + 'x)*/ = Box::borrow_mut(pool_ref);
user(pool_borrow);
}
Now, from the perspective of the last line of parent, we can work out the following equivalences by just reading the definition of user and substituting the lifetimes we have in parent:
'a = 'x
'b = 'i
'b = 'x
Furthermore, this lets us conclude that:
'x = 'i
This is the problem. Because of the way you've defined user, you've put yourself in a situation where the lifetime of the pool_ref borrow (which is equal to the lifetime of the pool storage location you're borrowing from) must be the same as the lifetime 'x being used in the thing being stored in pool.
It's a bit like the Box being able to have a pointer to itself before it exists, which doesn't make any sense.
Either way, the fix is simple. Change user to actually have the correct type:
fn user<'a, 'b>(obj: &'b mut (Trait<'a> + 'a)) {}
This matches the type produced by new. Alternately, just don't use borrow_mut:
user(&mut *pool)
This works because it is "re-borrowing". Calling borrow_mut translates the lifetimes more or less directly, but re-borrowing allows the compiler to narrow the borrows to shorter lifetimes. To put it another way, explicitly calling borrow_mut doesn't allow the compiler enough freedom to "fudge" the lifetimes to make them all line up, re-borrowing does.
As a quick aside:
I'm not even using the borrowed value!
Irrelevant. Rust does type- and lifetime-checking entirely locally. It never looks at the body of another function to see what it's doing; it goes on the interface alone. The compiler neither checks, nor cares, what you're doing inside a different function.
Note that there's more to the error message:
error: `pool` does not live long enough
--> src/main.rs:25:10
|>
25 |> user(pool.borrow_mut());
|> ^^^^
note: reference must be valid for the block at 23:25...
--> src/main.rs:23:26
|>
23 |> fn parent<'a>(x: &'a u8) {
|> ^
note: ...but borrowed value is only valid for the block suffix following statement 0 at 24:25
--> src/main.rs:24:26
|>
24 |> let mut pool = new();
|> ^
Let's look at user:
fn user<'a>(obj: &mut Trait<'a>) {}
This says that it will accept a mutable reference (with an unnamed lifetime) to a trait object parameterized with the lifetime 'a.
Turning to new, I'd say the method is highly suspicious:
fn new<'a>() -> Box<Trait<'a> + 'a> {
Box::new(Impl { myref: None })
}
This says that it will return a boxed trait object with whatever lifetime the caller specifies. That basically never makes sense.
All that said, I'm not clear why the code chooses to use borrow_mut. I would have written that more directly:
user(&mut *pool);
This dereferences the Box<Trait> to get a Trait, then takes a mutable reference, yielding &mut Trait, which compiles.
I cannot currently explain why BorrowMut differs in behavior.
I'm not sure why this error happens, but I can give solutions!
First, it seems that using borrow_mut unnecessarily restricts the lifetime of the returned reference. Using operators to create the reference solves the error.
fn parent() {
let mut pool = new();
user(&mut *pool);
}
However, if we don't do that, we can solve the error by adding a lifetime bound to the Trait object in user's obj argument.
fn user<'a>(obj: &mut (Trait<'a> + 'a)) {}

Is it possible to build an iterator that yields a reference to an object that it modifies in next()?

I'm trying to build an iterator that yields a reference to a Vec. I'll try to explain my rationale to understand where my flaw is.
My first attempt was to have the iterator own the object:
pub struct VecIter<T> {
x: Vec<T>,
}
However, according to Iterator returning items by reference, lifetime issue, this would not work. There were two suggestions in the above answer: don't return a reference, or have a reference to the object.
Quoting from the answer:
For your specific, presumably simple example, you should either stop
yielding references, or alter it so that your iterator object does not
contain the data that you are iterating over—let it merely contain a
reference to it, e.g. &'a [T] or even something like Items<'a, T>.
I want to implement the second option: i.e, return a reference by having the iterator contain a reference.
I've reduced the code to the simplest version that I cannot make it compile:
pub struct VecIter<'a, T> where T: 'a {
x: &'a mut Vec<T>,
}
impl<'a, T> VecIter<'a, T> {
fn next_(&'a mut self) -> Option<&'a Vec<T>> {
// do something to modify self.x
Some(self.x)
}
}
pub fn main() {
let mut vec_i = VecIter{x: &mut vec![100,200,300]};
while let Some(x) = vec_i.next_() {
// ...
}
}
I would expect the above code to work because each mutable borrow only lives inside the loop body. So the idea is to borrow the reference for the body of the loop, use it inside the loop, and end the borrow at the end of the loop.
Is it possible to build such an iterator? i.e., build an iterator that yields a reference to an object that it modifies in next()?
EDIT:
In a comment by Matthieu M, it was suggested that for this to work I should:
remove the 'a so next_(&'a mut self) becomes next_(&mut self)
Maybe I'm understanding something wrong, but I tried this and I got the following compile error. To avoid any confusion here's the code that I tried (playground):
<anon>:8:14: 8:20 error: cannot infer an appropriate lifetime for automatic coercion due to conflicting requirements [E0495]
<anon>:8 Some(self.x)
^~~~~~
<anon>:6:5: 9:6 help: consider using an explicit lifetime parameter as shown: fn next_(&'a mut self) -> Option<&'a Vec<T>>
<anon>:6 fn next_(&mut self) -> Option<&'a Vec<T>> {
<anon>:7 // do something to modify self.x
<anon>:8 Some(self.x)
<anon>:9 }
error: aborting due to previous error
playpen: application terminated with error code 101
Here's a modification of your next_() method that seems to work:
fn next_<'b>(&'b mut self) -> Option<&'b Vec<T>>
where 'a: 'b { ... }
The 'b parameter will be elided (lifetime elision), so this will work just as well:
fn next_(&mut self) -> Option<&Vec<T>> { ... }
The lifetimes of self and of self.x are different. I'm having some trouble figuring out the precise reason this doesn't work, but in general, you don't need to write &'x self, and if you ever do, 'x is never a parameter on the type of self.
EDIT: Ok, I get it now. I kept overlooking the fact that self.x is a mutable borrow of a Vec, but you're trying to return an immutable reference to it. If self.x were not marked mut, you could just return Some(self.x) and it would be copied. But you can't copy a mutable reference, so it has to be reborrowed. Furthermore, the existence of a reborrowed (immutable) reference would make it impossible to call &mut self methods or destroy self until the reference was destroyed, so self has to outlast the new borrow. That's why you can't return &'a Vec<T>: if you could, it would become impossible to destroy self.

Unable to infer lifetime for borrow expression when using a trait with an explicit lifetime

use std::io::BufReader;
struct Foo {
buf: [u8, ..10]
}
trait Bar<'a> {
fn test(&self, arg: BufReader<'a>) {}
}
impl<'a, T: Bar<'a>> Foo {
fn bar(&'a mut self, t: T) {
t.test(BufReader::new(&self.buf));
let b = &mut self.buf;
}
fn baz(&self, t: T) {
t.test(BufReader::new(&self.buf));
}
}
fn main() {}
The code above fails to compile, with the error message:
lifetimes.rs:17:31: 17:40 error: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
lifetimes.rs:17 t.test(BufReader::new(&self.buf));
^~~~~~~~~
lifetimes.rs:16:5: 18:6 help: consider using an explicit lifetime parameter as shown: fn baz(&'a self, t: T)
lifetimes.rs:16 fn baz(&self, t: T) {
lifetimes.rs:17 t.test(BufReader::new(&self.buf));
lifetimes.rs:18 }
error: aborting due to previous error
However, if I add the named lifetime parameter, I cannot mutable borrow the buf field after calling test, as seen in fn bar. Commenting out the fn baz and trying to compile results in:
lifetimes.rs:13:22: 13:30 error: cannot borrow `self.buf` as mutable because it is also borrowed as immutable
lifetimes.rs:13 let b = &mut self.buf;
^~~~~~~~
lifetimes.rs:12:32: 12:40 note: previous borrow of `self.buf` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `self.buf` until the borrow ends
lifetimes.rs:12 t.test(BufReader::new(&self.buf));
^~~~~~~~
lifetimes.rs:14:6: 14:6 note: previous borrow ends here
lifetimes.rs:11 fn bar(&'a mut self, t: T) {
lifetimes.rs:12 t.test(BufReader::new(&self.buf));
lifetimes.rs:13 let b = &mut self.buf;
lifetimes.rs:14 }
^
error: aborting due to previous error
My understanding of this is that by adding the named lifetime 'a to the &'a mut self parameter, the reference taken by BufReader has a lifetime as long as the self reference is valid, which is until the end of the function. This conflicts with the mutable borrow of self.buf on the line after.
However, I am not sure why I need the named lifetime parameter on the self. It seems to me that the BufReader reference should be able to only exist for the lifetime of the t.test method call. Is the compiler complaining because the self.buf borrow must be ensured to live only as long as the &self borrow? How would I go about doing that while still only borrowing it for the lifetime of the method call?
Any help in going about fixing this problem and understanding more about the semantics here would be much appreciated!
Update
So I am still looking into this problem, and I have found this test case and this issue that show basically what I am trying to do. I would very much like to understand why the error pointed to by the test case link is an error.
I can see in the issue rustc output that attempts to point out what the error is, but I am having trouble understanding what exactly it is trying to say.
Removing all explicit lifetimes also works. I've found that I only add lifetimes when I'm sure I need them (i.e. to specifiy that two lifetimes should intersect at a given point which can't be known to the compiler).
I'm not sure exactly what you're going for, but this compiles (on rustc 0.13.0-nightly (cc19e3380 2014-12-20 20:00:36 +0000)).
use std::io::BufReader;
struct Foo {
buf: [u8, ..10]
}
trait Bar {
fn test(&self, arg: BufReader) {}
}
impl<T: Bar> Foo {
fn bar(&mut self, t: T) {
t.test(BufReader::new(&self.buf));
let b = &mut self.buf;
}
fn baz(&self, t: T) {
t.test(BufReader::new(&self.buf));
}
}
Edit
I'm going to copy-edit my comment here:
I originally thought that adding a lifetime or generic parameter to the trait / struct / enum was a shorthand for putting it on every method in the trait, but I was wrong. My current understanding is that you add a lifetime to the trait / struct / enum when that item needs to participate in the lifetime, likely because it is storing a reference with that lifetime.
struct Keeper<'a> {
counts: Vec<&'a i32>,
}
impl<'a> Keeper<'a> {
fn add_one(&mut self, count: &'a i32) {
if *count > 5 {
self.counts.push(count);
}
}
fn add_two<'b>(&mut self, count: &'b i32) -> i32 {
*count + 1
}
}
fn main() {
let mut cnt1 = 1;
let mut cnt2 = 2;
let mut k = Keeper { counts: Vec::new() };
k.add_one(&cnt1);
k.add_two(&cnt2);
// cnt1 += 1; // Errors: cannot assign to `cnt1` because it is borrowed
cnt2 += 1; // Just fine
println!("{}, {}", cnt1, cnt2)
}
Here, we've added a lifetime to Keeper because it might store the reference it is given. The borrow checker must assume that the reference is stored for good when we call add_one, so once we call that method, we can no longer mutate the value.
add_two, on the other hand, creates a fresh lifetime that can only be applied to that function invocation, so the borrow checker knows that once the function returns, it is the One True Owner.
The upshot is, if you need to store a reference, then there's nothing you can do at this level. Rust can't make sure you are safe, and that's something it takes seriously.
However, I bet you don't need to store the reference. Move the <'a, T: Bar<'a>> from the impl to the fn and you'll be good to go.
Said another way: I bet you should never have impl<A> if your trait or struct don't require it. Put the generics on the methods instead.
Original
This compiles, but I'm not 100% sure it does what you intended:
impl Foo {
fn baz<'a, T: Bar<'a>>(&'a self, t: T) {
t.test(BufReader::new(&self.buf));
}
}
I fell into this trap myself, so I'll paste what I was told:
Everything in the impl block is parameterized. I've actually never
seen type parameters added to impl blocks themselves that aren't part
of the trait or type definition. It's far more common to parameterize
the individual methods that need it.
Perhaps other comments / answers can help explain in further detail.

Resources