Aquire &'a T from Option<T<'a>> - reference

I'm afraid this may be very basic but I haven't been able to figure it out on my own. I have this map:
subscriptions_map: HashMap<SubscriptionKey, Subscription<'a>>
and this vector:
subscriptions: Vec<&'a Subscription<'a>>,
I want to insert a value into the HashMap and a reference to the same item into the vector. I've tried to do it like this:
let subs: &'a Subscription = &self.subscriptions_map.insert(id, item).unwrap();
self.subscriptions.push(subs);
But it gets this error:
error: borrowed value does not live long enough
let subs: &'a Subscription = &self.subscriptions_map.insert(id, item).unwrap();
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
note: reference must be valid for the lifetime 'a as defined on the block at 40:70...
pub fn add_subscription(&'a mut self, mut item: Subscription<'a>) {
let id = item.get_id();
let _lock = self.lock.lock().unwrap();
let subs: &'a Subscription = &self.subscriptions_map.insert(id, item).unwrap();
...
note: ...but borrowed value is only valid for the block suffix following statement 2 at 45:87
let subs: &'a Subscription = &self.subscriptions_map.insert(id, item).unwrap();
self.subscriptions.push(subs);
}
error: aborting due to previous error
I guess my question boils down to: If I have an Option<T<'a>>, how can I get a &'a T?

HashMap.insert() returns the old value for the given key, not the value you just passed. That's not what you want!
After you've inserted an item into the HashMap, you must call HashMap.get() to retrieve a pointer to the value. As HashMap.insert() takes ownership of both the key and the value, we need to pass a clone of id to insert() so we can use the original id for the get() call. (If the type of id is Copy, you may omit the call to clone() and let the compiler copy the value.)
use std::collections::HashMap;
#[derive(Eq, PartialEq, Hash, Clone)]
struct SubscriptionKey;
struct Subscription<'a>(&'a ());
struct Foo<'a> {
subscriptions_map: HashMap<SubscriptionKey, Subscription<'a>>,
subscriptions: Vec<&'a Subscription<'a>>,
}
impl<'a> Foo<'a> {
fn add(&'a mut self, id: SubscriptionKey, item: Subscription<'a>) {
self.subscriptions_map.insert(id.clone(), item);
let subs = self.subscriptions_map.get(&id).unwrap();
self.subscriptions.push(subs);
}
}
fn main() {
let subscription_data = &();
let mut f = Foo {
subscriptions_map: HashMap::new(),
subscriptions: Vec::new(),
};
f.add(SubscriptionKey, Subscription(subscription_data));
}
This works fine, but it falls apart if we try to add another subscription. If we do this:
fn main() {
let subscription_data = &();
let subscription_data2 = &();
let mut f = Foo {
subscriptions_map: HashMap::new(),
subscriptions: Vec::new(),
};
f.add(SubscriptionKey, Subscription(subscription_data));
f.add(SubscriptionKey, Subscription(subscription_data2));
}
the compiler gives the following messages:
<anon>:30:5: 30:6 error: cannot borrow `f` as mutable more than once at a time [E0499]
<anon>:30 f.add(SubscriptionKey, Subscription(subscription_data2));
^
<anon>:30:5: 30:6 help: see the detailed explanation for E0499
<anon>:29:5: 29:6 note: previous borrow of `f` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `f` until the borrow ends
<anon>:29 f.add(SubscriptionKey, Subscription(subscription_data));
^
<anon>:31:2: 31:2 note: previous borrow ends here
<anon>:20 fn main() {
...
<anon>:31 }
^
What's going on? Why does the mutable borrow persist after the first call to Foo::add?
The problem comes from the definition of the subscriptions field. It's defined as a Vec<&'a Subscription<'a>>. Satisfying the 'a in Subscription<'a> is easy, since we receive the object with the correct lifetime in add. Satisfying the 'a in &'a ... is harder, since the Subscription<'a> value doesn't have a fixed address until we insert it into subscriptions_map (in my example, a Subscription<'a> is moved from a local variable in main() to a parameter in Foo::add() to inside self.subscriptions_map).
In order to satisfy the outer 'a, Foo::add() must define its self parameter as &'a mut self. If we defined it as &mut self, we couldn't be sure that the references we get out of subscriptions_map would live long enough (their lifetime could be shorter than 'a).
However, by inserting a &'a Subscription<'a> inside of a Foo<'a>, we are effectively locking down the Foo for further modifications, since we are now storing a borrow from self.subscriptions_map in self.subscriptions. Consider what would happen if we inserted another item in subscriptions_map: how can we be sure that the HashMap won't move its items around in memory? If the HashMap does move our item, the pointer in self.subscriptions wouldn't be updated automatically and would be dangling.
Now, suppose that we have this buggy remove() method:
impl<'a> Foo<'a> {
fn remove(&mut self, id: &SubscriptionKey) {
self.subscriptions_map.remove(id);
}
}
This method compiles fine. However, if we tried to call this on a Foo on which we called add() earlier, then self.subscriptions would contain a dangling reference to an item that used to be in self.subscriptions_map.
So the reason why the mutable borrow persists after calling add() is that, since the 'a in Foo<'a> is equal to the lifetime of the Foo<'a> itself, the compiler sees that the object borrows from itself. As you know, we can't have a mutable borrow and another borrow (mutable or not) active at the same time, so Rust prevents us from taking a mutable borrow on f while f itself retains an active borrow. In fact, since we used a method that takes self by mutable reference, Rust assumes that Foo<'a> stores a mutable reference, even though that's not the case, since Rust only looks at the signatures to determine borrows (this is to ensure that changing a private field from &'a T to &'a mut T doesn't cause borrow checking failures to you and, if you're developing a library, to your users). Since the type of an object never changes, the Foo<'a> is locked for the rest of its lifetime.
Now, what can you do? Clearly, you can't usefully have a Vec<&'a Subscription<'a>> in your struct. HashMap provides a values() iterator, but it enumerates the values in an unspecified order, so it won't help you if you want to enumerate the values in the order in which they were added. Instead of using borrowed pointers, you could use Rc:
use std::collections::HashMap;
use std::rc::Rc;
#[derive(Eq, PartialEq, Hash)]
struct SubscriptionKey;
struct Subscription<'a>(&'a ());
struct Foo<'a> {
subscriptions_map: HashMap<SubscriptionKey, Rc<Subscription<'a>>>,
subscriptions: Vec<Rc<Subscription<'a>>>,
}
impl<'a> Foo<'a> {
fn add(&mut self, id: SubscriptionKey, item: Subscription<'a>) {
let item = Rc::new(item);
self.subscriptions_map.insert(id, item.clone());
self.subscriptions.push(item);
}
}
fn main() {
let subscription_data = &();
let mut f = Foo {
subscriptions_map: HashMap::new(),
subscriptions: Vec::new(),
};
f.add(SubscriptionKey, Subscription(subscription_data));
}

