Add iter macro

This adds an `iter!` macro that can be used to create movable
generators.

This also adds a yield_expr feature so the `yield` keyword can be used
within iter! macro bodies. This was needed because several unstable
features each need `yield` expressions, so this allows us to stabilize
them separately from any individual feature.

Co-authored-by: Oli Scherer <github35764891676564198441@oli-obk.de>
Co-authored-by: Jieyou Xu <jieyouxu@outlook.com>
Co-authored-by: Travis Cross <tc@traviscross.com>
This commit is contained in:
Oli Scherer
2025-02-27 09:51:23 +00:00
committed by Eric Holk
parent aae43c4532
commit 5fbdfc3e10
43 changed files with 826 additions and 61 deletions

View File

@@ -11,7 +11,7 @@ use std::ops::ControlFlow;
use hir::LangItem;
use hir::def_id::DefId;
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
use rustc_hir as hir;
use rustc_hir::{self as hir, CoroutineDesugaring, CoroutineKind};
use rustc_infer::traits::{Obligation, PolyTraitObligation, SelectionError};
use rustc_middle::ty::fast_reject::DeepRejectCtxt;
use rustc_middle::ty::{self, Ty, TypeVisitableExt, TypingMode, elaborate};
@@ -438,6 +438,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
}
#[instrument(level = "debug", skip(self, candidates))]
fn assemble_async_closure_candidates(
&mut self,
obligation: &PolyTraitObligation<'tcx>,
@@ -446,15 +447,30 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let goal_kind =
self.tcx().async_fn_trait_kind_from_def_id(obligation.predicate.def_id()).unwrap();
debug!("self_ty = {:?}", obligation.self_ty().skip_binder().kind());
match *obligation.self_ty().skip_binder().kind() {
ty::CoroutineClosure(_, args) => {
ty::CoroutineClosure(def_id, args) => {
if let Some(closure_kind) =
args.as_coroutine_closure().kind_ty().to_opt_closure_kind()
&& !closure_kind.extends(goal_kind)
{
return;
}
candidates.vec.push(AsyncClosureCandidate);
// Make sure this is actually an async closure.
let Some(coroutine_kind) =
self.tcx().coroutine_kind(self.tcx().coroutine_for_closure(def_id))
else {
bug!("coroutine with no kind");
};
debug!(?coroutine_kind);
match coroutine_kind {
CoroutineKind::Desugared(CoroutineDesugaring::Async, _) => {
candidates.vec.push(AsyncClosureCandidate);
}
_ => (),
}
}
// Closures and fn pointers implement `AsyncFn*` if their return types
// implement `Future`, which is checked later.