我的借阅检查程序有问题;这是我正在尝试的简化版本:
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
调用期间被借用,而不是之后,但错误仍然存在。
问题是
'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);
}