简体   繁体   English

何时无法推断 Rust 借用检查器的寿命?

[英]When it is not possible to infer the lifetime in the Rust borrow checker?

In most cases, the Rust compiler can infer the lifetime.在大多数情况下,Rust 编译器可以推断寿命。 if the lifetime scope is determined at runtime, it says that the lifetime must be explicitly marked.如果生命周期 scope 在运行时确定,则表示必须明确标记生命周期。

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

Here,这里,

  • The lifetime is generic.生命周期是通用的。
  • This means that there is a scope bound to the lifetime 'a after the function result is returned.这意味着在返回 function 结果后,有一个 scope 绑定到生命周期 'a。
  • the compiler can know information that the memory is valid for the minimum lifetime 'a.编译器可以知道 memory 在最短生命周期内有效的信息'a.

I'am very curious.我很好奇。 instead of using a lifetime syntax, can't the compiler just adopt the fewer scope area to which lifetime 'a can be bound?而不是使用生命周期语法,编译器不能只采用较少的 scope 区域,生命周期 '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.即使调用方的调用栈比较复杂,scope 区域是在借用时确定的,所以同样的问题似乎是可能的。

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

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 .在编译 function (例如您展示的main()时,借用检查器不会检查它调用的各个函数的内容,例如 long longest() ,它只检查它们的签名 This is a feature: it allows the implementation of a function to change without affecting the guarantees provided by its signature.这是一个特性:它允许 function 的实现在不影响其签名提供的保证的情况下进行更改。 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.如果main()成功编译,您可以确定它会继续编译,但是只要您不更改其声明,您修改的longest

In case of longest() , the unannotated signature is ambiguous:在 long longest()的情况下,未注释的签名是模棱两可的:

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

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 .如果没有生命周期注释,我们无法仅通过查看声明来判断返回的&str是来自第一个&str 、第二个&str 、一个共同的生命周期,还是可能来自 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 .对于非常简单的函数,比如接受和返回单个引用的函数,编译器会执行“ 生命周期省略”,它会机械地选择未注释签名的“明显”解释,允许您编写 fnlongest fn longest(x: &str) -> &str作为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.但是当 function 接受多个引用时,编译器拒绝猜测并让您拼出您想要的内容。

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.正如答案开头所指出的,这常常使初学者感到困惑,编译器绝对拒绝做的是从 function 主体推断生命周期签名,因为这会使签名依赖于实现。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM