about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2024-01-18 16:39:20 +0000
committerMichael Goulet <michael@errs.io>2024-02-05 20:33:25 +0000
commit16cbdd0321f342093b71026dc1c5126606e4abe9 (patch)
treef2b339fadda9888ca0724d3c6fe29472e5e02997
parentea37e8091fe87ae0a7e204c034e7d55061e56790 (diff)
downloadrust-16cbdd0321f342093b71026dc1c5126606e4abe9.tar.gz
rust-16cbdd0321f342093b71026dc1c5126606e4abe9.zip
Allow desugaring async fn in trait to compatible, concrete future types
-rw-r--r--compiler/rustc_hir_analysis/messages.ftl4
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs31
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs11
-rw-r--r--tests/ui/async-await/in-trait/async-example-desugared-boxed.rs2
-rw-r--r--tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr11
-rw-r--r--tests/ui/async-await/in-trait/async-example-desugared-manual.rs2
-rw-r--r--tests/ui/async-await/in-trait/async-example-desugared-manual.stderr11
-rw-r--r--tests/ui/async-await/in-trait/fn-not-async-err.rs2
-rw-r--r--tests/ui/async-await/in-trait/fn-not-async-err.stderr18
9 files changed, 15 insertions, 77 deletions
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index 54d0fb6ffab..d0fb0e3fb76 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -33,10 +33,6 @@ hir_analysis_associated_type_trait_uninferred_generic_params = cannot use the as
 
 hir_analysis_associated_type_trait_uninferred_generic_params_multipart_suggestion = use a fully qualified path with explicit lifetimes
 
