Repository: rust
Issue: nondeterministic error messages in incremental builds, evaluating whether Future is Send
Labels: T-compiler,A-incr-comp,C-bug

I encountered a bit of code that returns two different error messages, depending on the state of the incremental build.

A reduced version of the code that shows the problem:
```rust
pub struct Watch;

impl Watch {
    pub async fn run(self) {
        self.handle_events().await
    }

    // This always works
    fn spawn_new() {
        executor::spawn(Watch.run());
    }

    async fn handle_events(self) {
        Self::spawn_new();

        let watch = Watch;

        // Comment and uncomment to perturb the error message
        executor::spawn(watch.run());
    }
}

// Fake executor, to make the example self-contained.
mod executor {
    use std::future::Future;
    use std::marker::PhantomData;

    pub struct JoinHandle<T> {
        _p: PhantomData<T>,
    }

    #[track_caller]
    pub fn spawn<F>(future: F) -> JoinHandle<F::Output>
    where
        F: Future + Send + 'static,
        F::Output: Send + 'static,
    {
        todo!()
    }
}
```

I can reproduce the problem with these steps:
1. `cargo check` -- fails with `future cannot be sent between threads safely`
2. Comment out the marked line in handle_events
3. `cargo check` -- succeeds
4. Uncomment the line from step 2 
5. `cargo check` -- fails with `cycle detected when type-checking <impl at src/lib.rs:3:1: 3:11>::handle_events`

The problem is not present if I set `CARGO_INCREMENTAL=0` or use `cargo check --release`.

The full error messages are:
(step 1)
```plaintext
error: future cannot be sent between threads safely
  --> src/lib.rs:19:25
   |
19 |         executor::spawn(watch.run());
   |                         ^^^^^^^^^^^ future returned by `run` is not `Send`
   |
note: opaque type is declared here
  --> src/lib.rs:13:5
   |
13 |     async fn handle_events(self) {
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: this item depends on auto traits of the hidden type, but may also be registering the hidden type. This is not supported right now. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule
  --> src/lib.rs:13:14
   |
13 |     async fn handle_events(self) {
   |              ^^^^^^^^^^^^^
note: future is not `Send` as it awaits another future which is not `Send`
  --> src/lib.rs:5:9
   |
5  |         self.handle_events().await
   |         ^^^^^^^^^^^^^^^^^^^^ await occurs here on type `impl Future<Output = ()>`, which is not `Send`
note: required by a bound in `executor::spawn`
  --> src/lib.rs:35:21
   |
33 |     pub fn spawn<F>(future: F) -> JoinHandle<F::Output>
   |            ----- required by a bound in this function
34 |     where
35 |         F: Future + Send + 'static,
   |                     ^^^^ required by this bound in `spawn`
```

(step 5)
```plaintext
error[E0391]: cycle detected when type-checking `<impl at src/lib.rs:3:1: 3:11>::handle_events`
  --> src/lib.rs:19:9
   |
19 |         executor::spawn(watch.run());
   |         ^^^^^^^^^^^^^^^
   |
   = note: ...which requires evaluating trait selection obligation `<impl at src/lib.rs:3:1: 3:11>::run::{opaque#0}: core::marker::Send`...
   = note: ...which again requires type-checking `<impl at src/lib.rs:3:1: 3:11>::handle_events`, completing the cycle
   = note: cycle used when running analysis passes on this crate
   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
```

### Meta

`rustc --version --verbose`:
```
rustc 1.75.0 (82e1608df 2023-12-21)
binary: rustc
commit-hash: 82e1608dfa6e0b5569232559e3d385fea5a93112
commit-date: 2023-12-21
host: x86_64-unknown-linux-gnu
release: 1.75.0
LLVM version: 17.0.6
```

The same error occurs on `1.78.0-nightly (b11fbfbf3 2024-02-03)`.