何时无法在Rust借阅检查器中推断寿命? [英] When it is not possible to infer the lifetime in the Rust borrow checker?

查看:34
本文介绍了何时无法在Rust借阅检查器中推断寿命?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在大多数情况下,Rust编译器可以推断生存期.如果生存期范围是在运行时确定的,则表明必须明确标记生存期.

In most cases, the Rust compiler can infer the lifetime. if the lifetime scope is determined at runtime, it says that the lifetime must be explicitly marked.

fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

在这里

  • 生命周期是通用的.
  • 这意味着在返回函数结果之后,存在一个与生存期'a绑定的作用域.
  • 编译器可以知道有关内存在最小生存期'a内有效的信息.

我很好奇.

fn main() { //larger scope
    let s1 = String::from("long string is long");

    { //fewer scope
        let s2 = String::from("xyz");
        let result = longest(s1.as_str(), s2.as_str());
        println!("The longest string is {}", result); 
    } 
      
}

即使调用方的调用栈更复杂,作用域区域还是在借用时确定的,因此同样的问题似乎也是可能的.

Even if the call stack is more complex on the caller side, the scope area is determined at the time of borrowing, so the same question seems to be possible.

fn func1<'a>(x: &'a str, y: &'a str) {
   let c = String::from("hello");
   let result = func2 (a,b,c)
   ...
}

推荐答案

我认为您正在以错误的方式解决这个问题.编译显示的 main()之类的函数时,借位检查器不会检查它调用的各个函数的 contents ,例如 longest(),它仅检查其签名.这是一个功能:它允许更改函数的实现而不会影响其签名所提供的保证.如果 main() 成功编译,你可以确定它会继续编译,但是你修改 longest 只要你不改变它的声明.

I think you're approaching the question the wrong way. When compiling a function such as the main() you've shown, the borrow checker doesn't examine the contents of individual functions it calls, like longest(), it only examines their signatures. This is a feature: it allows the implementation of a function to change without affecting the guarantees provided by its signature. If main() successfully compiles, you can be sure that it will keep compiling however you modify longest as long as you don't change its declaration.

对于 longest(),未注释的签名是不明确的:

In case of longest(), the unannotated signature is ambiguous:

fn longest(x: &str, y: &str) -> &str

// does the above mean:
fn longest<'a, 'b>(x: &'a str, y: &'b str) -> &'a str // returns sub-slice of x
fn longest<'a, 'b>(x: &'a str, y: &'b str) -> &'b str // returns sub-slice of y
fn longest<'c>    (x: &'c str, y: &'c str) -> &'c str // returns sub-slice outlived by x and y
fn longest<'a, 'b>(x: &'a str, y: &'b str) -> &'static str  // returns static data

没有生命周期注释,仅通过查看声明就无法判断返回的& str 是否来自第一个& str ,第二个& str ,普通的生命周期或静态的& str .对于非常简单的功能(例如那些接受并返回单个引用的功能),编译器将执行" longest(x:& str)->& str 作为 fn longest<'a>(x:&'a str)->的简单简写&'a str .但是,当一个函数接受多个引用时,编译器将拒绝猜测并使您拼出想要的内容.

Without lifetime annotations we can't tell from just looking at the declaration whether the returned &str comes from the first &str, the second &str, a common lifetime, or possibly a static &str. For very simple functions, like those that accept and return a single reference, the compiler performs "lifetime elision" where it mechanically picks the "obvious" interpretation of the unannotated signature, allowing you to write fn longest(x: &str) -> &str as a simple shorthand for fn longest<'a>(x: &'a str) -> &'a str. But when a function accepts multiple references, the compiler refuses to guess and makes you spell out what you wanted.

正如答案开头所指出的那样,这常常使初学者感到困惑,编译器绝对拒绝做的是从函数体中推断生命周期签名 ,因为这会使签名依赖在实施上.

As pointed out at the beginning of the answer, and this often confuses beginners, what the compiler definitely refuses to do is infer the lifetime signatures from the function body, because that would make the signature dependent on the implementation.

这篇关于何时无法在Rust借阅检查器中推断寿命?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