From 4e05cfb5ff5f6c27cc02ca76f7c4809c310371a4 Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Fri, 28 Apr 2023 20:21:03 +0000
Subject: [PATCH] Don't duplicate anonymous lifetimes for async fn in traits

---
 compiler/rustc_resolve/src/late.rs            |  6 +--
 tests/ui/async-await/in-trait/nested-rpit.rs  |  4 +-
 .../issue-110963-early.rs                     | 48 ++++++++++++++++++
 .../issue-110963-early.stderr                 | 45 +++++++++++++++++
 .../return-type-notation/issue-110963-late.rs | 50 +++++++++++++++++++
 .../issue-110963-late.stderr                  | 19 +++++++
 6 files changed, 164 insertions(+), 8 deletions(-)
 create mode 100644 tests/ui/async-await/return-type-notation/issue-110963-early.rs
 create mode 100644 tests/ui/async-await/return-type-notation/issue-110963-early.stderr
 create mode 100644 tests/ui/async-await/return-type-notation/issue-110963-late.rs
 create mode 100644 tests/ui/async-await/return-type-notation/issue-110963-late.stderr

diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index a97857e05e2e9..5c02e7193a216 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -859,13 +859,9 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
                             sig.decl.inputs.iter().map(|Param { ty, .. }| (None, &**ty)),
                             &sig.decl.output,
                         );
-
-                        this.record_lifetime_params_for_async(
-                            fn_id,
-                            sig.header.asyncness.opt_return_id(),
-                        );
                     },
                 );
+                self.record_lifetime_params_for_async(fn_id, sig.header.asyncness.opt_return_id());
                 return;
             }
             FnKind::Fn(..) => {
diff --git a/tests/ui/async-await/in-trait/nested-rpit.rs b/tests/ui/async-await/in-trait/nested-rpit.rs
index 41d72ebb4d4c5..9cdc23bbc7809 100644
--- a/tests/ui/async-await/in-trait/nested-rpit.rs
+++ b/tests/ui/async-await/in-trait/nested-rpit.rs
@@ -1,7 +1,5 @@
 // edition: 2021
-// known-bug: #105197
-// failure-status:101
-// dont-check-compiler-stderr
+// check-pass
 
 #![feature(async_fn_in_trait)]
 #![feature(return_position_impl_trait_in_trait)]
diff --git a/tests/ui/async-await/return-type-notation/issue-110963-early.rs b/tests/ui/async-await/return-type-notation/issue-110963-early.rs
new file mode 100644
index 0000000000000..0ecbca5c13bdd
--- /dev/null
+++ b/tests/ui/async-await/return-type-notation/issue-110963-early.rs
@@ -0,0 +1,48 @@
+// edition: 2021
+// known-bug: #110963
+
+#![feature(return_type_notation)]
+#![feature(async_fn_in_trait)]
+
+trait HealthCheck {
+    async fn check<'a: 'a>(&'a mut self) -> bool;
+}
+
+async fn do_health_check_par<HC>(hc: HC)
+where
+    HC: HealthCheck<check(): Send> + Send + 'static,
+{
+    spawn(async move {
+        let mut hc = hc;
+        if !hc.check().await {
+            log_health_check_failure().await;
+        }
+    });
+}
+
+async fn log_health_check_failure() {}
+
+fn main() {}
+
+// Fake tokio spawn
+
+use std::future::Future;
+use std::pin::Pin;
+use std::task::{Context, Poll};
+
+fn spawn<F>(future: F) -> JoinHandle
+where
+    F: Future + Send + 'static,
+    F::Output: Send + 'static,
+{
+    loop {}
+}
+
+struct JoinHandle;
+
+impl Future for JoinHandle {
+    type Output = ();
+    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        loop {}
+    }
+}
diff --git a/tests/ui/async-await/return-type-notation/issue-110963-early.stderr b/tests/ui/async-await/return-type-notation/issue-110963-early.stderr
new file mode 100644
index 0000000000000..b4a3924d8dab9
--- /dev/null
+++ b/tests/ui/async-await/return-type-notation/issue-110963-early.stderr
@@ -0,0 +1,45 @@
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-110963-early.rs:4:12
+   |
+LL | #![feature(return_type_notation)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-110963-early.rs:5:12
+   |
+LL | #![feature(async_fn_in_trait)]
+   |            ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+
+error: higher-ranked lifetime error
+  --> $DIR/issue-110963-early.rs:15:5
+   |
+LL | /     spawn(async move {
+LL | |         let mut hc = hc;
+LL | |         if !hc.check().await {
+LL | |             log_health_check_failure().await;
+LL | |         }
+LL | |     });
+   | |______^
+   |
+   = note: could not prove `[async block@$DIR/issue-110963-early.rs:15:11: 20:6]: Send`
+
+error: higher-ranked lifetime error
+  --> $DIR/issue-110963-early.rs:15:5
+   |
+LL | /     spawn(async move {
+LL | |         let mut hc = hc;
+LL | |         if !hc.check().await {
+LL | |             log_health_check_failure().await;
+LL | |         }
+LL | |     });
+   | |______^
+   |
+   = note: could not prove `[async block@$DIR/issue-110963-early.rs:15:11: 20:6]: Send`
+
+error: aborting due to 2 previous errors; 2 warnings emitted
+
diff --git a/tests/ui/async-await/return-type-notation/issue-110963-late.rs b/tests/ui/async-await/return-type-notation/issue-110963-late.rs
new file mode 100644
index 0000000000000..2a35922eaa1b5
--- /dev/null
+++ b/tests/ui/async-await/return-type-notation/issue-110963-late.rs
@@ -0,0 +1,50 @@
+// edition: 2021
+// check-pass
+
+#![feature(return_type_notation)]
+//~^ WARN the feature `return_type_notation` is incomplete
+#![feature(async_fn_in_trait)]
+//~^ WARN the feature `async_fn_in_trait` is incomplete
+
+trait HealthCheck {
+    async fn check(&mut self) -> bool;
+}
+
+async fn do_health_check_par<HC>(hc: HC)
+where
+    HC: HealthCheck<check(): Send> + Send + 'static,
+{
+    spawn(async move {
+        let mut hc = hc;
+        if !hc.check().await {
+            log_health_check_failure().await;
+        }
+    });
+}
+
+async fn log_health_check_failure() {}
+
+fn main() {}
+
+// Fake tokio spawn
+
+use std::future::Future;
+use std::pin::Pin;
+use std::task::{Context, Poll};
+
+fn spawn<F>(future: F) -> JoinHandle
+where
+    F: Future + Send + 'static,
+    F::Output: Send + 'static,
+{
+    loop {}
+}
+
+struct JoinHandle;
+
+impl Future for JoinHandle {
+    type Output = ();
+    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        loop {}
+    }
+}
diff --git a/tests/ui/async-await/return-type-notation/issue-110963-late.stderr b/tests/ui/async-await/return-type-notation/issue-110963-late.stderr
new file mode 100644
index 0000000000000..36ef3ad0a4c82
--- /dev/null
+++ b/tests/ui/async-await/return-type-notation/issue-110963-late.stderr
@@ -0,0 +1,19 @@
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-110963-late.rs:4:12
+   |
+LL | #![feature(return_type_notation)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-110963-late.rs:6:12
+   |
+LL | #![feature(async_fn_in_trait)]
+   |            ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+
+warning: 2 warnings emitted
+