rust-lang / rust-lang/rust-clippy
Invalid `manual_map` suggestion for `#[track_caller]` function
Open
@willwang-io is already working on this.
Since Sep 8, 2026.
C-bug
I-false-positive
I-suggestion-causes-bug
- Dominant language
- Rust
- Stars
- 13.5k
- Forks
- 2.2k
- Avg merge
- 2d 10h
- Merged PRs (30d)
- 32
Description
Summary
The manual_map lint does not take into account that introducing a closure breaks propagation of #[track_caller].
Lint Name
manual_map
Reproducer
I tried this code:
#[track_caller]
pub fn timeout<F>(duration: Duration, future: F) -> Timeout<F::IntoFuture>
where
F: IntoFuture,
{
Timeout {
value: future.into_future(),
delay: match Instant::now().checked_add(duration) {
Some(deadline) => Some(Sleep::new_timeout(deadline, trace::caller_location())),
None => None,
},
}
}
I saw this happen:
warning: manual implementation of `Option::map`
--> tokio/src/time/timeout.rs:93:16
|
93 | delay: match Instant::now().checked_add(duration) {
| ________________^
94 | | Some(deadline) => Some(Sleep::new_timeout(deadline, trace:...
95 | | None => None,
96 | | },
| |_________^ help: try: `Instant::now().checked_add(duration).map(|deadline| Sleep::new_timeout(deadline, trace::caller_location()))`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.97.0/index.html#manual_map
= note: `#[warn(clippy::manual_map)]` on by default
But this suggestion breaks this test:
#[test]
fn timeout_panic_caller() -> Result<(), Box<dyn Error>> {
let panic_location_file = test_panic(|| {
// Runtime without `enable_time` so it has no current timer set.
let rt = Builder::new_current_thread().build().unwrap();
rt.block_on(async {
let _timeout = timeout(Duration::from_millis(5), future::pending::<()>());
});
});
// The panic location should be in this file
assert_eq!(&panic_location_file.unwrap(), file!());
Ok(())
}
running 1 test
test timeout_panic_caller ... FAILED
failures:
---- timeout_panic_caller stdout ----
thread 'timeout_panic_caller' (1565071) panicked at tokio/tests/time_panic.rs:135:5:
assertion `left == right` failed
left: "tokio/src/time/timeout.rs"
right: "tokio/tests/time_panic.rs"
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
failures:
timeout_panic_caller
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 5 filtered out; finished in 0.00s
error: test failed, to rerun pass `--test time_panic`
Clippy should not emit this warning when the surrounding function is #[track_caller] and the closure invokes an #[track_caller] method.
Version
rustc 1.97.0 (2d8144b78 2026-07-07)
binary: rustc
commit-hash: 2d8144b7880597b6e6d3dfd63a9a9efae3f533d3
commit-date: 2026-07-07
host: x86_64-unknown-linux-gnu
release: 1.97.0
LLVM version: 22.1.6
Additional Labels
@rustbot label +I-suggestion-causes-bug
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.