借来的价值寿命不够长,不确定为什么它仍然是借来的

问题描述 投票:0回答:1

我的借阅检查程序有问题;这是我正在尝试的简化版本:

trait CommitmentScheme<In> {
    type Com;

    fn commit(input: In) -> Self::Com;
    
    fn open(com1: &Self::Com, com2: &Self::Com);
}

fn prove<CS: for<'a> CommitmentScheme<&'a [u32]>>() {
    let msg1 = vec![1u32];
    let com1 = CS::commit(&msg1);
    let msg2 = vec![2u32];
    let com2 = CS::commit(&msg2);
    CS::open(&com1, &com2);
}

游乐场链接

编译失败,出现以下错误,

error[E0597]: `msg2` does not live long enough
  --> src/lib.rs:13:27
   |
12 |     let msg2 = vec![2u32];
   |         ---- binding `msg2` declared here
13 |     let com2 = CS::commit(&msg2);
   |                           ^^^^^ borrowed value does not live long enough
14 |     CS::open(&com1, &com2);
15 | }
   | -
   | |
   | `msg2` dropped here while still borrowed
   | borrow might be used here, when `com1` is dropped and runs the destructor for type `<CS as CommitmentScheme<&[u32]>>::Com`
   |
   = note: values in a scope are dropped in the opposite order they are defined

提前声明

msg2
可以避免错误,但在我的设置中,直到第一次
msg2
调用之后才能构建
commit

我对这个问题的理解是,返回的

Com
可以保留对已提交消息的引用。然而,根据相反顺序规则,似乎每个承诺都应该在它可能引用的消息之前被删除。我首先尝试手动
drop
做出承诺,但没有成功。

我还尝试声明

type Com: 'static;
,我认为这基本上可以保证
commit
返回无借用的内容(除了可能的静态借用,这似乎不是问题)。我认为这将确保
msg1
msg2
仅在
commit
调用期间被借用,而不是之后,但错误仍然存在。

rust borrow-checker
1个回答
0
投票

问题是

'a
中的每个生命周期
for<'a>
都会强加一个不同的实现。就像
CS
多次实现
CommitmentScheme
,每个生命周期一次。当
open()
Self::Com
时,它实际上需要
<Self as CommitmentScheme<In>>::Com
,其中
In
包含此处使用的实际生命周期。因此两个参数的寿命必须相等。

'static
无法将关联类型指定为非捕获生命周期的原因在问题#114801中进行了解释,链接于告诉编译器泛型返回类型不会借用任何对参数的引用? 。解决方案是为
Com
使用不同的泛型参数,它不能从生命周期中借用,因为它在声明时尚未声明:

fn prove<Com, CS: for<'a> CommitmentScheme<&'a [u32], Com = Com>>() {
    let msg1 = vec![1u32];
    let com1 = CS::commit(&msg1);
    let msg2 = vec![2u32];
    let com2 = CS::commit(&msg2);
    CS::open(&com1, &com2);
}
© www.soinside.com 2019 - 2024. All rights reserved.