简体   繁体   English

锈:一生的问题,需要帮助

[英]rust: lifetime issue, need a hand

I am making an analog of c++'s iostream for rust recently, but get confused by the lifetime system. 我最近正在模拟c ++的iostream进行锈蚀,但是对生命周期系统感到困惑。 I want to store a reference of reader or a bare reader in the IStream , so I store an Q in the structure. 我想在IStream存储阅读器或裸阅读器的引用,因此我在结构中存储了Q And than I use an phantom type D for converting Q to R . 然后我使用幻影类型DQ转换为R

Here's the explaination: 这里是解释:

  • R is the Reader where I actually need. R是我真正需要的Reader
  • Q is the store type of R , so Q maybe a bare R or reference &mut R . QR的商店类型,因此Q可能是裸R或引用&mut R
  • I use D to convert Q to R . 我用DQ转换为R Because borrow_from_mut(&mut R) gives me an &mut R , and borrow_from_mut(R) also gives me an &mut R . 因为borrow_from_mut(&mut R)给了我&mut R ,而borrow_from_mut(R)也给了我&mut R borrow_from_mut(R) Thus it could be D: BorrowFromMut<Q> . 因此它可能是D: BorrowFromMut<Q>
  • and D can be converted to R by derefrence. D可以通过反折射转换为R So &mut D: DerefMut<R> 所以&mut D: DerefMut<R>
  • because &mut D can be dereferenced to D , but I need the &mut D dereferenced to R , here must use a trait object to dynamic dispatch the deref_mut method, because of the absence of UFCS .(trick: let tmp: &'c mut Q = &mut *self.istream.borrow_mut(); ) 因为可以将&mut D取消引用到D ,但我需要将&mut D取消引用到R ,在这里必须使用trait object动态调度deref_mut方法,因为缺少UFCS 。(技巧: let tmp: &'c mut Q = &mut *self.istream.borrow_mut();

Such trick makes IStream able to store both &mut R and R . 这种技巧使IStream能够存储&mut RR

But the code can't compile because of a lifetime issue: 但是由于存在生命周期问题,因此无法编译代码:

let tmp: &'c mut Q = &mut *self.istream.borrow_mut();
//the Q borrowed from the RefCell only valid in the block, doesn't out live 'c.

how can I solve it? 我该如何解决?

here is the code sample: 这是代码示例:

pub struct IStream<'a,'b,R:'a+'b,Q:'a+'b,Sized? D:'b> where R: Reader, D: BorrowFromMut<Q>, &'b mut D: DerefMut<R> {
    istream: Rc<RefCell<Q>>
}

impl<'a,'b,R,Q,D> Clone for IStream<'a,'b,R,Q,D> where R: Reader, D: BorrowFromMut<Q>, &'b mut D: DerefMut<R> {
    fn clone(&self) -> IStream<'a,'b,R,Q,D> {
        IStream {
            istream: self.istream.clone()
        }
    }
}

impl<'a,'b,'c,F,R,Q,D> Shr<&'b mut F,IStream<'a,'c,R,Q,D>> for IStream<'a,'c,R,Q,D> where R: Reader, F: FromStr + Default, D: BorrowFromMut<Q>, &'c mut D: DerefMut<R> {
    fn shr(mut self, output: &mut F) -> IStream<'a,'c,R,Q,D> {
        let tmp: &'c mut Q = &mut *self.istream.borrow_mut();
        let mut reader: &mut D = BorrowFromMut::borrow_from_mut(tmp);
        let mut real_reader: &DerefMut<R> = &reader;

        let mut buf = String::new(); // a string buffer

        loop {
            if let Ok(byte) = (*real_reader.deref_mut()).read_byte() {
                if byte == '\u{A}' as u8 || byte == '\u{20}' as u8 {
                    break
                } else {
                    buf.push(byte as char);
                }
            } else {
                break
            }
        }

        *output = FromStr::from_str(buf[]).unwrap_or_default();
        IStream {
            istream: self.istream.clone()
        }
    }
}

I think you're trying to outsmart yourself. 我认为您正试图超越自己。 You don't need to be able to store a reader or a mutable reference to a reader at the same time, because you can easily convert such mutable reference to a full-fledged reader. 您不需要同时存储阅读器或对阅读器的可变引用,因为您可以轻松地将此类可变引用转换为完整的阅读器。 Without these complications your code will look like this (note the example of by_ref() below): 没有这些复杂性,您的代码将如下所示(请注意下面的by_ref()示例):

#![feature(slicing_syntax)]

use std::cell::RefCell;
use std::rc::Rc;
use std::str::FromStr;
use std::default::Default;
use std::io::ByRefReader;

pub struct IStream<R> where R: Reader {
    istream: Rc<RefCell<R>>
}

impl<R> Clone for IStream<R> where R: Reader {
    fn clone(&self) -> IStream<R> {
        IStream {
            istream: self.istream.clone()
        }
    }
}

impl<'b, F, R> Shr<&'b mut F, IStream<R>> for IStream<R> where R: Reader, F: FromStr + Default {
    fn shr(self, output: &'b mut F) -> IStream<R> {  // '
        let mut real_reader = self.istream.borrow_mut();

        let mut buf = String::new(); // a string buffer
        loop {
            if let Ok(byte) = real_reader.read_byte() {
                if byte == '\u{A}' as u8 || byte == '\u{20}' as u8 {
                    break
                } else {
                    buf.push(byte as char);
                }
            } else {
                break
            }
        }

        *output = FromStr::from_str(buf[]).unwrap_or_default();

        self.clone()
    }
}

fn main() {
    let mut stdin = std::io::stdin();
    let stdin_ref: &mut _ = &mut stdin;  // a mutable reference to a reader

    let is = IStream { istream: Rc::new(RefCell::new(stdin_ref.by_ref())) };

    let mut x: uint = 0;
    let mut y: uint = 0;

    is >> &mut x >> &mut y;

    println!("{}, {}", x, y);
}

Here's a reproduction of the error you mentioned: 这是您提到的错误的再现:

use std::cell::RefCell;

fn foo<'a>(rc: &'a RefCell<u8>) { 
    let b: &'a u8 = &*rc.borrow();
}

fn main() {
}

This fails to compile with 这无法编译

borrowed value does not live long enough 借来的价值寿命不长

By definition, the result of borrow() has a scope that is tied to the scope it's called in, you can't "trick" it by specifying a different lifetime. 根据定义, borrow()的结果的作用域与其调用的作用域绑定在一起,您不能通过指定其他生存期来“欺骗”它。 All that does is make the compiler tell you you can't do that. 所有要做的就是使编译器告诉您不能这样做。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM