rustc_traits/
coroutine_witnesses.rs1use rustc_infer::infer::TyCtxtInferExt;
2use rustc_infer::infer::canonical::QueryRegionConstraint;
3use rustc_infer::infer::canonical::query_response::make_query_region_constraints;
4use rustc_infer::infer::resolve::OpportunisticRegionResolver;
5use rustc_infer::traits::{Obligation, ObligationCause};
6use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, fold_regions};
7use rustc_span::def_id::DefId;
8use rustc_trait_selection::traits::{ObligationCtxt, with_replaced_escaping_bound_vars};
9
10pub(crate) fn coroutine_hidden_types<'tcx>(
14 tcx: TyCtxt<'tcx>,
15 def_id: DefId,
16) -> ty::EarlyBinder<'tcx, ty::Binder<'tcx, ty::CoroutineWitnessTypes<TyCtxt<'tcx>>>> {
17 let coroutine_layout = tcx.mir_coroutine_witnesses(def_id);
18 let mut vars = ::alloc::vec::Vec::new()vec![];
19 let bound_tys = tcx.mk_type_list_from_iter(
20 coroutine_layout
21 .as_ref()
22 .map_or_else(|| [].iter(), |l| l.field_tys.iter())
23 .filter(|decl| !decl.ignore_for_traits)
24 .map(|decl| {
25 let ty = fold_regions(tcx, decl.ty, |re, debruijn| {
26 {
match (&re, &tcx.lifetimes.re_erased) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};assert_eq!(re, tcx.lifetimes.re_erased);
27 let var = ty::BoundVar::from_usize(vars.len());
28 vars.push(ty::BoundVariableKind::Region(ty::BoundRegionKind::Anon));
29 ty::Region::new_bound(
30 tcx,
31 debruijn,
32 ty::BoundRegion { var, kind: ty::BoundRegionKind::Anon },
33 )
34 });
35 ty
36 }),
37 );
38
39 let assumptions = compute_assumptions(tcx, def_id, bound_tys);
40
41 ty::EarlyBinder::bind(
42 tcx,
43 ty::Binder::bind_with_vars(
44 ty::CoroutineWitnessTypes { types: bound_tys, assumptions },
45 tcx.mk_bound_variable_kinds(&vars),
46 ),
47 )
48}
49
50fn compute_assumptions<'tcx>(
51 tcx: TyCtxt<'tcx>,
52 def_id: DefId,
53 bound_tys: &'tcx ty::List<Ty<'tcx>>,
54) -> &'tcx ty::List<ty::ArgOutlivesPredicate<'tcx>> {
55 let infcx = tcx
56 .infer_ctxt()
57 .build(ty::TypingMode::Typeck { defining_opaque_types_and_generators: ty::List::empty() });
58 with_replaced_escaping_bound_vars(&infcx, &mut ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[None]))vec![None], bound_tys, |bound_tys| {
59 let param_env = tcx.param_env(def_id);
60 let ocx = ObligationCtxt::new(&infcx);
61
62 ocx.register_obligations(bound_tys.iter().map(|ty| {
63 Obligation::new(
64 tcx,
65 ObligationCause::dummy(),
66 param_env,
67 ty::ClauseKind::WellFormed(ty.into()),
68 )
69 }));
70 let _errors = ocx.evaluate_obligations_error_on_ambiguity();
71
72 let region_obligations = infcx.take_registered_region_obligations();
73 let region_assumptions = infcx.take_registered_region_assumptions();
74 let region_constraints = infcx.take_and_reset_region_constraints();
75
76 let constraints = make_query_region_constraints(
77 region_obligations,
78 ®ion_constraints,
79 region_assumptions,
80 )
81 .constraints
82 .fold_with(&mut OpportunisticRegionResolver::new(&infcx));
83
84 tcx.mk_outlives_from_iter(
85 constraints
86 .into_iter()
87 .flat_map(|QueryRegionConstraint { constraint, .. }| constraint.iter_outlives())
88 .filter(|o| !o.has_infer()),
92 )
93 })
94}