I would like to branch and decide on a Trait implementation to use within a function at runtime (see poly_read
in the code sample below). The trait object is constructed inside of the branch arms of an if expression and only needs to live for the life of poly_read
yet I need to Box
it because the trait can't be borrowed from within the expression arm, up to the binding that I'm attempting to assign it to.
I understand logically why the borrow ends too early, but it seems like the borrow checker should be able to extend the borrow up to the surrounding scope when the if expression's value is bound. I realize this is probably a naive notion, but I'd like to understand more about why it's not possible.
I'm a bit unhappy with the solution I have now because it requires a heap allocation even though I feel like I shouldn't need one, since I only hold onto the box for the life of the function. I suppose this is because we don't know the size of reader
that would be required on the stack until the branch is taken, but couldn't it just be represented as a union in the compiler, since we at least know the maximum size.
As an aside, I actually don't know how valid my concern about the Box
being heap allocated is to begin with. In general how expensive is boxing the value?
#![feature(io)]
#![feature(path)]
const BYTES: &'static [u8] = &[1u8, 2, 3, 4, 5];
const PATH: &'static str = "/usr/share/dict/words";
use std::old_io::{File, Reader, BufReader};
fn read(r: &mut Reader) {
let some_bytes = r.read_exact(5).unwrap();
assert!(some_bytes.len() == 5);
println!("{:?}", some_bytes);
}
fn poly_read(from_file: bool) {
// Is there any way to extend the lifetime of the ``&mut Reader`` in these branch arms without
// boxing them as I'm doing now. It seems wasteful to do a heap allocation when the actual
// borrow only needs to happen for body of poly_read?
let mut reader = if from_file {
Box::new(File::open(&Path::new(PATH)).unwrap()) as Box<Reader>
// Would like to say:
// File::open(&Path::new(FILE)).unwrap() as &mut Reader
} else {
Box::new(BufReader::new(BYTES)) as Box<Reader>
// Would like to say:
// BufReader::new(BYTES) as &mut Reader
};
// It feels like I'd like the lifetime of values returned from if expressions to be of the
// surrounding scope, rather than the branch arms.
read(&mut reader);
}
fn main() {
poly_read(true);
poly_read(false);
}