You are actually wrong about ::scope_guard::ScopeGuard<_, _, ::scope_guard::Always> (the one you gave an implementation for) not being “zero cost”,
since
if <S as ::scope_guard::Strategy>::should_run() {
dropfn(value);
}
becomes
if true {
dropfn(value);
}
when S = Always, and then the if true { ... } gets optimized into { ... }.
(That is, by the way, the whole point of using structs generic over a trait instead of structs having bool-like fields.)
With the other Strategy-s, there is a runtime check since it does have to know whether it is panicking or not. That case could be optimised by forcing the end user to silently drop the closure after the “panicable section” (e.g. by using a macro). I was thinking of releasing such a crate because I had the same “idea” as the OP, but as usual, someone had already done it (c.f. ::scope_guard).