2015-01-01 2 views
2

Я делаю аналог iostream C++ для ржавчины в последнее время, но запутаюсь в системе жизни. Я хочу сохранить ссылку читателя или голого читателя в IStream, поэтому я сохраняю Q в структуре. И чем я использую фантомный тип D для преобразования Q в R.ржавчина: пожизненная проблема, нужна рука

Вот объяснений:

  • R является Reader, где я на самом деле нужно.
  • Q является типом магазина R, поэтому Q может быть голым R или ссылкой &mut R.
  • Я использую D для преобразования Q в R. Потому что borrow_from_mut(&mut R) дает мне &mut R, а borrow_from_mut(R) также дает мне &mut R. Таким образом, это может быть D: BorrowFromMut<Q>.
  • и D могут быть преобразованы в R от derefrence. Так &mut D: DerefMut<R>
  • потому что &mut D может быть разыменовываются к D, но мне нужен &mut D разыменовываются к R, здесь необходимо использовать trait object для динамической диспетчеризации метод deref_mut, из-за отсутствия UFCS (трюк: let tmp: &'c mut Q = &mut *self.istream.borrow_mut();).

Такой трюк делает IStream способным хранить как &mut R, так и R.

Но код не может скомпилировать из-за пожизненной выпуска:

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

Было бы полезно, если бы вы могли сделать ваш пример как [меньшим, так и компилируемым] (http://stackoverflow.com/help/mcve). Если мы сможем вставить его в [playpen] (http://play.rust-lang.org/) и запустим его, чтобы увидеть вашу ошибку, тогда гораздо легче помочь. – Shepmaster

ответ

2

Я думаю, что вы пытаетесь перехитрить себя. Вам не нужно сохранять читатель или изменяемую ссылку на читателя одновременно, потому что вы используете 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); 
} 
1

Вот репродукция ошибки вы упомянули:

use std::cell::RefCell; 

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

fn main() { 
} 

Это не может скомпилировать с

Задолженность по займам не достаточно долгое время

По определению, результат borrow() имеет область видимости, которая привязана к области, в которую она вызвана, вы не можете «обмануть» ее, указав другое время жизни. Все, что делает, это заставить компилятор сказать вам, что вы не можете этого сделать.