gpt4 book ai didi

rust - 令人困惑的借用检查器消息 : "lifetime mismatch"

转载 作者:行者123 更新时间:2023-12-04 18:55:07 28 4
gpt4 key购买 nike

我最近遇到了一条我从未见过的借用检查器消息,我试图理解它。这是重现它的代码(简化的,现实生活中的例子更复杂)- playground :

fn foo(v1: &mut Vec<u8>, v2: &mut Vec<u8>, which: bool) {
let dest = if which { &mut v1 } else { &mut v2 };
dest.push(1);
}

它无法编译并出现以下错误:
error[E0623]: lifetime mismatch
--> src/main.rs:2:44
|
1 | fn foo(v1: &mut Vec<u8>, v2: &mut Vec<u8>, which: bool) {
| ------------ ------------ these two types are declared with different lifetimes...
2 | let dest = if which { &mut v1 } else { &mut v2 };
| ^^^^^^^ ...but data from `v2` flows into `v1` here

...接着是另一篇关于来自 v1 的数据流的文章进入 v2 .

我的问题是:这个错误是什么意思?什么是数据流以及它是如何发生在两个变量之间的,假设代码只是推送 Copy数据到其中之一?

如果我遵循编译器并强制 v1 的生命周期和 v2为了匹配,函数编译( playground ):

fn foo<'a>(mut v1: &'a mut Vec<u8>, mut v2: &'a mut Vec<u8>, which: bool) {
let dest = if which { &mut v1 } else { &mut v2 };
dest.push(1);
}

然而,进一步检查发现原始代码不必要地复杂,是从 v1 时遗留下来的。和 v2实际 Vec s,而不是引用。一个更简单、更自然的变体是设置 dest不至 &mut v1&mut v2 ,但更简单的 v1v2 ,这是开始的引用。这也可以编译( playground ):

fn foo(v1: &mut Vec<u8>, v2: &mut Vec<u8>, which: bool) {
let dest = if which { v1 } else { v2 };
dest.push(1);
}

在这个看似等效的公式中, v1 的生命周期和 v2不再需要匹配。

最佳答案

问题是&'a mut TinvariantT .

首先,让我们看一下工作代码:

fn foo(v1: &mut Vec<u8>, v2: &mut Vec<u8>, which: bool) {
let dest = if which { v1 } else { v2 };
dest.push(1);
}
v1的种类和 v2省略了生命周期参数。让我们明确说明:
fn foo<'a, 'b>(v1: &'a mut Vec<u8>, v2: &'b mut Vec<u8>, which: bool) {
let dest = if which { v1 } else { v2 };
dest.push(1);
}

编译器必须弄清楚 dest 的类型. if的两个分支表达式产生不同类型的值: &'a mut Vec<u8>&'b mut Vec<u8> .尽管如此,编译器还是能够找出与这两种类型都兼容的类型;让我们称这种类型 &'c mut Vec<u8> ,其中 'a: 'c, 'b: 'c . &'c mut Vec<u8>这是一个常见的 supertype两者的 &'a mut Vec<u8>&'b mut Vec<u8> , 因为两者都是 'a'b生命周期更长 'c (即 'c'a'b 的生命周期更短/更小)。

现在,让我们检查错误的代码:
fn foo<'a, 'b>(v1: &'a mut Vec<u8>, v2: &'b mut Vec<u8>, which: bool) {
let dest = if which { &mut v1 } else { &mut v2 };
dest.push(1);
}

同样,编译器必须弄清楚 dest 的类型. if的两个分支表达式产生以下类型的值: &'c mut &'a mut Vec<u8>&'d mut &'b mut Vec<u8>分别(其中 'c'd 是新鲜的生命周期)。

我之前说过 &'a mut TT 上不变.这意味着我们无法更改 T&'a mut T这样我们就可以产生 &'a mut T 的子类型或父类(super class)型.在这里, T类型是 &'a mut Vec<u8>&'b mut Vec<u8> .它们不是同一类型,因此我们必须得出结论,类型 &'c mut &'a mut Vec<u8>&'d mut &'b mut Vec<u8>是不相关的。因此, dest 没有有效的类型。 .

关于rust - 令人困惑的借用检查器消息 : "lifetime mismatch",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59923581/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com