rustc_traits/
coroutine_witnesses.rs

1use rustc_hir::def_id::DefId;
2use rustc_middle::ty::{self, TyCtxt, fold_regions};
3
4/// Return the set of types that should be taken into account when checking
5/// trait bounds on a coroutine's internal state. This properly replaces
6/// `ReErased` with new existential bound lifetimes.
7pub(crate) fn coroutine_hidden_types<'tcx>(
8    tcx: TyCtxt<'tcx>,
9    def_id: DefId,
10) -> ty::EarlyBinder<'tcx, ty::Binder<'tcx, ty::CoroutineWitnessTypes<TyCtxt<'tcx>>>> {
11    let coroutine_layout = tcx.mir_coroutine_witnesses(def_id);
12    let mut vars = vec![];
13    let bound_tys = tcx.mk_type_list_from_iter(
14        coroutine_layout
15            .as_ref()
16            .map_or_else(|| [].iter(), |l| l.field_tys.iter())
17            .filter(|decl| !decl.ignore_for_traits)
18            .map(|decl| {
19                let ty = fold_regions(tcx, decl.ty, |re, debruijn| {
20                    assert_eq!(re, tcx.lifetimes.re_erased);
21                    let var = ty::BoundVar::from_usize(vars.len());
22                    vars.push(ty::BoundVariableKind::Region(ty::BoundRegionKind::Anon));
23                    ty::Region::new_bound(
24                        tcx,
25                        debruijn,
26                        ty::BoundRegion { var, kind: ty::BoundRegionKind::Anon },
27                    )
28                });
29                ty
30            }),
31    );
32
33    ty::EarlyBinder::bind(ty::Binder::bind_with_vars(
34        ty::CoroutineWitnessTypes { types: bound_tys },
35        tcx.mk_bound_variable_kinds(&vars),
36    ))
37}