I want to be able to express that a value of a certain type should never be dropped. One possible motivation is that the cleanup procedure requires error handling. Another motivation is that you want to release multiple resources in bulk (which is the case in my example).
To enforce this, you can panic in the Drop implementation like so:
impl Drop for BufferName {
fn drop(&mut self) {
// Only panic if not already panicking. Solve problems one by
// one, don't create more of them.
if thread::panicking() == false {
panic!("Forgot to free {:?}", *self)
}
}
}
This is however a run-time solution and I'm curious if there is a compile time solution. Something along the lines of a "prevent_drop" attribute on my type. That would help library users discover un-dropped values at compile time instead of after writing and executing extensive tests.
I do realize this is very niche and probably only works when your type is wrapped in an Option so you can take and forget or something similar.
Full example: Rust Playground. Important parts are the tests forget_to_free and gen_and_drop.
I read this as "I want the compiler to check" if there's a path to drop, excluding panic or exit. A classic "does not live long enough" error, for a specific lifetime circumstance or requirement.
Prior to yesterday, I might have said something about the 'static lifetime, but now what little I knew about lifetimes is all wrong, and this one is called out explicitly as not actually meaning this.
To me it looks like most use cases are requiring you to call some function that prevents drop from running. A lint would help but not complying means the program will not function, so a hard error would make more sense.
Thanks to a friend who pointed me to incomplete (which currently allows me to safely create undef values :/) I arrived on this thread where @jugglerchris suggested using a link error. It looks promising:
I expect the compiler to elide the drop call in any scenario but I have yet to confirm belief. In the case that drop does get called, the link error tells you what type was being dropped but finding the place where it gets dropped can be a little more challenging.
error: linking with `cc` failed: exit code: 1
|
= ...
= note: /playground/target/release/deps/playground-014d023c6d9e2470.playground4-c73c0d6f28ac447285153be845763aee.rs.rcgu.o: In function `core::ops::function::FnOnce::call_once':
playground4-c73c0d6f28ac447285153be845763aee.rs:(.text._ZN4core3ops8function6FnOnce9call_once17h9a51fd5e3c078478E+0x1): undefined reference to `prevent_drop_BufferName'
collect2: error: ld returned 1 exit status
Here is a macro to generate the drop prevention code, can be extended to use a run time method if the code is not being optimized. Didn't do that to keep it straightforward.