rust-lang / rust-lang/rust-clippy

[New Lint Request] If possible, suggest releasing sync locks early

Open
#9,399 4 comments 0 reactions 1 assignee View on GitHub

@c410-f3r is already working on this.

Since Jan 1, 2023.

A-lint E-hard L-pedantic L-restriction
Dominant language
Rust
Stars
13.5k
Forks
2.2k
Avg merge
2d 10h
Merged PRs (30d)
32

Description

Problem

Code that heavily depends on synchronous primitives like Mutex can suffer unnecessary resource contention if the lock is only released at the end of its scope through Drop but could in fact be released early.

fn example_1() {
  let locked = some_sync_resource.lock();
  let owned_rslt = locked.do_stuff_with_resource();
  // Only `owned_rslt` is needed but `locked` is still held
  do_heavy_computation_that_takes_time(owned_rslt);
}

fn example_2() {
  let locked = some_sync_resource.lock();
  let reference = locked.get_inner_resource_ref();
  let _ = reference.do_stuff();
  let _ = reference.do_other_things();
  // From this point forward, `locked` is not needed anymore
  let _ = compute_foo();
  let _ = compute_bar();
  let _ = compute_baz();
}

Request

A new lint called sync_lock_drop that asks for an explicit "inline" expression or an explicit drop call. The above snippets would then be rewritten as follows:

fn example_1() {
  let owned_rslt = some_sync_resource.lock().do_stuff_with_resource();
  do_heavy_computation_that_takes_time(owned_rslt);
}

fn example_2() {
  let locked = some_sync_resource.lock();
  let reference = locked.get_inner_resource_ref();
  let _ = reference.do_stuff();
  let _ = reference.do_other_things();
  drop(locked);
  let _ = compute_foo();
  let _ = compute_bar();
  let _ = compute_baz();
}

Implementation

It is trivial to detect synchronous primitives of the standard library but third-party implementations are tricky to detect. What should be done here? Hard code a list of well-known crates or allow users to provide a list of custom types?

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.