Skip to content

Conversation

@estebank
Copy link
Contributor

@estebank estebank commented Nov 4, 2025

Point at return type of async fns instead of their def Span.

Correctly provide suggestions when encountering async fn with a dyn Trait return type.

Correctly address type Alias = dyn Trait when fn foo() -> Alias { .. }.

Fix #147894.

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Nov 4, 2025
@rustbot
Copy link
Collaborator

rustbot commented Nov 4, 2025

r? @jackh726

rustbot has assigned @jackh726.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

```
error[E0277]: the size for values of type `(dyn Debug + 'static)` cannot be known at compilation time
  --> $DIR/dyn-trait-type-alias-return-type.rs:4:11
   |
LL | fn f() -> T { loop {} }
   |           ^ doesn't have a size known at compile-time
   |
   = help: the trait `Sized` is not implemented for `(dyn Debug + 'static)`
note: this type alias is unsized
  --> $DIR/dyn-trait-type-alias-return-type.rs:1:1
   |
LL | type T = dyn core::fmt::Debug;
   | ^^^^^^
   = note: the return type of a function must have a statically known size
```
@rust-log-analyzer
Copy link
Collaborator

The job x86_64-gnu-tools failed! Check out the build log: (web) (plain enhanced) (plain)

Click to see the possible cause of the failure (guessed by this bot)
tests/ui/size_of_in_element_count/functions.rs ... ok
tests/ui/crashes/third-party/conf_allowlisted.rs ... ok

FAILED TEST: tests/ui/future_not_send.rs
command: CLIPPY_CONF_DIR="tests" RUSTC_ICE="0" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/release/clippy-driver" "--error-format=json" "--emit=metadata" "-Aunused" "-Ainternal_features" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "-Dwarnings" "-Ldependency=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/release/deps" "--sysroot=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2" "--out-dir" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/ui_test/0/tests/ui" "tests/ui/future_not_send.rs" "--extern" "futures=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/debug/deps/libfutures-a8bf6f69c9b80e37.rlib" "--extern" "futures=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/debug/deps/libfutures-a8bf6f69c9b80e37.rmeta" "--extern" "itertools=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/debug/deps/libitertools-2d82d3ce68d9c3ee.rlib" "--extern" "itertools=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/debug/deps/libitertools-2d82d3ce68d9c3ee.rmeta" "--extern" "libc=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/debug/deps/liblibc-e86cd1a7c22fc60c.rlib" "--extern" "libc=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/debug/deps/liblibc-e86cd1a7c22fc60c.rmeta" "--extern" "parking_lot=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/debug/deps/libparking_lot-a94abfa769f04e5d.rlib" "--extern" "parking_lot=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/debug/deps/libparking_lot-a94abfa769f04e5d.rmeta" "--extern" "quote=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/debug/deps/libquote-22b65b7753b00e23.rlib" "--extern" "quote=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/debug/deps/libquote-22b65b7753b00e23.rmeta" "--extern" "regex=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/debug/deps/libregex-4368476ea091f8ef.rlib" "--extern" "regex=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/debug/deps/libregex-4368476ea091f8ef.rmeta" "--extern" "serde=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/debug/deps/libserde-978a92b8a77cdf3d.rlib" "--extern" "serde=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/debug/deps/libserde-978a92b8a77cdf3d.rmeta" "--extern" "syn=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/debug/deps/libsyn-fdddf18d670fbd00.rlib" "--extern" "syn=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/debug/deps/libsyn-fdddf18d670fbd00.rmeta" "--extern" "tokio=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/debug/deps/libtokio-1fc6a815de90452d.rlib" "--extern" "tokio=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/debug/deps/libtokio-1fc6a815de90452d.rmeta" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/debug/deps" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/debug/deps" "--edition" "2024"

error: actual output differed from expected
Execute `./x test src/tools/clippy --bless` to update `tests/ui/future_not_send.stderr` to the actual output
--- tests/ui/future_not_send.stderr
+++ <stderr output>
 error: future cannot be sent between threads safely
-  --> tests/ui/future_not_send.rs:8:1
+  --> tests/ui/future_not_send.rs:8:62
    |
 LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `private_future` is not `Send`
+   |                                                              ^^^^ future returned by `private_future` is not `Send`
    |
 note: future is not `Send` as this value is used across an await
... 16 lines skipped ...
 
 error: future cannot be sent between threads safely
-  --> tests/ui/future_not_send.rs:14:1
+  --> tests/ui/future_not_send.rs:14:41
    |
 LL | pub async fn public_future(rc: Rc<[u8]>) {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `public_future` is not `Send`
+   |                                         ^ future returned by `public_future` is not `Send`
    |
 note: future is not `Send` as this value is used across an await
... 8 lines skipped ...
 
 error: future cannot be sent between threads safely
-  --> tests/ui/future_not_send.rs:24:1
+  --> tests/ui/future_not_send.rs:24:63
    |
 LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `private_future2` is not `Send`
+   |                                                               ^^^^ future returned by `private_future2` is not `Send`
    |
 note: captured value is not `Send`
... 11 lines skipped ...
 
 error: future cannot be sent between threads safely
-  --> tests/ui/future_not_send.rs:30:1
+  --> tests/ui/future_not_send.rs:30:42
    |
 LL | pub async fn public_future2(rc: Rc<[u8]>) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `public_future2` is not `Send`
+   |                                          ^ future returned by `public_future2` is not `Send`
    |
 note: captured value is not `Send`
... 5 lines skipped ...
 
 error: future cannot be sent between threads safely
---
-  --> tests/ui/future_not_send.rs:49:5
+  --> tests/ui/future_not_send.rs:49:38
    |
 LL |     pub async fn public_future(&self) {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `public_future` is not `Send`
+   |                                      ^ future returned by `public_future` is not `Send`
    |
 note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync`
... 5 lines skipped ...
 
 error: future cannot be sent between threads safely
---
    |
-LL | / async fn generic_future<T>(t: T) -> T
-LL | |
-LL | | where
-LL | |     T: Send,
-   | |____________^ future returned by `generic_future` is not `Send`
+LL | async fn generic_future<T>(t: T) -> T
+   |                                     ^ future returned by `generic_future` is not `Send`
    |
 note: future is not `Send` as this value is used across an await
... 7 lines skipped ...
 
 error: future cannot be sent between threads safely
-  --> tests/ui/future_not_send.rs:83:1
+  --> tests/ui/future_not_send.rs:83:51
    |
 LL | async fn generic_future_always_unsend<T>(_: Rc<T>) {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `generic_future_always_unsend` is not `Send`
+   |                                                   ^ future returned by `generic_future_always_unsend` is not `Send`
    |
 note: future is not `Send` as this value is used across an await
... 9 lines skipped ...
 error: aborting due to 8 previous errors
 

Full unnormalized output:
error: future cannot be sent between threads safely
##[error]  --> tests/ui/future_not_send.rs:8:62
   |
LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
   |                                                              ^^^^ future returned by `private_future` is not `Send`
   |
note: future is not `Send` as this value is used across an await
  --> tests/ui/future_not_send.rs:11:20
   |
LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
   |                         -- has type `std::rc::Rc<[u8]>` which is not `Send`
...
LL |     async { true }.await
   |                    ^^^^^ await occurs here, with `rc` maybe used later
   = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send`
note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync`
  --> tests/ui/future_not_send.rs:8:39
   |
LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
   |                                       ^^^^ has type `&std::cell::Cell<usize>` which is not `Send`, because `std::cell::Cell<usize>` is not `Sync`
   = note: `std::cell::Cell<usize>` doesn't implement `std::marker::Sync`
   = note: `-D clippy::future-not-send` implied by `-D warnings`
   = help: to override `-D warnings` add `#[allow(clippy::future_not_send)]`

error: future cannot be sent between threads safely
##[error]  --> tests/ui/future_not_send.rs:14:41
   |
LL | pub async fn public_future(rc: Rc<[u8]>) {
   |                                         ^ future returned by `public_future` is not `Send`
   |
note: future is not `Send` as this value is used across an await
  --> tests/ui/future_not_send.rs:17:20
   |
LL | pub async fn public_future(rc: Rc<[u8]>) {
   |                            -- has type `std::rc::Rc<[u8]>` which is not `Send`
...
LL |     async { true }.await;
   |                    ^^^^^ await occurs here, with `rc` maybe used later
   = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send`

error: future cannot be sent between threads safely
##[error]  --> tests/ui/future_not_send.rs:24:63
   |
LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
   |                                                               ^^^^ future returned by `private_future2` is not `Send`
   |
note: captured value is not `Send`
  --> tests/ui/future_not_send.rs:24:26
   |
LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
   |                          ^^ has type `std::rc::Rc<[u8]>` which is not `Send`
   = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send`
note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync`
  --> tests/ui/future_not_send.rs:24:40
   |
LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
   |                                        ^^^^ has type `&std::cell::Cell<usize>` which is not `Send`, because `std::cell::Cell<usize>` is not `Sync`
   = note: `std::cell::Cell<usize>` doesn't implement `std::marker::Sync`

error: future cannot be sent between threads safely
##[error]  --> tests/ui/future_not_send.rs:30:42
   |
LL | pub async fn public_future2(rc: Rc<[u8]>) {}
   |                                          ^ future returned by `public_future2` is not `Send`
   |
note: captured value is not `Send`
  --> tests/ui/future_not_send.rs:30:29
   |
LL | pub async fn public_future2(rc: Rc<[u8]>) {}
   |                             ^^ has type `std::rc::Rc<[u8]>` which is not `Send`
   = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send`

error: future cannot be sent between threads safely
##[error]  --> tests/ui/future_not_send.rs:42:39
   |
LL |     async fn private_future(&self) -> usize {
   |                                       ^^^^^ future returned by `private_future` is not `Send`
   |
note: future is not `Send` as this value is used across an await
  --> tests/ui/future_not_send.rs:45:24
   |
LL |     async fn private_future(&self) -> usize {
   |                             ----- has type `&Dummy` which is not `Send`
...
LL |         async { true }.await;
   |                        ^^^^^ await occurs here, with `&self` maybe used later
   = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Sync`

error: future cannot be sent between threads safely
##[error]  --> tests/ui/future_not_send.rs:49:38
   |
LL |     pub async fn public_future(&self) {
   |                                      ^ future returned by `public_future` is not `Send`
   |
note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync`
  --> tests/ui/future_not_send.rs:49:32
   |
LL |     pub async fn public_future(&self) {
   |                                ^^^^^ has type `&Dummy` which is not `Send`, because `Dummy` is not `Sync`
   = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Sync`

error: future cannot be sent between threads safely
##[error]  --> tests/ui/future_not_send.rs:61:37
   |
LL | async fn generic_future<T>(t: T) -> T
   |                                     ^ future returned by `generic_future` is not `Send`
   |
note: future is not `Send` as this value is used across an await
  --> tests/ui/future_not_send.rs:67:20
   |
LL |     let rt = &t;
   |         -- has type `&T` which is not `Send`
LL |     async { true }.await;
   |                    ^^^^^ await occurs here, with `rt` maybe used later
   = note: `T` doesn't implement `std::marker::Sync`

error: future cannot be sent between threads safely
##[error]  --> tests/ui/future_not_send.rs:83:51
   |
LL | async fn generic_future_always_unsend<T>(_: Rc<T>) {
   |                                                   ^ future returned by `generic_future_always_unsend` is not `Send`
   |
note: future is not `Send` as this value is used across an await
  --> tests/ui/future_not_send.rs:86:20
   |
LL | async fn generic_future_always_unsend<T>(_: Rc<T>) {
   |                                          - has type `std::rc::Rc<T>` which is not `Send`
...
LL |     async { true }.await;
   |                    ^^^^^ await occurs here, with `_` maybe used later
   = note: `std::rc::Rc<T>` doesn't implement `std::marker::Send`

error: aborting due to 8 previous errors



full stderr:
error: future cannot be sent between threads safely
##[error]  --> tests/ui/future_not_send.rs:8:62
   |
LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
   |                                                              ^^^^ future returned by `private_future` is not `Send`
   |
note: future is not `Send` as this value is used across an await
  --> tests/ui/future_not_send.rs:11:20
   |
LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
   |                         -- has type `std::rc::Rc<[u8]>` which is not `Send`
...
LL |     async { true }.await
   |                    ^^^^^ await occurs here, with `rc` maybe used later
   = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send`
note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync`
  --> tests/ui/future_not_send.rs:8:39
   |
LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
   |                                       ^^^^ has type `&std::cell::Cell<usize>` which is not `Send`, because `std::cell::Cell<usize>` is not `Sync`
   = note: `std::cell::Cell<usize>` doesn't implement `std::marker::Sync`
   = note: `-D clippy::future-not-send` implied by `-D warnings`
   = help: to override `-D warnings` add `#[allow(clippy::future_not_send)]`

error: future cannot be sent between threads safely
##[error]  --> tests/ui/future_not_send.rs:14:41
   |
LL | pub async fn public_future(rc: Rc<[u8]>) {
   |                                         ^ future returned by `public_future` is not `Send`
   |
note: future is not `Send` as this value is used across an await
  --> tests/ui/future_not_send.rs:17:20
   |
LL | pub async fn public_future(rc: Rc<[u8]>) {
   |                            -- has type `std::rc::Rc<[u8]>` which is not `Send`
...
LL |     async { true }.await;
   |                    ^^^^^ await occurs here, with `rc` maybe used later
   = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send`

error: future cannot be sent between threads safely
##[error]  --> tests/ui/future_not_send.rs:24:63
   |
LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
   |                                                               ^^^^ future returned by `private_future2` is not `Send`
   |
note: captured value is not `Send`
  --> tests/ui/future_not_send.rs:24:26
   |
LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
   |                          ^^ has type `std::rc::Rc<[u8]>` which is not `Send`
   = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send`
note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync`
  --> tests/ui/future_not_send.rs:24:40
   |
LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
   |                                        ^^^^ has type `&std::cell::Cell<usize>` which is not `Send`, because `std::cell::Cell<usize>` is not `Sync`
   = note: `std::cell::Cell<usize>` doesn't implement `std::marker::Sync`

error: future cannot be sent between threads safely
##[error]  --> tests/ui/future_not_send.rs:30:42
   |
LL | pub async fn public_future2(rc: Rc<[u8]>) {}
   |                                          ^ future returned by `public_future2` is not `Send`
   |
note: captured value is not `Send`
  --> tests/ui/future_not_send.rs:30:29
   |
LL | pub async fn public_future2(rc: Rc<[u8]>) {}
   |                             ^^ has type `std::rc::Rc<[u8]>` which is not `Send`
   = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send`

error: future cannot be sent between threads safely
##[error]  --> tests/ui/future_not_send.rs:42:39
   |
LL |     async fn private_future(&self) -> usize {
   |                                       ^^^^^ future returned by `private_future` is not `Send`
   |
note: future is not `Send` as this value is used across an await
  --> tests/ui/future_not_send.rs:45:24
   |
LL |     async fn private_future(&self) -> usize {
   |                             ----- has type `&Dummy` which is not `Send`
...
LL |         async { true }.await;
   |                        ^^^^^ await occurs here, with `&self` maybe used later
   = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Sync`

error: future cannot be sent between threads safely
##[error]  --> tests/ui/future_not_send.rs:49:38
   |
LL |     pub async fn public_future(&self) {
   |                                      ^ future returned by `public_future` is not `Send`
   |
note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync`
  --> tests/ui/future_not_send.rs:49:32
   |
LL |     pub async fn public_future(&self) {
   |                                ^^^^^ has type `&Dummy` which is not `Send`, because `Dummy` is not `Sync`
   = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Sync`

error: future cannot be sent between threads safely
##[error]  --> tests/ui/future_not_send.rs:61:37
   |
LL | async fn generic_future<T>(t: T) -> T
   |                                     ^ future returned by `generic_future` is not `Send`
   |
note: future is not `Send` as this value is used across an await
  --> tests/ui/future_not_send.rs:67:20
   |
LL |     let rt = &t;
   |         -- has type `&T` which is not `Send`
LL |     async { true }.await;
   |                    ^^^^^ await occurs here, with `rt` maybe used later
   = note: `T` doesn't implement `std::marker::Sync`

error: future cannot be sent between threads safely
##[error]  --> tests/ui/future_not_send.rs:83:51
   |
LL | async fn generic_future_always_unsend<T>(_: Rc<T>) {
   |                                                   ^ future returned by `generic_future_always_unsend` is not `Send`
   |
note: future is not `Send` as this value is used across an await
  --> tests/ui/future_not_send.rs:86:20
   |
LL | async fn generic_future_always_unsend<T>(_: Rc<T>) {
   |                                          - has type `std::rc::Rc<T>` which is not `Send`
...
LL |     async { true }.await;
   |                    ^^^^^ await occurs here, with `_` maybe used later
   = note: `std::rc::Rc<T>` doesn't implement `std::marker::Send`

error: aborting due to 8 previous errors


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

rust compiler yields obviously broken suggestions around dyn/impl use when tickled right

4 participants