Only compute layout of opaque if coroutine is the cause of an opaque cycle
This commit is contained in:
parent
199af7cef0
commit
fa2ff51ace
4 changed files with 53 additions and 12 deletions
|
@ -17,7 +17,7 @@ use rustc_middle::middle::stability::EvalResult;
|
||||||
use rustc_middle::traits::{DefiningAnchor, ObligationCauseCode};
|
use rustc_middle::traits::{DefiningAnchor, ObligationCauseCode};
|
||||||
use rustc_middle::ty::fold::BottomUpFolder;
|
use rustc_middle::ty::fold::BottomUpFolder;
|
||||||
use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
|
use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
|
||||||
use rustc_middle::ty::util::{Discr, IntTypeExt};
|
use rustc_middle::ty::util::{Discr, InspectCoroutineFields, IntTypeExt};
|
||||||
use rustc_middle::ty::GenericArgKind;
|
use rustc_middle::ty::GenericArgKind;
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
AdtDef, ParamEnv, RegionKind, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
|
AdtDef, ParamEnv, RegionKind, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
|
||||||
|
@ -232,16 +232,33 @@ pub(super) fn check_opaque_for_cycles<'tcx>(
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> Result<(), ErrorGuaranteed> {
|
) -> Result<(), ErrorGuaranteed> {
|
||||||
let args = GenericArgs::identity_for_item(tcx, def_id);
|
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 = opaque_type_cycle_error(tcx, def_id, span);
|
// First, try to look at any opaque expansion cycles, considering coroutine fields
|
||||||
Err(reported)
|
// (even though these aren't necessarily true errors).
|
||||||
} else if let Err(&LayoutError::Cycle(guar)) =
|
if tcx
|
||||||
tcx.layout_of(tcx.param_env(def_id).and(Ty::new_opaque(tcx, def_id.to_def_id(), args)))
|
.try_expand_impl_trait_type(def_id.to_def_id(), args, InspectCoroutineFields::Yes)
|
||||||
|
.is_err()
|
||||||
{
|
{
|
||||||
Err(guar)
|
// Look for true opaque expansion cycles, but ignore coroutines.
|
||||||
} else {
|
// This will give us any true errors. Coroutines are only problematic
|
||||||
Ok(())
|
// if they cause layout computation errors.
|
||||||
|
if tcx
|
||||||
|
.try_expand_impl_trait_type(def_id.to_def_id(), args, InspectCoroutineFields::No)
|
||||||
|
.is_err()
|
||||||
|
{
|
||||||
|
let reported = opaque_type_cycle_error(tcx, def_id, span);
|
||||||
|
return Err(reported);
|
||||||
|
}
|
||||||
|
|
||||||
|
// And also look for cycle errors in the layout of coroutines.
|
||||||
|
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)))
|
||||||
|
{
|
||||||
|
return Err(guar);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check that the concrete type behind `impl Trait` actually implements `Trait`.
|
/// Check that the concrete type behind `impl Trait` actually implements `Trait`.
|
||||||
|
|
|
@ -702,6 +702,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
self,
|
self,
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
args: GenericArgsRef<'tcx>,
|
args: GenericArgsRef<'tcx>,
|
||||||
|
inspect_coroutine_fields: InspectCoroutineFields,
|
||||||
) -> Result<Ty<'tcx>, Ty<'tcx>> {
|
) -> Result<Ty<'tcx>, Ty<'tcx>> {
|
||||||
let mut visitor = OpaqueTypeExpander {
|
let mut visitor = OpaqueTypeExpander {
|
||||||
seen_opaque_tys: FxHashSet::default(),
|
seen_opaque_tys: FxHashSet::default(),
|
||||||
|
@ -712,6 +713,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
check_recursion: true,
|
check_recursion: true,
|
||||||
expand_coroutines: true,
|
expand_coroutines: true,
|
||||||
tcx: self,
|
tcx: self,
|
||||||
|
inspect_coroutine_fields,
|
||||||
};
|
};
|
||||||
|
|
||||||
let expanded_type = visitor.expand_opaque_ty(def_id, args).unwrap();
|
let expanded_type = visitor.expand_opaque_ty(def_id, args).unwrap();
|
||||||
|
@ -885,6 +887,13 @@ struct OpaqueTypeExpander<'tcx> {
|
||||||
/// recursion, and 'false' otherwise to avoid unnecessary work.
|
/// recursion, and 'false' otherwise to avoid unnecessary work.
|
||||||
check_recursion: bool,
|
check_recursion: bool,
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
|
inspect_coroutine_fields: InspectCoroutineFields,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
|
pub enum InspectCoroutineFields {
|
||||||
|
No,
|
||||||
|
Yes,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> OpaqueTypeExpander<'tcx> {
|
impl<'tcx> OpaqueTypeExpander<'tcx> {
|
||||||
|
@ -923,7 +932,20 @@ impl<'tcx> OpaqueTypeExpander<'tcx> {
|
||||||
}
|
}
|
||||||
let args = args.fold_with(self);
|
let args = args.fold_with(self);
|
||||||
if !self.check_recursion || self.seen_opaque_tys.insert(def_id) {
|
if !self.check_recursion || self.seen_opaque_tys.insert(def_id) {
|
||||||
let expanded_ty = Ty::new_coroutine_witness(self.tcx, def_id, args);
|
let expanded_ty = match self.expanded_cache.get(&(def_id, args)) {
|
||||||
|
Some(expanded_ty) => *expanded_ty,
|
||||||
|
None => {
|
||||||
|
if matches!(self.inspect_coroutine_fields, InspectCoroutineFields::Yes) {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
};
|
||||||
if self.check_recursion {
|
if self.check_recursion {
|
||||||
self.seen_opaque_tys.remove(&def_id);
|
self.seen_opaque_tys.remove(&def_id);
|
||||||
}
|
}
|
||||||
|
@ -1495,6 +1517,7 @@ pub fn reveal_opaque_types_in_bounds<'tcx>(
|
||||||
check_recursion: false,
|
check_recursion: false,
|
||||||
expand_coroutines: false,
|
expand_coroutines: false,
|
||||||
tcx,
|
tcx,
|
||||||
|
inspect_coroutine_fields: InspectCoroutineFields::No,
|
||||||
};
|
};
|
||||||
val.fold_with(&mut visitor)
|
val.fold_with(&mut visitor)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
// edition: 2021
|
// edition: 2021
|
||||||
|
// build-fail
|
||||||
|
|
||||||
#![feature(impl_trait_in_assoc_type)]
|
#![feature(impl_trait_in_assoc_type)]
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0733]: recursion in an async block requires boxing
|
error[E0733]: recursion in an async block requires boxing
|
||||||
--> $DIR/indirect-recursion-issue-112047.rs:21:9
|
--> $DIR/indirect-recursion-issue-112047.rs:22:9
|
||||||
|
|
|
|
||||||
LL | async move { recur(self).await; }
|
LL | async move { recur(self).await; }
|
||||||
| ^^^^^^^^^^^^^-----------------^^^
|
| ^^^^^^^^^^^^^-----------------^^^
|
||||||
|
@ -7,7 +7,7 @@ LL | async move { recur(self).await; }
|
||||||
| recursive call here
|
| recursive call here
|
||||||
|
|
|
|
||||||
note: which leads to this async fn
|
note: which leads to this async fn
|
||||||
--> $DIR/indirect-recursion-issue-112047.rs:13:1
|
--> $DIR/indirect-recursion-issue-112047.rs:14:1
|
||||||
|
|
|
|
||||||
LL | async fn recur(t: impl Recur) {
|
LL | async fn recur(t: impl Recur) {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue