Now, whenever a Ptr_To_Source_Resource is dropped, we want ResrouceManager to be notified, so we do something like this:
pub struct Ptr_To_Some_Resource{
resource_manager: Rc<ResourceManager>
}
impl Drop for Ptr_To_Some_Resource {
// use self.resource_manager to notify
}
Now, alternatively I am wondering if we can do something else: make it a compile time error for Ptr_To_Some_Resource to drop ?
Basically I want something where Ptr_To_Some_Resource can only be destroyed manually via Resource_Manager, and an error if it drops via any other way.
=== EDIT
pub struct ResourceManager {}
impl ResourceManager {
pub fn create() -> Ptr_To_Some_Resource ;
// only valid way to destroy a Ptr_To_Some_Resource
// make just dropping a Ptr_To_Some_Resource a compile time error
pub fn destroy(&mut self, p: Ptr_to_Some_Resource);
}
Rust has something called an "affine" type system where values can be used at most once (it's the technincal term for move semantics), whereas in a "linear" type system a value must be used exactly once (imagine needing to call something taking self by value in every possible code path).
That means there isn't going to be a way to - at compile time - enforce destroy() is always called. The next best thing is probably to enforce it at runtime using the drop_bomb crate.
Although, if it were me then I'd probably prefer the impl Drop for Ptr_To_Some_Resource method. As a side note, if you use some sort of shared communication mechanism like channels instead of holding an Rc<ResourceManager> directly, the ResourceManager won't be forced to use &self methods and interior mutability.
In this case, Ptr_To_Some_Resource essentially couldn't be passed anywhere by value, except mem::forget, since by transferring ownership we make the called function responsible for dropping the now-owned value. Is this what you've intended?
But if Ptr_to_Some_Resource can't be dropped, then this function is illegal to call - its signature doesn't guarantee that the value isn't dropped inside it, so the caller would conservatively assume it it.
That's not how destructuring works. You'd just get &mut references to each of the members, which doesn't let you drop them unless you use something like Option::take()[1].
Let's not even go into ManuallyDrop, which would be a footgun waiting to happen. ↩︎
You could put an invalid link symbol in the Drop implementation - this doesn't produce a pretty compiler error but it does produce one (you have to mem::forget the value in the "manual" destructor).
It will likely also false-positive in debug builds.