Skip to content

mistake in section 11.3.4 concerning elision in impl blocks of types with lifetime parameters #12

@Morgane55440

Description

@Morgane55440

the first block of section 11.3.4 starts as follows :

// An Excerpt struct holding a reference to a part of a string ('str').
// The lifetime parameter 'a is declared on the struct name.
struct Excerpt<'a> {
    // The 'part' field holds a reference tied to the lifetime 'a.
    // This means the data referenced by 'part' must live at least as long as 'a.
    part: &'a str,
}

// When implementing methods for a struct with lifetimes, declare them after 'impl'.
impl<'a> Excerpt<'a> {
    // Method returning the held reference.
    // Lifetime elision rule #3 applies because of '&self'.
    // The return type implicitly gets the lifetime of '&self', which is 'a.
    fn get_part(&self) -> &str { // Implicitly -> &'a str
        self.part
    }
}

the explanation on get_part is incorrect.
it is correct that elision rule #3 applies, but that does not result in 'a at all.
the full explicit signature would be

 fn get_part<'b>(self : &'b Excerpt<'a>) -> &'b str {
        self.part
    }

in fact, writing

 fn get_part_long(&self) -> &'a str {
        self.part
   }
// i.e. : 
 fn get_part_long<'b>(self : &'b Excerpt<'a>) -> &'a str {
        self.part
   }

instead is possible (here part is simply copied), and leads to very different behavior.

fn main() {
    let novel = String::from("Call me Ishmael. Some years ago...");
    let mut i = Excerpt { part: &novel };
    
    let part = i.get_part_long(); // fails to compile with `get_part`, 

    drop(i);
   
    println!("Excerpt part: {part }");
}

this is why i would always recommend to write get_part_long over get_part (as it is a strictly superior version) , unless you have a good reason not to. this of course only applies to immutable references which may be copied.

as to how to fix it, i'm not sure if the full explanation that i gave would be useful, but at leas saying that the lifetime of self and 'a are different would t be an improvement.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions