How can I panic if I a method wasn't called before the struct was dropped? E.g. I want this code to panic:
struct Foo;
impl Foo {
/// Call this before the struct is dropped.
fn finish(self) {}
}
fn main() {
let foo = Foo;
// Panic!
}
I thought of writing something like this:
struct Foo {
finish_was_called: bool,
}
impl Foo {
fn finish(mut self) {
self.finish_was_called = true;
}
}
impl Drop for Foo {
fn drop(&mut self) {
if !self.finish_was_called {
panic!("you must call finish");
}
}
}
but it doesn't feel like the best solution. I think I've seen some examples of this being done but I can't remember where. I also thought of using #[must_use] but I don't think that would work for this use case since other methods may be called.
I can't think of a better way offhand. If the information isn't in the struct it'd have to be in some locky unique-struct-identifying global resource or such.
But FYI, #[must_use] just makes sure you somehow acknowledge the returned value, you don't really even have to use it:
use std::io::Write;
fn main() {
// Warns
std::io::stdout().write_all(b"hello ");
// Does not warn
let _ = std::io::stdout().write_all(b"world\n");
}
(It's also a compile time lint and not a run time panic.)
Be aware that code must not rely on destructors being called for safety purposes. You might want to read Pre-Pooping Your Pants With Rust (no, really).
This comment is incorrect. Transmuting between two repr(Rust) types is not safe because two repr(Rust) types are not guaranteed to have the same layout. Quoting the Nomicon:
So how do you know if the layouts are the same? For repr(C) types and repr(transparent) types, layout is precisely defined. But for your
run-of-the-mill repr(Rust), it is not. Even different instances of the same
generic type can have wildly different layout. Vec<i32> and Vec<u32> might have their fields in the same order, or they might not. The details of
what exactly is and is not guaranteed for data layout are still being worked
out over at the UCG WG.