Reputation: 20422
Here is the code (with a Rust beginner difficulty):
use std::cell::RefCell;
use std::collections::HashMap;
pub trait TIndex<'a> {
// cut
}
pub struct HashMapIndex<'a> {
pub filter_by_keyword: HashMap<String, &'a str> // simplified (and ugly)
}
impl<'a> TIndex<'a> for HashMapIndex<'a> {
// cut
}
pub struct Matcher<'a> {
pub index: &'a RefCell<Box<dyn TIndex<'a> + 'a>>
}
impl<'a> Matcher<'a> {
pub fn new(index: &'a RefCell<Box<dyn TIndex<'a> + 'a>>) -> Self {
Matcher {
index
}
}
}
pub fn main() {
let index = HashMapIndex {
filter_by_keyword: HashMap::new()
};
let boxed_index: Box<dyn TIndex> = Box::new(index);
let refcell = RefCell::from(boxed_index);
let mut _matcher = Matcher::new(
&refcell // `refcell` does not live long enough
);
}
I'm not sure i understand what is wrong (but something is definitely).
'a
is a main()
function scope here, index
and refcell
live until main() exits. matcher
accepts a reference to RefCell
that lives at least 'a
and references to a box that lives at least 'a
and point to a TIndex
trait object that lives at least 'a
and whose internals live at least 'a
.
How should it be changed (and what's wrong in lifetimes declarations here)?
PS. I'm getting a compiler hint (at main()
closing }
):
}
| -
| |
| `refcell` dropped here while still borrowed
| borrow might be used here, when `refcell` is dropped and runs the destructor for type `RefCell<Box<dyn TIndex<'_>>>`
not sure i understand it as refcell
is passed by reference (borrowed by _matcher
).
Upvotes: 1
Views: 165
Reputation: 42492
not sure i understand it as refcell is passed by reference (borrowed by _matcher).
The problem is that you're defining Matcher
such that the lifetimes of the RefCell
and the lifetime of the contents of the RefCell
must be the same.
This means you're telling rustc the RefCell
must live as long what it contains, meaning once you've put the RefCell
inside the Matcher
... your program can't work anymore, because a container can't rightly outlive its contents.
You need to split your lifetimes so rustc knows how they nest, at the very least you need to give a different lifetime to the &RefCell
and its contents -- and tell rustc that the contents outlive the &RefCell
:
pub struct Matcher<'a, 'b> {
pub index: &'a RefCell<Box<dyn TIndex<'b> + 'b>>
}
impl<'a, 'b: 'a> Matcher<'a, 'b> {
pub fn new(index: &'a RefCell<Box<dyn TIndex<'b> + 'b>>) -> Self {
Matcher {
index
}
}
}
It might also be a good idea to split the lifetime parameter of the TIndex
and the lifetime bound of the TIndex
(the contents of the TIndex should outlive it), but it doesn't seem necessary for the repro you've posted here.
Upvotes: 2