Related

error: cannot borrow ... as immutable because it is also borrowed as mutable

I've instantiated a struct result and pass it as mutable ref to another function, that fills this struct with data.
AFTER that, I pass this struct as immutable ref to other functions, to insert the data into a database.
let mut result = indexer::IndexRefreshResultHolder {
putlist: Vec::new(),
dellist: Vec::new(),
};
indexer::refresh_indeces(&mut new_idx_set, old_idx_set_opt, &mut result);
pg::delete_index_rows(&mut tx, &result.dellist).await?;
pg::insert_index_rows(&mut tx, &result.putlist).await?;
Signature of refresh_indeces is like below:
pub fn refresh_indeces<'a>(
new_idx: &'a mut IndexSet,
old_idx_opt: Option<&'a mut IndexSet>,
result: &'a mut IndexRefreshResultHolder<'a>,
) -> Result<(), AppError>
The function takes data from new_idx and old_idx and merges it into result.
Compiler error:
cannot borrow 'result.dellist' as immutable because it is also borrowed as mutable. Same for 'result.putlist'.
I understand that since the struct was mutable borrowed to refresh_indeces it can not be made sure, that data changes afterwards.
My question now is: "How can I make the compiler understand, that result is not changed after refresh_indeces was called" or in other words: "How can result passed as immutable ref again after it was passed once as mutable ref?
Thanks for you help.
Playground
Just use a new scope so the &mut is dropped before the other refs need to be used:
let mut result = indexer::IndexRefreshResultHolder {
putlist: Vec::new(),
dellist: Vec::new(),
};
{
indexer::refresh_indeces(&mut new_idx_set, old_idx_set_opt, &mut result);
}
pg::delete_index_rows(&mut tx, &result.dellist).await?;
pg::insert_index_rows(&mut tx, &result.putlist).await?;
EDIT: Actually your lifetimes are wrong, since they are enforcing to extend a lifetime for the &mut. You can separate them:
fn refresh_indeces<'a, 'b, 'c>(
new_idx: &'a mut IndexSet,
old_idx_opt: Option<&'a mut IndexSet>,
result: &'b mut IndexRefreshResultHolder<'a>,
) -> Result<(), std::io::Error>
Playground
Also, you are creating some temporary references in your playground that will need fixing. And after that another bunch of fixes about ownership will come too
Resolved it by replacing slicing:
result.dellist.extend(old_idx.rows[i_old..].to_vec().iter());
with an iterator:
for row in old_idx.rows.iter().skip(i_old) {
result.dellist.push(row);
}

