gpt4 book ai didi

rust - 由于关联类型导致的错误推断生命周期

转载 作者:行者123 更新时间:2023-11-29 07:50:51 25 4
gpt4 key购买 nike

以下代码示例是我遇到的问题的缩小版本。

trait Offset: Default {}

trait Reader {
type Offset: Offset;
}

impl Offset for usize {}

impl<'a> Reader for &'a [u8] {
type Offset = usize;
}

// OK
// struct Header<R: Reader>(R, usize);

// Bad
struct Header<R: Reader>(R, R::Offset);

impl <R: Reader<Offset=usize>> Header<R> {
fn new(r: R) -> Self {
Header(r, 0)
}
}

fn test<R: Reader>(_: Header<R>, _: Header<R>) {}

fn main() {
let buf1 = [0u8];
let slice1 = &buf1[..];
let header1 = Header::new(slice1);

let buf2 = [0u8];
let slice2 = &buf2[..];
let header2 = Header::new(slice2);

test(header1, header2);
}

我目前的代码使用 usize 而不是 Offset 关联类型。我正在尝试概括我的代码,以便它可以与其他类型一起使用以进行偏移。但是,添加此关联类型导致许多现有代码停止编译并出现如下错误:

error[E0597]: `buf2` does not live long enough
--> src/main.rs:37:1
|
33 | let slice2 = &buf2[..];
| ---- borrow occurs here
...
37 | }
| ^ `buf2` dropped here while still borrowed
|
= note: values in a scope are dropped in the opposite order they are created

颠倒 header1buf2 的顺序解决了这个例子的问题,但我不想在所有地方都进行这种更改(并且可能无法到),我不明白为什么这是个问题。

最佳答案

原因

Variance是问题的原因。

  • struct Header<R: Reader>(R, usize); , Header<R>协变 w.r.t. R .
  • 但是,在 struct Header<R: Reader>(R, R::Offset); , Header<R>不变 w.r.t. R .

子类型化 是生命周期的安全转换。例如,&'static [u8]可以转换为&'a [u8] .

Variance 描述了如何将子类型提升为复杂类型。例如,如果 Header<_>是协变的并且RS 的子类型, Header<R>Header<S> 的子类型.不变结构不是这种情况。

在当前的 Rust 中,traits 总是不变的,因为在当前语法中无法推断或指定 trait variance。同样的限制适用于投影类型,如 R::Offset .

在您的代码中,自 Header是不变的,Header<&'a [u8]>无法升级到 Header<&'b [u8]>即使'a: 'b .自 fn test两个参数需要相同的类型,编译器需要相同的生命周期 slice1slice2 .

解决方案

一种可能的临时解决方案是为 fn test 泛化签名, 如果可行的话。

fn test<R: Reader, S: Reader>(_: Header<R>, _: Header<S>) {}

另一个解决方案是制作Header以某种方式协变。

也许假设 Header 是安全的如果 type Offset 是协变的有'static绑定(bind),但当前的编译器不会进行如此巧妙的推​​理。

也许您可以将生命周期拆分为 Header 的参数.这恢复了协方差。

trait Offset: Default {}

trait Reader {
type Offset: Offset;
}

impl Offset for usize {}

impl Reader for [u8] {
type Offset = usize;
}

struct Header<'a, R: Reader + ?Sized + 'a>(&'a R, R::Offset);

impl <'a, R: Reader<Offset=usize> + ?Sized> Header<'a, R> {
fn new(r: &'a R) -> Self {
Header(r, 0)
}
}

fn test<R: Reader + ?Sized>(_: Header<R>, _: Header<R>) {}

fn main() {
let buf1 = [0u8];
let slice1 = &buf1[..];
let header1 = Header::new(slice1);

let buf2 = [0u8];
let slice2 = &buf2[..];
let header2 = Header::new(slice2);

test(header1, header2);
}

关于rust - 由于关联类型导致的错误推断生命周期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45273361/

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