-hir_analysis_async_trait_impl_should_be_async =
-    method `{$method_name}` should be async because the method from the trait is async
-    .trait_item_label = required because the trait method is async
-
 hir_analysis_auto_deref_reached_recursion_limit = reached the recursion limit while auto-dereferencing `{$ty}`
     .label = deref recursion limit reached
     .help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`)
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index 379c1154e5f..f9c1ed0e0e1 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -74,7 +74,6 @@ fn check_method_is_structurally_compatible<'tcx>(
     compare_generic_param_kinds(tcx, impl_m, trait_m, delay)?;
     compare_number_of_method_arguments(tcx, impl_m, trait_m, delay)?;
     compare_synthetic_generics(tcx, impl_m, trait_m, delay)?;
-    compare_asyncness(tcx, impl_m, trait_m, delay)?;
     check_region_bounds_on_impl_item(tcx, impl_m, trait_m, delay)?;
     Ok(())
 }
@@ -414,36 +413,6 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for RemapLateBound<'_, 'tcx> {
     }
 }
 
-fn compare_asyncness<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    impl_m: ty::AssocItem,
-    trait_m: ty::AssocItem,
-    delay: bool,
-) -> Result<(), ErrorGuaranteed> {
-    if tcx.asyncness(trait_m.def_id).is_async() {
-        match tcx.fn_sig(impl_m.def_id).skip_binder().skip_binder().output().kind() {
-            ty::Alias(ty::Opaque, ..) => {
-                // allow both `async fn foo()` and `fn foo() -> impl Future`
-            }
-            ty::Error(_) => {
-                // We don't know if it's ok, but at least it's already an error.
-            }
-            _ => {
-                return Err(tcx
-                    .dcx()
-                    .create_err(crate::errors::AsyncTraitImplShouldBeAsync {
-                        span: tcx.def_span(impl_m.def_id),
-                        method_name: trait_m.name,
-                        trait_item_span: tcx.hir().span_if_local(trait_m.def_id),
-                    })
-                    .emit_unless(delay));
-            }
-        };
-    }
-
-    Ok(())
-}
-
 /// Given a method def-id in an impl, compare the method signature of the impl
 /// against the trait that it's implementing. In doing so, infer the hidden types
 /// that this method's signature provides to satisfy each return-position `impl Trait`
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index 4eba31e327f..8b8c0f7ff8d 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -167,17 +167,6 @@ pub struct LifetimesOrBoundsMismatchOnTrait {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_async_trait_impl_should_be_async)]
-pub struct AsyncTraitImplShouldBeAsync {
-    #[primary_span]
-    // #[label]
-    pub span: Span,
-    #[label(hir_analysis_trait_item_label)]
-    pub trait_item_span: Option<Span>,
-    pub method_name: Symbol,
-}
-
-#[derive(Diagnostic)]
 #[diag(hir_analysis_drop_impl_on_wrong_item, code = E0120)]
 pub struct DropImplOnWrongItem {
     #[primary_span]
diff --git a/tests/ui/async-await/in-trait/async-example-desugared-boxed.rs b/tests/ui/async-await/in-trait/async-example-desugared-boxed.rs
index c5a9841029e..4008e09998e 100644
--- a/tests/ui/async-await/in-trait/async-example-desugared-boxed.rs
+++ b/tests/ui/async-await/in-trait/async-example-desugared-boxed.rs
@@ -1,4 +1,5 @@
 // edition: 2021
+// check-pass
 
 use std::future::Future;
 use std::pin::Pin;
@@ -9,7 +10,6 @@ trait MyTrait {
 
 impl MyTrait for i32 {
     fn foo(&self) -> Pin<Box<dyn Future<Output = i32> + '_>> {
-        //~^ ERROR method `foo` should be async
         Box::pin(async { *self })
     }
 }
diff --git a/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr b/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr
deleted file mode 100644
index 1462c694e16..00000000000
--- a/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error: method `foo` should be async because the method from the trait is async
-  --> $DIR/async-example-desugared-boxed.rs:11:5
-   |
-LL |     async fn foo(&self) -> i32;
-   |     --------------------------- required because the trait method is async
-...
-LL |     fn foo(&self) -> Pin<Box<dyn Future<Output = i32> + '_>> {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/async-await/in-trait/async-example-desugared-manual.rs b/tests/ui/async-await/in-trait/async-example-desugared-manual.rs
index c287b9a5b84..75f4ba1d076 100644
--- a/tests/ui/async-await/in-trait/async-example-desugared-manual.rs
+++ b/tests/ui/async-await/in-trait/async-example-desugared-manual.rs
@@ -1,4 +1,5 @@
 // edition: 2021
+// check-pass
 
 use std::future::Future;
 use std::task::Poll;
@@ -17,7 +18,6 @@ impl Future for MyFuture {
 
 impl MyTrait for u32 {
     fn foo(&self) -> MyFuture {
-        //~^ ERROR method `foo` should be async
         MyFuture
     }
 }
diff --git a/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr b/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr
deleted file mode 100644
index a2f1060e36f..00000000000
--- a/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error: method `foo` should be async because the method from the trait is async
-  --> $DIR/async-example-desugared-manual.rs:19:5
-   |
-LL |     async fn foo(&self) -> i32;
-   |     --------------------------- required because the trait method is async
-...
-LL |     fn foo(&self) -> MyFuture {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/async-await/in-trait/fn-not-async-err.rs b/tests/ui/async-await/in-trait/fn-not-async-err.rs
index 60077a7e00c..6261ed1f1b7 100644
--- a/tests/ui/async-await/in-trait/fn-not-async-err.rs
+++ b/tests/ui/async-await/in-trait/fn-not-async-err.rs
@@ -8,7 +8,7 @@ trait MyTrait {
 
 impl MyTrait for i32 {
     fn foo(&self) -> i32 {
-        //~^ ERROR: method `foo` should be async
+        //~^ ERROR: `i32` is not a future
         *self
     }
 }
diff --git a/tests/ui/async-await/in-trait/fn-not-async-err.stderr b/tests/ui/async-await/in-trait/fn-not-async-err.stderr
index f75ccb65d15..dc46077d583 100644
--- a/tests/ui/async-await/in-trait/fn-not-async-err.stderr
+++ b/tests/ui/async-await/in-trait/fn-not-async-err.stderr
@@ -1,11 +1,17 @@
-error: method `foo` should be async because the method from the trait is async
-  --> $DIR/fn-not-async-err.rs:10:5
+error[E0277]: `i32` is not a future
+  --> $DIR/fn-not-async-err.rs:10:22
    |
-LL |     async fn foo(&self) -> i32;
-   |     --------------------------- required because the trait method is async
-...
 LL |     fn foo(&self) -> i32 {
-   |     ^^^^^^^^^^^^^^^^^^^^
+   |                      ^^^ `i32` is not a future
+   |
+   = help: the trait `Future` is not implemented for `i32`
+   = note: i32 must be a future or must implement `IntoFuture` to be awaited
+note: required by a bound in `MyTrait::{opaque#0}`
+  --> $DIR/fn-not-async-err.rs:6:5
+   |
+LL |     async fn foo(&self) -> i32;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `MyTrait::{opaque#0}`
 
 error: aborting due to 1 previous error
 
+For more information about this error, try `rustc --explain E0277`.