How to write a function with lifetime constraints for fields?

In the example below, I have a lifetime constraint for the one member. The first call to set_one works, however a second call doesn't:
struct One {
name: String,
}
struct Two<'a> {
one: Option<&'a One>,
}
fn set_one<'a>(two: &'a mut Two<'a>, one: &'a mut One) {
one.name = "something".to_owned();
two.one = Some(one);
}
fn main() {
let mut one = One { name: "".to_owned() };
let mut two = Two { one: None };
set_one(&mut two, &mut one);
set_one(&mut two, &mut one); // error: "two" already borrowed!
}
Playground here.
My understanding is that after the first call to set_one the ownership is given back to the original caller, so when the function returns the borrow for two is gone. But apparently I'm missing something.
What's wrong with the lifetimes of the example above?
For this to make sense you need to recognize that there are 3 lifetimes involved in the calling of set_one
fn set_one<'a, 'b, 'c>(two: &'a mut Two<'b>, one: &'c mut One)
The lifetime of the reference two the lifetime of the reference one and the lifetime of the reference one within Two. These are 'a, 'b and 'c respectively in the signature above.
When you write the signature as
fn set_one<'a>(two: &'a mut Two<'a>, one: &'a mut One)
You are forcing the 3 lifetimes to be the same. And to put it simply this forces these lifetimes to take the 'bigger' lifetime.
Examining the main function:
fn main() {
let mut one = One { name: "".to_owned() }; |
let mut two = Two { one: None }; | Lifetime of 'a
|
set_one(&mut two, &mut one); |
set_one(&mut two, &mut one); |
}
We can see that implicitly now the struct two is a Two<'a> with the lifetime 'a as marked in the code.
Then when we call set_one we force the lifetime of the three parameters to be 'a.
You could declare the lifetimes as:
fn set_one<'a, 'b>(two: &'a mut Two<'b>, one: &'a mut One)
However, this has a problem which is at the root of what you want to do:
fn set_one<'a>(two: &'a mut Two<'a>, one: &'a mut One) {
one.name = "something".to_owned();
two.one = Some(one); // <--- This
}
When you do this two.one = Some(one); you need the reference within Two to live as long as one. Therefore, there is no escaping the fact that you can't call set_one twice because you will need 2 mutable borrows that will live as long as the scope of one in the main function.

Save mutable reference for later even when aliased

