Confused about borrow [SOLVED]


#1

I am trying to make a simple grep, and I got a error when compile my program.

error[E0597]: `arg` does not live long enough
  --> src/main.rs:11:27
   |
11 |     let cb = get_handler(&arg);
   |                           ^^^ does not live long enough
12 |     test(&cb);
13 | }
   | - borrowed value only lives until here
   |
   = note: borrowed value must be valid for the static lifetime...

It seems to be about borrow, but I passed &arg to function get_handler, it’s a reference, why borrow still here? I am confused.

This is my code
src/main.rs:

extern crate rgrep;
extern crate regex;
use std::io::{self, Read};
use std::path::Path;
use std::fs::{File, read_dir};
use regex::Regex;
use rgrep::Argument;

fn main() {
    let arg = Argument::new().get_arg();
    let cb = get_handler(&arg);
    test(&cb);
}

fn get_handler<'a>(arg: &'a Argument) -> Box<Fn(&Path, &String) + 'a> {
    let string = arg.string.as_str();
    if arg.regex {
        Box::new(move |file: &Path, content: &String| {
            let re = Regex::new(string).unwrap();
            for caps in re.captures_iter(content) {
                println!("in {:?}: {:?}", file, caps);
            }
        })
    } else {
        Box::new(move |file: &Path, content: &String| {
            for line in content.lines() {
                if line.contains(string) {
                    println!("in {:?}: {}", file, line);
                }
            }
        })
    }
}

fn test(cb: &Box<Fn(&Path, &String)>) {
    let path = Path::new("/path/to/file");
    let content = String::from("some text");
    cb(&path, &content);
}

src/lib.rs

extern crate clap;
use clap::{Arg, App};

#[derive(Debug)]
pub struct Argument {
    pub string: String,
    pub file: String,
    pub regex: bool,
    pub iregex: bool,
    pub is_dir: bool
}

impl Argument {
    pub fn new() -> Argument {
        Argument {
            string: String::from(""),
            file: String::from(""),
            regex: false,
            iregex: false,
            is_dir: false
        }
    }

    pub fn get_arg(mut self) -> Self {
        //get program arguments here
        //code ...
        //code ...
        self.string.push_str("pattern");
        self.file.push_str("/path/to/file");
        self.regex = true;
        self.iregex = true;
        self.is_dir = true;
        self
    }
}

#2

The culprit is the signature of the test function. This works:

fn test<'a>(cb: &Box<Fn(&Path, &String) + 'a>)

Trait objects have 'static lifetime bound by default, so your test function is in fact

fn test(cb: &Box<Fn(&Path, &String) + 'static>)

#3

@red75prime Thank you! :grinning: