I don't completely understand lifetimes, but I think b
's lifetime will end before self
's.
So, how to edit this code? Do I copy something in memory? If I make a new instance, this lifetime must adhere to this case.
pub struct Formater {
layout: &'static str,
}
impl Formater {
pub fn new(layout: &'static str) -> Formater {
let regex = Regex::new(r"%\{([a-z]+)(?::(.*?[^\\]))?\}").unwrap();
let b = regex.replace_all(layout, "{}");
return Formater {
layout: &b,
};
}
}
The 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...
The scope of
b
is thenew
function, so its memory will be freed when the function returns. But you are trying to return a reference tob
from that function. If Rust let you do this, the only code that could possibly use that reference would use it after the value is invalid. The borrow checker is protecting you from undefined behaviour.Making
layout
to be&'static str
sounds like you are making things simple, but it is unreasonable to expect the dynamically allocated memory fromregex.replace_all
to be static. Without getting intounsafe
code, you should consider anything in the'static
lifetime to be a compile-time constant. For example, a string literal.As others have said, you probably want
layout
to be aString
. AString
is similar to&str
, but it owns the underlyingstr
. That means when you move theString
, the underlyingstr
moves with it. A&str
is a reference and must not outlive the owner of thestr
that it points to.If you really want it to be
&str
, an alternative but less ergonomic approach is to have the caller ofnew()
own the&str
, and pass it in as a mutable reference.This moves the problem one layer up the call stack and means that the reference you pass to
new
will be mutated bynew
.Now
s
is owned bymain
, soformatter
is valid as long as it is used only in a smaller scope thanmain
.But overall, I think this method is messier and you should just stick with
String
unless you have a good reason.