Blog post: Contexts and capabilities in Rust

Yes, this can be done with lifetimes and borrowing.

struct WithAlloc<'a,T,A: Allocator + 'a> {
   data: *mut T,
   _pd: PhantomData<fn(&'a ()) -> &'a ()>,  //this gives us invariant lifetime, which cannot be weaken nor strengthen
}

Here, WithAlloc struct doesn't borrow an allocator, but yet, an instance of the type may not be called with a reference to a wrong allocator.

If it is a type produced by desugaring, then the following example is correct (Edit: it is not - I didn't understood how ghost-cell works):

let alloc1 = ...;
let alloc2 = ...;

let box_in_1;
with alloc: Allocator = &alloc1 {
   box_in_1 = Box::new(...); //there, `box_in_1` has got a branded reference to `alloc1`
}

with alloc = &alloc1 {
   drop(box_in_1) //OK, since both references have the same lifetime.
}

with alloc = &alloc2 {
   drop(box_in_1) //Error, because lifetime of `&alloc2` is not the same as of `&alloc1`
}

So we can prove whether we had allocated with some specific allocator or not.

1 Like