Only compute layout of opaque if coroutine is the cause of an opaque cycle
This commit is contained in:
parent
199af7cef0
commit
fa2ff51ace
compiler
tests/ui/type-alias-impl-trait
@ -17,7 +17,7 @@ use rustc_middle::middle::stability::EvalResult;
|
||||
use rustc_middle::traits::{DefiningAnchor, ObligationCauseCode};
|
||||
use rustc_middle::ty::fold::BottomUpFolder;
|
||||
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::{
|
||||
AdtDef, ParamEnv, RegionKind, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
|
||||
@ -232,16 +232,33 @@ pub(super) fn check_opaque_for_cycles<'tcx>(
|
||||
span: Span,
|
||||
) -> 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 = 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)))
|
||||
|
||||
// First, try to look at any opaque expansion cycles, considering coroutine fields
|
||||
// (even though these aren't necessarily true errors).
|
||||
if tcx
|
||||
.try_expand_impl_trait_type(def_id.to_def_id(), args, InspectCoroutineFields::Yes)
|
||||
.is_err()
|
||||
{
|
||||
Err(guar)
|
||||
} else {
|
||||
Ok(())
|
||||
// Look for true opaque expansion cycles, but ignore coroutines.
|
||||
// This will give us any true errors. Coroutines are only problematic
|
||||
// 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`.
|
||||
|
@ -702,6 +702,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
self,
|
||||
def_id: DefId,
|
||||
args: GenericArgsRef<'tcx>,
|
||||
inspect_coroutine_fields: InspectCoroutineFields,
|
||||
) -> Result<Ty<'tcx>, Ty<'tcx>> {
|
||||
let mut visitor = OpaqueTypeExpander {
|
||||
seen_opaque_tys: FxHashSet::default(),
|
||||
@ -712,6 +713,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
check_recursion: true,
|
||||
expand_coroutines: true,
|
||||
tcx: self,
|
||||
inspect_coroutine_fields,
|
||||
};
|
||||
|
||||
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.
|
||||
check_recursion: bool,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
inspect_coroutine_fields: InspectCoroutineFields,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
pub enum InspectCoroutineFields {
|
||||
No,
|
||||
Yes,
|
||||
}
|
||||
|
||||
impl<'tcx> OpaqueTypeExpander<'tcx> {
|
||||
@ -923,7 +932,20 @@ impl<'tcx> OpaqueTypeExpander<'tcx> {
|
||||
}
|
||||
let args = args.fold_with(self);
|
||||
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 {
|
||||
self.seen_opaque_tys.remove(&def_id);
|
||||
}
|
||||
@ -1495,6 +1517,7 @@ pub fn reveal_opaque_types_in_bounds<'tcx>(
|
||||
check_recursion: false,
|
||||
expand_coroutines: false,
|
||||
tcx,
|
||||
inspect_coroutine_fields: InspectCoroutineFields::No,
|
||||
};
|
||||
val.fold_with(&mut visitor)
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
// edition: 2021
|
||||
// build-fail
|
||||
|
||||
#![feature(impl_trait_in_assoc_type)]
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
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; }
|
||||
| ^^^^^^^^^^^^^-----------------^^^
|
||||
@ -7,7 +7,7 @@ LL | async move { recur(self).await; }
|
||||
| recursive call here
|
||||
|
|
||||
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) {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
Loading…
x
Reference in New Issue
Block a user