Skip to content

rustc suggests adding Send trait to the wrong item #127555

Closed
@zabackary

Description

@zabackary

Code

pub trait Foo {
    fn bar<F>(&mut self, func: F) -> impl std::future::Future<Output = ()> + Send
    where
        F: FnMut();
}

struct Baz {}

impl Foo for Baz {
    async fn bar<F>(&mut self, _func: F) -> ()
    where
        F: FnMut() + Send,
    {
        ()
    }
}

Current output

$ cargo check
   Checking playground v0.0.1 (/playground)
error[E0277]: `F` cannot be sent between threads safely
  --> src/lib.rs:10:5
   |
10 | /     async fn bar<F>(&mut self, _func: F) -> ()
11 | |     where
12 | |         F: FnMut() + Send,
   | |__________________________^ `F` cannot be sent between threads safely
   |
note: required by a bound in `<Baz as Foo>::bar`
  --> src/lib.rs:12:22
   |
10 |     async fn bar<F>(&mut self, _func: F) -> ()
   |              --- required by a bound in this associated function
11 |     where
12 |         F: FnMut() + Send,
   |                      ^^^^ required by this bound in `<Baz as Foo>::bar`
help: consider further restricting this bound
   |
12 |         F: FnMut() + Send + std::marker::Send,
   |                           +++++++++++++++++++

error[E0276]: impl has stricter requirements than trait
  --> src/lib.rs:12:22
   |
2  | /     fn bar<F>(&mut self, func: F) -> impl std::future::Future<Output = ()> + Send
3  | |     where
4  | |         F: FnMut();
   | |___________________- definition of `bar` from trait
...
12 |           F: FnMut() + Send,
   |                        ^^^^ impl has extra requirement `F: Send`

Some errors have detailed explanations: E0276, E0277.
For more information about an error, try `rustc --explain E0276`.
error: could not compile `playground` (lib) due to 2 previous errors

Desired output

$ cargo check
   Checking playground v0.0.1 (/playground)
error[E0277]: `F` cannot be sent between threads safely
  --> src/lib.rs:10:5
   |
10 | /     async fn bar<F>(&mut self, _func: F) -> ()
11 | |     where
12 | |         F: FnMut() + Send,
   | |__________________________^ `F` cannot be sent between threads safely
   |
note: required by a bound in `<Baz as Foo>::bar`
  --> src/lib.rs:12:22
   |
10 |     async fn bar<F>(&mut self, _func: F) -> ()
   |              --- required by a bound in this associated function
11 |     where
12 |         F: FnMut() + Send,
   |                      ^^^^ required by this bound in `<Baz as Foo>::bar`
help: consider further restricting this bound
   |
 4 |         F: FnMut() + std::marker::Send,
   |                      +++++++++++++++++++

error[E0276]: impl has stricter requirements than trait
  --> src/lib.rs:12:22
   |
2  | /     fn bar<F>(&mut self, func: F) -> impl std::future::Future<Output = ()> + Send
3  | |     where
4  | |         F: FnMut();
   | |___________________- definition of `bar` from trait
...
12 |           F: FnMut() + Send,
   |                        ^^^^ impl has extra requirement `F: Send`

Some errors have detailed explanations: E0276, E0277.
For more information about an error, try `rustc --explain E0276`.
error: could not compile `playground` (lib) due to 2 previous errors

Rationale and extra context

rustc's suggestion to add the std::marker::Send trait to the impl Foo for Baz impl block is incorrect -- the function in that block already has the marker trait. Instead, it should suggest to add the trait in the where F: FnMut() in the trait definition instead, or raise the error on the trait definition instead, because the real error is made there.

If the suggestion is applied, it will result in a second Send bound added to line 12, which is definitely not correct.

Other cases

No response

Rust Version

$ rustc --version --verbose
rustc 1.79.0 (129f3b996 2024-06-10)
binary: rustc
commit-hash: 129f3b9964af4d4a709d1383930ade12dfe7c081
commit-date: 2024-06-10
host: x86_64-pc-windows-msvc
release: 1.79.0
LLVM version: 18.1.7

Anything else?

This is my first bug on the Rust issue tracker, so apologies if I'm confusing or did something wrong. I've been using Rust for around a year now on and off and it's really such a good language!

Metadata

Metadata

Assignees

Labels

A-diagnosticsArea: Messages for errors, warnings, and lintsT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions