This code is simplest thing that illustrates my problem. After almost 2 days I cant get the compiler to accept this, and yet the idea is quite simple;
- pass an element, containing a string slice, into a Doc constructor
- the string slice is copied into a string 'owned' by the doc and a new slice created accordingly
- add the new slice into the doc.elements vector
..all lifetimes are the same indicating there cannot be any dangling references
pub type Element<'a> = Option<&'a str>;
pub type Elements<'a> = Vec<Element<'a>>;
pub type ElementIndex = usize;
pub struct Doc<'a> {
pub xml_doc: String,
pub strings: Vec<String>,
pub elements: Elements<'a>,
}
impl<'a> Doc<'a> {
pub fn new_element(&mut self, mut el: Element<'a>) -> ElementIndex {
let index: ElementIndex = self.elements.len();
if let Some(text_val) = el {
let text_val = String::from(text_val);
let idx = self.strings.len();
self.strings.push(text_val);
el = Some(self.strings[idx].as_str());
}
self.elements.push(el);
index
}
pub fn new_with_capacity(xml_doc: String, capacity: usize) -> Self {
let mut doc = Doc {
xml_doc,
strings: Vec::new(),
elements: Vec::with_capacity(capacity),
};
doc.new_element(Some("[document]"));
doc
}
}
pub fn main() {
Doc::new_with_capacity(String::from("example"), 1024);
}
here is the project on rust playground or repl.it if you prefer
I'm getting this compile error;
error[E0505]: cannot move out of
doc
because it is borrowed
--> src/main.rs:35:9
|
11 | impl<'a> Doc<'a> {
| -- lifetime'a
defined here
...
29 | let mut doc = Doc { // possibly remove mut and line below
| ------- bindingdoc
declared here
...
34 | doc.new_element(Some("[document]")); // possibly remove this line
| --- borrow ofdoc
occurs here
35 | doc
| ^^^
| |
| move out ofdoc
occurs here
| returning this value requires thatdoc
is borrowed for'a
Why does the borrow last beyond line 34? Note, cloning Doc is not an option.
The interesting thing is that if I remove line 34 and the 'mut' on line 29 and add in line 41 in the main function.. it compiles! But if I then try to turn main() into a Doc constructor within the Doc impl, eg;
pub fn main() -> Self {
let mut doc = Doc::new_with_capacity(String::from("example"), 1024);
doc.new_element(Element::new_node("[document]", ""));
doc
}
the same problem comes back.
I suspect the lifetime annotations on lines 11 to 14, but after 2 days of trying I can find no combinations of anything that works. I also checked the Polonius problem cases but they don't seem to apply here. Is this an 'arena' issue?