While I understand why the compiler doesn't like the last statement in this code:
struct Person<'a> {
name: &'a str,
}
impl<'a> Person<'a> {
pub fn replace_name(&mut self, newname: &'a str) {
self.name = newname;
}
}
#[test]
fn test_person() {
let firstname = "John".to_string();
let mut p = Person { name: &firstname };
assert_eq!(p.name, "John");
{
let newname = "Bob".to_string();
p.replace_name(&newname);
assert_eq!(p.name, "Bob");
p.replace_name(&firstname);
}
// This will fail because the lifetime of newname is shorter than p:
//assert_eq!(p.name, "John");
}
How can I tell it that it's OK because I replaced the newname
with firstname
?
While I understand why the compiler doesn't like the last statement in this code:
struct Person<'a> {
name: &'a str,
}
impl<'a> Person<'a> {
pub fn replace_name(&mut self, newname: &'a str) {
self.name = newname;
}
}
#[test]
fn test_person() {
let firstname = "John".to_string();
let mut p = Person { name: &firstname };
assert_eq!(p.name, "John");
{
let newname = "Bob".to_string();
p.replace_name(&newname);
assert_eq!(p.name, "Bob");
p.replace_name(&firstname);
}
// This will fail because the lifetime of newname is shorter than p:
//assert_eq!(p.name, "John");
}
How can I tell it that it's OK because I replaced the newname
with firstname
?
1 Answer
Reset to default 1The way to solve this for the code you're actually showing is to copy or borrow Person
to make a new local Person
with a shorter lifetime:
impl Person<'_> {
pub fn shorten(&self) -> Person<'_> {
Person { name: self.name }
}
}
let firstname = "John".to_string();
let mut person = Person { name: &firstname };
assert_eq!(person.name, "John");
{
let newname = "Bob".to_string();
let mut new_person = person.shorten();
new_person.replace_name(&newname);
}
assert_eq!(person.name, "John");
This doesn't mutate the original person, but instead creates a different person that borrows the original one that can be mutated with local data. At the end of the {}
local scope, the new person is dropped, and the old person still exists, with the old data and longer lifetime.
I don't know for sure if this solves whatever actual use-case you have, but for the sample code you've posted it neatly resolves this issue.
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745117601a4612222.html
replace_name()
could containif rng.gen::<bool>() { self.name = newname }
. In other words, given the signature ofreplace_name()
, there is no guarantee that it's safe to lengthen the lifetime to that offirstname
. For this to work,replace_name()
should consumeself
and return one with a new lifetime: play.rust-lang./… – user4815162342 Commented Mar 2 at 21:45