s/generator/coroutine/

This commit is contained in:
Oli Scherer 2023-10-19 21:46:28 +00:00
parent 60956837cf
commit e96ce20b34
468 changed files with 2201 additions and 2197 deletions

View file

@ -191,18 +191,18 @@ pub(super) trait GoalKind<'tcx>:
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx>;
/// A generator (that comes from an `async` desugaring) is known to implement
/// `Future<Output = O>`, where `O` is given by the generator's return type
/// A coroutine (that comes from an `async` desugaring) is known to implement
/// `Future<Output = O>`, where `O` is given by the coroutine's return type
/// that was computed during type-checking.
fn consider_builtin_future_candidate(
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx>;
/// A generator (that doesn't come from an `async` desugaring) is known to
/// A coroutine (that doesn't come from an `async` desugaring) is known to
/// implement `Coroutine<R, Yield = Y, Return = O>`, given the resume, yield,
/// and return types of the generator computed during type-checking.
fn consider_builtin_generator_candidate(
/// and return types of the coroutine computed during type-checking.
fn consider_builtin_coroutine_candidate(
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx>;
@ -467,7 +467,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
ty::Alias(_, _) | ty::Placeholder(..) | ty::Error(_) => (),
// FIXME: These should ideally not exist as a self type. It would be nice for
// the builtin auto trait impls of generators to instead directly recurse
// the builtin auto trait impls of coroutines to instead directly recurse
// into the witness.
ty::CoroutineWitness(..) => (),
@ -553,7 +553,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
} else if lang_items.future_trait() == Some(trait_def_id) {
G::consider_builtin_future_candidate(self, goal)
} else if lang_items.gen_trait() == Some(trait_def_id) {
G::consider_builtin_generator_candidate(self, goal)
G::consider_builtin_coroutine_candidate(self, goal)
} else if lang_items.discriminant_kind_trait() == Some(trait_def_id) {
G::consider_builtin_discriminant_kind_candidate(self, goal)
} else if lang_items.destruct_trait() == Some(trait_def_id) {

View file

@ -12,7 +12,7 @@ use crate::solve::EvalCtxt;
// Calculates the constituent types of a type for `auto trait` purposes.
//
// For types with an "existential" binder, i.e. generator witnesses, we also
// For types with an "existential" binder, i.e. coroutine witnesses, we also
// instantiate the binder with placeholders eagerly.
pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>(
ecx: &EvalCtxt<'_, 'tcx>,
@ -57,13 +57,13 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>(
ty::Closure(_, ref args) => Ok(vec![args.as_closure().tupled_upvars_ty()]),
ty::Coroutine(_, ref args, _) => {
let generator_args = args.as_generator();
Ok(vec![generator_args.tupled_upvars_ty(), generator_args.witness()])
let coroutine_args = args.as_coroutine();
Ok(vec![coroutine_args.tupled_upvars_ty(), coroutine_args.witness()])
}
ty::CoroutineWitness(def_id, args) => Ok(ecx
.tcx()
.generator_hidden_types(def_id)
.coroutine_hidden_types(def_id)
.map(|bty| {
ecx.instantiate_binder_with_placeholders(replace_erased_lifetimes_with_bound_vars(
tcx,
@ -192,9 +192,9 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>(
ty::Closure(_, args) => Ok(vec![args.as_closure().tupled_upvars_ty()]),
ty::Coroutine(_, args, Movability::Movable) => {
if ecx.tcx().features().generator_clone {
let generator = args.as_generator();
Ok(vec![generator.tupled_upvars_ty(), generator.witness()])
if ecx.tcx().features().coroutine_clone {
let coroutine = args.as_coroutine();
Ok(vec![coroutine.tupled_upvars_ty(), coroutine.witness()])
} else {
Err(NoSolution)
}
@ -202,7 +202,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>(
ty::CoroutineWitness(def_id, args) => Ok(ecx
.tcx()
.generator_hidden_types(def_id)
.coroutine_hidden_types(def_id)
.map(|bty| {
ecx.instantiate_binder_with_placeholders(replace_erased_lifetimes_with_bound_vars(
ecx.tcx(),

View file

@ -465,11 +465,11 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
// Coroutines are not futures unless they come from `async` desugaring
let tcx = ecx.tcx();
if !tcx.generator_is_async(def_id) {
if !tcx.coroutine_is_async(def_id) {
return Err(NoSolution);
}
let term = args.as_generator().return_ty().into();
let term = args.as_coroutine().return_ty().into();
Self::consider_implied_clause(
ecx,
@ -480,12 +480,12 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
}
.to_predicate(tcx),
// Technically, we need to check that the future type is Sized,
// but that's already proven by the generator being WF.
// but that's already proven by the coroutine being WF.
[],
)
}
fn consider_builtin_generator_candidate(
fn consider_builtin_coroutine_candidate(
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx> {
@ -494,19 +494,19 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
return Err(NoSolution);
};
// `async`-desugared generators do not implement the generator trait
// `async`-desugared coroutines do not implement the coroutine trait
let tcx = ecx.tcx();
if tcx.generator_is_async(def_id) {
if tcx.coroutine_is_async(def_id) {
return Err(NoSolution);
}
let generator = args.as_generator();
let coroutine = args.as_coroutine();
let name = tcx.associated_item(goal.predicate.def_id()).name;
let term = if name == sym::Return {
generator.return_ty().into()
coroutine.return_ty().into()
} else if name == sym::Yield {
generator.yield_ty().into()
coroutine.yield_ty().into()
} else {
bug!("unexpected associated item `<{self_ty} as Coroutine>::{name}`")
};
@ -518,13 +518,13 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
projection_ty: ty::AliasTy::new(
ecx.tcx(),
goal.predicate.def_id(),
[self_ty, generator.resume_ty()],
[self_ty, coroutine.resume_ty()],
),
term,
}
.to_predicate(tcx),
// Technically, we need to check that the future type is Sized,
// but that's already proven by the generator being WF.
// but that's already proven by the coroutine being WF.
[],
)
}

View file

@ -325,17 +325,17 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
// Coroutines are not futures unless they come from `async` desugaring
let tcx = ecx.tcx();
if !tcx.generator_is_async(def_id) {
if !tcx.coroutine_is_async(def_id) {
return Err(NoSolution);
}
// Async generator unconditionally implement `Future`
// Async coroutine unconditionally implement `Future`
// Technically, we need to check that the future output type is Sized,
// but that's already proven by the generator being WF.
// but that's already proven by the coroutine being WF.
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
}
fn consider_builtin_generator_candidate(
fn consider_builtin_coroutine_candidate(
ecx: &mut EvalCtxt<'_, 'tcx>,
goal: Goal<'tcx, Self>,
) -> QueryResult<'tcx> {
@ -348,20 +348,20 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
return Err(NoSolution);
};
// `async`-desugared generators do not implement the generator trait
// `async`-desugared coroutines do not implement the coroutine trait
let tcx = ecx.tcx();
if tcx.generator_is_async(def_id) {
if tcx.coroutine_is_async(def_id) {
return Err(NoSolution);
}
let generator = args.as_generator();
let coroutine = args.as_coroutine();
Self::consider_implied_clause(
ecx,
goal,
ty::TraitRef::new(tcx, goal.predicate.def_id(), [self_ty, generator.resume_ty()])
ty::TraitRef::new(tcx, goal.predicate.def_id(), [self_ty, coroutine.resume_ty()])
.to_predicate(tcx),
// Technically, we need to check that the generator types are Sized,
// but that's already proven by the generator being WF.
// Technically, we need to check that the coroutine types are Sized,
// but that's already proven by the coroutine being WF.
[],
)
}

View file

@ -102,7 +102,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let node = hir.find(hir_id)?;
match &node {
hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. }) => {
self.describe_generator(*body_id).or_else(|| {
self.describe_coroutine(*body_id).or_else(|| {
Some(match sig.header {
hir::FnHeader { asyncness: hir::IsAsync::Async(_), .. } => {
"an async function"
@ -114,11 +114,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
hir::Node::TraitItem(hir::TraitItem {
kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(body_id)),
..
}) => self.describe_generator(*body_id).or_else(|| Some("a trait method")),
}) => self.describe_coroutine(*body_id).or_else(|| Some("a trait method")),
hir::Node::ImplItem(hir::ImplItem {
kind: hir::ImplItemKind::Fn(sig, body_id),
..
}) => self.describe_generator(*body_id).or_else(|| {
}) => self.describe_coroutine(*body_id).or_else(|| {
Some(match sig.header {
hir::FnHeader { asyncness: hir::IsAsync::Async(_), .. } => "an async method",
_ => "a method",
@ -127,7 +127,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
hir::Node::Expr(hir::Expr {
kind: hir::ExprKind::Closure(hir::Closure { body, movability, .. }),
..
}) => self.describe_generator(*body).or_else(|| {
}) => self.describe_coroutine(*body).or_else(|| {
Some(if movability.is_some() { "an async closure" } else { "a closure" })
}),
hir::Node::Expr(hir::Expr { .. }) => {

View file

@ -54,25 +54,25 @@ pub enum CoroutineInteriorOrUpvar {
Upvar(Span),
}
// This type provides a uniform interface to retrieve data on generators, whether it originated from
// This type provides a uniform interface to retrieve data on coroutines, whether it originated from
// the local crate being compiled or from a foreign crate.
#[derive(Debug)]
struct CoroutineData<'tcx, 'a>(&'a TypeckResults<'tcx>);
impl<'tcx, 'a> CoroutineData<'tcx, 'a> {
/// Try to get information about variables captured by the generator that matches a type we are
/// Try to get information about variables captured by the coroutine that matches a type we are
/// looking for with `ty_matches` function. We uses it to find upvar which causes a failure to
/// meet an obligation
fn try_get_upvar_span<F>(
&self,
infer_context: &InferCtxt<'tcx>,
generator_did: DefId,
coroutine_did: DefId,
ty_matches: F,
) -> Option<CoroutineInteriorOrUpvar>
where
F: Fn(ty::Binder<'tcx, Ty<'tcx>>) -> bool,
{
infer_context.tcx.upvars_mentioned(generator_did).and_then(|upvars| {
infer_context.tcx.upvars_mentioned(coroutine_did).and_then(|upvars| {
upvars.iter().find_map(|(upvar_id, upvar)| {
let upvar_ty = self.0.node_type(*upvar_id);
let upvar_ty = infer_context.resolve_vars_if_possible(upvar_ty);
@ -246,7 +246,7 @@ pub trait TypeErrCtxtExt<'tcx> {
err: &mut Diagnostic,
interior_or_upvar_span: CoroutineInteriorOrUpvar,
is_async: bool,
outer_generator: Option<DefId>,
outer_coroutine: Option<DefId>,
trait_pred: ty::TraitPredicate<'tcx>,
target_ty: Ty<'tcx>,
obligation: &PredicateObligation<'tcx>,
@ -1982,7 +1982,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let argument_kind = match expected.skip_binder().self_ty().kind() {
ty::Closure(..) => "closure",
ty::Coroutine(..) => "generator",
ty::Coroutine(..) => "coroutine",
_ => "function",
};
let mut err = struct_span_err!(
@ -2144,33 +2144,33 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let hir = self.tcx.hir();
// Attempt to detect an async-await error by looking at the obligation causes, looking
// for a generator to be present.
// for a coroutine to be present.
//
// When a future does not implement a trait because of a captured type in one of the
// generators somewhere in the call stack, then the result is a chain of obligations.
// coroutines somewhere in the call stack, then the result is a chain of obligations.
//
// Given an `async fn` A that calls an `async fn` B which captures a non-send type and that
// future is passed as an argument to a function C which requires a `Send` type, then the
// chain looks something like this:
//
// - `BuiltinDerivedObligation` with a generator witness (B)
// - `BuiltinDerivedObligation` with a generator (B)
// - `BuiltinDerivedObligation` with a coroutine witness (B)
// - `BuiltinDerivedObligation` with a coroutine (B)
// - `BuiltinDerivedObligation` with `impl std::future::Future` (B)
// - `BuiltinDerivedObligation` with a generator witness (A)
// - `BuiltinDerivedObligation` with a generator (A)
// - `BuiltinDerivedObligation` with a coroutine witness (A)
// - `BuiltinDerivedObligation` with a coroutine (A)
// - `BuiltinDerivedObligation` with `impl std::future::Future` (A)
// - `BindingObligation` with `impl_send` (Send requirement)
//
// The first obligation in the chain is the most useful and has the generator that captured
// the type. The last generator (`outer_generator` below) has information about where the
// bound was introduced. At least one generator should be present for this diagnostic to be
// The first obligation in the chain is the most useful and has the coroutine that captured
// the type. The last coroutine (`outer_coroutine` below) has information about where the
// bound was introduced. At least one coroutine should be present for this diagnostic to be
// modified.
let (mut trait_ref, mut target_ty) = match obligation.predicate.kind().skip_binder() {
ty::PredicateKind::Clause(ty::ClauseKind::Trait(p)) => (Some(p), Some(p.self_ty())),
_ => (None, None),
};
let mut generator = None;
let mut outer_generator = None;
let mut coroutine = None;
let mut outer_coroutine = None;
let mut next_code = Some(obligation.cause.code());
let mut seen_upvar_tys_infer_tuple = false;
@ -2191,17 +2191,17 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
match *ty.kind() {
ty::Coroutine(did, ..) | ty::CoroutineWitness(did, _) => {
generator = generator.or(Some(did));
outer_generator = Some(did);
coroutine = coroutine.or(Some(did));
outer_coroutine = Some(did);
}
ty::Tuple(_) if !seen_upvar_tys_infer_tuple => {
// By introducing a tuple of upvar types into the chain of obligations
// of a generator, the first non-generator item is now the tuple itself,
// of a coroutine, the first non-coroutine item is now the tuple itself,
// we shall ignore this.
seen_upvar_tys_infer_tuple = true;
}
_ if generator.is_none() => {
_ if coroutine.is_none() => {
trait_ref = Some(cause.derived.parent_trait_pred.skip_binder());
target_ty = Some(ty);
}
@ -2220,17 +2220,17 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
match *ty.kind() {
ty::Coroutine(did, ..) | ty::CoroutineWitness(did, ..) => {
generator = generator.or(Some(did));
outer_generator = Some(did);
coroutine = coroutine.or(Some(did));
outer_coroutine = Some(did);
}
ty::Tuple(_) if !seen_upvar_tys_infer_tuple => {
// By introducing a tuple of upvar types into the chain of obligations
// of a generator, the first non-generator item is now the tuple itself,
// of a coroutine, the first non-coroutine item is now the tuple itself,
// we shall ignore this.
seen_upvar_tys_infer_tuple = true;
}
_ if generator.is_none() => {
_ if coroutine.is_none() => {
trait_ref = Some(derived_obligation.parent_trait_pred.skip_binder());
target_ty = Some(ty);
}
@ -2243,48 +2243,48 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
}
}
// Only continue if a generator was found.
debug!(?generator, ?trait_ref, ?target_ty);
let (Some(generator_did), Some(trait_ref), Some(target_ty)) =
(generator, trait_ref, target_ty)
// Only continue if a coroutine was found.
debug!(?coroutine, ?trait_ref, ?target_ty);
let (Some(coroutine_did), Some(trait_ref), Some(target_ty)) =
(coroutine, trait_ref, target_ty)
else {
return false;
};
let span = self.tcx.def_span(generator_did);
let span = self.tcx.def_span(coroutine_did);
let generator_did_root = self.tcx.typeck_root_def_id(generator_did);
let coroutine_did_root = self.tcx.typeck_root_def_id(coroutine_did);
debug!(
?generator_did,
?generator_did_root,
?coroutine_did,
?coroutine_did_root,
typeck_results.hir_owner = ?self.typeck_results.as_ref().map(|t| t.hir_owner),
?span,
);
let generator_body = generator_did
let coroutine_body = coroutine_did
.as_local()
.and_then(|def_id| hir.maybe_body_owned_by(def_id))
.map(|body_id| hir.body(body_id));
let mut visitor = AwaitsVisitor::default();
if let Some(body) = generator_body {
if let Some(body) = coroutine_body {
visitor.visit_body(body);
}
debug!(awaits = ?visitor.awaits);
// Look for a type inside the generator interior that matches the target type to get
// Look for a type inside the coroutine interior that matches the target type to get
// a span.
let target_ty_erased = self.tcx.erase_regions(target_ty);
let ty_matches = |ty| -> bool {
// Careful: the regions for types that appear in the
// generator interior are not generally known, so we
// coroutine interior are not generally known, so we
// want to erase them when comparing (and anyway,
// `Send` and other bounds are generally unaffected by
// the choice of region). When erasing regions, we
// also have to erase late-bound regions. This is
// because the types that appear in the generator
// because the types that appear in the coroutine
// interior generally contain "bound regions" to
// represent regions that are part of the suspended
// generator frame. Bound regions are preserved by
// coroutine frame. Bound regions are preserved by
// `erase_regions` and so we must also call
// `erase_late_bound_regions`.
let ty_erased = self.tcx.erase_late_bound_regions(ty);
@ -2294,41 +2294,41 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
eq
};
// Get the typeck results from the infcx if the generator is the function we are currently
// Get the typeck results from the infcx if the coroutine is the function we are currently
// type-checking; otherwise, get them by performing a query. This is needed to avoid
// cycles. If we can't use resolved types because the generator comes from another crate,
// cycles. If we can't use resolved types because the coroutine comes from another crate,
// we still provide a targeted error but without all the relevant spans.
let generator_data = match &self.typeck_results {
Some(t) if t.hir_owner.to_def_id() == generator_did_root => CoroutineData(&t),
_ if generator_did.is_local() => {
CoroutineData(self.tcx.typeck(generator_did.expect_local()))
let coroutine_data = match &self.typeck_results {
Some(t) if t.hir_owner.to_def_id() == coroutine_did_root => CoroutineData(&t),
_ if coroutine_did.is_local() => {
CoroutineData(self.tcx.typeck(coroutine_did.expect_local()))
}
_ => return false,
};
let generator_within_in_progress_typeck = match &self.typeck_results {
Some(t) => t.hir_owner.to_def_id() == generator_did_root,
let coroutine_within_in_progress_typeck = match &self.typeck_results {
Some(t) => t.hir_owner.to_def_id() == coroutine_did_root,
_ => false,
};
let mut interior_or_upvar_span = None;
let from_awaited_ty = generator_data.get_from_await_ty(visitor, hir, ty_matches);
let from_awaited_ty = coroutine_data.get_from_await_ty(visitor, hir, ty_matches);
debug!(?from_awaited_ty);
// Avoid disclosing internal information to downstream crates.
if generator_did.is_local()
if coroutine_did.is_local()
// Try to avoid cycles.
&& !generator_within_in_progress_typeck
&& let Some(generator_info) = self.tcx.mir_generator_witnesses(generator_did)
&& !coroutine_within_in_progress_typeck
&& let Some(coroutine_info) = self.tcx.mir_coroutine_witnesses(coroutine_did)
{
debug!(?generator_info);
debug!(?coroutine_info);
'find_source: for (variant, source_info) in
generator_info.variant_fields.iter().zip(&generator_info.variant_source_info)
coroutine_info.variant_fields.iter().zip(&coroutine_info.variant_source_info)
{
debug!(?variant);
for &local in variant {
let decl = &generator_info.field_tys[local];
let decl = &coroutine_info.field_tys[local];
debug!(?decl);
if ty_matches(ty::Binder::dummy(decl.ty)) && !decl.ignore_for_traits {
interior_or_upvar_span = Some(CoroutineInteriorOrUpvar::Interior(
@ -2343,21 +2343,21 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
if interior_or_upvar_span.is_none() {
interior_or_upvar_span =
generator_data.try_get_upvar_span(&self, generator_did, ty_matches);
coroutine_data.try_get_upvar_span(&self, coroutine_did, ty_matches);
}
if interior_or_upvar_span.is_none() && !generator_did.is_local() {
if interior_or_upvar_span.is_none() && !coroutine_did.is_local() {
interior_or_upvar_span = Some(CoroutineInteriorOrUpvar::Interior(span, None));
}
debug!(?interior_or_upvar_span);
if let Some(interior_or_upvar_span) = interior_or_upvar_span {
let is_async = self.tcx.generator_is_async(generator_did);
let is_async = self.tcx.coroutine_is_async(coroutine_did);
self.note_obligation_cause_for_async_await(
err,
interior_or_upvar_span,
is_async,
outer_generator,
outer_coroutine,
trait_ref,
target_ty,
obligation,
@ -2377,7 +2377,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
err: &mut Diagnostic,
interior_or_upvar_span: CoroutineInteriorOrUpvar,
is_async: bool,
outer_generator: Option<DefId>,
outer_coroutine: Option<DefId>,
trait_pred: ty::TraitPredicate<'tcx>,
target_ty: Ty<'tcx>,
obligation: &PredicateObligation<'tcx>,
@ -2387,7 +2387,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
let (await_or_yield, an_await_or_yield) =
if is_async { ("await", "an await") } else { ("yield", "a yield") };
let future_or_generator = if is_async { "future" } else { "generator" };
let future_or_coroutine = if is_async { "future" } else { "coroutine" };
// Special case the primary error message when send or sync is the trait that was
// not implemented.
@ -2400,19 +2400,19 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
err.clear_code();
err.set_primary_message(format!(
"{future_or_generator} cannot be {trait_verb} between threads safely"
"{future_or_coroutine} cannot be {trait_verb} between threads safely"
));
let original_span = err.span.primary_span().unwrap();
let mut span = MultiSpan::from_span(original_span);
let message = outer_generator
.and_then(|generator_did| {
Some(match self.tcx.generator_kind(generator_did).unwrap() {
CoroutineKind::Gen => format!("generator is not {trait_name}"),
let message = outer_coroutine
.and_then(|coroutine_did| {
Some(match self.tcx.coroutine_kind(coroutine_did).unwrap() {
CoroutineKind::Gen => format!("coroutine is not {trait_name}"),
CoroutineKind::Async(AsyncCoroutineKind::Fn) => self
.tcx
.parent(generator_did)
.parent(coroutine_did)
.as_local()
.map(|parent_did| hir.local_def_id_to_hir_id(parent_did))
.and_then(|parent_hir_id| hir.opt_name(parent_hir_id))
@ -2427,7 +2427,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
}
})
})
.unwrap_or_else(|| format!("{future_or_generator} is not {trait_name}"));
.unwrap_or_else(|| format!("{future_or_coroutine} is not {trait_name}"));
span.push_span_label(original_span, message);
err.set_span(span);
@ -2471,7 +2471,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
);
err.span_note(
span,
format!("{future_or_generator} {trait_explanation} as this value is used across {an_await_or_yield}"),
format!("{future_or_coroutine} {trait_explanation} as this value is used across {an_await_or_yield}"),
);
};
match interior_or_upvar_span {
@ -2810,7 +2810,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
err.note("the return type of a function must have a statically known size");
}
ObligationCauseCode::SizedYieldType => {
err.note("the yield type of a generator must have a statically known size");
err.note("the yield type of a coroutine must have a statically known size");
}
ObligationCauseCode::AssignmentLhsSized => {
err.note("the left-hand-side of an assignment must have a statically known size");
@ -2880,8 +2880,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
err.span_label(span, "this closure captures all values by move");
}
}
ObligationCauseCode::SizedCoroutineInterior(generator_def_id) => {
let what = match self.tcx.generator_kind(generator_def_id) {
ObligationCauseCode::SizedCoroutineInterior(coroutine_def_id) => {
let what = match self.tcx.coroutine_kind(coroutine_def_id) {
None | Some(hir::CoroutineKind::Gen) => "yield",
Some(hir::CoroutineKind::Async(..)) => "await",
};
@ -2945,7 +2945,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
if is_future
&& obligated_types.last().is_some_and(|ty| match ty.kind() {
ty::Coroutine(last_def_id, ..) => {
tcx.generator_is_async(*last_def_id)
tcx.coroutine_is_async(*last_def_id)
}
_ => false,
})
@ -2962,7 +2962,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// FIXME: only print types which don't meet the trait requirement
let mut msg =
"required because it captures the following types: ".to_owned();
for bty in tcx.generator_hidden_types(*def_id) {
for bty in tcx.coroutine_hidden_types(*def_id) {
let ty = bty.instantiate(tcx, args);
write!(msg, "`{ty}`, ").unwrap();
}
@ -2971,8 +2971,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
ty::Coroutine(def_id, _, _) => {
let sp = self.tcx.def_span(def_id);
// Special-case this to say "async block" instead of `[static generator]`.
let kind = tcx.generator_kind(def_id).unwrap().descr();
// Special-case this to say "async block" instead of `[static coroutine]`.
let kind = tcx.coroutine_kind(def_id).unwrap().descr();
err.span_note(
sp,
with_forced_trimmed_paths!(format!(
@ -3271,7 +3271,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
) {
if let Some(body_id) = self.tcx.hir().maybe_body_owned_by(obligation.cause.body_id) {
let body = self.tcx.hir().body(body_id);
if let Some(hir::CoroutineKind::Async(_)) = body.generator_kind {
if let Some(hir::CoroutineKind::Async(_)) = body.coroutine_kind {
let future_trait = self.tcx.require_lang_item(LangItem::Future, None);
let self_ty = self.resolve_vars_if_possible(trait_pred.self_ty());
@ -4332,7 +4332,7 @@ impl<'v> Visitor<'v> for ReturnsVisitor<'v> {
fn visit_body(&mut self, body: &'v hir::Body<'v>) {
assert!(!self.in_block_tail);
if body.generator_kind().is_none() {
if body.coroutine_kind().is_none() {
if let hir::ExprKind::Block(block, None) = body.value.kind {
if block.expr.is_some() {
self.in_block_tail = true;

View file

@ -1036,7 +1036,7 @@ pub(super) trait InferCtxtPrivExt<'tcx> {
ignoring_lifetimes: bool,
) -> Option<CandidateSimilarity>;
fn describe_generator(&self, body_id: hir::BodyId) -> Option<&'static str>;
fn describe_coroutine(&self, body_id: hir::BodyId) -> Option<&'static str>;
fn find_similar_impl_candidates(
&self,
@ -1613,9 +1613,9 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
}
}
fn describe_generator(&self, body_id: hir::BodyId) -> Option<&'static str> {
self.tcx.hir().body(body_id).generator_kind.map(|gen_kind| match gen_kind {
hir::CoroutineKind::Gen => "a generator",
fn describe_coroutine(&self, body_id: hir::BodyId) -> Option<&'static str> {
self.tcx.hir().body(body_id).coroutine_kind.map(|gen_kind| match gen_kind {
hir::CoroutineKind::Gen => "a coroutine",
hir::CoroutineKind::Async(hir::AsyncCoroutineKind::Block) => "an async block",
hir::CoroutineKind::Async(hir::AsyncCoroutineKind::Fn) => "an async function",
hir::CoroutineKind::Async(hir::AsyncCoroutineKind::Closure) => "an async closure",

View file

@ -2003,7 +2003,7 @@ fn confirm_select_candidate<'cx, 'tcx>(
let trait_def_id = obligation.predicate.trait_def_id(selcx.tcx());
let lang_items = selcx.tcx().lang_items();
if lang_items.gen_trait() == Some(trait_def_id) {
confirm_generator_candidate(selcx, obligation, data)
confirm_coroutine_candidate(selcx, obligation, data)
} else if lang_items.future_trait() == Some(trait_def_id) {
confirm_future_candidate(selcx, obligation, data)
} else if selcx.tcx().fn_trait_kind_from_def_id(trait_def_id).is_some() {
@ -2030,7 +2030,7 @@ fn confirm_select_candidate<'cx, 'tcx>(
}
}
fn confirm_generator_candidate<'cx, 'tcx>(
fn confirm_coroutine_candidate<'cx, 'tcx>(
selcx: &mut SelectionContext<'cx, 'tcx>,
obligation: &ProjectionTyObligation<'tcx>,
nested: Vec<PredicateObligation<'tcx>>,
@ -2040,7 +2040,7 @@ fn confirm_generator_candidate<'cx, 'tcx>(
else {
unreachable!()
};
let gen_sig = args.as_generator().poly_sig();
let gen_sig = args.as_coroutine().poly_sig();
let Normalized { value: gen_sig, obligations } = normalize_with_depth(
selcx,
obligation.param_env,
@ -2049,13 +2049,13 @@ fn confirm_generator_candidate<'cx, 'tcx>(
gen_sig,
);
debug!(?obligation, ?gen_sig, ?obligations, "confirm_generator_candidate");
debug!(?obligation, ?gen_sig, ?obligations, "confirm_coroutine_candidate");
let tcx = selcx.tcx();
let gen_def_id = tcx.require_lang_item(LangItem::Coroutine, None);
let predicate = super::util::generator_trait_ref_and_outputs(
let predicate = super::util::coroutine_trait_ref_and_outputs(
tcx,
gen_def_id,
obligation.predicate.self_ty(),
@ -2092,7 +2092,7 @@ fn confirm_future_candidate<'cx, 'tcx>(
else {
unreachable!()
};
let gen_sig = args.as_generator().poly_sig();
let gen_sig = args.as_coroutine().poly_sig();
let Normalized { value: gen_sig, obligations } = normalize_with_depth(
selcx,
obligation.param_env,

View file

@ -257,20 +257,20 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
ty::Coroutine(_, args, _movability) => {
// rust-lang/rust#49918: types can be constructed, stored
// in the interior, and sit idle when generator yields
// in the interior, and sit idle when coroutine yields
// (and is subsequently dropped).
//
// It would be nice to descend into interior of a
// generator to determine what effects dropping it might
// coroutine to determine what effects dropping it might
// have (by looking at any drop effects associated with
// its interior).
//
// However, the interior's representation uses things like
// CoroutineWitness that explicitly assume they are not
// traversed in such a manner. So instead, we will
// simplify things for now by treating all generators as
// simplify things for now by treating all coroutines as
// if they were like trait objects, where its upvars must
// all be alive for the generator's (potential)
// all be alive for the coroutine's (potential)
// destructor.
//
// In particular, skipping over `_interior` is safe
@ -279,20 +279,20 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>(
// derived from lifetimes attached to the upvars and resume
// argument, and we *do* incorporate those here.
if !args.as_generator().is_valid() {
if !args.as_coroutine().is_valid() {
// By the time this code runs, all type variables ought to
// be fully resolved.
tcx.sess.delay_span_bug(
span,
format!("upvar_tys for generator not found. Expected capture information for generator {ty}",),
format!("upvar_tys for coroutine not found. Expected capture information for coroutine {ty}",),
);
return Err(NoSolution);
}
constraints
.outlives
.extend(args.as_generator().upvar_tys().iter().map(ty::GenericArg::from));
constraints.outlives.push(args.as_generator().resume_ty().into());
.extend(args.as_coroutine().upvar_tys().iter().map(ty::GenericArg::from));
constraints.outlives.push(args.as_coroutine().resume_ty().into());
}
ty::Adt(def, args) => {

View file

@ -231,7 +231,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
let args = data.args.try_fold_with(self)?;
let recursion_limit = self.interner().recursion_limit();
if !recursion_limit.value_within_limit(self.anon_depth) {
// A closure or generator may have itself as in its upvars.
// A closure or coroutine may have itself as in its upvars.
// This should be checked handled by the recursion check for opaque
// types, but we may end up here before that check can happen.
// In that case, we delay a bug to mark the trip, and continue without

View file

@ -111,7 +111,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
if lang_items.gen_trait() == Some(def_id) {
self.assemble_generator_candidates(obligation, &mut candidates);
self.assemble_coroutine_candidates(obligation, &mut candidates);
} else if lang_items.future_trait() == Some(def_id) {
self.assemble_future_candidates(obligation, &mut candidates);
}
@ -201,25 +201,25 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
Ok(())
}
fn assemble_generator_candidates(
fn assemble_coroutine_candidates(
&mut self,
obligation: &PolyTraitObligation<'tcx>,
candidates: &mut SelectionCandidateSet<'tcx>,
) {
// Okay to skip binder because the args on generator types never
// Okay to skip binder because the args on coroutine types never
// touch bound regions, they just capture the in-scope
// type/region parameters.
let self_ty = obligation.self_ty().skip_binder();
match self_ty.kind() {
// async constructs get lowered to a special kind of generator that
// async constructs get lowered to a special kind of coroutine that
// should *not* `impl Coroutine`.
ty::Coroutine(did, ..) if !self.tcx().generator_is_async(*did) => {
debug!(?self_ty, ?obligation, "assemble_generator_candidates",);
ty::Coroutine(did, ..) if !self.tcx().coroutine_is_async(*did) => {
debug!(?self_ty, ?obligation, "assemble_coroutine_candidates",);
candidates.vec.push(CoroutineCandidate);
}
ty::Infer(ty::TyVar(_)) => {
debug!("assemble_generator_candidates: ambiguous self-type");
debug!("assemble_coroutine_candidates: ambiguous self-type");
candidates.ambiguous = true;
}
_ => {}
@ -233,9 +233,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
) {
let self_ty = obligation.self_ty().skip_binder();
if let ty::Coroutine(did, ..) = self_ty.kind() {
// async constructs get lowered to a special kind of generator that
// async constructs get lowered to a special kind of coroutine that
// should directly `impl Future`.
if self.tcx().generator_is_async(*did) {
if self.tcx().coroutine_is_async(*did) {
debug!(?self_ty, ?obligation, "assemble_future_candidates",);
candidates.vec.push(FutureCandidate);
@ -518,11 +518,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
{
match movability {
hir::Movability::Static => {
// Immovable generators are never `Unpin`, so
// Immovable coroutines are never `Unpin`, so
// suppress the normal auto-impl candidate for it.
}
hir::Movability::Movable => {
// Movable generators are always `Unpin`, so add an
// Movable coroutines are always `Unpin`, so add an
// unconditional builtin candidate.
candidates.vec.push(BuiltinCandidate { has_nested: false });
}

View file

@ -84,8 +84,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
CoroutineCandidate => {
let vtable_generator = self.confirm_generator_candidate(obligation)?;
ImplSource::Builtin(BuiltinImplSource::Misc, vtable_generator)
let vtable_coroutine = self.confirm_coroutine_candidate(obligation)?;
ImplSource::Builtin(BuiltinImplSource::Misc, vtable_coroutine)
}
FutureCandidate => {
@ -711,23 +711,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
trait_obligations
}
fn confirm_generator_candidate(
fn confirm_coroutine_candidate(
&mut self,
obligation: &PolyTraitObligation<'tcx>,
) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
// Okay to skip binder because the args on generator types never
// Okay to skip binder because the args on coroutine types never
// touch bound regions, they just capture the in-scope
// type/region parameters.
let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
let ty::Coroutine(generator_def_id, args, _) = *self_ty.kind() else {
let ty::Coroutine(coroutine_def_id, args, _) = *self_ty.kind() else {
bug!("closure candidate for non-closure {:?}", obligation);
};
debug!(?obligation, ?generator_def_id, ?args, "confirm_generator_candidate");
debug!(?obligation, ?coroutine_def_id, ?args, "confirm_coroutine_candidate");
let gen_sig = args.as_generator().poly_sig();
let gen_sig = args.as_coroutine().poly_sig();
// NOTE: The self-type is a generator type and hence is
// NOTE: The self-type is a coroutine type and hence is
// in fact unparameterized (or at least does not reference any
// regions bound in the obligation).
let self_ty = obligation
@ -736,7 +736,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
.no_bound_vars()
.expect("unboxed closure type should not capture bound vars from the predicate");
let trait_ref = super::util::generator_trait_ref_and_outputs(
let trait_ref = super::util::coroutine_trait_ref_and_outputs(
self.tcx(),
obligation.predicate.def_id(),
self_ty,
@ -745,7 +745,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
.map_bound(|(trait_ref, ..)| trait_ref);
let nested = self.confirm_poly_trait_refs(obligation, trait_ref)?;
debug!(?trait_ref, ?nested, "generator candidate obligations");
debug!(?trait_ref, ?nested, "coroutine candidate obligations");
Ok(nested)
}
@ -754,17 +754,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
&mut self,
obligation: &PolyTraitObligation<'tcx>,
) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
// Okay to skip binder because the args on generator types never
// Okay to skip binder because the args on coroutine types never
// touch bound regions, they just capture the in-scope
// type/region parameters.
let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
let ty::Coroutine(generator_def_id, args, _) = *self_ty.kind() else {
let ty::Coroutine(coroutine_def_id, args, _) = *self_ty.kind() else {
bug!("closure candidate for non-closure {:?}", obligation);
};
debug!(?obligation, ?generator_def_id, ?args, "confirm_future_candidate");
debug!(?obligation, ?coroutine_def_id, ?args, "confirm_future_candidate");
let gen_sig = args.as_generator().poly_sig();
let gen_sig = args.as_coroutine().poly_sig();
let trait_ref = super::util::future_trait_ref_and_outputs(
self.tcx(),
@ -1235,12 +1235,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
stack.push(args.as_closure().tupled_upvars_ty());
}
ty::Coroutine(_, args, _) => {
let generator = args.as_generator();
stack.extend([generator.tupled_upvars_ty(), generator.witness()]);
let coroutine = args.as_coroutine();
stack.extend([coroutine.tupled_upvars_ty(), coroutine.witness()]);
}
ty::CoroutineWitness(def_id, args) => {
let tcx = self.tcx();
stack.extend(tcx.generator_hidden_types(def_id).map(|bty| {
stack.extend(tcx.coroutine_hidden_types(def_id).map(|bty| {
let ty = bty.instantiate(tcx, args);
debug_assert!(!ty.has_late_bound_regions());
ty

View file

@ -2190,20 +2190,20 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
}
ty::Coroutine(_, args, hir::Movability::Movable) => {
if self.tcx().features().generator_clone {
if self.tcx().features().coroutine_clone {
let resolved_upvars =
self.infcx.shallow_resolve(args.as_generator().tupled_upvars_ty());
self.infcx.shallow_resolve(args.as_coroutine().tupled_upvars_ty());
let resolved_witness =
self.infcx.shallow_resolve(args.as_generator().witness());
self.infcx.shallow_resolve(args.as_coroutine().witness());
if resolved_upvars.is_ty_var() || resolved_witness.is_ty_var() {
// Not yet resolved.
Ambiguous
} else {
let all = args
.as_generator()
.as_coroutine()
.upvar_tys()
.iter()
.chain([args.as_generator().witness()])
.chain([args.as_coroutine().witness()])
.collect::<Vec<_>>();
Where(obligation.predicate.rebind(all))
}
@ -2213,7 +2213,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
}
ty::CoroutineWitness(def_id, ref args) => {
let hidden_types = bind_generator_hidden_types_above(
let hidden_types = bind_coroutine_hidden_types_above(
self.infcx,
def_id,
args,
@ -2312,13 +2312,13 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
}
ty::Coroutine(_, ref args, _) => {
let ty = self.infcx.shallow_resolve(args.as_generator().tupled_upvars_ty());
let witness = args.as_generator().witness();
let ty = self.infcx.shallow_resolve(args.as_coroutine().tupled_upvars_ty());
let witness = args.as_coroutine().witness();
t.rebind([ty].into_iter().chain(iter::once(witness)).collect())
}
ty::CoroutineWitness(def_id, ref args) => {
bind_generator_hidden_types_above(self.infcx, def_id, args, t.bound_vars())
bind_coroutine_hidden_types_above(self.infcx, def_id, args, t.bound_vars())
}
// For `PhantomData<T>`, we pass `T`.
@ -3054,12 +3054,12 @@ pub enum ProjectionMatchesProjection {
No,
}
/// Replace all regions inside the generator interior with late bound regions.
/// Replace all regions inside the coroutine interior with late bound regions.
/// Note that each region slot in the types gets a new fresh late bound region, which means that
/// none of the regions inside relate to any other, even if typeck had previously found constraints
/// that would cause them to be related.
#[instrument(level = "trace", skip(infcx), ret)]
fn bind_generator_hidden_types_above<'tcx>(
fn bind_coroutine_hidden_types_above<'tcx>(
infcx: &InferCtxt<'tcx>,
def_id: DefId,
args: ty::GenericArgsRef<'tcx>,
@ -3074,7 +3074,7 @@ fn bind_generator_hidden_types_above<'tcx>(
let mut counter = num_bound_variables;
let hidden_types: Vec<_> = tcx
.generator_hidden_types(def_id)
.coroutine_hidden_types(def_id)
// Deduplicate tys to avoid repeated work.
.filter(|bty| seen_tys.insert(*bty))
.map(|mut bty| {

View file

@ -275,7 +275,7 @@ pub fn closure_trait_ref_and_return_type<'tcx>(
sig.map_bound(|sig| (trait_ref, sig.output()))
}
pub fn generator_trait_ref_and_outputs<'tcx>(
pub fn coroutine_trait_ref_and_outputs<'tcx>(
tcx: TyCtxt<'tcx>,
fn_trait_def_id: DefId,
self_ty: Ty<'tcx>,

View file

@ -673,13 +673,13 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
}
ty::Coroutine(did, args, ..) => {
// Walk ALL the types in the generator: this will
// Walk ALL the types in the coroutine: this will
// include the upvar types as well as the yield
// type. Note that this is mildly distinct from
// the closure case, where we have to be careful
// about the signature of the closure. We don't
// have the problem of implied bounds here since
// generators don't take arguments.
// coroutines don't take arguments.
let obligations = self.nominal_obligations(did, args);
self.out.extend(obligations);
}