首页 > 解决方案 > 闭包不能返回引用吗?

问题描述

fn main() {
    let a = String::from("foo");
    let f = || &a;
    fn_immut(f);
    println!("{}", a);
}

fn fn_immut<F>(f: F)
               where F: Fn() -> &String
{
    println!("calling Fn closure from fn, {}", f());
}

这段代码无法编译,rustc告诉我应该添加这样的代码'static

fn fn_immut<F>(f: F)
               where F: Fn() -> &'static String

我试图这样做,但它仍然不起作用。并且rustc还告诉我“这个函数的返回类型包含一个借来的值,但没有可以借用的值”。

我的问题是:在这段代码中,闭包已经a在其范围内捕获了变量的引用,为什么 rustc 仍然告诉我“它没有借用的价值”?

标签: rust

解决方案


来自编译器的关键信息确实是缺少返回字符串的闭包的生命周期说明符。由于特征定义的签名Fn() -> &String没有任何函数参数,因此编译器无法从中推断返回引用的生命周期。

error[E0106]: missing lifetime specifier
  --> src/main.rs:10:16
   |
10 |     F: Fn() -> &String,
   |                ^ help: consider giving it a 'static lifetime: `&'static`
   |
   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from

在此处添加'static无助于解决问题,因为实际上返回的字符串不会有那个生命周期。需要在 中引入一个新的生命周期参数fn_immut,从该参数可以转移到F的约束。

fn fn_immut<'a, F>(f: F)
where
    F: Fn() -> &'a String,

您还可以返回字符串切片 ( &str) 而不是&String. 完整代码:

fn main() {
    let a = String::from("foo");
    let f = || &*a;
    fn_immut(f);
    println!("{}", a);
}

fn fn_immut<'a, F>(f: F)
where
    F: Fn() -> &'a str,
{
    println!("calling Fn closure from fn, {}", f());
}

操场


推荐阅读