Hi all,
I am unable to understand a problem that I have encountered in a library that I am writing and am hoping that someone will be able to help me.
Below I have produced what I think is a minimal example that reproduces the problem. My library provides two traits, Plugin
and PluginError
. These traits should be implemented for custom types that are provided by authors who are writing plugin implementations in separate libraries. To make it easier for plugin authors, I want to provide default implementations of a few methods. In the example below, I provide a default implementation of the method named attribute_name
.
Minimal example
The example may be found both below and at the playground here: Rust Playground
use std::{
cell::{Ref, RefCell},
error::Error,
ffi::CString,
rc::Rc,
};
type Attributes<T, E> = Rc<RefCell<Vec<Attribute<T, E>>>>;
struct Attribute<T, E> {
name: CString,
callback: fn() -> Result<T, E>,
}
trait PluginError: Error {
fn new() -> Self;
}
trait Plugin<E: PluginError>
where
Self: Sized,
{
fn attributes(&self) -> Attributes<Self, E>;
fn attribute_name(&self, id: usize) -> Result<Ref<CString>, E> {
let attributes = self.attributes().borrow();
// I'm not sure how to do the bounds check here so I index twice
// into the attributes Vec. I don't think that this is pertinent.
match attributes.get(id) {
Some(_) => Ok(Ref::map(attributes, |a| &a[id].name)),
None => Err(E::new()),
}
}
}
Error returned by the compiler
The following error message is repeated ~8 times before compilation outright fails.
error[E0311]: the parameter type `E` may not live long enough
--> src/main.rs:26:26
|
26 | let attributes = self.attributes().borrow();
| ^^^^^^^^^^^^^^^^^
|
= help: consider adding an explicit lifetime bound for `E`
note: the parameter type `E` must be valid for the anonymous lifetime #1 defined on the method body at 25:5...
--> src/main.rs:25:5
|
25 | / fn attribute_name(&self, id: usize) -> Result<Ref<CString>, E> {
26 | | let attributes = self.attributes().borrow();
27 | | // I'm not sure how to do the bounds check here so I index twice into
28 | | // the attributes Vec. I don't think that this is pertinent.
... |
32 | | }
33 | | }
| |_____^
note: ...so that the type `std::rc::Rc<std::cell::RefCell<std::vec::Vec<Attribute<Self, E>>>>` is not borrowed for too long
--> src/main.rs:26:26
|
26 | let attributes = self.attributes().borrow();
| ^^^^^^^^^^^^^^^^^
Could anyone provide an explanation of what I am doing wrong and how I might fix the problem? I suspect that there is a lifetime that is associated with the Ref
that is returned by the attribute_name
function and this is somehow conflicting another lifetime, but I have made little progress in even understanding what the issue is.
Thanks a lot!