I'm trying to implement something like a zipper but taking advantage of mutable references to avoid having to deconstruct and reconstruct the data structure as I move through it. I've got example code for an attempt with a linked list, although I'd ideally like to apply it to other structures, like trees.
pub enum List<T> {
Empty,
Cons { head: T, tail: Box<List<T>> },
}
pub struct Zipper<'a, T: 'a> {
trail: Option<Box<Zipper<'a, T>>>,
focus: &'a mut List<T>,
}
impl<'a, T: 'a> Zipper<'a, T> {
pub fn down(&'a mut self) {
match self.focus {
&mut List::Empty => (),
&mut List::Cons {
tail: ref mut xs, ..
} => {
//We need a way to convince rust that we won't use oldZipper
//until xs goes out of scope
let oldZipper = std::mem::replace(
self,
Zipper {
trail: None,
focus: xs,
},
);
self.trail = Some(Box::new(oldZipper));
}
}
}
}
The borrow checker is not happy with this:
error[E0499]: cannot borrow `*self` as mutable more than once at a time
--> src/main.rs:21:21
|
16 | tail: ref mut xs, ..
| ---------- first mutable borrow occurs here
...
21 | self,
| ^^^^ second mutable borrow occurs here
...
30 | }
| - first borrow ends here
This isn't surprising: if we have a zipper focused on a list and call down on it, we get zipper with a mutable reference to the tail of that list, so we have mutable aliasing.
However, if we never use the Zipper's trail before focus goes out of scope, we'll never be able to "see" the mutable aliasing. This seems analogous to normal mutable borrowing: you can't use the variable you borrowed from until the borrow goes out of scope.
Is there some way to explain this to the borrow checker? If you want to "explain" to the borrow checker that borrowing two non-overlapping slices from an array is okay, you can use split_at: is there some corresponding function that will enforce that trail is never used before focus goes out of scope, and in doing so, satisfies the borrow checker?
In order to achieve your goal, we need to get rid of the mutable reference in the Zipper struct. We can use mutable raw pointers instead: they let us mutate their referent, and we can more than one such pointer pointing at a particular object, but dereferencing them is unsafe.
Here's the code:
use std::mem;
use std::marker::PhantomData;
pub enum List<T> {
Empty,
Cons { head: T, tail: Box<List<T>> },
}
pub struct Zipper<'a, T: 'a> {
trail: Option<Box<Zipper<'a, T>>>,
focus: *mut List<T>,
_list: PhantomData<&'a mut List<T>>,
}
impl<'a, T: 'a> Zipper<'a, T> {
pub fn new(list: &'a mut List<T>) -> Zipper<'a, T> {
Zipper {
trail: None,
focus: list as *mut List<T>,
_list: PhantomData,
}
}
pub fn down(&mut self) {
unsafe {
match *self.focus {
List::Empty => (),
List::Cons {
tail: ref mut xs, ..
} => {
let old_zipper = mem::replace(
self,
Zipper::new(xs),
);
self.trail = Some(Box::new(old_zipper));
}
}
}
}
}
fn main() {
let mut list = List::Cons { head: 1, tail: Box::new(List::Empty) };
let mut zipper = Zipper::new(&mut list);
zipper.down();
zipper.down();
}
The focus field in the Zipper struct is now a *mut List<T>. Because this is a raw pointer, we can copy it around freely. This resolves the compiler error you had in Zipper::down. There's also a new field, _list, of type PhantomData<&'a mut List<T>>. PhantomData is a special type that is meant to tell the compiler "pretend I'm storing/owning a T, even though I'm not". Without this field, the compiler would complain that the lifetime parameter 'a is unused.
Notice that Zipper::new still expects a &'a mut List<T> as a parameter: this allows Zipper to provide a safe interface by requiring the caller to have a unique mutable reference to the List<T>, a fact we can use to declare that the other unsafe operations in the struct are indeed safe since we have full knowledge of the available mutable references. As far as the compiler is concerned, a Zipper is mutably borrowing the List; if you try to mutate a List while a Zipper on the List is in scope, you'll get an error that the List is already mutably borrowed.
You haven't shown any code that would let the user get a reference to the Zipper's focus. I've been thinking of a possible implementation that would be unsafe, and it's tempting to go that route, but the compiler won't tell you it's wrong. Let me show you:
impl<'a, T: 'a> Zipper<'a, T> {
pub fn focus(&mut self) -> &'a mut List<T> {
unsafe { &mut *self.focus }
}
}
It's tempting to return a &'a mut List<T> because that's what we were given. However, it's wrong because the return value's lifetime is not bound to self in any way, which means that we could call focus twice to obtain two mutable references to the same List<T>. If we still had a &'a mut List<T> in Zipper, the compiler would tell us if we tried to return a &'a mut List<T> (unless we used unsafe code to work around it). A correct implementation would be:
impl<'a, T: 'a> Zipper<'a, T> {
pub fn focus(&mut self) -> &mut List<T> {
unsafe { &mut *self.focus }
}
}
In this implementation, the Zipper will be mutably borrowed as long as the returned &mut List<T> is around, which means we can't call focus (or down) until the &mut List<T> goes out of scope.

Why doesn't my struct live long enough?

