Do I need to implement drop for State Machine?

I created a state machine for GPIO based on exmaple from the Rust Embedded Book:

pub struct Pin<FN> {
    number: u8,
    registers: &'static mut Registers,
    function: FN
}

impl<FN> Pin<FN> {
    fn select_function<F>(self, function: F, fsel: u32) -> Pin<F> {
        let v = fsel << (self.number % 10) * 3;
        let r = &self.registers.gpfsel[(self.number / 10) as usize];
        r.modify(|x| x | v);
        Pin {
            number: self.number,
            registers: self.registers,
            function
        }
    }

    fn into_default(self) -> Pin<Default> {
        Pin {
            number: self.number,
            registers: self.registers,
            function: Default
        }
    }
}

impl Pin<Default> {
    pub fn take(number: u8) -> Option<Self> {
        if PIN_ENABLED.set_bit(number) {
            None
        } else {
            Some(Pin {
                number,
                registers: unsafe {
                    &mut *(BASE_ADDR as *mut Registers)
                },
                function: Default
            })
        }
    }

    pub fn into_output(self) -> Pin<Output> {
        self.select_function(Output, 1)
    }
}

impl Pin<Output> {
    pub fn set(&self) {
        let v = 1u32 << (self.number % 32);
        let r = &self.registers.gpset[(self.number / 32) as usize];
        r.write(v);
    }

    pub fn clear(&self) {
        let v = 1u32 << (self.number % 32);
        let r = &self.registers.gpclr[(self.number / 32) as usize];
        r.write(v);
    }

    pub fn level(&self) -> bool {
        let r = &self.registers.gplev[(self.number / 32) as usize];
        r.read() & 1u32 << (self.number % 32) != 0
    }
}

Well, I'm still not pretty sure I know exactly what I'm doing, but as far as I understand it, in select_function() I use self so that the function takes ownership and self goes out of scope on return, and an instance of new type is created. But do I need to implement Drop for the Pin<FN> type so that it's dropped when goes out of scope?

No, unless you want custom code to be executed upon destruction. Types are automatically and recursively dropped by default, so unless you manually manage memory or other resources yourself (e.g. using raw pointers and an allocator function), you don't need to implement Drop manually in order for your values to be correctly cleaned up on scope exit. This is perhaps one of the most important aspects of automatic memory management in Rust, and (part of) it is usually called RAII.

3 Likes