【问题标题】:rust: lifetime issue, need a hand生锈:终身问题,需要帮助
【发布时间】:2015-01-01 15:27:02
【问题描述】:

我最近正在为 rust 制作 c++ 的 iostream 的模拟,但被生命周期系统弄糊涂了。 我想在IStream 中存储读者或裸读者的引用,所以我在结构中存储了Q。而且我使用幻象类型DQ 转换为R

解释如下:

  • R 是我真正需要的Reader
  • QR 的存储类型,所以 Q 可能是一个裸露的 R 或引用 &mut R
  • 我使用DQ 转换为R。因为borrow_from_mut(&mut R) 给了我一个&mut R,而borrow_from_mut(R) 也给了我一个&mut R。因此它可能是D: BorrowFromMut<Q>
  • D 可以通过 derefence 转换为 R。所以&mut D: DerefMut<R>
  • 因为&mut D可以解引用到D,但是我需要&mut D解引用到R,这里必须使用trait object来动态调度deref_mut方法,因为没有@ 987654352@.(绝招:let tmp: &'c mut Q = &mut *self.istream.borrow_mut();)

这样的技巧使IStream 能够同时存储&mut RR

但由于生命周期问题,代码无法编译:

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.

我该如何解决?

这里是代码示例:

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()
        }
    }
}

【问题讨论】:

  • 如果您可以同时将您的示例设为smaller and compilable,那将会很有用。如果我们可以将其粘贴到playpen 并运行它以查看您的错误,那么帮助会容易得多。

标签: rust type-systems lifetime


【解决方案1】:

我认为你在试图超越自己。您不需要能够同时存储阅读器或对阅读器的可变引用,因为您can easily convert 对成熟阅读器的这种可变引用。如果没有这些复杂性,您的代码将如下所示(注意下面的 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);
}

【讨论】:

    【解决方案2】:

    这里是你提到的错误的复制:

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

    编译失败

    借来的价值不够长

    根据定义,borrow() 的结果具有与调用它的范围相关联的范围,您不能通过指定不同的生命周期来“欺骗”它。所做的只是让编译器告诉你不能这样做。

    【讨论】:

      猜你喜欢
      • 2016-03-14
      • 2014-09-12
      • 1970-01-01
      • 1970-01-01
      • 2011-05-22
      • 2011-01-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多