Skip to content

as_underscore async closure suggestion tricky #15282

@matthiaskrgr

Description

@matthiaskrgr

Using the following flags

--force-warn clippy::as-underscore

this code:

// Check various forms of dynamic closure calls

//@ edition: 2021
//@ revisions: cfi kcfi
// FIXME(#122848) Remove only-linux once OSX CFI binaries work
//@ only-linux
//@ [cfi] needs-sanitizer-cfi
//@ [kcfi] needs-sanitizer-kcfi
//@ compile-flags: -C target-feature=-crt-static
//@ [cfi] compile-flags: -C codegen-units=1 -C lto -C prefer-dynamic=off -C opt-level=0
//@ [cfi] compile-flags: -Z sanitizer=cfi
//@ [kcfi] compile-flags: -Z sanitizer=kcfi
//@ [kcfi] compile-flags: -C panic=abort -Z panic-abort-tests -C prefer-dynamic=off
//@ run-pass

#![feature(async_fn_traits)]

use std::ops::AsyncFn;

#[inline(never)]
fn identity<T>(x: T) -> T { x }

// We can't actually create a `dyn AsyncFn()`, because it's dyn-incompatible, but we should check
// that we don't bug out when we encounter one.

fn main() {
   let f = identity(async || ());
   let _ = f.async_call(());
   let _ = f();
   let g: Box<dyn FnOnce() -> _> = Box::new(f) as _;
   let _ = g();
}

caused the following diagnostics:

    Checking _async-closures_351853ab1a710924a3ef703bfab0d227adb0da25 v0.1.0 (/tmp/icemaker_global_tempdir.1kJ28KieRA6o/icemaker_clippyfix_tempdir.L3yCMvBmbs7E/_async-closures_351853ab1a710924a3ef703bfab0d227adb0da25)
warning: using `as _` conversion
  --> src/main.rs:30:36
   |
30 |    let g: Box<dyn FnOnce() -> _> = Box::new(f) as _;
   |                                    ^^^^^^^^^^^^^^^-
   |                                                   |
   |                                                   help: consider giving the type explicitly: `std::boxed::Box<dyn std::ops::FnOnce() -> {async closure body@src/main.rs:27:30: 27:32}>`
   |
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#as_underscore
   = note: requested on the command line with `--force-warn clippy::as-underscore`

warning: `_async-closures_351853ab1a710924a3ef703bfab0d227adb0da25` (bin "_async-closures_351853ab1a710924a3ef703bfab0d227adb0da25") generated 1 warning (run `cargo clippy --fix --bin "_async-closures_351853ab1a710924a3ef703bfab0d227adb0da25"` to apply 1 suggestion)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.39s

However after applying these diagnostics, the resulting code:

// Check various forms of dynamic closure calls

//@ edition: 2021
//@ revisions: cfi kcfi
// FIXME(#122848) Remove only-linux once OSX CFI binaries work
//@ only-linux
//@ [cfi] needs-sanitizer-cfi
//@ [kcfi] needs-sanitizer-kcfi
//@ compile-flags: -C target-feature=-crt-static
//@ [cfi] compile-flags: -C codegen-units=1 -C lto -C prefer-dynamic=off -C opt-level=0
//@ [cfi] compile-flags: -Z sanitizer=cfi
//@ [kcfi] compile-flags: -Z sanitizer=kcfi
//@ [kcfi] compile-flags: -C panic=abort -Z panic-abort-tests -C prefer-dynamic=off
//@ run-pass

#![feature(async_fn_traits)]

use std::ops::AsyncFn;

#[inline(never)]
fn identity<T>(x: T) -> T { x }

// We can't actually create a `dyn AsyncFn()`, because it's dyn-incompatible, but we should check
// that we don't bug out when we encounter one.

fn main() {
   let f = identity(async || ());
   let _ = f.async_call(());
   let _ = f();
   let g: Box<dyn FnOnce() -> _> = (Box::new(f) as std::boxed::Box)<dyn std::ops::FnOnce() -> {async closure body@src/main.rs:27:30: 27:32}>;
   let _ = g();
}

no longer compiled:

    Checking _async-closures_351853ab1a710924a3ef703bfab0d227adb0da25 v0.1.0 (/tmp/icemaker_global_tempdir.1kJ28KieRA6o/icemaker_clippyfix_tempdir.L3yCMvBmbs7E/_async-closures_351853ab1a710924a3ef703bfab0d227adb0da25)
error: expected expression, found keyword `dyn`
  --> src/main.rs:30:69
   |
30 |    let g: Box<dyn FnOnce() -> _> = (Box::new(f) as std::boxed::Box)<dyn std::ops::FnOnce() -> {async closure body@src/main.rs:27:30: 27:3...
   |                                                                     ^^^ expected expression

error: could not compile `_async-closures_351853ab1a710924a3ef703bfab0d227adb0da25` (bin "_async-closures_351853ab1a710924a3ef703bfab0d227adb0da25") due to 1 previous error
warning: build failed, waiting for other jobs to finish...
error: could not compile `_async-closures_351853ab1a710924a3ef703bfab0d227adb0da25` (bin "_async-closures_351853ab1a710924a3ef703bfab0d227adb0da25" test) due to 1 previous error

Version:

rustc 1.90.0-nightly (a00149764 2025-07-14)
binary: rustc
commit-hash: a001497644bc229f1abcc5b2528733386591647f
commit-date: 2025-07-14
host: x86_64-unknown-linux-gnu
release: 1.90.0-nightly
LLVM version: 20.1.8

Metadata

Metadata

Assignees

Labels

I-suggestion-causes-errorIssue: The suggestions provided by this Lint cause an ICE/error when applied

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions