4

I feel a little confused about the usage of mem::forget(...) when reading impl Imbalance<T::Balance> for PositiveImbalance<T, I> in pallet-balances pallet.

Accord the forget docs:

Takes ownership and “forgets” about the value without running its destructor.

Why not use drop to dispose of the value forever, any specific reason for this?

fn split(self, amount: T::Balance) -> (Self, Self) {
    let first = self.0.min(amount);
    let second = self.0 - first;

    mem::forget(self); // here
    (Self(first), Self(second))
}
1
  • I think it would be a good idea to leave a comment there, since it might be not obvious
    – pepyakin
    May 25 at 23:01

1 Answer 1

4

Take a look at the trait docs - fn split is meant to return two more instances of Self that still need to be handled. You cannot drop an Imbalance that's yet to be handled because it has a custom Drop impl that adjusts TotalIssuance when an imbalance gets dropped from memory:

impl<T: Config<I>, I: 'static> Drop for PositiveImbalance<T, I> {
    /// Basic drop handler will just square up the total issuance.
    fn drop(&mut self) {
        <super::TotalIssuance<T, I>>::mutate(
            |v| *v = v.saturating_add(self.0)
        );
    }
}

impl<T: Config<I>, I: 'static> Drop for NegativeImbalance<T, I> {
    /// Basic drop handler will just square up the total issuance.
    fn drop(&mut self) {
        <super::TotalIssuance<T, I>>::mutate(
            |v| *v = v.saturating_sub(self.0)
        );
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.