The volume b is the new function, so its memory will be freed when the function returns. But you are trying to return a link to b from this function. If Rust allows you to do this, the only code that can use this link will use it after the value is invalid. The borrow controller protects you from undefined behavior.
Creating a layout for &'static str sounds like you are doing everything simple, but it is unreasonable to expect that the dynamically allocated memory from regex.replace_all will be static. Without going into unsafe code, you should consider anything in 'static lifetime 'static compile-time constant. For example, a string literal.
As others have said, you probably want layout be String . A String is like &str , but it owns the base str . This means that when you move a String base str moves with it. A &str is a reference and should not worry about the str owner that it points to.
If you really want it to be &str , an alternative but less ergonomic approach should have the &str owner calling new() and pass it as a mutable reference.
pub struct Formatter<'a> { layout: &'a str, } impl <'a> Formatter<'a> { pub fn new(layout: &'a mut &str) -> Formatter<'a> { let regex = Regex::new(r"%\{([az]+)(?::(.*?[^\\]))?\}").unwrap(); *layout = regex.replace_all(layout, "{}"); return Formatter { layout: layout, }; } }
This moves the problem one level up the call stack and means that the link you pass to new will be mutated with new .
pub fn main() { let mut s = "blah %{blah}"; { let formatter = Formatter::new(&mut s); println!("{:?}", formatter.layout); // "blah {}" } println!("{:?}", s); // "blah {}" }
Now s belongs to main , so formatter valid as long as it is used only to a lesser extent than main .
But overall, I think this method is more messy, and you should just stick with String unless you have a good reason.