< 返回版块

Lexo-0 发表于 2021-09-20 21:49

Tags:生命周期


mod test {
//不能通过编译
    enum Body {
        Bytes(Vec<u8>),
    }

    impl std::io::Read for Body {
        fn read(&mut self, buf: &mut [u8]) -> futures_io::Result<usize> {
            todo!()
        }
    }

    impl std::io::BufRead for Body {
        fn fill_buf(&mut self) -> futures_io::Result<&[u8]> {
            match self{
                Body::Bytes(bytes) => Ok(bytes.as_ref()),
            }
        }

        fn consume(&mut self, amt: usize) {
            todo!()
        }
    }
}

mod test2 {
//能通过编译
    struct Body (Vec<u8>);
    

    impl std::io::Read for Body {
        fn read(&mut self, buf: &mut [u8]) -> futures_io::Result<usize> {
            todo!()
        }
    }

    impl std::io::BufRead for Body {
        fn fill_buf(&mut self) -> futures_io::Result<&[u8]> {
            Ok(self.0.as_ref())
            
        }

        fn consume(&mut self, amt: usize) {
            todo!()
        }
    }
}

fn main(){
    
}

为什么使用enum就无法通过编译,使用struct就能编译?


error[E0515]: cannot return value referencing local variable `bytes`
  --> src/main.rs:16:39
   |
16 |                 Body::Bytes(bytes) => Ok(bytes.as_ref()),
   |                                       ^^^-----^^^^^^^^^^
   |                                       |  |
   |                                       |  `bytes` is borrowed here
   |                                       returns a value referencing data owned by the current function

更新:改成Body::Bytes(ref bytes)就过编译了,不知道为什么。

playground:

https://play.rust-lang.org/#:~:text=Permalink%20to%20the%20playground


Ext Link: https://play.rust-lang.org/#:~:text=Permalink%20to%20the%20playground

评论区

写评论
Grainspring 2021-10-15 11:36

无法通过编译的原因在于要求严格的类型匹配,&mut self与&self存在不同。

as_ref声明接收的参数是&self,不是&mut self

impl<T, A: Allocator> AsRef<[T]> for Vec<T, A> { fn as_ref(&self) -> &[T] { self } }

--->>>可以使用ref方式来转换类型,也可以通过bytes.as_mut() as &[u8])来转换。

下面修改后的代码则可以编译通过。

mod test {

enum Body {
    Bytes(Vec<u8>),
}

impl std::io::Read for Body {
    fn read(&mut self, buf: &mut [u8]) -> futures_io::Result<usize> {
        todo!()
    }
}

impl std::io::BufRead for Body {
    fn fill_buf(&mut self) -> futures_io::Result<&[u8]> {
        match self{
            // bytes绑定类型为&mut Vec<u8>,调用它的as_mut方法返回&mut [u8],然后手动转换成&[u8]
            Body::Bytes(bytes) => Ok(bytes.as_mut() as &[u8])),
        }
    }

    fn consume(&mut self, amt: usize) {
        todo!()
    }
}

// 使用&self来调用as_ref的示例
impl Body {
    fn get_buf(&self) -> Result<&[u8], std::io::Error> {
        match self{
            // bytes绑定类型为&Vec<u8>,正好符合as_ref的定义声明
            Body::Bytes(bytes) => Ok(bytes.as_ref()),
        }
    }
}

}

Bai-Jinlin 2021-09-21 17:07

你把as_ref改成as_mut或者as_slice就能通过,你的代码不能通过编译的原因有一点复杂。你的bytes的类型是&mut Vec,对这个调用as_ref写全了的话是<&mut Vec as AsRef<[u8]>>::as_ref(&bytes),这时候的as_ref的签名类似于fn func<'a,'b:'a>(r:&'b &'a mut Vec)->&'b [u8],也就是说返回值的生命周期对应的是你临时创建的引用&bytes,所以才会报错。

用ref可以运行是因为使用ref模式bytes的类型就会变为&Vec,这时调用的as_ref是https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#impl-AsRef%3C%5BT%5D%3E,不会出现上面的问题。

Neutron3529 2021-09-20 21:58
       returns a value referencing data owned by the current function

enum的话,你是创建了一个临时变量的引用并return

return的时候,临时变量会被释放

1 共 3 条评论, 1 页