fn new_coroutine_witness_for_coroutine woops
This commit is contained in:
@@ -830,6 +830,31 @@ impl<'tcx> Ty<'tcx> {
|
|||||||
Ty::new(tcx, CoroutineWitness(def_id, args))
|
Ty::new(tcx, CoroutineWitness(def_id, args))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn new_coroutine_witness_for_coroutine(
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
def_id: DefId,
|
||||||
|
coroutine_args: GenericArgsRef<'tcx>,
|
||||||
|
) -> Ty<'tcx> {
|
||||||
|
tcx.debug_assert_args_compatible(def_id, coroutine_args);
|
||||||
|
// HACK: Coroutine witness types are lifetime erased, so they
|
||||||
|
// never reference any lifetime args from the coroutine. We erase
|
||||||
|
// the regions here since we may get into situations where a
|
||||||
|
// coroutine is recursively contained within itself, leading to
|
||||||
|
// witness types that differ by region args. This means that
|
||||||
|
// cycle detection in fulfillment will not kick in, which leads
|
||||||
|
// to unnecessary overflows in async code. See the issue:
|
||||||
|
// <https://github.com/rust-lang/rust/issues/145151>.
|
||||||
|
let args =
|
||||||
|
ty::GenericArgs::for_item(tcx, tcx.typeck_root_def_id(def_id), |def, _| {
|
||||||
|
match def.kind {
|
||||||
|
ty::GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
|
||||||
|
ty::GenericParamDefKind::Type { .. }
|
||||||
|
| ty::GenericParamDefKind::Const { .. } => coroutine_args[def.index as usize],
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Ty::new_coroutine_witness(tcx, def_id, args)
|
||||||
|
}
|
||||||
|
|
||||||
// misc
|
// misc
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -988,6 +1013,14 @@ impl<'tcx> rustc_type_ir::inherent::Ty<TyCtxt<'tcx>> for Ty<'tcx> {
|
|||||||
Ty::new_coroutine_witness(interner, def_id, args)
|
Ty::new_coroutine_witness(interner, def_id, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn new_coroutine_witness_for_coroutine(
|
||||||
|
interner: TyCtxt<'tcx>,
|
||||||
|
def_id: DefId,
|
||||||
|
coroutine_args: ty::GenericArgsRef<'tcx>,
|
||||||
|
) -> Self {
|
||||||
|
Ty::new_coroutine_witness_for_coroutine(interner, def_id, coroutine_args)
|
||||||
|
}
|
||||||
|
|
||||||
fn new_ptr(interner: TyCtxt<'tcx>, ty: Self, mutbl: hir::Mutability) -> Self {
|
fn new_ptr(interner: TyCtxt<'tcx>, ty: Self, mutbl: hir::Mutability) -> Self {
|
||||||
Ty::new_ptr(interner, ty, mutbl)
|
Ty::new_ptr(interner, ty, mutbl)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,17 +75,10 @@ where
|
|||||||
Ok(ty::Binder::dummy(vec![args.as_coroutine_closure().tupled_upvars_ty()]))
|
Ok(ty::Binder::dummy(vec![args.as_coroutine_closure().tupled_upvars_ty()]))
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::Coroutine(def_id, args) => {
|
ty::Coroutine(def_id, args) => Ok(ty::Binder::dummy(vec![
|
||||||
let coroutine_args = args.as_coroutine();
|
args.as_coroutine().tupled_upvars_ty(),
|
||||||
Ok(ty::Binder::dummy(vec![
|
Ty::new_coroutine_witness_for_coroutine(ecx.cx(), def_id, args),
|
||||||
coroutine_args.tupled_upvars_ty(),
|
])),
|
||||||
Ty::new_coroutine_witness(
|
|
||||||
ecx.cx(),
|
|
||||||
def_id,
|
|
||||||
ecx.cx().mk_args(coroutine_args.parent_args().as_slice()),
|
|
||||||
),
|
|
||||||
]))
|
|
||||||
}
|
|
||||||
|
|
||||||
ty::CoroutineWitness(def_id, args) => Ok(ecx
|
ty::CoroutineWitness(def_id, args) => Ok(ecx
|
||||||
.cx()
|
.cx()
|
||||||
@@ -251,14 +244,9 @@ where
|
|||||||
Movability::Static => Err(NoSolution),
|
Movability::Static => Err(NoSolution),
|
||||||
Movability::Movable => {
|
Movability::Movable => {
|
||||||
if ecx.cx().features().coroutine_clone() {
|
if ecx.cx().features().coroutine_clone() {
|
||||||
let coroutine = args.as_coroutine();
|
|
||||||
Ok(ty::Binder::dummy(vec![
|
Ok(ty::Binder::dummy(vec![
|
||||||
coroutine.tupled_upvars_ty(),
|
args.as_coroutine().tupled_upvars_ty(),
|
||||||
Ty::new_coroutine_witness(
|
Ty::new_coroutine_witness_for_coroutine(ecx.cx(), def_id, args),
|
||||||
ecx.cx(),
|
|
||||||
def_id,
|
|
||||||
ecx.cx().mk_args(coroutine.parent_args().as_slice()),
|
|
||||||
),
|
|
||||||
]))
|
]))
|
||||||
} else {
|
} else {
|
||||||
Err(NoSolution)
|
Err(NoSolution)
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
|
|
||||||
use std::assert_matches::assert_matches;
|
use std::assert_matches::assert_matches;
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell};
|
||||||
|
use std::cmp;
|
||||||
use std::fmt::{self, Display};
|
use std::fmt::{self, Display};
|
||||||
use std::ops::ControlFlow;
|
use std::ops::ControlFlow;
|
||||||
use std::{cmp, iter};
|
|
||||||
|
|
||||||
use hir::def::DefKind;
|
use hir::def::DefKind;
|
||||||
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
||||||
@@ -2185,32 +2185,23 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|
|||||||
ty::Binder::dummy(vec![ty])
|
ty::Binder::dummy(vec![ty])
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::Coroutine(coroutine_def_id, args) => {
|
ty::Coroutine(def_id, args) => match self.tcx().coroutine_movability(def_id) {
|
||||||
match self.tcx().coroutine_movability(coroutine_def_id) {
|
|
||||||
hir::Movability::Static => {
|
hir::Movability::Static => {
|
||||||
unreachable!("tried to assemble `Sized` for static coroutine")
|
unreachable!("tried to assemble `Clone` for static coroutine")
|
||||||
}
|
}
|
||||||
hir::Movability::Movable => {
|
hir::Movability::Movable => {
|
||||||
if self.tcx().features().coroutine_clone() {
|
if self.tcx().features().coroutine_clone() {
|
||||||
ty::Binder::dummy(
|
ty::Binder::dummy(vec![
|
||||||
args.as_coroutine()
|
args.as_coroutine().tupled_upvars_ty(),
|
||||||
.upvar_tys()
|
Ty::new_coroutine_witness_for_coroutine(self.tcx(), def_id, args),
|
||||||
.iter()
|
])
|
||||||
.chain([Ty::new_coroutine_witness(
|
|
||||||
self.tcx(),
|
|
||||||
coroutine_def_id,
|
|
||||||
self.tcx().mk_args(args.as_coroutine().parent_args()),
|
|
||||||
)])
|
|
||||||
.collect::<Vec<_>>(),
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
unreachable!(
|
unreachable!(
|
||||||
"tried to assemble `Sized` for coroutine without enabled feature"
|
"tried to assemble `Clone` for coroutine without enabled feature"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
|
||||||
|
|
||||||
ty::CoroutineWitness(def_id, args) => self
|
ty::CoroutineWitness(def_id, args) => self
|
||||||
.infcx
|
.infcx
|
||||||
@@ -2334,25 +2325,9 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|
|||||||
ty::Coroutine(def_id, args) => {
|
ty::Coroutine(def_id, args) => {
|
||||||
let ty = self.infcx.shallow_resolve(args.as_coroutine().tupled_upvars_ty());
|
let ty = self.infcx.shallow_resolve(args.as_coroutine().tupled_upvars_ty());
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
let witness = Ty::new_coroutine_witness(
|
let witness = Ty::new_coroutine_witness_for_coroutine(tcx, def_id, args);
|
||||||
tcx,
|
|
||||||
def_id,
|
|
||||||
ty::GenericArgs::for_item(tcx, def_id, |def, _| match def.kind {
|
|
||||||
// HACK: Coroutine witnesse types are lifetime erased, so they
|
|
||||||
// never reference any lifetime args from the coroutine. We erase
|
|
||||||
// the regions here since we may get into situations where a
|
|
||||||
// coroutine is recursively contained within itself, leading to
|
|
||||||
// witness types that differ by region args. This means that
|
|
||||||
// cycle detection in fulfillment will not kick in, which leads
|
|
||||||
// to unnecessary overflows in async code. See the issue:
|
|
||||||
// <https://github.com/rust-lang/rust/issues/145151>.
|
|
||||||
ty::GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
|
|
||||||
ty::GenericParamDefKind::Type { .. }
|
|
||||||
| ty::GenericParamDefKind::Const { .. } => args[def.index as usize],
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
ty::Binder::dummy(AutoImplConstituents {
|
ty::Binder::dummy(AutoImplConstituents {
|
||||||
types: [ty].into_iter().chain(iter::once(witness)).collect(),
|
types: vec![ty, witness],
|
||||||
assumptions: vec![],
|
assumptions: vec![],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,6 +91,12 @@ pub trait Ty<I: Interner<Ty = Self>>:
|
|||||||
|
|
||||||
fn new_coroutine_witness(interner: I, def_id: I::DefId, args: I::GenericArgs) -> Self;
|
fn new_coroutine_witness(interner: I, def_id: I::DefId, args: I::GenericArgs) -> Self;
|
||||||
|
|
||||||
|
fn new_coroutine_witness_for_coroutine(
|
||||||
|
interner: I,
|
||||||
|
def_id: I::DefId,
|
||||||
|
coroutine_args: I::GenericArgs,
|
||||||
|
) -> Self;
|
||||||
|
|
||||||
fn new_ptr(interner: I, ty: Self, mutbl: Mutability) -> Self;
|
fn new_ptr(interner: I, ty: Self, mutbl: Mutability) -> Self;
|
||||||
|
|
||||||
fn new_ref(interner: I, region: I::Region, ty: Self, mutbl: Mutability) -> Self;
|
fn new_ref(interner: I, region: I::Region, ty: Self, mutbl: Mutability) -> Self;
|
||||||
|
|||||||
Reference in New Issue
Block a user