Skip to main content

rustc_traits/
coroutine_witnesses.rs

1use 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
10/// Return the set of types that should be taken into account when checking
11/// trait bounds on a coroutine's internal state. This properly replaces
12/// `ReErased` with new existential bound lifetimes.
13pub(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
50// FIXME: The assumptions are only used in the old solver when `-Zhigher-ranked-assumptions`
51// is true. `-Zhigher-ranked-assumptions` is superseded by `assumptions-on-binders`.
52// We can remove this function soon.
53fn compute_assumptions<'tcx>(
54    tcx: TyCtxt<'tcx>,
55    def_id: DefId,
56    bound_tys: &'tcx ty::List<Ty<'tcx>>,
57) -> &'tcx ty::List<ty::ArgOutlivesClause<'tcx>> {
58    if tcx.next_trait_solver_globally() || !tcx.sess.opts.unstable_opts.higher_ranked_assumptions {
59        return &ty::List::empty();
60    }
61
62    let infcx = tcx
63        .infer_ctxt()
64        .build(ty::TypingMode::Typeck { defining_opaque_types_and_generators: ty::List::empty() });
65    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| {
66        let param_env = tcx.param_env(def_id);
67        let ocx = ObligationCtxt::new(&infcx);
68
69        ocx.register_obligations(bound_tys.iter().map(|ty| {
70            Obligation::new(
71                tcx,
72                ObligationCause::dummy(),
73                param_env,
74                ty::ClauseKind::WellFormed(ty.into()),
75            )
76        }));
77        let _errors = ocx.evaluate_obligations_error_on_ambiguity();
78
79        let region_obligations = infcx.take_registered_region_obligations();
80        let region_assumptions = infcx.take_registered_region_assumptions();
81        let region_constraints = infcx.take_and_reset_region_constraints();
82
83        let constraints = make_query_region_constraints(
84            region_obligations,
85            &region_constraints,
86            region_assumptions,
87        )
88        .constraints
89        .fold_with(&mut OpportunisticRegionResolver::new(&infcx));
90
91        tcx.mk_outlives_from_iter(
92            constraints
93                .into_iter()
94                .flat_map(|QueryRegionConstraint { constraint, .. }| constraint.iter_outlives())
95                // FIXME(higher_ranked_auto): We probably should deeply resolve these before
96                // filtering out infers which only correspond to unconstrained infer regions
97                // which we can sometimes get.
98                .filter(|o| !o.has_infer()),
99        )
100    })
101}