Need help with lifetime

I am learning rust
I have a struct which has a borrowed field company_name. At first the company_name has borrowed value from old_company_name so the lifetime is set till the old_company_name lives. Then inside a new scope new_company_name variable is defined and i have changed the value of company_name filed to new_company_name now the life time till which the emp will live
is tied with new_company_name, but if i can change the lifetime like this, then on reverting back to the company_name to old_company_name why do I get error ?

rohit@Rohits-MacBook-Air activities % cargo build -q --bin demo2
error[E0597]: new_company_name does not live long enough
--> src/bin/demo2.rs:30:33
|
27 | let new_company_name = String::from("RiRo");
| ---------------- binding new_company_name declared here
...
30 | emp.change_company_name(&new_company_name);
| ^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
...
36 | }
| - new_company_name dropped here while still borrowed
37 | println!("{:?}", old_company_name);
38 | println!("{:?}", emp);
| --- borrow later used here
For more information about this error, try rustc --explain E0597.
error: could not compile activities (bin "demo2") due to 1 previous error

#[derive(Debug)]
struct Employee<'a> {
    name: String,
    company_name: &'a str,
}
impl<'a> Employee<'a> {
    fn change_name(&mut self, name: String) {
        self.name = name
    }
    fn change_company_name(&mut self, new_name: &'a str) {
        self.company_name = new_name;
    }
}

fn main() {
    let name = String::from("Rohit");
    let old_company_name = String::from("RoRi");
    let mut emp = Employee {
        name: name,
        company_name: &old_company_name,
    };

    println!("Working with Old Company ");
    println!("{:?}", emp);

    {
        let new_company_name = String::from("RiRo");

        emp.change_name(String::from("Riya"));
        emp.change_company_name(&new_company_name);

        println!("{:?}", emp);
        
        emp.change_company_name(&old_company_name);
        // new_company name scope end here
    }
    println!("{:?}", old_company_name);
    println!("{:?}", emp);
}

I tried asking chatgpt and here the reponse

3. Main Flow

let name = String::from("Rohit Singh");
let old_company_name = String::from("RoRi");
let mut emp = Employee {
    name: name,
    company_name: &old_company_name,
};

Here:

  • emp has lifetime 'a referring to old_company_name.
  • Both live in the outer scope, so all good.

4. Temporary Borrowing Problem

{
    let new_company_name = String::from("RiRo");
    emp.change_name(String::from("Riya"));
    emp.change_company_name(&new_company_name);

At this moment:

  • emp.company_name points to new_company_name.
  • new_company_name will be dropped at the end of this inner block.

If you didn’t change it back before leaving the scope, emp would end up holding a dangling reference after new_company_name is dropped.
That’s why Rust would complain — it enforces lifetime safety at compile time.


5. Why Your “Fix” Works

emp.change_company_name(&old_company_name);

This resets emp.company_name to reference a variable that lives as long as emp.
Now, when new_company_name is dropped, emp no longer depends on it, so there’s no lifetime conflict.

Don't put temporary loans in structs. This is a design error in almost all cases of regular structs that are supposed to hold data.

& forbids storing data. It's not a general-purpose thing for storing data "by reference". It's a special construct that means the Employee<'temporary> doesn't hold a company name, and it's not a normal struct, but a temporary view into data stored elsewhere. Due to use of &, it will never be freely usable outside of the function or scope where the data has been borrowed.

Use String for a real non-temporary string, or Rc<str> for a shared reference to string data without imposing a temporary scope restriction on the type and everything that has it.

4 Likes

Thankyou for clearing my doubt :smiley:

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.