SoFunction
Updated on 2025-03-10

Analyze the life cycle in Rust struct

Recently, I am writing a redis data verification tool using rust. redis-rs has redis::ConnectionLike trait, which can better abstract the verification process. In development, it is inevitable to define some elements in struct as trait object, which brings about life cycle problems in the rust language.
This article will not discuss the data verification process of redis in detail, but will use a simple example to talk about the life cycle of the trait object element in struct.

First, define a base trait, which contains only one function and returns the String type.

pub trait Base {
    fn say(&self) -> String;
}

Next, define two structs AFromBase and BFromBase that implement Base trait

pub struct AFromBase {
    content: String,
}

impl Base for AFromBase {
    fn say(&self) -> String {
        ()
    }
}

pub struct BFromBase {
    text: String,
}

impl Base for BFromBase {
    fn say(&self) -> String {
        ()
    }
}

Next, define a trait object containing two Base traits, and then implement a function that is the splicing result of the string output by the say function.
According to other writing habits without life cycle languages, I intuitively write this

pub struct AddTowBase {
    a: &mut dyn Base,
    b: &mut dyn Base,
}

impl AddTowBase {
    fn add(&self) -> String {
        let result = () + &();
        result
    }
}

Finally, make a main function to verify it.
The complete code is as follows

pub trait Base {
    fn say(&self) -> String;
}

pub struct AFromBase {
    content: String,
}

impl Base for AFromBase {
    fn say(&self) -> String {
        ()
    }
}

pub struct BFromBase {
    text: String,
}

impl Base for BFromBase {
    fn say(&self) -> String {
        ()
    }
}

pub struct AddTowBase {
    a: &mut dyn Base,
    b: &mut dyn Base,
}

impl<'a> AddTowBase<'a> {
    fn add(&self) -> String {
        let result = () + &();
        result
    }
}

fn main() {
    let mut a = AFromBase {
        content: "baseA".to_string(),
    };

    let mut b = BFromBase {
        text: "baseB".to_string(),
    };

    let addtow = AddTowBase {
        a: &mut a,
        b: &mut b,
    };
    let r = ();
    println!("{}", r);
}

Unfortunately, the above code cannot be compiled and passed, and the following error is reported in the compilation time.

error[E0106]: missing lifetime specifier
  --> examples/:26:8
   |
26 |     a: &mut dyn Base,
   |        ^ expected named lifetime parameter
   |
help: consider introducing a named lifetime parameter
   |
25 ~ pub struct AddTowBase<'a> {
26 ~     a: &'a mut dyn Base,
   |

error[E0106]: missing lifetime specifier
  --> examples/:27:8
   |
27 |     b: &mut dyn Base,
   |        ^ expected named lifetime parameter
   |
help: consider introducing a named lifetime parameter
   |
25 ~ pub struct AddTowBase<'a> {
26 |     a: &mut dyn Base,
27 ~     b: &'a mut dyn Base,
   |

For more information about this error, try `rustc --explain E0106`.
error: could not compile `wenpan-rust` due to 2 previous errors

The prompt given by the compiler is very clear. Add lifecycle parameters to the trait object, make sure that the struct and its trait object element are in the same life cycle, and avoid hanging pointers.
We follow the compiler's prompt to modify the code

pub struct AddTowBase<'a> {
    a: &'a mut dyn Base,
    b: &'a mut dyn Base,
}

impl<'a> AddTowBase<'a> {
    fn add(self) -> String {
        let result = () + &();
        result
    }
}

The code was compiled smoothly.
The life cycle of rust ensures memory security and also increases the mental burden on developers. Is it a trade off problem to write code before going online, or to search for problems after going online? As the saying goes, "I am just as heavy as I hold my back." I myself tend to control the problem before going online and make less trouble for users.

This is the end of this article about the life cycle in Rust struct. For more related content on Rust struct life cycle, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!