为什么将字段从'&'a [u8]`更改为`&'a mut [u8]`会导致生命周期错误?

Shmoopy

此代码编译:

struct BufRef<'a> {
    buf: &'a [u8],
}

struct Foo<'a> {
    buf_ref: BufRef<'a>,
}

impl<'a> Iterator for Foo<'a> {
    type Item = &'a [u8];

    fn next(&mut self) -> Option<Self::Item> {
        let result = &self.buf_ref.buf;
        Some(result)
    }
}

但是,如果我更改BufRef为:

struct BufRef<'a> {
    buf: &'a mut [u8],
}

编译器说:

error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
  --> src\main.rs:13:16
   |
13 |         let result = &self.buf_ref.buf;
   |                      ^^^^^^^^^^^^^^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 12:5...
  --> src\main.rs:12:5
   |
12 | /     fn next(&mut self) -> Option<Self::Item> {
13 | |         let result = &self.buf_ref.buf;
14 | |         Some(result)
15 | |     }
   | |_____^
note: ...so that reference does not outlive borrowed content
  --> src\main.rs:13:16
   |
13 |         let result = &self.buf_ref.buf;
   |                      ^^^^^^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 9:6...
  --> src\main.rs:9:6
   |
9  | impl<'a> Iterator for Foo<'a> {
   |      ^^
   = note: ...so that the types are compatible:
           expected std::iter::Iterator
              found std::iter::Iterator

为什么更改字段会&'a mut [u8]导致错误?

另外,编译器的含义是:

...so that the types are compatible:
               expected std::iter::Iterator
                  found std::iter::Iterator
罗德里戈

我认为误导您的是您的代码具有折叠的引用。

您的next函数基本上等效于以下代码:

fn next(&mut self) -> Option<&'a [u8]> {
    let result: &&'a [u8] = &self.buf_ref.buf;
    Some(result)
}

之所以可行,是因为双引用折叠为单个引用。在这种情况下,双重引用只会混淆代码。写就好了:

fn next(&mut self) -> Option<Self::Item> {
    Some(self.buf_ref.buf)
}

这行之有效,因为引用始终是Copy

但是现在,将定义更改为会发生什么&'a mut您现在可能正在猜测...可变引用不是 Copy,因此相同的简单代码将为您提供易于阅读的错误消息:

不能移出self.buf_ref.buf可变引用的后面

自然地,您可以将可变的ref作为const重新借用,然后尝试返回它,但是不幸的是,这不会起作用,因为重新借用不能使用与可变变量相同的生存期,它必须严格变小(或者您必须可以将指向的值作为别名)。编译器将此重新借用的生存期分配为next函数的生存期,但是现在您无法返回此借用,因为它是本地引用!

不幸的是,我不知道任何安全的方法来编译您的代码。实际上,我非常确定它将创建一个不完善的API。也就是说,如果您设法编译了代码,则此安全代码将创建未定义的行为:

fn main() {
    let mut buf = vec![1,2,3];
    let buf_ref = BufRef { buf: &mut buf };
    let mut foo = Foo { buf_ref };
    let x: &[u8] = foo.next().unwrap();
    //note that x's lifetime is that of buf, foo is not borrowed
    //x and foo.buf_ref.buf alias the same memory!
    //but the latter is mutable    
    println!("{}", x[0]); //prints 1
    foo.buf_ref.buf[0] = 4;
    println!("{}", x[0]); //prints what?
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

将* mut u8转换为不带std的&[u8]

如何轻松地将非mut&[u8]复制到&mut [u8]

如何使用Rust和Web-sys将Clamped <Vec <u8 >>转换为Clamped <&mut [u8]>?

为什么重新借用 &mut[u8] 使其大小在编译时未知?

如何在 Rust 中定义 &mut [u8]

如何从Rust字符串创建* mut u8?

无法将&u8与u8进行比较

我可以从单个字节(u8)创建可变切片&mut [u8]吗?

为什么从 Rust 中的函数返回 &[u8] 而不是 u8 借用 self?

将str转换为&[u8]

将&[u8]强制转换为std :: io :: Read导致出现大小错误

将u8数组的引用转换为<Vec <u8 >>

如何将Vec <Rgb <u8 >>转换为Vec <u8>

Rust将Option <Vec <u8 >>与Option <&[u8]>进行比较

将Vec <Vec <u8 >>转换为&[&[u8]]

如何将&[u8]转换为&[u8; 64]?

暂时将[u8]转换为[u16]

将 Map<Vec<u8>, Vec<u8>> 展平为 Vec<u8> 然后将其返回到 Map<Vec<u8>, Vec<u8>>

如何将&str转换为* const u8?

如何将'struct'转换为'&[u8]'?

将 &[Box<[u8]>] 转换为 String 或 &str

是否可以在不复制数据的情况下将 Vec<&[u8]> 展平为 &[u8] ?

为什么将“ Self”用作参数类型会导致生命周期错误?

为什么HashMap :: get_mut在生命周期方面比HashMap :: get更挑剔?

将&i64转换为&[u8;的惯用方式是什么?8]?

Rust:使用两个u8结构字段作为u16

为什么我不能使用u8作为Rust数组的索引值?

当Vec不工作时,为什么[u8]用作UdpSocket的缓冲区?

如何将两个 u8 和 u16 元素数组合并为一个 u8 元素数组?