I'd like to have some API that looks like this:
struct Machine;
struct Token<'a>;
impl Machine {
fn get_token<'a>(&'a self) -> Token<'a>;
fn give_token<'a>(&'a self, token: Token<'a>);
}
However, I want to make sure that every Token
is given back only to the Machine
which created it (for soundness reasons, to create a safe API for some unsafe backend). In particular, I want the following code to be illegal:
let m1 = Machine;
let m2 = Machine;
let token = m1.get_token();
m2.give_token(token); // should not be allowed
Backstory: working with identifiers for some borrowed datum
The backstory with this is that my `Machine`s have internally stored, partially-initialized data, split across a struct-of-arrays layout. The longer backstory is that it's for a nearest-neighbors search algorithm I'm playing with, but that's beyond the scope of this question.struct Machine {
data: Vec<MaybeUninit<FirstField>>;
data: Vec<MaybeUninit<SecondField>>;
}
struct Token(usize);
Each Machine
can be queried, and if we find something matching the query we return a Token
identifying the item inside the Machine
. When we want to get information about the item inside the machine, we can go back and ask for its fields:
impl Machine {
fn get_field_1<'a>(&'a Self, token: Token<'a>) -> &'a FirstField;
}
If Token
s cross between Machine
s, they could be used to access uninitialized data inside the second Machine
.
The only way that I know to implement this so far is to make give_token
a method on Token
rather than Machine
, but I don't like that since I intend for Token
to be extremely small and this will be run in a high-performance context. However, this is my current implementation, so it's not the end of the world if this is impossible.