How to use Pin to prevent safe code from invalidating a field

I'm writing a bytecode interpreter, the general structure is something like this:

struct Func {
    code: Box<[Op]>,
}
struct Task {
    funcs: Vec<Func>,
    ...
}

enum Op { ... }

impl Op {
    fn perform(&self, task: &mut Task) { ... }
}

the problem is the code field needs to be borrowed immutibly while the task is borrowed, but the task is borrowed mutably. my initial thought was to wrap the code field in RefCell and take the performance hit, but i'm not sure that actually helps.

I think Pin<NonNull<[Op]>> might be sound? although it would be annoying because i would have to deallocate manually.

Preferably I could just make Box not Unpin.

Sounds more like an Rc<[Op]> or Arc<[Op]> situation to me.

Or a view struct with code: &[Op], rest_of_task: &mut RestOfTask.

2 Likes

Are you doing anything else that needs Pin? If not, you can just write your own wrapper that doesn’t give out &mut references:

mod imm_box {
    pub struct ImmBox<T:?Sized>(Box<T>);
    impl<T:?Sized> From<Box<T>> for ImmBox<T> {
        fn from(x: Box<T>)->Self {
            ImmBox(x)
        }
    }
    impl<T:?Sized> Deref<T> for ImmBox<T> {
        fn deref(&self)->&T {
            &*self.0
        }
    }
}

struct Func {
    code: imm_box::ImmBox<[Op]>,
}

You don't want Box. There are various crates that provide box alternatives; I don't know if there's an agreed upon best one.

Or you want Box and Unpin or RFC 3467 or something. I haven't done the research to give a complete answer, just breadcrumbs.

1 Like

That depends entirely on what else @binarycat is doing in the code that isn’t shown. In particular, there’s no mention of any unsafe or any operation that would require it— Just a desire to have a Box that doesn’t provide &mut access.

I guess I read this...

...as "a usable &[Op] exists concurrently with newly minted &mut Task", not "I want to prevent mutation of a field under &mut Task".

But you're right, it's not entirely clear.

2 Likes

I think i've found an alternative solution, which is to prevent safe code from obtaining &mut Func once it is in the main array.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.