About capturing arguments and annotation in closure

#[test]
    fn read_test() {

        let mut f = BufReader::new(
            File::open("/home/ssss/.bashrc").unwrap()
        );

        let mut buf = Vec::with_capacity(8192);

        let r = |f: &mut BufReader<File>, buf:&mut Vec<u8>| f.by_ref().take(1024).read_to_end(buf).map(|n| {
            println!("n={}", n);
            n > 0
        });

        // r(&mut f, &mut buf);
        // r(&mut f, &mut buf);

        while let Ok(true) = r(&mut f, &mut buf) {
            println!(">>\n{}\n<<", String::from_utf8_lossy(&buf));
            buf.clear();
        }
    }

Hi.
Today I found something that made me wonder why.

In the above code works, but when removing the type annotation of buf in the closure, compiler says mutable borrow occur more than once

What is the difference between having and not having a type annotation in closure capturing?

I believe this is because type annotations in function arguments are implicitly translated into HRTBs. I.e., for some function-like type or trait, fn(&T) -> U actually means for<'a> fn(&'a T) -> U. This is an intentional special case in the language, because this is what you want most of the time.

In contrast, if you omit the annotation, the closure argument will be inferred to have a single type, with a specific, fixed lifetime. That lifetime will be inferred from the context (e.g., scope of the borrowed buf, or the lifetime of the closure itself, or something like that – I'm not actually sure), and this is probably what will lead to the "first borrow used here, in later iteration of loop" error.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.