Lifetime in impl

pub struct FileRDD<'a> {
    sc: &'a SwiftContext,
    path: String,
}

impl<'a> FileRDD<'a> {
    pub fn new(para_sc: & SwiftContext, para_path: String) -> FileRDD { // this define
        FileRDD {sc: para_sc, path: para_path}
    }
}

pub struct SwiftContext {
    name: String,
}

the above code can pass, but What's the difference between the following code?

pub fn new(para_sc: &'a  SwiftContext, para_path: String) -> FileRDD 

pub fn new<'b>(para_sc: &'b SwiftContext, para_path: String) -> FileRDD {

According the rules: "Any reference being returned must have the same lifetime as an input or be static", so the lifetime of return type is always with para_sc? Is there any relationship between lifetime 'a and lifetime 'b ?

2 Likes

For clearness, after applying lifetime elision rules the signatures are

pub fn new(para_sc: &'a SwiftContext, para_path: String) -> FileRDD<'a>

pub fn new<'b>(para_sc: &'b SwiftContext, para_path: String) -> FileRDD<'b>
// which is the same as the original
pub fn new(para_sc: &SwiftContext, para_path: String) -> FileRDD

Since the 'b variant doesn't reference 'a and neither lifetime is constrained, they're equivalent.

This seeming redundancy disappears when you implement a method (it's easier to demonstrate with a mutable borrow of self):

impl<'a> FileRDD<'a> {
    pub fn sc<'b>(&'b mut self) -> &'a SwiftContext {
        // What is the type of `self`? It's `&'b mut FileRDD<'a>`
        // Changing 'a to 'b will break the code in main.
        &self.sc
    }
}

fn main(){
    let ctxt = SwiftContext { name: String::new() };
    let mut f = FileRDD { // 'a is approximately the lifetime of ctxt
        sc: &ctxt,
        path: String::new(),
    };
    let c1 = f.sc(); // 'b is just this statement; c1 is &'a SwiftContext
    let c2 = f.sc(); // ditto
}
2 Likes

Thanks for your reply! I got it, especially the wonderful example code.

It really made sense here, If 'b is removed from sc, it throws an error of multiple mutable references in the scope by inheriting 'a lifetime. So, the mutability has to be contained inside function definition itself allowing controlled mutability one after other.