The value is not long enough

I don’t quite understand the times of life, but I think that b all life will end before self "s.

So how to edit this code? Do I copy anything to memory? If I make a new instance, this lifetime should be appropriate for this case.

 pub struct Formater { layout: &'static str, } impl Formater { pub fn new(layout: &'static str) -> Formater { let regex = Regex::new(r"%\{([az]+)(?::(.*?[^\\]))?\}").unwrap(); let b = regex.replace_all(layout, "{}"); return Formater { layout: &b, }; } } 

Error:

 error: 'b' does not live long enough --> src/format.rs:16:22 | 16 | layout: &b, | ^ does not live long enough 17 | }; 18 | } | - borrowed value only lives until here | = note: borrowed value must be valid for the static lifetime... 
+9
source share
1 answer

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.

+8
source

Source: https://habr.com/ru/post/1264818/


All Articles