about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2023-06-13 20:41:15 +0000
committerMichael Goulet <michael@errs.io>2023-06-13 20:41:15 +0000
commitdbee24d94992df4c1888ebc2095d251fac22c05f (patch)
tree0f9caa7ad214715c9137a8c64e76ec61ca97b17a
parent2ca8d358e55bc56755b597ea96b557232ef8bc86 (diff)
downloadrust-dbee24d94992df4c1888ebc2095d251fac22c05f.tar.gz
rust-dbee24d94992df4c1888ebc2095d251fac22c05f.zip
Suggest correct signature on missing fn returning RPITIT/AFIT
-rw-r--r--compiler/rustc_hir_analysis/src/check/mod.rs31
-rw-r--r--tests/ui/impl-trait/in-trait/suggest-missing-item.fixed22
-rw-r--r--tests/ui/impl-trait/in-trait/suggest-missing-item.rs19
-rw-r--r--tests/ui/impl-trait/in-trait/suggest-missing-item.stderr18
4 files changed, 88 insertions, 2 deletions
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index c9e74896ac0..d8e9e5a0152 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -403,7 +403,32 @@ fn fn_sig_suggestion<'tcx>(
         .flatten()
         .collect::<Vec<String>>()
         .join(", ");
-    let output = sig.output();
+    let mut output = sig.output();
+
+    let asyncness = if tcx.asyncness(assoc.def_id).is_async() {
+        output = if let ty::Alias(_, alias_ty) = *output.kind() {
+            tcx.explicit_item_bounds(alias_ty.def_id)
+                .subst_iter_copied(tcx, alias_ty.substs)
+                .find_map(|(bound, _)| {
+                    bound.to_opt_poly_projection_pred()?.no_bound_vars()?.term.ty()
+                })
+                .unwrap_or_else(|| {
+                    span_bug!(
+                        ident.span,
+                        "expected async fn to have `impl Future` output, but it returns {output}"
+                    )
+                })
+        } else {
+            span_bug!(
+                ident.span,
+                "expected async fn to have `impl Future` output, but it returns {output}"
+            )
+        };
+        "async "
+    } else {
+        ""
+    };
+
     let output = if !output.is_unit() { format!(" -> {output}") } else { String::new() };
 
     let unsafety = sig.unsafety.prefix_str();
@@ -414,7 +439,9 @@ fn fn_sig_suggestion<'tcx>(
     // lifetimes between the `impl` and the `trait`, but this should be good enough to
     // fill in a significant portion of the missing code, and other subsequent
     // suggestions can help the user fix the code.
-    format!("{unsafety}fn {ident}{generics}({args}){output}{where_clauses} {{ todo!() }}")
+    format!(
+        "{unsafety}{asyncness}fn {ident}{generics}({args}){output}{where_clauses} {{ todo!() }}"
+    )
 }
 
 pub fn ty_kind_suggestion(ty: Ty<'_>) -> Option<&'static str> {
diff --git a/tests/ui/impl-trait/in-trait/suggest-missing-item.fixed b/tests/ui/impl-trait/in-trait/suggest-missing-item.fixed
new file mode 100644
index 00000000000..16c4d15ddcd
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/suggest-missing-item.fixed
@@ -0,0 +1,22 @@
+// edition:2021
+// run-rustfix
+
+#![feature(async_fn_in_trait, return_position_impl_trait_in_trait)]
+
+trait Trait {
+    async fn foo();
+
+    async fn bar() -> i32;
+
+    fn test(&self) -> impl Sized + '_;
+}
+
+struct S;
+
+impl Trait for S {fn test(&self) -> impl Sized + '_ { todo!() }
+async fn bar() -> i32 { todo!() }
+async fn foo() { todo!() }
+}
+//~^ ERROR not all trait items implemented
+
+fn main() {}
diff --git a/tests/ui/impl-trait/in-trait/suggest-missing-item.rs b/tests/ui/impl-trait/in-trait/suggest-missing-item.rs
new file mode 100644
index 00000000000..f218e6cb581
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/suggest-missing-item.rs
@@ -0,0 +1,19 @@
+// edition:2021
+// run-rustfix
+
+#![feature(async_fn_in_trait, return_position_impl_trait_in_trait)]
+
+trait Trait {
+    async fn foo();
+
+    async fn bar() -> i32;
+
+    fn test(&self) -> impl Sized + '_;
+}
+
+struct S;
+
+impl Trait for S {}
+//~^ ERROR not all trait items implemented
+
+fn main() {}
diff --git a/tests/ui/impl-trait/in-trait/suggest-missing-item.stderr b/tests/ui/impl-trait/in-trait/suggest-missing-item.stderr
new file mode 100644
index 00000000000..d96641fe163
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/suggest-missing-item.stderr
@@ -0,0 +1,18 @@
+error[E0046]: not all trait items implemented, missing: `foo`, `bar`, `test`
+  --> $DIR/suggest-missing-item.rs:16:1
+   |
+LL |     async fn foo();
+   |     --------------- `foo` from trait
+LL |
+LL |     async fn bar() -> i32;
+   |     ---------------------- `bar` from trait
+LL |
+LL |     fn test(&self) -> impl Sized + '_;
+   |     ---------------------------------- `test` from trait
+...
+LL | impl Trait for S {}
+   | ^^^^^^^^^^^^^^^^ missing `foo`, `bar`, `test` in implementation
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0046`.