summary refs log tree commit diff
path: root/compiler/rustc_next_trait_solver/src
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2024-08-07 12:36:41 -0400
committerMichael Goulet <michael@errs.io>2024-08-08 14:07:31 -0400
commitec1c424293c04258da127ed4dfc8d4289834efe6 (patch)
treee93b77620ed6b1b0adc919be489bf03eb16eb363 /compiler/rustc_next_trait_solver/src
parent9bad7ba324099d124c77c5b06aebf68e11763f7b (diff)
downloadrust-ec1c424293c04258da127ed4dfc8d4289834efe6.tar.gz
rust-ec1c424293c04258da127ed4dfc8d4289834efe6.zip
Don't implement AsyncFn for FnDef/FnPtr that wouldnt implement Fn
Diffstat (limited to 'compiler/rustc_next_trait_solver/src')
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs60
1 files changed, 39 insertions, 21 deletions
diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
index e69d8d84d7d..00837f7cdd8 100644
--- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs
@@ -458,28 +458,23 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<I:
             ))
         }
 
-        ty::FnDef(..) | ty::FnPtr(..) => {
-            let bound_sig = self_ty.fn_sig(cx);
-            let sig = bound_sig.skip_binder();
-            let future_trait_def_id = cx.require_lang_item(TraitSolverLangItem::Future);
-            // `FnDef` and `FnPtr` only implement `AsyncFn*` when their
-            // return type implements `Future`.
-            let nested = vec![
-                bound_sig
-                    .rebind(ty::TraitRef::new(cx, future_trait_def_id, [sig.output()]))
-                    .upcast(cx),
-            ];
-            let future_output_def_id = cx.require_lang_item(TraitSolverLangItem::FutureOutput);
-            let future_output_ty = Ty::new_projection(cx, future_output_def_id, [sig.output()]);
-            Ok((
-                bound_sig.rebind(AsyncCallableRelevantTypes {
-                    tupled_inputs_ty: Ty::new_tup(cx, sig.inputs().as_slice()),
-                    output_coroutine_ty: sig.output(),
-                    coroutine_return_ty: future_output_ty,
-                }),
-                nested,
-            ))
+        ty::FnDef(def_id, _) => {
+            let sig = self_ty.fn_sig(cx);
+            if sig.skip_binder().is_fn_trait_compatible() && !cx.has_target_features(def_id) {
+                fn_item_to_async_callable(cx, sig)
+            } else {
+                Err(NoSolution)
+            }
+        }
+        ty::FnPtr(..) => {
+            let sig = self_ty.fn_sig(cx);
+            if sig.skip_binder().is_fn_trait_compatible() {
+                fn_item_to_async_callable(cx, sig)
+            } else {
+                Err(NoSolution)
+            }
         }
+
         ty::Closure(_, args) => {
             let args = args.as_closure();
             let bound_sig = args.sig();
@@ -563,6 +558,29 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<I:
     }
 }
 
+fn fn_item_to_async_callable<I: Interner>(
+    cx: I,
+    bound_sig: ty::Binder<I, ty::FnSig<I>>,
+) -> Result<(ty::Binder<I, AsyncCallableRelevantTypes<I>>, Vec<I::Predicate>), NoSolution> {
+    let sig = bound_sig.skip_binder();
+    let future_trait_def_id = cx.require_lang_item(TraitSolverLangItem::Future);
+    // `FnDef` and `FnPtr` only implement `AsyncFn*` when their
+    // return type implements `Future`.
+    let nested = vec![
+        bound_sig.rebind(ty::TraitRef::new(cx, future_trait_def_id, [sig.output()])).upcast(cx),
+    ];
+    let future_output_def_id = cx.require_lang_item(TraitSolverLangItem::FutureOutput);
+    let future_output_ty = Ty::new_projection(cx, future_output_def_id, [sig.output()]);
+    Ok((
+        bound_sig.rebind(AsyncCallableRelevantTypes {
+            tupled_inputs_ty: Ty::new_tup(cx, sig.inputs().as_slice()),
+            output_coroutine_ty: sig.output(),
+            coroutine_return_ty: future_output_ty,
+        }),
+        nested,
+    ))
+}
+
 /// Given a coroutine-closure, project to its returned coroutine when we are *certain*
 /// that the closure's kind is compatible with the goal.
 fn coroutine_closure_to_certain_coroutine<I: Interner>(