Description
Here is a very simple program which employs trait objects:
c.rc
:
#[crate_id = "c#0.1"];
#[crate_type = "bin"];
mod m1;
mod m2;
m1.rs
:
use std::io;
pub struct Container<'a> {
priv reader: &'a mut Reader
}
impl<'a> Container<'a> {
pub fn wrap<'s>(reader: &'s mut Reader) -> Container<'s> {
Container { reader: reader }
}
pub fn read_to(&self, vec: &mut [u8]) {
self.reader.read(vec);
}
}
pub fn for_stdin<'a>() -> Container<'a> {
let mut r = io::stdin();
Container::wrap(&mut r as &mut Reader)
}
m2.rs
:
use std::vec;
use m1;
#[main]
fn main() {
let c = m1::for_stdin();
let mut v = vec::from_elem(10, 0u8);
c.read_to(v.as_mut_slice());
}
When this program is compiled and run, it fails with segmentation fault:
% rustc c.rc
% ./c
zsh: segmentation fault (core dumped) ./c
This program is not correct. You can see that m1::for_stdin()
function produces a Container<'a, ...>
for arbitrary lifetime 'a
, but the local variable r
is valid only for for_stdin()
body. A pointer to r
, however, is saved to the Container
, and when it is accessed inside m2::main()
, a segmentation fault occurs. However, Rust still compiles it. I thought that borrowing checker should prevent this kind of errors.
BTW, I can write &mut r
or &mut r as &mut Reader
and it will compile either way, but I thought that when going from plain pointers to trait objects I should always specify exact kind of trait object. Not sure that I'm right here thought.