rust-lang / rust-lang/rust-clippy

False positive for `await_holding_refcell_ref`: RefMut for keeping the awaited future alive

Open
#6,671 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

C-bug E-medium I-false-positive
Dominant language
Rust
Stars
13.5k
Forks
2.2k
Avg merge
2d 10h
Merged PRs (30d)
32

Description

Lint name: await_holding_refcell_ref

I tried this code:

#[wasm_bindgen]
struct IntoUnderlyingSink {
    inner: Rc<RefCell<Inner>>,
}

#[wasm_bindgen]
impl IntoUnderlyingSink {
    pub fn write(&mut self, chunk: JsValue) -> Promise {
        let inner = self.inner.clone();
        future_to_promise(async move {
            let mut inner = inner.try_borrow_mut().unwrap_throw();
            inner.write(chunk).await.map(|_| JsValue::undefined())
        })
    }
}

impl Inner {
    async fn write(&mut self, chunk: JsValue) -> Result<(), JsValue> {
        // ...
    }
}

(For more context, see the complete code.)

This might seem a bit of a contrived example, but it's actually the only way I found to use async fn inside a Rust struct exported to JavaScript with wasm-bindgen. 🤷 (Better suggestions are welcome though!)

I expected to see this happen: No error since the RefMut is necessary to keep the inner.write(chunk) future alive.

Instead, this happened: Causes a warning.

error: this RefCell Ref is held across an 'await' point. Consider ensuring the Ref is dropped before calling await.
  --> src\writable\into_underlying_sink.rs:30:17
   |
30 |             let mut inner = inner.try_borrow_mut().unwrap_throw();
   |                 ^^^^^^^^^
   |
   = note: `#[deny(clippy::await_holding_refcell_ref)]` on by default
note: these are all the await points this ref is held through
  --> src\writable\into_underlying_sink.rs:30:13
   |
30 | /             let mut inner = inner.try_borrow_mut().unwrap_throw();
31 | |             inner.write(chunk).await.map(|_| JsValue::undefined())
32 | |         })
   | |_________^
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#await_holding_refcell_ref
Meta
  • cargo clippy -V: clippy 0.0.212 (e1884a8e 2020-12-29)
  • rustc -Vv:
    rustc 1.49.0 (e1884a8e3 2020-12-29)
    binary: rustc
    commit-hash: e1884a8e3c3e813aada8254edfa120e85bf5ffca
    commit-date: 2020-12-29
    host: x86_64-pc-windows-msvc
    release: 1.49.0
    

I noticed that this particular lint was already downgraded in #6354 for Rust 1.50 (currently in beta). I can confirm that the warning does not show up when using Rust beta or nightly with the default settings. Since it only shows up in Rust 1.49, I worked around it on my end by disabling this lint.

Still, I opened this issue since I think this might be an interesting false positive. Feel free to close if you disagree, no hard feelings. 🙂

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.

Research direction

Start by reproducing the await_holding_refcell_ref warning with the Rust example and the linked src/writable/into_underlying_sink.rs code. Read the lint entry point and its existing tests, then verify that a RefMut needed to keep an awaited future alive is no longer reported while genuine RefCell references held across await points remain diagnosed.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust, wasm
Domain
devtools, tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.