]> git.lizzy.rs Git - rust.git/blobdiff - compiler/rustc_trait_selection/src/solve/trait_goals.rs
Auto merge of #107443 - cjgillot:generator-less-query, r=compiler-errors
[rust.git] / compiler / rustc_trait_selection / src / solve / trait_goals.rs
index 67bd2495665465d254ec83cc927ce42b0471c975..1ea8fb8fd3dcc8d0d40a2c9dd415e46d808bc101 100644 (file)
@@ -65,7 +65,9 @@ fn consider_assumption(
         goal: Goal<'tcx, Self>,
         assumption: ty::Predicate<'tcx>,
     ) -> QueryResult<'tcx> {
-        if let Some(poly_trait_pred) = assumption.to_opt_poly_trait_pred() {
+        if let Some(poly_trait_pred) = assumption.to_opt_poly_trait_pred()
+            && poly_trait_pred.def_id() == goal.predicate.def_id()
+        {
             // FIXME: Constness and polarity
             ecx.infcx.probe(|_| {
                 let assumption_trait_pred =
@@ -192,6 +194,50 @@ fn consider_builtin_pointee_candidate(
     ) -> QueryResult<'tcx> {
         ecx.make_canonical_response(Certainty::Yes)
     }
+
+    fn consider_builtin_future_candidate(
+        ecx: &mut EvalCtxt<'_, 'tcx>,
+        goal: Goal<'tcx, Self>,
+    ) -> QueryResult<'tcx> {
+        let ty::Generator(def_id, _, _) = *goal.predicate.self_ty().kind() else {
+            return Err(NoSolution);
+        };
+
+        // Generators are not futures unless they come from `async` desugaring
+        let tcx = ecx.tcx();
+        if !tcx.generator_is_async(def_id) {
+            return Err(NoSolution);
+        }
+
+        // Async generator unconditionally implement `Future`
+        ecx.make_canonical_response(Certainty::Yes)
+    }
+
+    fn consider_builtin_generator_candidate(
+        ecx: &mut EvalCtxt<'_, 'tcx>,
+        goal: Goal<'tcx, Self>,
+    ) -> QueryResult<'tcx> {
+        let self_ty = goal.predicate.self_ty();
+        let ty::Generator(def_id, substs, _) = *self_ty.kind() else {
+            return Err(NoSolution);
+        };
+
+        // `async`-desugared generators do not implement the generator trait
+        let tcx = ecx.tcx();
+        if tcx.generator_is_async(def_id) {
+            return Err(NoSolution);
+        }
+
+        let generator = substs.as_generator();
+        Self::consider_assumption(
+            ecx,
+            goal,
+            ty::Binder::dummy(
+                tcx.mk_trait_ref(goal.predicate.def_id(), [self_ty, generator.resume_ty()]),
+            )
+            .to_predicate(tcx),
+        )
+    }
 }
 
 impl<'tcx> EvalCtxt<'_, 'tcx> {
@@ -276,7 +322,7 @@ fn trait_candidate_should_be_dropped_in_favor_of(
         match (candidate.source, other.source) {
             (CandidateSource::Impl(_), _)
             | (CandidateSource::ParamEnv(_), _)
-            | (CandidateSource::AliasBound(_), _)
+            | (CandidateSource::AliasBound, _)
             | (CandidateSource::BuiltinImpl, _) => unimplemented!(),
         }
     }