简体   繁体   中英

How do I return a reference to a closure's argument from the closure?

I am a Rust newbie, and don't understand all the rules for lifetime elision and inference. I can't seem to get returning a reference into an argument from a closure to work, and the errors don't help much for someone with my amount of knowledge.

I can use a proper function with lifetime annotations in place of a closure, but can't figure out a way to annotate these lifetimes on the closure.

struct Person<'a> {
    name: &'a str,
}

impl<'a> Person<'a> {
    fn map<F, T>(&'a self, closure: F) -> T
        where F: Fn(&'a Person) -> T
    {
        closure(self)
    }
}

fn get_name<'a>(person: &'a Person) -> &'a str {
    person.name
}

fn main() {
    let p = Person { name: "hello" };
    let s: &str = p.map(|person| person.name); // Does not work
    // let s: &str = p.map(get_name);  // Works
    println!("{:?}", s);
}

And here is the compiler error:

error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
  --> src/main.rs:19:34
   |
19 |     let s: &str = p.map(|person| person.name); // Does not work
   |                                  ^^^^^^^^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the body at 19:33...
  --> src/main.rs:19:34
   |
19 |     let s: &str = p.map(|person| person.name); // Does not work
   |                                  ^^^^^^^^^^^
note: ...so that expression is assignable (expected &str, found &str)
  --> src/main.rs:19:34
   |
19 |     let s: &str = p.map(|person| person.name); // Does not work
   |                                  ^^^^^^^^^^^
note: but, the lifetime must be valid for the method call at 19:18...
  --> src/main.rs:19:19
   |
19 |     let s: &str = p.map(|person| person.name); // Does not work
   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that pointer is not dereferenced outside its lifetime
  --> src/main.rs:19:19
   |
19 |     let s: &str = p.map(|person| person.name); // Does not work
   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^

What is happening here, and how to change the closure for it to work?

I think I was confusing the lifetime of reference to the Person with the lifetime parameter of the struct (of the &str reference). This compiles:

struct Person<'a> {
    name: &'a str,
}

impl<'a> Person<'a> {
    fn map<F, T>(&self, closure: F) -> T
        where F: Fn(&Person<'a>) -> T
    {
        closure(self)
    }
}

fn get_name<'a>(person: &Person<'a>) -> &'a str {
    person.name
}

fn main() {
    let p = Person { name: "hello" };
    println!("{:?}", p.map(|person| person.name));
    println!("{:?}", p.map(get_name));
}

I'm not sure if my understanding of the lifetime annotations is correct, and perhaps someone else can pick apart the compiler error above. The language is extremely confusing.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM