"closure may outlive current function" but shouldn't


#1

All of the three alternatives in the following code give the error “closure may outlive current function” for each of the closures called process. Can someone explain the reason why all of them outlive the current function main?

type MyFn = FnMut();

trait DoesWork {
    fn work(&self, f: &mut MyFn);
}

struct Abc;

impl DoesWork for Abc {
    fn work(&self, f: &mut MyFn) {
      for _ in 0..5 {
        f();
      }
    }
}

impl Abc {
    fn work_no_env(f: &mut MyFn) {
      for _ in 0..5 {
        f();
      }
    }
}

fn global_work_no_env(f: &mut MyFn) {
  for _ in 0..5 {
    f();
  }
}

fn main() {
    let mut v = Vec::<String>::new();

    {
        let mut process = || {
            v.push("A".to_string());
        };
        global_work_no_env(&mut process);
    }

    {
        let mut process = || {
            v.push("A".to_string());
        };
        Abc::work_no_env(&mut process);
    }

    {
        let abc = Abc{};
        let mut process = || {
            v.push("A".to_string());
        };
        abc.work(&mut process);
    }
    println!("v={:?}", v);
}

#2

I think there’s an implicit 'static here. Try:

type MyFn<'a> = FnMut() + 'a;

#3

Also, if you didn’t intend to use trait objects with dynamic dispatch, you probably want to write this like this:

fn global_work_no_env<F: FnMut()>(f: &mut F) {
  for _ in 0..5 {
    f();
  }
}

and so forth.


#4

I wasn’t aware of the implicit static lifetime, and the error message isn’t really helpful. Hope this thread will help some more people later on :slight_smile:


#5

I agree. You could check there is already an issue open for that at https://github.com/rust-lang/rust and otherwise open one.


#6

Here goes the new issue: