drop to replace
ignore (unlock ..) for more lock-type-safety
This PR, coming out of joint work with @Armael, can be summarized by the corresponding mli documentation:
(** Releases any locks on the given global state and then ignores it. Using [drop gt] is equivalent to [ignore (unlock gt)], and safer than other uses of [ignore] where it is not enforced by the type-system that the value is unlocked before it is lost. *) val drop: 'a global_state -> unit
The idea is applied to all three kinds of states-with-locks (global, switch, repos), and then
Example from the patch:
- ignore (OpamSwitchState.unlock st); - ignore (clear_switch gt switch) + OpamSwitchState.drop st; + OpamGlobalState.drop (clear_switch gt switch)
I didn't find any instance where locks were silently ignored incorrectly. Besides the fact that the resulting code is generally nicer, the point of porting the whole opam codebase is to encourage clueless users of opam-lib (us, for example) to follow the same style and avoid mistakes there.
The text was updated successfully, but these errors were encountered:
Using `ignore` when dealing with locks introduces a risk of silently dropping a lock without unlocking it. The current opam codebase uses the `ignore (unlock ...)` pattern which is always safe, but also other patterns such as `ignore (pin ...)` which cannot be checked locally, but depend on the use of `with_` above. The goal of this `drop` function is to completely replace the usage of `ignore` on lock types, enforcing lock-safety by design. Note: profusely using `drop` results in `unlock` often being called several time on the same lock (typically the lock is scoped under a `with_` and would be dropped anyway), but this perfectly fine as `unlock` implementations can be used multiple time on the same lock (unlocking is idempotent). A previous version of this API change restricted `drop` to `unlocked` arguments (and was an alias for `ignore`), but we found that this doesn't cover many use-cases of `ignore` on locks in the opam codebase, necessiting an extra `with_drop` variable for total coverage. The current, more powerful `drop` function (suggested by Armaël Guéneau) is more flexible and can cover all `ignore` use-cases. Note: `drop` is implemented using `let _ = unlock lock in ()` instead of `ignore` directly, so that you can find code to improve by grepping for `ignore` without seeting these false positives.