rust - 如何检查 `impl Trait` 类型的返回值借用检查?

标签 rust borrow-checker

以下代码无法编译:

fn foo<'a, F: Fn() -> &'a str>(vec: Vec<i32>, fun: F) -> impl Iterator<Item = i32> {
    println!("{}", fun());
    vec.into_iter()
}

fn main() {
    let s = "hello, world!".to_string();
    let iter = foo(vec![1, 2, 3], || &s);
    drop(s);

    for x in iter {
        println!("{}", x);
    }
}
error[E0505]: cannot move out of `s` because it is borrowed
  --> src/main.rs:9:10
   |
8  |     let iter = foo(vec![1, 2, 3], || &s);
   |                                   --  - borrow occurs due to use in closure
   |                                   |
   |                                   borrow of `s` occurs here
9  |     drop(s);
   |          ^ move out of `s` occurs here
10 | 
11 |     for x in iter {
   |              ---- borrow later used here
如果我替换 foo,它会编译的签名与
fn foo<'a, F: Fn() -> &'a str>(vec: Vec<i32>, fun: F) -> <Vec<i32> as IntoIterator>::IntoIter {
    // ...
}
这让我相信 impl Trait类型的借用检查更为保守:编译器假定返回的对象捕获 fun即使没有。
然而,这个有趣的例子编译得很好:
fn foo(s: &str) -> impl Iterator<Item = i32> {
    println!("{}", s);
    vec![1, 2, 3].into_iter()
}

fn main() {
    let s = "hello, world!".to_string();
    let iter = foo(&s);
    drop(s);

    for x in iter {
        println!("{}", x);
    }
}
这里编译器似乎没有假设返回的 impl Iterator<Item = i32>s .
如何准确返回 impl Trait类型借检查?他们什么时候假设借用其他函数参数,就像在第一种情况下一样?什么时候假设他们不这样做,就像在后一种情况下一样?

最佳答案

我相信 this issue comment讲述这里的故事。听起来像保守的类型系统的故意限制,但我同意问题作者的观点,能够选择退出会很好:

The core reason for this behaviour is the variance behaviour of impl Trait in return position: the returned impl Trait is always variant over all generic input parameters, even if not technically used. This is done so that if you change the internal implementation of a public API returning impl Trait you don't have to worry about introducing an additional variance param to the API. This could break downstream code and is thus not desireable for Rust's semver system.

关于rust - 如何检查 `impl Trait` 类型的返回值借用检查?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68143578/

相关文章:

memory - 克隆语句是否被优化过?

python - 如何在 Rust 中收集传感器数据并使其在 Python 中可查询/可用?

rust - 为什么 Rust 无法识别我在闭包内重新分配给移动的变量?

rust - 如何在两个地方存储结构?

rust - 我是否错误地实现了 IntoIterator 以引用 LazyList 实现,或者这是一个 Rust 错误?

rust - 如何使用非词法生命周期对程序进行正式推理

string - 范围内的算术运算顺序问题

rust - 使用 `move` 关键字的闭包如何创建 FnMut 闭包?

rust - 如何使用 serde_cbor 打印有效的 CBOR?

rust - "cannot move out of variable because it is borrowed"旋转变量时