编辑:请停止将此帖子重复报告,如果您只阅读了前两行,您将了解它不是重复的。
pub struct BufferedTcpStream<'a> {
_socket: TcpStream,
input: BufReader<&'a TcpStream>;
output: BufWriter<&'a TcpStream>;
}
impl<'a> BufferedTcpStream<'a> {
pub fn new(socket: TcpStream) -> BufferedTcpStream<'a> {
BufferedTcpStream{
input : BufReader::new(&socket),
output: BufWriter::new(&socket),
_socket: socket,// <-- MOVE OF BORROWED VALUE HERE
}
}
pub fn reach(&mut self) -> (
&mut BufReader<&'a TcpStream>,
&mut BufWriter<&'a TcpStream>
) {
(&mut self.input, &mut self.output)
}
}
为了解决这个问题,我必须确保TcpStream
引用在整个结构生存期内均保持有效,我使用了Pin<Box<TcpStream>>
来确保它有效。
但是编译器仍然抱怨借入值socket
的移动。为了消除此障碍,我使用了transmute
。
现在,我想知道的是:
pub struct BufferedTcpStream<'a> {
_socket: Pin<Box<TcpStream>>,
input : BufReader<&'a TcpStream>,
output: BufWriter<&'a TcpStream>,
}
impl<'a> BufferedTcpStream<'a> {
pub fn new(socket: TcpStream) -> BufferedTcpStream<'a> {
let pin = Box::pin(socket);
unsafe {
BufferedTcpStream{
input : BufReader::new(std::mem::transmute(&*pin)),
output: BufWriter::new(std::mem::transmute(&*pin)),
_socket: pin,
}
}
}
pub fn reach(&mut self) -> (
&mut BufReader<&'a TcpStream>,
&mut BufWriter<&'a TcpStream>
) {
(&mut self.input, &mut self.output)
}
}
对TcpStream
的引用可以比结构本身更长寿:
let bad_ref = {
let buffer = BufferedTcpStream(TcpStream::connect("[::1]:4321").unwrap());
let (i, o) = buffer.reach();
*i.get_ref()
};
// bad_ref is now an invalid ref but the compiler won't see it
*i.get_ref()
的类型为&'a TcpStream
,但是&'a
的生存期永远不会由编译器推断出来,因此不会考虑在内。
可以通过将reach()
的生存期链接到返回的引用,将其固定在self
方法中:
fn reach<'b>(&'b mut self) -> (
&mut BufReader<&'b TcpStream>,
&mut BufWriter<&'b TcpStream>
) {
(&mut self.input, &mut self.output)
}
实际上,'a
中的struct BufferedTcpStream<'a>
生存期是无用的。可以将不安全引用的生存期设置为'static
。
pub struct BufferedTcpStream {
_socket: Pin<Box<TcpStream>>,
input : BufReader<&'static TcpStream>,
output: BufWriter<&'static TcpStream>,
}
impl BufferedTcpStream {
pub fn new(socket: TcpStream) -> BufferedTcpStream {
let pin = Box::pin(socket);
unsafe {
BufferedTcpStream{
input : BufReader::new(std::mem::transmute(&*pin)),
output: BufWriter::new(std::mem::transmute(&*pin)),
_socket: pin,
}
}
}
pub fn reach<'b>(&'b mut self) -> (
&mut BufReader<&'b TcpStream>,
&mut BufWriter<&'b TcpStream>
) {
unsafe {
std::mem::transmute((&mut self.input, &mut self.output))
}
}
}