In Rust, I get the following error:
<anon>:14:9: 14:17 error: `mystruct` does not live long enough
<anon>:14 mystruct.update();
^~~~~~~~
<anon>:10:5: 17:6 note: reference must be valid for the lifetime 'a as defined on the block at 10:4...
<anon>:10 {
<anon>:11 let initial = vec![Box::new(1), Box::new(2)];
<anon>:12 let mystruct = MyStruct { v : initial, p : &arg };
<anon>:13
<anon>:14 mystruct.update();
<anon>:15
...
<anon>:12:59: 17:6 note: ...but borrowed value is only valid for the block suffix following statement 1 at 12:58
<anon>:12 let mystruct = MyStruct { v : initial, p : &arg };
<anon>:13
<anon>:14 mystruct.update();
<anon>:15
<anon>:16 mystruct
<anon>:17 }
error: aborting due to previous error
for the following code:
struct MyStruct<'a>
{
v : Vec<Box<i32>>,
p : &'a i32
}
impl<'a> MyStruct<'a>
{
fn new(arg : &'a i32) -> MyStruct<'a>
{
let initial = vec![Box::new(1), Box::new(2)];
let mystruct = MyStruct { v : initial, p : &arg };
mystruct.update();
mystruct
}
fn update(&'a mut self)
{
self.p = &self.v.last().unwrap();
}
}
fn main() {
let x = 5;
let mut obj = MyStruct::new(&x);
}
(Playground)
I don't understand why mystruct does not live enough. If I comment out the mystruct.update() line it works fine though. What's more is, if I comment out the body of update the code still fails. Why does calling an empty function which borrows a mutable self changes things?
I don't understand which reference is the one the error talks about. Can somebody explain this?
The reference this error talks about is the one which is implicitly created when you call update(). Because update() takes &'a mut self, it means that it accepts a value of type &'a mut MyStruct<'a>. It means that in theory you should call update() like this:
(&mut mystruct).update();
It would be very inconvenient to write this everywhere, and so Rust is able to automatically insert necessary &s, &muts and *s in order to call a method. This is called "autoreference", and the only place it happens is method invocations/field access.
The problem is the definition of update() method:
impl<'a> MyStruct<'a> {
...
fn update(&'a mut self) { ... }
...
}
Here you are requesting that update() receives the value it is called at via a reference with lifetime 'a, where 'a is the lifetime of the reference stored in the structure.
However, when you have a structure value you're calling this method on, there should be already a reference to i32 you stored in this structure. Hence the lifetime of the structure value is strictly smaller than the lifetime designated by the lifetime parameter, so it is just impossible to construct &'a mut MyStruct<'a> with local variables (as in your case).
The solution is to use &mut self instead of &'a mut self:
fn update(&mut self) { ... }
// essentially equivalent to
fn update<'b>(&'b mut self) where 'a: 'b { ... }
// `'b` is a fresh local lifetime parameter
This way the lifetime of the structure in this method call is not tied to the reference this structure contains and can be smaller.
More in-depth explanation follows below.
By itself your definition is not nonsense. For example:
struct IntRefWrapper<'a> {
value: &'a i32
}
static X: i32 = 12345;
static Y: IntRefWrapper<'static> = IntRefWrapper { value: &X };
impl<'a> IntRefWrapper<'a> {
fn update(&'a self) { ... }
}
Y.update();
Here update() invocation won't cause compilation errors because both lifetimes (of Y and of X, reference to which is contained in Y) are 'static.
Let's consider your example, for comparison:
impl<'a> MyStruct<'a> {
fn new(arg : &'a i32) -> MyStruct<'a> {
let initial = vec![Box::new(1), Box::new(2)];
let mystruct = MyStruct { v : initial, p : &arg };
mystruct.update();
mystruct
}
}
Here we have a lifetime parameter, 'a, which is supplied by the caller of the function. For example, the caller could call this function with a static reference:
static X: i32 = 12345;
MyStruct::new(&X); // here &X has static lifetime
However, when update() method is invoked, mystruct lifetime is bounded by the block it is called in:
{
let initial = vec![Box::new(1), Box::new(2)];
let mystruct = MyStruct { v : initial, p : &arg }; // +
// |
mystruct.update(); // |
// |
mystruct // |
}
Naturally, the borrow checker can't prove that this lifetime is the same as the lifetime provided by the caller (and for any possible "external" lifetime it is indeed impossible for them to match), so it throws an error.
When update is defined like this:
fn update(&mut self) { ... }
// or, equivalently
fn update<'b>(&'b mut self) where 'a: 'b { ... }
then when you call it, it is no longer required that the value you call this method on must live exactly as long as 'a - it is sufficient for it to live for any lifetime which is smaller than or equal to 'a - and the lifetime inside the function perfectly matches these requirements. Thus you can call such method on your value, and the compiler won't complain.
Additionally (as noticed in the comments) the following line is indeed invalid and there is no way around it:
self.p = &self.v.last().unwrap();
The borrow check fails here because you're trying to store a reference with lifetime of the structure into the structure itself. In general this can't be done because it has nasty soundness issues. For example, suppose you were indeed able to store this reference into the structure. But now you can't mutate Vec<Box<i32>> in the structure because it may destroy an element which the previously stored references points at, making the code memory unsafe.
It is impossible to check for such things statically, and so it is disallowed on the borrow checking level. In fact, it is just a nice consequence of general borrow checking rules.

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