The borrow checker is correct, your code is not actually safe. Imagine this:
let mut info = build(String::from_str("this is a test")); info.text = String::from_str("this assignment drops the original string"); info.fields[0]; // Accesses freed memory. The thing is that `Info.text` is not guaranteed to live as long as `Info`. If you change the type of `Info.text` and the argument of `build` to `&'a str` and pass "this is a test" everything works nicely. I suppose it would be safe if you could convince the compiler that `Info.text` cannot change but there is only inherited immutability so that does not work. You could do something with arenas; by only having a borrowed reference to `Info` the compiler should ensure that you do not sneakily change either `Info.text` or 'Info.fields`. ---------------------------------------------------------------------- extern crate arena; fn main() { let ref ar = arena::Arena::new(); let info = build(ar, "this is a test"); println!("{}", info.fields[0]); } struct Info<'a> { text: &'a String, fields: Vec<&'a str>, } fn build<'a>(ar: &'a arena::Arena, text: &str) -> &'a Info<'a> { ar.alloc(||{ let mut result = Info { text: ar.alloc(||String::from_str(text)), fields: vec![], }; result.fields = result.text.as_slice().split(' ').collect(); result }) } ---------------------------------------------------------------------- On Wed, Aug 13, 2014 at 7:45 AM, David Brown <dav...@davidb.org> wrote: > I'm trying to figure out how to get something like this to compile. > What I want is a struct that owns a string as well as contains > structures containing slices of that string. My real use case is more > complicated, but it seems to boil down easily to this. > > This gives me an error: > > life.rs:16:21: 16:32 error: `result.text` does not live long enough > life.rs:16 result.fields = result.text.as_slice().split(' > ').collect(); > ^~~~~~~~~~~ > life.rs:13:40: 19:2 note: reference must be valid for the lifetime 'a as > defined on the block at 13:39... > life.rs:13 fn build<'a>(text: String) -> Info<'a> { > life.rs:14 let mut result = Info { text: text, fields: Vec::new() }; > life.rs:15 life.rs:16 result.fields = result.text.as_slice().split(' > ').collect(); > life.rs:17 life.rs:18 result > ... > life.rs:13:40: 19:2 note: ...but borrowed value is only valid for the > block at 13:39 > life.rs:13 fn build<'a>(text: String) -> Info<'a> { > life.rs:14 let mut result = Info { text: text, fields: Vec::new() }; > life.rs:15 life.rs:16 result.fields = result.text.as_slice().split(' > ').collect(); > life.rs:17 life.rs:18 result > ... > > Is there a way to do this, or do I need to allocate strings for the > copies of the individual slices? > > Thanks, > David Brown > > ---------------------------------------------------------------------- > // life.rs > > fn main() { > let info = build(String::from_str("this is a test")); > println!("{}", info.fields[0]); > } > > struct Info<'a> { > text: String, > fields: Vec<&'a str>, > } > > fn build<'a>(text: String) -> Info<'a> { > let mut result = Info { text: text, fields: Vec::new() }; > > result.fields = result.text.as_slice().split(' ').collect(); > > result > } > ---------------------------------------------------------------------- > _______________________________________________ > Rust-dev mailing list > Rust-dev@mozilla.org > https://mail.mozilla.org/listinfo/rust-dev >
_______________________________________________ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev