0

I'm porting an old project to Rust, and faced a problem I couldn't find a solution for. The only similar thing I found is this, which doesn't answer the actual question. The underlying problem is this:

struct A {
    a: Box<i32>,
    b: Box<i32>
}

impl A {
    fn get_a(&mut self) -> &mut Box<i32> { &mut self.a }
    fn get_b(&mut self) -> &mut Box<i32> { &mut self.b }
}

fn main() {
    let mut a = A{ a: Box::new(42), b: Box::new(28) };

    // This compiles:
    //let af = &mut a.a;
    //let bf = &mut a.b;

    // This doesn't!
    let af = a.get_a();
    let bf = a.get_b();

    println!("{}", af);
    println!("{}", bf);
}

In my real world code I have this:

struct GlyphPlacer {
    bitmap: Bitmap,
    bitmaps: Vec<(char, GlyphBitmap)>,

    current_scanline_buffer: usize,
    scanline_buffers: [Vec<Scanline>; 2]
}

impl GlyphPlacer {
    // ...

    fn immutable_scanline_buffer(&self) -> &Vec<Scanline> {
        &self.scanline_buffers[self.current_scanline_buffer]
    }

    fn draw_scanlines(&mut self) {
        for scanline in self.immutable_scanline_buffer() {
            // error: cannot borrow `self.bitmap` as mutable because `*self` is also borrowed as immutable [E0502]
            self.bitmap.draw_scanline(*scanline);
        }
    }
}

Which compiles only if I inline the implementation of theimmutable_scanline_buffer() method, and only because the draw_scanline() method is a method of the self.bitmap field, not the actual GlyphPlacer struct:

fn draw_scanlines(&mut self) {
    for scanline in &self.scanline_buffers[self.current_scanline_buffer] {
        self.bitmap.draw_scanline(*scanline);
    }
}

I understand why is this happening, but how to handle cases like this? I can not separate those two fields, because they are just parts of implementation of GlyphPlacer, and I can't always copy-paste code like that, because the implementation of functions like immutable_scanline_buffer() can't always be so short.

Community
  • 1
  • 1
  • *which doesn't answer the actual question* — there are **4** possible solutions outlined in the answer and none of them are acceptable? *I can not separate those two fields, because they are just parts of implementation* — I'm unclear why that prevents you from making a smaller structure and embedding it. You don't have to move both fields to different structures, but if you move both of them to another, then you can add the method there. – Shepmaster May 04 '16 at 22:31
  • @Shepmaster two last solutions just doesn't apply. Embedding scanline_buffer into a different structure with immutable_scanline_buffer method actually did worked out. I wasn't thinking about it first for some reason. So, It solves the problem. –  DRDivider May 04 '16 at 23:11

0 Answers0