diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 0fff9a6be926d..c07dbbc9d67ed 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -792,8 +792,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
// debuggers and debugger extensions expect it to be called `__awaitee`. They use
// this name to identify what is being awaited by a suspended async functions.
let awaitee_ident = Ident::with_dummy_span(sym::__awaitee);
- let (awaitee_pat, awaitee_pat_hid) =
- self.pat_ident_binding_mode(span, awaitee_ident, hir::BindingAnnotation::MUT);
+ let (awaitee_pat, awaitee_pat_hid) = self.pat_ident_binding_mode(
+ gen_future_span,
+ awaitee_ident,
+ hir::BindingAnnotation::MUT,
+ );
let task_context_ident = Ident::with_dummy_span(sym::_task_context);
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index c4e44a6a4e388..a8975f4f3a91a 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -1529,6 +1529,15 @@ pub enum CoroutineKind {
Coroutine,
}
+impl CoroutineKind {
+ pub fn is_fn_like(self) -> bool {
+ matches!(
+ self,
+ CoroutineKind::Async(CoroutineSource::Fn) | CoroutineKind::Gen(CoroutineSource::Fn)
+ )
+ }
+}
+
impl fmt::Display for CoroutineKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index e61ca232de643..30057f20e86d0 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -216,13 +216,12 @@ fn check_opaque(tcx: TyCtxt<'_>, id: hir::ItemId) {
return;
}
- let args = GenericArgs::identity_for_item(tcx, item.owner_id);
let span = tcx.def_span(item.owner_id.def_id);
if tcx.type_of(item.owner_id.def_id).instantiate_identity().references_error() {
return;
}
- if check_opaque_for_cycles(tcx, item.owner_id.def_id, args, span, &origin).is_err() {
+ if check_opaque_for_cycles(tcx, item.owner_id.def_id, span).is_err() {
return;
}
@@ -233,16 +232,16 @@ fn check_opaque(tcx: TyCtxt<'_>, id: hir::ItemId) {
pub(super) fn check_opaque_for_cycles<'tcx>(
tcx: TyCtxt<'tcx>,
def_id: LocalDefId,
- args: GenericArgsRef<'tcx>,
span: Span,
- origin: &hir::OpaqueTyOrigin,
) -> Result<(), ErrorGuaranteed> {
+ let args = GenericArgs::identity_for_item(tcx, def_id);
if tcx.try_expand_impl_trait_type(def_id.to_def_id(), args).is_err() {
- let reported = match origin {
- hir::OpaqueTyOrigin::AsyncFn(..) => async_opaque_type_cycle_error(tcx, span),
- _ => opaque_type_cycle_error(tcx, def_id, span),
- };
+ let reported = opaque_type_cycle_error(tcx, def_id, span);
Err(reported)
+ } else if let Err(&LayoutError::Cycle(guar)) =
+ tcx.layout_of(tcx.param_env(def_id).and(Ty::new_opaque(tcx, def_id.to_def_id(), args)))
+ {
+ Err(guar)
} else {
Ok(())
}
@@ -1324,16 +1323,6 @@ pub(super) fn check_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalModDefId
}
}
-fn async_opaque_type_cycle_error(tcx: TyCtxt<'_>, span: Span) -> ErrorGuaranteed {
- struct_span_err!(tcx.sess, span, E0733, "recursion in an `async fn` requires boxing")
- .span_label(span, "recursive `async fn`")
- .note("a recursive `async fn` must be rewritten to return a boxed `dyn Future`")
- .note(
- "consider using the `async_recursion` crate: https://crates.io/crates/async_recursion",
- )
- .emit()
-}
-
/// Emit an error for recursive opaque types.
///
/// If this is a return `impl Trait`, find the item's return expressions and point at them. For
diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs
index 113763450529c..945f17d5df2aa 100644
--- a/compiler/rustc_middle/src/query/keys.rs
+++ b/compiler/rustc_middle/src/query/keys.rs
@@ -40,7 +40,7 @@ pub trait Key: Sized {
None
}
- fn ty_adt_id(&self) -> Option {
+ fn ty_def_id(&self) -> Option {
None
}
}
@@ -406,9 +406,10 @@ impl<'tcx> Key for Ty<'tcx> {
DUMMY_SP
}
- fn ty_adt_id(&self) -> Option {
- match self.kind() {
+ fn ty_def_id(&self) -> Option {
+ match *self.kind() {
ty::Adt(adt, _) => Some(adt.did()),
+ ty::Coroutine(def_id, ..) => Some(def_id),
_ => None,
}
}
@@ -452,6 +453,10 @@ impl<'tcx, T: Key> Key for ty::ParamEnvAnd<'tcx, T> {
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
self.value.default_span(tcx)
}
+
+ fn ty_def_id(&self) -> Option {
+ self.value.ty_def_id()
+ }
}
impl Key for Symbol {
@@ -550,7 +555,7 @@ impl<'tcx> Key for (ValidityRequirement, ty::ParamEnvAnd<'tcx, Ty<'tcx>>) {
DUMMY_SP
}
- fn ty_adt_id(&self) -> Option {
+ fn ty_def_id(&self) -> Option {
match self.1.value.kind() {
ty::Adt(adt, _) => Some(adt.did()),
_ => None,
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index f9ec368361c59..deb0d7e63edfe 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -1390,6 +1390,8 @@ rustc_queries! {
) -> Result, &'tcx ty::layout::LayoutError<'tcx>> {
depth_limit
desc { "computing layout of `{}`", key.value }
+ // we emit our own error during query cycle handling
+ cycle_delay_bug
}
/// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers.
diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs
index f4a8ada8f685e..5a9c839d783fb 100644
--- a/compiler/rustc_middle/src/query/plumbing.rs
+++ b/compiler/rustc_middle/src/query/plumbing.rs
@@ -53,7 +53,7 @@ pub struct DynamicQuery<'tcx, C: QueryCache> {
fn(tcx: TyCtxt<'tcx>, key: &C::Key, index: SerializedDepNodeIndex) -> bool,
pub hash_result: HashResult,
pub value_from_cycle_error:
- fn(tcx: TyCtxt<'tcx>, cycle: &[QueryInfo], guar: ErrorGuaranteed) -> C::Value,
+ fn(tcx: TyCtxt<'tcx>, cycle_error: &CycleError, guar: ErrorGuaranteed) -> C::Value,
pub format_value: fn(&C::Value) -> String,
}
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 4223e503f5e22..aca6acd783b92 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -215,7 +215,7 @@ pub enum LayoutError<'tcx> {
SizeOverflow(Ty<'tcx>),
NormalizationFailure(Ty<'tcx>, NormalizationError<'tcx>),
ReferencesError(ErrorGuaranteed),
- Cycle,
+ Cycle(ErrorGuaranteed),
}
impl<'tcx> LayoutError<'tcx> {
@@ -226,7 +226,7 @@ impl<'tcx> LayoutError<'tcx> {
Unknown(_) => middle_unknown_layout,
SizeOverflow(_) => middle_values_too_big,
NormalizationFailure(_, _) => middle_cannot_be_normalized,
- Cycle => middle_cycle,
+ Cycle(_) => middle_cycle,
ReferencesError(_) => middle_layout_references_error,
}
}
@@ -240,7 +240,7 @@ impl<'tcx> LayoutError<'tcx> {
NormalizationFailure(ty, e) => {
E::NormalizationFailure { ty, failure_ty: e.get_type_for_failure() }
}
- Cycle => E::Cycle,
+ Cycle(_) => E::Cycle,
ReferencesError(_) => E::ReferencesError,
}
}
@@ -261,7 +261,7 @@ impl<'tcx> fmt::Display for LayoutError<'tcx> {
t,
e.get_type_for_failure()
),
- LayoutError::Cycle => write!(f, "a cycle occurred during layout computation"),
+ LayoutError::Cycle(_) => write!(f, "a cycle occurred during layout computation"),
LayoutError::ReferencesError(_) => write!(f, "the type has an unknown layout"),
}
}
@@ -333,7 +333,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
Err(err @ LayoutError::Unknown(_)) => err,
// We can't extract SizeSkeleton info from other layout errors
Err(
- e @ LayoutError::Cycle
+ e @ LayoutError::Cycle(_)
| e @ LayoutError::SizeOverflow(_)
| e @ LayoutError::NormalizationFailure(..)
| e @ LayoutError::ReferencesError(_),
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index a251518d14575..ca9c354ccdb8e 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -747,9 +747,13 @@ impl<'tcx> TyCtxt<'tcx> {
match def_kind {
DefKind::AssocFn if self.associated_item(def_id).fn_has_self_parameter => "method",
DefKind::Coroutine => match self.coroutine_kind(def_id).unwrap() {
- rustc_hir::CoroutineKind::Async(..) => "async closure",
- rustc_hir::CoroutineKind::Coroutine => "coroutine",
- rustc_hir::CoroutineKind::Gen(..) => "gen closure",
+ hir::CoroutineKind::Async(hir::CoroutineSource::Fn) => "async fn",
+ hir::CoroutineKind::Async(hir::CoroutineSource::Block) => "async block",
+ hir::CoroutineKind::Async(hir::CoroutineSource::Closure) => "async closure",
+ hir::CoroutineKind::Gen(hir::CoroutineSource::Fn) => "gen fn",
+ hir::CoroutineKind::Gen(hir::CoroutineSource::Block) => "gen block",
+ hir::CoroutineKind::Gen(hir::CoroutineSource::Closure) => "gen closure",
+ hir::CoroutineKind::Coroutine => "coroutine",
},
_ => def_kind.descr(def_id),
}
@@ -765,9 +769,9 @@ impl<'tcx> TyCtxt<'tcx> {
match def_kind {
DefKind::AssocFn if self.associated_item(def_id).fn_has_self_parameter => "a",
DefKind::Coroutine => match self.coroutine_kind(def_id).unwrap() {
- rustc_hir::CoroutineKind::Async(..) => "an",
- rustc_hir::CoroutineKind::Coroutine => "a",
- rustc_hir::CoroutineKind::Gen(..) => "a",
+ hir::CoroutineKind::Async(..) => "an",
+ hir::CoroutineKind::Coroutine => "a",
+ hir::CoroutineKind::Gen(..) => "a",
},
_ => def_kind.article(),
}
@@ -850,18 +854,7 @@ impl<'tcx> OpaqueTypeExpander<'tcx> {
}
let args = args.fold_with(self);
if !self.check_recursion || self.seen_opaque_tys.insert(def_id) {
- let expanded_ty = match self.expanded_cache.get(&(def_id, args)) {
- Some(expanded_ty) => *expanded_ty,
- None => {
- for bty in self.tcx.coroutine_hidden_types(def_id) {
- let hidden_ty = bty.instantiate(self.tcx, args);
- self.fold_ty(hidden_ty);
- }
- let expanded_ty = Ty::new_coroutine_witness(self.tcx, def_id, args);
- self.expanded_cache.insert((def_id, args), expanded_ty);
- expanded_ty
- }
- };
+ let expanded_ty = Ty::new_coroutine_witness(self.tcx, def_id, args);
if self.check_recursion {
self.seen_opaque_tys.remove(&def_id);
}
diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs
index f30993c9a694d..8b992ce810b8e 100644
--- a/compiler/rustc_middle/src/values.rs
+++ b/compiler/rustc_middle/src/values.rs
@@ -6,7 +6,7 @@ use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_middle::ty::Representability;
use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_query_system::query::QueryInfo;
+use rustc_query_system::query::{report_cycle, CycleError};
use rustc_query_system::Value;
use rustc_span::def_id::LocalDefId;
use rustc_span::{ErrorGuaranteed, Span};
@@ -14,7 +14,7 @@ use rustc_span::{ErrorGuaranteed, Span};
use std::fmt::Write;
impl<'tcx> Value> for Ty<'_> {
- fn from_cycle_error(tcx: TyCtxt<'tcx>, _: &[QueryInfo], guar: ErrorGuaranteed) -> Self {
+ fn from_cycle_error(tcx: TyCtxt<'tcx>, _: &CycleError, guar: ErrorGuaranteed) -> Self {
// SAFETY: This is never called when `Self` is not `Ty<'tcx>`.
// FIXME: Represent the above fact in the trait system somehow.
unsafe { std::mem::transmute::, Ty<'_>>(Ty::new_error(tcx, guar)) }
@@ -22,13 +22,13 @@ impl<'tcx> Value> for Ty<'_> {
}
impl<'tcx> Value> for Result>, CyclePlaceholder> {
- fn from_cycle_error(_tcx: TyCtxt<'tcx>, _: &[QueryInfo], guar: ErrorGuaranteed) -> Self {
+ fn from_cycle_error(_tcx: TyCtxt<'tcx>, _: &CycleError, guar: ErrorGuaranteed) -> Self {
Err(CyclePlaceholder(guar))
}
}
impl<'tcx> Value> for ty::SymbolName<'_> {
- fn from_cycle_error(tcx: TyCtxt<'tcx>, _: &[QueryInfo], _guar: ErrorGuaranteed) -> Self {
+ fn from_cycle_error(tcx: TyCtxt<'tcx>, _: &CycleError, _guar: ErrorGuaranteed) -> Self {
// SAFETY: This is never called when `Self` is not `SymbolName<'tcx>`.
// FIXME: Represent the above fact in the trait system somehow.
unsafe {
@@ -40,10 +40,14 @@ impl<'tcx> Value> for ty::SymbolName<'_> {
}
impl<'tcx> Value> for ty::Binder<'_, ty::FnSig<'_>> {
- fn from_cycle_error(tcx: TyCtxt<'tcx>, stack: &[QueryInfo], guar: ErrorGuaranteed) -> Self {
+ fn from_cycle_error(
+ tcx: TyCtxt<'tcx>,
+ cycle_error: &CycleError,
+ guar: ErrorGuaranteed,
+ ) -> Self {
let err = Ty::new_error(tcx, guar);
- let arity = if let Some(frame) = stack.get(0)
+ let arity = if let Some(frame) = cycle_error.cycle.get(0)
&& frame.query.dep_kind == dep_kinds::fn_sig
&& let Some(def_id) = frame.query.def_id
&& let Some(node) = tcx.hir().get_if_local(def_id)
@@ -70,10 +74,14 @@ impl<'tcx> Value> for ty::Binder<'_, ty::FnSig<'_>> {
}
impl<'tcx> Value> for Representability {
- fn from_cycle_error(tcx: TyCtxt<'tcx>, cycle: &[QueryInfo], _guar: ErrorGuaranteed) -> Self {
+ fn from_cycle_error(
+ tcx: TyCtxt<'tcx>,
+ cycle_error: &CycleError,
+ _guar: ErrorGuaranteed,
+ ) -> Self {
let mut item_and_field_ids = Vec::new();
let mut representable_ids = FxHashSet::default();
- for info in cycle {
+ for info in &cycle_error.cycle {
if info.query.dep_kind == dep_kinds::representability
&& let Some(field_id) = info.query.def_id
&& let Some(field_id) = field_id.as_local()
@@ -87,9 +95,9 @@ impl<'tcx> Value> for Representability {
item_and_field_ids.push((item_id.expect_local(), field_id));
}
}
- for info in cycle {
+ for info in &cycle_error.cycle {
if info.query.dep_kind == dep_kinds::representability_adt_ty
- && let Some(def_id) = info.query.ty_adt_id
+ && let Some(def_id) = info.query.ty_def_id
&& let Some(def_id) = def_id.as_local()
&& !item_and_field_ids.iter().any(|&(id, _)| id == def_id)
{
@@ -102,24 +110,104 @@ impl<'tcx> Value> for Representability {
}
impl<'tcx> Value> for ty::EarlyBinder> {
- fn from_cycle_error(tcx: TyCtxt<'tcx>, cycle: &[QueryInfo], guar: ErrorGuaranteed) -> Self {
- ty::EarlyBinder::bind(Ty::from_cycle_error(tcx, cycle, guar))
+ fn from_cycle_error(
+ tcx: TyCtxt<'tcx>,
+ cycle_error: &CycleError,
+ guar: ErrorGuaranteed,
+ ) -> Self {
+ ty::EarlyBinder::bind(Ty::from_cycle_error(tcx, cycle_error, guar))
}
}
impl<'tcx> Value> for ty::EarlyBinder>> {
- fn from_cycle_error(tcx: TyCtxt<'tcx>, cycle: &[QueryInfo], guar: ErrorGuaranteed) -> Self {
- ty::EarlyBinder::bind(ty::Binder::from_cycle_error(tcx, cycle, guar))
+ fn from_cycle_error(
+ tcx: TyCtxt<'tcx>,
+ cycle_error: &CycleError,
+ guar: ErrorGuaranteed,
+ ) -> Self {
+ ty::EarlyBinder::bind(ty::Binder::from_cycle_error(tcx, cycle_error, guar))
}
}
impl<'tcx, T> Value> for Result> {
- fn from_cycle_error(_tcx: TyCtxt<'tcx>, _cycle: &[QueryInfo], _guar: ErrorGuaranteed) -> Self {
+ fn from_cycle_error(
+ tcx: TyCtxt<'tcx>,
+ cycle_error: &CycleError,
+ _guar: ErrorGuaranteed,
+ ) -> Self {
+ let guar = if cycle_error.cycle[0].query.dep_kind == dep_kinds::layout_of
+ && let Some(def_id) = cycle_error.cycle[0].query.ty_def_id
+ && let Some(def_id) = def_id.as_local()
+ && let def_kind = tcx.def_kind(def_id)
+ && matches!(def_kind, DefKind::Coroutine)
+ {
+ let coroutine_kind = tcx
+ .coroutine_kind(def_id)
+ .expect("expected coroutine to have a coroutine_kind");
+ // FIXME: `def_span` for an fn-like coroutine will point to the fn's body
+ // due to interactions between the desugaring into a closure expr and the
+ // def_span code. I'm not motivated to fix it, because I tried and it was
+ // not working, so just hack around it by grabbing the parent fn's span.
+ let span = if coroutine_kind.is_fn_like() {
+ tcx.def_span(tcx.local_parent(def_id))
+ } else {
+ tcx.def_span(def_id)
+ };
+ let mut diag = struct_span_err!(
+ tcx.sess,
+ span,
+ E0733,
+ "recursion in {} {} requires boxing",
+ tcx.def_kind_descr_article(def_kind, def_id.to_def_id()),
+ tcx.def_kind_descr(def_kind, def_id.to_def_id()),
+ );
+ for (i, frame) in cycle_error.cycle.iter().enumerate() {
+ if frame.query.dep_kind != dep_kinds::layout_of {
+ continue;
+ }
+ let Some(frame_def_id) = frame.query.ty_def_id else {
+ continue;
+ };
+ let def_kind = tcx.def_kind(frame_def_id);
+ if !matches!(def_kind, DefKind::Coroutine) {
+ continue;
+ }
+ let frame_span = frame
+ .query
+ .default_span(cycle_error.cycle[(i + 1) % cycle_error.cycle.len()].span);
+ if frame_span.is_dummy() {
+ continue;
+ }
+ if i == 0 {
+ diag.span_label(frame_span, "recursive call here");
+ } else {
+ let coroutine_span: Span = if tcx
+ .coroutine_kind(frame_def_id)
+ .expect("expected coroutine to have a coroutine_kind").is_fn_like() {
+ tcx.def_span(tcx.parent(frame_def_id))
+ } else {
+ tcx.def_span(frame_def_id)
+ };
+ let mut multispan = MultiSpan::from_span(coroutine_span);
+ multispan.push_span_label(frame_span, "...leading to this recursive call");
+ diag.span_note(multispan, format!("which leads to this {}", tcx.def_kind_descr(def_kind, frame_def_id)));
+ }
+ }
+ if matches!(coroutine_kind, hir::CoroutineKind::Async(_)) {
+ diag.note("a recursive `async fn` call must introduce indirection such as `Box::pin` to avoid an infinitely sized future");
+ diag.note(
+ "consider using the `async_recursion` crate: https://crates.io/crates/async_recursion",
+ );
+ }
+ diag.emit()
+ } else {
+ report_cycle(tcx.sess, cycle_error).emit()
+ };
+
// tcx.arena.alloc cannot be used because we are not allowed to use &'tcx LayoutError under
// min_specialization. Since this is an error path anyways, leaking doesn't matter (and really,
// tcx.arena.alloc is pretty much equal to leaking).
- // FIXME: `Cycle` should carry the ErrorGuaranteed
- Err(Box::leak(Box::new(ty::layout::LayoutError::Cycle)))
+ Err(Box::leak(Box::new(ty::layout::LayoutError::Cycle(guar))))
}
}
diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs
index a1465dabed697..5aa7273d62017 100644
--- a/compiler/rustc_query_impl/src/lib.rs
+++ b/compiler/rustc_query_impl/src/lib.rs
@@ -38,7 +38,7 @@ use rustc_middle::ty::TyCtxt;
use rustc_query_system::dep_graph::SerializedDepNodeIndex;
use rustc_query_system::ich::StableHashingContext;
use rustc_query_system::query::{
- get_query_incr, get_query_non_incr, HashResult, QueryCache, QueryConfig, QueryInfo, QueryMap,
+ get_query_incr, get_query_non_incr, CycleError, HashResult, QueryCache, QueryConfig, QueryMap,
QueryMode, QueryState,
};
use rustc_query_system::HandleCycleError;
@@ -147,10 +147,10 @@ where
fn value_from_cycle_error(
self,
tcx: TyCtxt<'tcx>,
- cycle: &[QueryInfo],
+ cycle_error: &CycleError,
guar: ErrorGuaranteed,
) -> Self::Value {
- (self.dynamic.value_from_cycle_error)(tcx, cycle, guar)
+ (self.dynamic.value_from_cycle_error)(tcx, cycle_error, guar)
}
#[inline(always)]
diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs
index 6ad72e37a8c41..78821995e5ae4 100644
--- a/compiler/rustc_query_impl/src/plumbing.rs
+++ b/compiler/rustc_query_impl/src/plumbing.rs
@@ -339,9 +339,9 @@ pub(crate) fn create_query_frame<
hasher.finish::()
})
};
- let ty_adt_id = key.ty_adt_id();
+ let ty_def_id = key.ty_def_id();
- QueryStackFrame::new(description, span, def_id, def_kind, kind, ty_adt_id, hash)
+ QueryStackFrame::new(description, span, def_id, def_kind, kind, ty_def_id, hash)
}
pub(crate) fn encode_query_results<'a, 'tcx, Q>(
diff --git a/compiler/rustc_query_system/src/query/config.rs b/compiler/rustc_query_system/src/query/config.rs
index c025fac2631a8..958d9fdb52ae5 100644
--- a/compiler/rustc_query_system/src/query/config.rs
+++ b/compiler/rustc_query_system/src/query/config.rs
@@ -5,7 +5,7 @@ use crate::error::HandleCycleError;
use crate::ich::StableHashingContext;
use crate::query::caches::QueryCache;
use crate::query::DepNodeIndex;
-use crate::query::{QueryContext, QueryInfo, QueryState};
+use crate::query::{CycleError, QueryContext, QueryState};
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_span::ErrorGuaranteed;
@@ -57,7 +57,7 @@ pub trait QueryConfig: Copy {
fn value_from_cycle_error(
self,
tcx: Qcx::DepContext,
- cycle: &[QueryInfo],
+ cycle_error: &CycleError,
guar: ErrorGuaranteed,
) -> Self::Value;
diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs
index f2c1f84fccc1d..e0d7110009d47 100644
--- a/compiler/rustc_query_system/src/query/job.rs
+++ b/compiler/rustc_query_system/src/query/job.rs
@@ -553,7 +553,7 @@ pub fn deadlock(query_map: QueryMap, registry: &rayon_core::Registry) {
#[inline(never)]
#[cold]
-pub(crate) fn report_cycle<'a>(
+pub fn report_cycle<'a>(
sess: &'a Session,
CycleError { usage, cycle: stack }: &CycleError,
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs
index 05dee9f12dbdb..81d6544693cc3 100644
--- a/compiler/rustc_query_system/src/query/mod.rs
+++ b/compiler/rustc_query_system/src/query/mod.rs
@@ -4,7 +4,9 @@ pub use self::plumbing::*;
mod job;
#[cfg(parallel_compiler)]
pub use self::job::deadlock;
-pub use self::job::{print_query_stack, QueryInfo, QueryJob, QueryJobId, QueryJobInfo, QueryMap};
+pub use self::job::{
+ print_query_stack, report_cycle, QueryInfo, QueryJob, QueryJobId, QueryJobInfo, QueryMap,
+};
mod caches;
pub use self::caches::{
@@ -33,7 +35,8 @@ pub struct QueryStackFrame {
span: Option,
pub def_id: Option,
pub def_kind: Option,
- pub ty_adt_id: Option,
+ /// A def-id that is extracted from a `Ty` in a query key
+ pub ty_def_id: Option,
pub dep_kind: DepKind,
/// This hash is used to deterministically pick
/// a query to remove cycles in the parallel compiler.
@@ -49,7 +52,7 @@ impl QueryStackFrame {
def_id: Option,
def_kind: Option,
dep_kind: DepKind,
- ty_adt_id: Option,
+ ty_def_id: Option,
_hash: impl FnOnce() -> Hash64,
) -> Self {
Self {
@@ -57,7 +60,7 @@ impl QueryStackFrame {
span,
def_id,
def_kind,
- ty_adt_id,
+ ty_def_id,
dep_kind,
#[cfg(parallel_compiler)]
hash: _hash(),
diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs
index 1f3403d09be63..b7a97c271a49e 100644
--- a/compiler/rustc_query_system/src/query/plumbing.rs
+++ b/compiler/rustc_query_system/src/query/plumbing.rs
@@ -122,7 +122,7 @@ where
match query.handle_cycle_error() {
Error => {
let guar = error.emit();
- query.value_from_cycle_error(*qcx.dep_context(), &cycle_error.cycle, guar)
+ query.value_from_cycle_error(*qcx.dep_context(), cycle_error, guar)
}
Fatal => {
error.emit();
@@ -131,7 +131,7 @@ where
}
DelayBug => {
let guar = error.delay_as_bug();
- query.value_from_cycle_error(*qcx.dep_context(), &cycle_error.cycle, guar)
+ query.value_from_cycle_error(*qcx.dep_context(), cycle_error, guar)
}
Stash => {
let guar = if let Some(root) = cycle_error.cycle.first()
@@ -142,7 +142,7 @@ where
} else {
error.emit()
};
- query.value_from_cycle_error(*qcx.dep_context(), &cycle_error.cycle, guar)
+ query.value_from_cycle_error(*qcx.dep_context(), cycle_error, guar)
}
}
}
@@ -204,7 +204,7 @@ where
}
#[derive(Clone)]
-pub(crate) struct CycleError {
+pub struct CycleError {
/// The query and related span that uses the cycle.
pub usage: Option<(Span, QueryStackFrame)>,
pub cycle: Vec,
diff --git a/compiler/rustc_query_system/src/values.rs b/compiler/rustc_query_system/src/values.rs
index 8848fda9da3d0..cf2e48c0b28b9 100644
--- a/compiler/rustc_query_system/src/values.rs
+++ b/compiler/rustc_query_system/src/values.rs
@@ -1,20 +1,21 @@
use rustc_span::ErrorGuaranteed;
use crate::dep_graph::DepContext;
-use crate::query::QueryInfo;
+use crate::query::CycleError;
pub trait Value: Sized {
- fn from_cycle_error(tcx: Tcx, cycle: &[QueryInfo], guar: ErrorGuaranteed) -> Self;
+ fn from_cycle_error(tcx: Tcx, cycle_error: &CycleError, guar: ErrorGuaranteed) -> Self;
}
impl Value for T {
- default fn from_cycle_error(tcx: Tcx, cycle: &[QueryInfo], _guar: ErrorGuaranteed) -> T {
+ default fn from_cycle_error(tcx: Tcx, cycle_error: &CycleError, _guar: ErrorGuaranteed) -> T {
tcx.sess().abort_if_errors();
// Ideally we would use `bug!` here. But bug! is only defined in rustc_middle, and it's
// non-trivial to define it earlier.
panic!(
- "<{} as Value>::from_cycle_error called without errors: {cycle:#?}",
- std::any::type_name::()
+ "<{} as Value>::from_cycle_error called without errors: {:#?}",
+ std::any::type_name::(),
+ cycle_error.cycle,
);
}
}
diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
index 2e31b560b38ff..12aec6ea9f14d 100644
--- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
@@ -241,16 +241,13 @@ impl<'cx, 'tcx> FallibleTypeFolder> for QueryNormalizer<'cx, 'tcx>
}
let generic_ty = self.interner().type_of(data.def_id);
- let concrete_ty = generic_ty.instantiate(self.interner(), args);
+ let mut concrete_ty = generic_ty.instantiate(self.interner(), args);
self.anon_depth += 1;
if concrete_ty == ty {
- bug!(
- "infinite recursion generic_ty: {:#?}, args: {:#?}, \
- concrete_ty: {:#?}, ty: {:#?}",
- generic_ty,
- args,
- concrete_ty,
- ty
+ concrete_ty = Ty::new_error_with_message(
+ self.interner(),
+ DUMMY_SP,
+ "recursive opaque type",
);
}
let folded_ty = ensure_sufficient_stack(|| self.try_fold_ty(concrete_ty));
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index 283862b5e1cc6..52f723eba80ef 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -740,11 +740,11 @@ fn coroutine_layout<'tcx>(
};
let tag_layout = cx.tcx.mk_layout(LayoutS::scalar(cx, tag));
- let promoted_layouts = ineligible_locals
- .iter()
- .map(|local| subst_field(info.field_tys[local].ty))
- .map(|ty| Ty::new_maybe_uninit(tcx, ty))
- .map(|ty| Ok(cx.layout_of(ty)?.layout));
+ let promoted_layouts = ineligible_locals.iter().map(|local| {
+ let field_ty = subst_field(info.field_tys[local].ty);
+ let uninit_ty = Ty::new_maybe_uninit(tcx, field_ty);
+ Ok(cx.spanned_layout_of(uninit_ty, info.field_tys[local].source_info.span)?.layout)
+ });
let prefix_layouts = args
.as_coroutine()
.prefix_tys()
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index d226701ba4ade..92a47a047b3a0 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -6,7 +6,6 @@ use rustc_hir as hir;
use rustc_hir::def::CtorKind;
use rustc_hir::def_id::DefId;
use rustc_index::IndexVec;
-use rustc_middle::query::Key;
use rustc_middle::ty::{self, TyCtxt};
use rustc_span::hygiene::MacroKind;
use rustc_span::symbol::{kw, sym, Symbol};
@@ -1263,7 +1262,7 @@ fn item_type_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &c
clean::TypeAliasInnerType::Enum { variants, is_non_exhaustive } => {
let variants_iter = || variants.iter().filter(|i| !i.is_stripped());
let ty = cx.tcx().type_of(it.def_id().unwrap()).instantiate_identity();
- let enum_def_id = ty.ty_adt_id().unwrap();
+ let enum_def_id = ty.ty_adt_def().unwrap().did();
wrap_item(w, |w| {
let variants_len = variants.len();
diff --git a/src/librustdoc/html/templates/type_layout.html b/src/librustdoc/html/templates/type_layout.html
index b8b7785a2a191..c75fc34a9dfe7 100644
--- a/src/librustdoc/html/templates/type_layout.html
+++ b/src/librustdoc/html/templates/type_layout.html
@@ -54,7 +54,7 @@
{# #}
- {% when Err(LayoutError::Cycle) %}
+ {% when Err(LayoutError::Cycle(_)) %}
{# #}
Note: Encountered an error during type layout; {#+ #}
the type's layout depended on the type's layout itself. {# #}
diff --git a/src/tools/clippy/clippy_lints/src/copies.rs b/src/tools/clippy/clippy_lints/src/copies.rs
index e3a09636e2496..80ca53035222f 100644
--- a/src/tools/clippy/clippy_lints/src/copies.rs
+++ b/src/tools/clippy/clippy_lints/src/copies.rs
@@ -12,7 +12,6 @@ use rustc_errors::Applicability;
use rustc_hir::def_id::DefIdSet;
use rustc_hir::{intravisit, BinOpKind, Block, Expr, ExprKind, HirId, HirIdSet, Stmt, StmtKind};
use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::query::Key;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::hygiene::walk_chain;
use rustc_span::source_map::SourceMap;
@@ -574,7 +573,7 @@ fn method_caller_is_mutable(cx: &LateContext<'_>, caller_expr: &Expr<'_>, ignore
let caller_ty = cx.typeck_results().expr_ty(caller_expr);
// Check if given type has inner mutability and was not set to ignored by the configuration
let is_inner_mut_ty = is_interior_mut_ty(cx, caller_ty)
- && !matches!(caller_ty.ty_adt_id(), Some(adt_id) if ignored_ty_ids.contains(&adt_id));
+ && !matches!(caller_ty.ty_adt_def(), Some(adt) if ignored_ty_ids.contains(&adt.did()));
is_inner_mut_ty
|| caller_ty.is_mutable_ptr()
diff --git a/src/tools/clippy/clippy_lints/src/methods/drain_collect.rs b/src/tools/clippy/clippy_lints/src/methods/drain_collect.rs
index 6a82d8f756ad0..3a8ca37610a95 100644
--- a/src/tools/clippy/clippy_lints/src/methods/drain_collect.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/drain_collect.rs
@@ -6,7 +6,6 @@ use clippy_utils::ty::is_type_lang_item;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, LangItem, Path, QPath};
use rustc_lint::LateContext;
-use rustc_middle::query::Key;
use rustc_middle::ty;
use rustc_middle::ty::Ty;
use rustc_span::{sym, Symbol};
@@ -18,10 +17,10 @@ use rustc_span::{sym, Symbol};
/// `vec![1,2].drain(..).collect::>()`
/// ^^^^^^^^^ ^^^^^^^^^^ false
fn types_match_diagnostic_item(cx: &LateContext<'_>, expr: Ty<'_>, recv: Ty<'_>, sym: Symbol) -> bool {
- if let Some(expr_adt_did) = expr.ty_adt_id()
- && let Some(recv_adt_did) = recv.ty_adt_id()
+ if let Some(expr_adt) = expr.ty_adt_def()
+ && let Some(recv_adt) = recv.ty_adt_def()
{
- cx.tcx.is_diagnostic_item(sym, expr_adt_did) && cx.tcx.is_diagnostic_item(sym, recv_adt_did)
+ cx.tcx.is_diagnostic_item(sym, expr_adt.did()) && cx.tcx.is_diagnostic_item(sym, recv_adt.did())
} else {
false
}
diff --git a/src/tools/clippy/clippy_lints/src/methods/redundant_as_str.rs b/src/tools/clippy/clippy_lints/src/methods/redundant_as_str.rs
index 98cd6afc2b79f..2a2feedd2b495 100644
--- a/src/tools/clippy/clippy_lints/src/methods/redundant_as_str.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/redundant_as_str.rs
@@ -4,7 +4,6 @@ use clippy_utils::source::snippet_with_applicability;
use rustc_errors::Applicability;
use rustc_hir::Expr;
use rustc_lint::LateContext;
-use rustc_middle::query::Key;
use rustc_span::Span;
pub(super) fn check(
@@ -14,11 +13,7 @@ pub(super) fn check(
as_str_span: Span,
other_method_span: Span,
) {
- if cx
- .tcx
- .lang_items()
- .string()
- .is_some_and(|id| Some(id) == cx.typeck_results().expr_ty(recv).ty_adt_id())
+ if cx.typeck_results().expr_ty(recv).ty_adt_def().is_some_and(|adt| Some(adt.did()) == cx.tcx.lang_items().string())
{
let mut applicability = Applicability::MachineApplicable;
span_lint_and_sugg(
diff --git a/src/tools/clippy/clippy_lints/src/mut_key.rs b/src/tools/clippy/clippy_lints/src/mut_key.rs
index ebfd53f1ee9aa..bc274fb419c6f 100644
--- a/src/tools/clippy/clippy_lints/src/mut_key.rs
+++ b/src/tools/clippy/clippy_lints/src/mut_key.rs
@@ -4,7 +4,6 @@ use clippy_utils::{def_path_def_ids, trait_ref_of_method};
use rustc_data_structures::fx::FxHashSet;
use rustc_hir as hir;
use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::query::Key;
use rustc_middle::ty::{Adt, Ty};
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::def_id::LocalDefId;
@@ -162,7 +161,7 @@ impl MutableKeyType {
// Determines if a type contains interior mutability which would affect its implementation of
// [`Hash`] or [`Ord`].
if is_interior_mut_ty(cx, subst_ty)
- && !matches!(subst_ty.ty_adt_id(), Some(adt_id) if self.ignore_mut_def_ids.contains(&adt_id))
+ && !matches!(subst_ty.ty_adt_def(), Some(adt) if self.ignore_mut_def_ids.contains(&adt.did()))
{
span_lint(cx, MUTABLE_KEY_TYPE, span, "mutable key type");
}
diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
index 54cec066ba10c..03140a707bdef 100644
--- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs
+++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
@@ -16,7 +16,6 @@ use rustc_hir::{
};
use rustc_lint::{LateContext, LateLintPass, Lint};
use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult, GlobalId};
-use rustc_middle::query::Key;
use rustc_middle::ty::adjustment::Adjust;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_session::{declare_tool_lint, impl_lint_pass};
@@ -189,7 +188,7 @@ impl NonCopyConst {
}
fn is_ty_ignored(&self, ty: Ty<'_>) -> bool {
- matches!(ty.ty_adt_id(), Some(adt_id) if self.ignore_mut_def_ids.contains(&adt_id))
+ matches!(ty.ty_adt_def(), Some(adt) if self.ignore_mut_def_ids.contains(&adt.did()))
}
fn is_unfrozen<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_non_zero.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_non_zero.rs
index c0d0d2b93dc03..5df645491ff81 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_non_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_non_zero.rs
@@ -4,7 +4,6 @@ use clippy_utils::sugg;
use rustc_errors::Applicability;
use rustc_hir::Expr;
use rustc_lint::LateContext;
-use rustc_middle::query::Key;
use rustc_middle::ty::{self, Ty};
use rustc_span::symbol::sym;
@@ -17,10 +16,10 @@ pub(super) fn check<'tcx>(
to_ty: Ty<'tcx>,
arg: &'tcx Expr<'_>,
) -> bool {
- let (ty::Int(_) | ty::Uint(_), Some(to_ty_id)) = (&from_ty.kind(), to_ty.ty_adt_id()) else {
+ let (ty::Int(_) | ty::Uint(_), Some(to_ty_adt)) = (&from_ty.kind(), to_ty.ty_adt_def()) else {
return false;
};
- let Some(to_type_sym) = cx.tcx.get_diagnostic_name(to_ty_id) else {
+ let Some(to_type_sym) = cx.tcx.get_diagnostic_name(to_ty_adt.did()) else {
return false;
};
diff --git a/tests/ui/async-await/in-trait/async-recursive-generic.rs b/tests/ui/async-await/in-trait/async-recursive-generic.rs
index c6031ce28d1d0..33eb2b2de131b 100644
--- a/tests/ui/async-await/in-trait/async-recursive-generic.rs
+++ b/tests/ui/async-await/in-trait/async-recursive-generic.rs
@@ -6,7 +6,7 @@ trait MyTrait {
impl MyTrait for T where T: Copy {
async fn foo_recursive(&self, n: usize) -> T {
- //~^ ERROR recursion in an `async fn` requires boxing
+ //~^ ERROR recursion in an async fn requires boxing
if n > 0 {
self.foo_recursive(n - 1).await
} else {
diff --git a/tests/ui/async-await/in-trait/async-recursive-generic.stderr b/tests/ui/async-await/in-trait/async-recursive-generic.stderr
index cf0bcd741fc31..365b89d9d6961 100644
--- a/tests/ui/async-await/in-trait/async-recursive-generic.stderr
+++ b/tests/ui/async-await/in-trait/async-recursive-generic.stderr
@@ -1,10 +1,13 @@
-error[E0733]: recursion in an `async fn` requires boxing
+error[E0733]: recursion in an async fn requires boxing
--> $DIR/async-recursive-generic.rs:8:5
|
LL | async fn foo_recursive(&self, n: usize) -> T {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ recursive `async fn`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | self.foo_recursive(n - 1).await
+ | ------------------------------- recursive call here
|
- = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`
+ = note: a recursive `async fn` call must introduce indirection such as `Box::pin` to avoid an infinitely sized future
= note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion
error: aborting due to previous error
diff --git a/tests/ui/async-await/in-trait/async-recursive.rs b/tests/ui/async-await/in-trait/async-recursive.rs
index 09f1ffe499e32..2534c43413ed2 100644
--- a/tests/ui/async-await/in-trait/async-recursive.rs
+++ b/tests/ui/async-await/in-trait/async-recursive.rs
@@ -6,7 +6,7 @@ trait MyTrait {
impl MyTrait for i32 {
async fn foo_recursive(&self, n: usize) -> i32 {
- //~^ ERROR recursion in an `async fn` requires boxing
+ //~^ ERROR recursion in an async fn requires boxing
if n > 0 {
self.foo_recursive(n - 1).await
} else {
diff --git a/tests/ui/async-await/in-trait/async-recursive.stderr b/tests/ui/async-await/in-trait/async-recursive.stderr
index b959652ea167f..e482e9b4391ca 100644
--- a/tests/ui/async-await/in-trait/async-recursive.stderr
+++ b/tests/ui/async-await/in-trait/async-recursive.stderr
@@ -1,10 +1,13 @@
-error[E0733]: recursion in an `async fn` requires boxing
+error[E0733]: recursion in an async fn requires boxing
--> $DIR/async-recursive.rs:8:5
|
LL | async fn foo_recursive(&self, n: usize) -> i32 {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ recursive `async fn`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | self.foo_recursive(n - 1).await
+ | ------------------------------- recursive call here
|
- = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`
+ = note: a recursive `async fn` call must introduce indirection such as `Box::pin` to avoid an infinitely sized future
= note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion
error: aborting due to previous error
diff --git a/tests/ui/async-await/in-trait/indirect-recursion-issue-112047.rs b/tests/ui/async-await/in-trait/indirect-recursion-issue-112047.rs
index 8443cbcf4ac89..103f5d060d673 100644
--- a/tests/ui/async-await/in-trait/indirect-recursion-issue-112047.rs
+++ b/tests/ui/async-await/in-trait/indirect-recursion-issue-112047.rs
@@ -1,6 +1,5 @@
// edition: 2021
// build-fail
-//~^^ ERROR cycle detected when computing layout of
fn main() {
let _ = async {
@@ -31,6 +30,7 @@ where
C: First,
{
async fn second(self) {
+ //~^ ERROR recursion in an async fn requires boxing
self.first().await.second().await;
}
}
diff --git a/tests/ui/async-await/in-trait/indirect-recursion-issue-112047.stderr b/tests/ui/async-await/in-trait/indirect-recursion-issue-112047.stderr
index ce02c1e99675c..fca4cb1ea907c 100644
--- a/tests/ui/async-await/in-trait/indirect-recursion-issue-112047.stderr
+++ b/tests/ui/async-await/in-trait/indirect-recursion-issue-112047.stderr
@@ -1,10 +1,12 @@
-error[E0391]: cycle detected when computing layout of `{async fn body@$DIR/indirect-recursion-issue-112047.rs:33:27: 35:6}`
+error[E0733]: recursion in an async fn requires boxing
+ --> $DIR/indirect-recursion-issue-112047.rs:32:5
|
- = note: ...which requires computing layout of `<::Second as Second>::{opaque#0}`...
- = note: ...which again requires computing layout of `{async fn body@$DIR/indirect-recursion-issue-112047.rs:33:27: 35:6}`, completing the cycle
- = note: cycle used when computing layout of `{async block@$DIR/indirect-recursion-issue-112047.rs:6:13: 8:6}`
- = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
+LL | async fn second(self) {
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: a recursive `async fn` call must introduce indirection such as `Box::pin` to avoid an infinitely sized future
+ = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion
error: aborting due to previous error
-For more information about this error, try `rustc --explain E0391`.
+For more information about this error, try `rustc --explain E0733`.
diff --git a/tests/ui/async-await/mutually-recursive-async-impl-trait-type.rs b/tests/ui/async-await/mutually-recursive-async-impl-trait-type.rs
index bb2a61f03ce1f..fedc814b0418a 100644
--- a/tests/ui/async-await/mutually-recursive-async-impl-trait-type.rs
+++ b/tests/ui/async-await/mutually-recursive-async-impl-trait-type.rs
@@ -2,11 +2,11 @@
// Test that impl trait does not allow creating recursive types that are
// otherwise forbidden when using `async` and `await`.
-async fn rec_1() { //~ ERROR recursion in an `async fn`
+async fn rec_1() { //~ ERROR recursion in an async fn
rec_2().await;
}
-async fn rec_2() { //~ ERROR recursion in an `async fn`
+async fn rec_2() {
rec_1().await;
}
diff --git a/tests/ui/async-await/mutually-recursive-async-impl-trait-type.stderr b/tests/ui/async-await/mutually-recursive-async-impl-trait-type.stderr
index 9442609e80586..af0844ff3e213 100644
--- a/tests/ui/async-await/mutually-recursive-async-impl-trait-type.stderr
+++ b/tests/ui/async-await/mutually-recursive-async-impl-trait-type.stderr
@@ -1,21 +1,21 @@
-error[E0733]: recursion in an `async fn` requires boxing
+error[E0733]: recursion in an async fn requires boxing
--> $DIR/mutually-recursive-async-impl-trait-type.rs:5:1
|
LL | async fn rec_1() {
- | ^^^^^^^^^^^^^^^^ recursive `async fn`
+ | ^^^^^^^^^^^^^^^^
+LL | rec_2().await;
+ | ------------- recursive call here
|
- = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`
- = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion
-
-error[E0733]: recursion in an `async fn` requires boxing
+note: which leads to this async fn
--> $DIR/mutually-recursive-async-impl-trait-type.rs:9:1
|
LL | async fn rec_2() {
- | ^^^^^^^^^^^^^^^^ recursive `async fn`
- |
- = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`
+ | ^^^^^^^^^^^^^^^^
+LL | rec_1().await;
+ | ------------- ...leading to this recursive call
+ = note: a recursive `async fn` call must introduce indirection such as `Box::pin` to avoid an infinitely sized future
= note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion
-error: aborting due to 2 previous errors
+error: aborting due to previous error
For more information about this error, try `rustc --explain E0733`.
diff --git a/tests/ui/async-await/recursive-async-impl-trait-type.rs b/tests/ui/async-await/recursive-async-impl-trait-type.rs
index edc4cb8ac5df3..9351ee53f0754 100644
--- a/tests/ui/async-await/recursive-async-impl-trait-type.rs
+++ b/tests/ui/async-await/recursive-async-impl-trait-type.rs
@@ -3,7 +3,7 @@
// otherwise forbidden when using `async` and `await`.
async fn recursive_async_function() -> () {
- //~^ ERROR recursion in an `async fn` requires boxing
+ //~^ ERROR recursion in an async fn requires boxing
recursive_async_function().await;
}
diff --git a/tests/ui/async-await/recursive-async-impl-trait-type.stderr b/tests/ui/async-await/recursive-async-impl-trait-type.stderr
index 64917329c499f..6fa71137e60f1 100644
--- a/tests/ui/async-await/recursive-async-impl-trait-type.stderr
+++ b/tests/ui/async-await/recursive-async-impl-trait-type.stderr
@@ -1,10 +1,13 @@
-error[E0733]: recursion in an `async fn` requires boxing
+error[E0733]: recursion in an async fn requires boxing
--> $DIR/recursive-async-impl-trait-type.rs:5:1
|
LL | async fn recursive_async_function() -> () {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ recursive `async fn`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |
+LL | recursive_async_function().await;
+ | -------------------------------- recursive call here
|
- = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`
+ = note: a recursive `async fn` call must introduce indirection such as `Box::pin` to avoid an infinitely sized future
= note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion
error: aborting due to previous error
diff --git a/tests/ui/impl-trait/recursive-coroutine.rs b/tests/ui/impl-trait/recursive-coroutine.rs
index 6351cef95a618..1f8ec9d1ca4fe 100644
--- a/tests/ui/impl-trait/recursive-coroutine.rs
+++ b/tests/ui/impl-trait/recursive-coroutine.rs
@@ -1,14 +1,13 @@
+// check-pass
+// This works because the coroutine is boxed!
+
#![feature(coroutines, coroutine_trait)]
use std::ops::{Coroutine, CoroutineState};
fn foo() -> impl Coroutine {
- //~^ ERROR cannot resolve opaque type
- //~| NOTE recursive opaque type
- //~| NOTE in this expansion of desugaring of
|| {
let mut gen = Box::pin(foo());
- //~^ NOTE coroutine captures itself here
let mut r = gen.as_mut().resume(());
while let CoroutineState::Yielded(v) = r {
yield v;
diff --git a/tests/ui/impl-trait/recursive-coroutine.stderr b/tests/ui/impl-trait/recursive-coroutine.stderr
deleted file mode 100644
index d36a58a864343..0000000000000
--- a/tests/ui/impl-trait/recursive-coroutine.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0720]: cannot resolve opaque type
- --> $DIR/recursive-coroutine.rs:5:13
- |
-LL | fn foo() -> impl Coroutine {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ recursive opaque type
-...
-LL | let mut gen = Box::pin(foo());
- | ------- coroutine captures itself here
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0720`.
diff --git a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.rs b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.rs
index 8331eec906e10..a6bca107b1ec8 100644
--- a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.rs
+++ b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.rs
@@ -70,8 +70,8 @@ fn substs_change() -> impl Sized {
}
fn coroutine_hold() -> impl Sized {
- //~^ ERROR
move || {
+ //~^ ERROR
let x = coroutine_hold();
yield;
x;
diff --git a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.stderr b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.stderr
index 8e9aa8ad0a690..16a9012958e9e 100644
--- a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.stderr
+++ b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.stderr
@@ -109,14 +109,14 @@ LL |
LL | (substs_change::<&T>(),)
| ------------------------ returning here with type `(impl Sized,)`
-error[E0720]: cannot resolve opaque type
- --> $DIR/recursive-impl-trait-type-indirect.rs:72:24
+error[E0733]: recursion in a coroutine requires boxing
+ --> $DIR/recursive-impl-trait-type-indirect.rs:73:5
|
-LL | fn coroutine_hold() -> impl Sized {
- | ^^^^^^^^^^ recursive opaque type
-...
+LL | move || {
+ | ^^^^^^^
+LL |
LL | let x = coroutine_hold();
- | - coroutine captures itself here
+ | - recursive call here
error[E0720]: cannot resolve opaque type
--> $DIR/recursive-impl-trait-type-indirect.rs:86:26
@@ -144,4 +144,5 @@ LL | mutual_recursion()
error: aborting due to 14 previous errors
-For more information about this error, try `rustc --explain E0720`.
+Some errors have detailed explanations: E0720, E0733.
+For more information about an error, try `rustc --explain E0720`.
diff --git a/tests/ui/lifetimes/issue-76168-hr-outlives-3.rs b/tests/ui/lifetimes/issue-76168-hr-outlives-3.rs
index b0b6b318d8f78..172b5ae2bddeb 100644
--- a/tests/ui/lifetimes/issue-76168-hr-outlives-3.rs
+++ b/tests/ui/lifetimes/issue-76168-hr-outlives-3.rs
@@ -7,6 +7,7 @@ async fn wrapper(f: F)
//~^ ERROR: expected a `FnOnce(&'a mut i32)` closure, found `i32`
//~| ERROR: expected a `FnOnce(&'a mut i32)` closure, found `i32`
//~| ERROR: expected a `FnOnce(&'a mut i32)` closure, found `i32`
+//~| ERROR: expected a `FnOnce(&'a mut i32)` closure, found `i32`
where
F:,
for<'a> >::Output: Future