[rust-dev] wrapping a C library (ownership/mutability questions)

Josh Haberman jhaberman at gmail.com
Fri Jan 17 16:53:57 PST 2014


On Fri, Jan 17, 2014 at 4:32 PM, Alex Crichton <alex at crichton.co> wrote:
>> This is the part that I don't follow; why can't I just mark
>> my mutable-only methods as taking a mutable self?
>
> The problem with this is that it requires that the *owner* of a type
> have a *mutable slot*, and you cannot prevent owners from declaring
> their slots as mutable. In the example you gave, you could write "let
> mut var2 = Box { x: 2 }" and it would compile, there's nothing
> preventing usage of the "mut" at the owner.

Are you saying (if I may lapse into C++ vocab for a moment) that I can't
hide the copy constructor? Anyone can copy my non-mut struct into a
mut struct at any time and I don't have any say in the matter?

Feel free to correct this into Rust-speak.  :)

> One possible solution is to use a thing called "shadow type parameters"
>
> pub enum Mutable {}
> pub enum Frozen {}
> pub struct Box<State> {
>     priv x: i32,
> }
>
> // methods that only work on a mutable box
> impl Box<Mutable> {
>     fn new() -> Box<Mutable> { Box { x: 2 } }
>     fn set_x(&mut self, val: i32) -> { self.x = val; }
>     fn freeze(self) -> Box<Frozen> { Box { x: self.x } }
> }
>
> // methods that work on all boxes (mutable and immutable)
> impl<T> Box<T> {
>     fn x(&self) -> i32 { self.x }
> }
>
> impl Clone for Box<Frozen> { ... }
>
> impl<T> Drop for Box<T> { ... }
>
> With something like this you can write code that works over generic
> boxes (immutable or mutable), but you have a clear separation of what
> a mutable box can do and what a frozen box can do.

Hmm, this looks promising. Not as nice as mut/non but not as bad as
two unrelated types. What does the declaration/use of these types
look like syntactically? Does the user write out Mutable and Frozen?

>> What I was asking is how to furnish
>> the second parameter to my ref/unref functions: the "owner".
>> In my API all refs have an "owner", which is simply a
>> "const void*" that must be distinct from all other ref owners
>> for this object.  It's a debugging facility that makes it
>> easier to track down ref leaks.  In C or C++, I usually use
>> the address of the variable that is storing the pointer to
>> my MessageDef object as the ref owner.
>
> Sadly this doesn't translate to rust. In your example, you're
> declaring the owner as a stack pointer, but then that stack pointer is
> invalidated as soon as the function returns. You'll probably not want
> to implement the trait Clone or you'll want to find some other way to
> track owners perhaps.

Yeah, maybe I'll have to allow people to pass NULL as an owner
if they can't easily provide one. Hopefully this wouldn't give up
too much since cases like this should be guaranteed correct by
Rust anyway (assuming I write the wrappers right).

Thanks,
Josh


More information about the Rust-dev mailing list