about summary refs log tree commit diff
path: root/compiler/rustc_trait_selection/src
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2024-01-25 19:17:21 +0000
committerMichael Goulet <michael@errs.io>2024-02-06 02:22:58 +0000
commitc98d6994a390044410c55c45195d330e4c8cd3d7 (patch)
tree52cd52eceb02c3bbfd65cff7f227417b27a68a84 /compiler/rustc_trait_selection/src
parent37184e86ea58bc90b8cd97f877d52ccce8ea02ab (diff)
downloadrust-c98d6994a390044410c55c45195d330e4c8cd3d7.tar.gz
rust-c98d6994a390044410c55c45195d330e4c8cd3d7.zip
More comments, final tweaks
Diffstat (limited to 'compiler/rustc_trait_selection/src')
-rw-r--r--compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs24
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs3
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs2
5 files changed, 28 insertions, 7 deletions
diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
index dbf3e4876a9..d02578c4846 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
@@ -309,14 +309,19 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>(
 }
 
 // Returns a binder of the tupled inputs types, output type, and coroutine type
-// from a builtin async closure type.
+// from a builtin coroutine-closure type. If we don't yet know the closure kind of
+// the coroutine-closure, emit an additional trait predicate for `AsyncFnKindHelper`
+// which enforces the closure is actually callable with the given trait. When we
+// know the kind already, we can short-circuit this check.
 pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tcx>(
     tcx: TyCtxt<'tcx>,
     self_ty: Ty<'tcx>,
     goal_kind: ty::ClosureKind,
     env_region: ty::Region<'tcx>,
-) -> Result<(ty::Binder<'tcx, (Ty<'tcx>, Ty<'tcx>, Ty<'tcx>)>, Vec<ty::Predicate<'tcx>>), NoSolution>
-{
+) -> Result<
+    (ty::Binder<'tcx, (Ty<'tcx>, Ty<'tcx>, Ty<'tcx>)>, Option<ty::Predicate<'tcx>>),
+    NoSolution,
+> {
     match *self_ty.kind() {
         ty::CoroutineClosure(def_id, args) => {
             let args = args.as_coroutine_closure();
@@ -339,7 +344,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc
                         );
                         (sig.tupled_inputs_ty, sig.return_ty, coroutine_ty)
                     }),
-                    vec![],
+                    None,
                 ))
             } else {
                 let async_fn_kind_trait_def_id =
@@ -350,6 +355,13 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc
                     .next()
                     .unwrap()
                     .def_id;
+                // When we don't know the closure kind (and therefore also the closure's upvars,
+                // which are computed at the same time), we must delay the computation of the
+                // generator's upvars. We do this using the `AsyncFnKindHelper`, which as a trait
+                // goal functions similarly to the old `ClosureKind` predicate, and ensures that
+                // the goal kind <= the closure kind. As a projection `AsyncFnKindHelper::Upvars`
+                // will project to the right upvars for the generator, appending the inputs and
+                // coroutine upvars respecting the closure kind.
                 Ok((
                     args.coroutine_closure_sig().map_bound(|sig| {
                         let tupled_upvars_ty = Ty::new_projection(
@@ -373,14 +385,14 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc
                         );
                         (sig.tupled_inputs_ty, sig.return_ty, coroutine_ty)
                     }),
-                    vec![
+                    Some(
                         ty::TraitRef::new(
                             tcx,
                             async_fn_kind_trait_def_id,
                             [kind_ty, Ty::from_closure_kind(tcx, goal_kind)],
                         )
                         .to_predicate(tcx),
-                    ],
+                    ),
                 ))
             }
         }
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index a8d6b9812be..955c81eee6b 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -2491,6 +2491,9 @@ fn confirm_async_closure_candidate<'cx, 'tcx>(
     // since all this does is make the solver do more work.
     //
     // The code duplication due to the different length args is kind of weird, too.
+    //
+    // See the logic in `structural_traits` in the new solver to understand a bit
+    // more clearly how this *should* look.
     let poly_cache_entry = args.coroutine_closure_sig().map_bound(|sig| {
         let (projection_ty, term) = match tcx.item_name(obligation.predicate.def_id) {
             sym::CallOnceFuture => {
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index dda68fd4244..2258e796103 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -121,9 +121,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     self.assemble_async_fn_kind_helper_candidates(obligation, &mut candidates);
                 }
 
+                // FIXME: Put these into `else if` blocks above, since they're built-in.
                 self.assemble_closure_candidates(obligation, &mut candidates);
                 self.assemble_async_closure_candidates(obligation, &mut candidates);
                 self.assemble_fn_pointer_candidates(obligation, &mut candidates);
+
                 self.assemble_candidates_from_impls(obligation, &mut candidates);
                 self.assemble_candidates_from_object_ty(obligation, &mut candidates);
             }
@@ -382,6 +384,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             return;
         }
 
+        // Check that the self kind extends the goal kind. If it does,
+        // then there's nothing else to check.
         if let Some(closure_kind) = self_ty.to_opt_closure_kind()
             && let Some(goal_kind) = target_kind_ty.to_opt_closure_kind()
         {
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 79336a9d4e8..c9d06b0f675 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -88,6 +88,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 ImplSource::Builtin(BuiltinImplSource::Misc, vtable_closure)
             }
 
+            // No nested obligations or confirmation process. The checks that we do in
+            // candidate assembly are sufficient.
             AsyncFnKindHelperCandidate => ImplSource::Builtin(BuiltinImplSource::Misc, vec![]),
 
             CoroutineCandidate => {
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index 88584a61b13..b4f13ee95a6 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -728,7 +728,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
                 }
 
                 ty::CoroutineClosure(did, args) => {
-                    // See the above comments.
+                    // See the above comments. The same apply to coroutine-closures.
                     walker.skip_current_subtree();
                     self.compute(args.as_coroutine_closure().tupled_upvars_ty().into());
                     let obligations = self.nominal_obligations(did, args);