diff options
Diffstat (limited to 'compiler/rustc_traits')
| -rw-r--r-- | compiler/rustc_traits/src/coroutine_witnesses.rs | 58 |
1 files changed, 56 insertions, 2 deletions
diff --git a/compiler/rustc_traits/src/coroutine_witnesses.rs b/compiler/rustc_traits/src/coroutine_witnesses.rs index 447e13126cc..87d17f3e131 100644 --- a/compiler/rustc_traits/src/coroutine_witnesses.rs +++ b/compiler/rustc_traits/src/coroutine_witnesses.rs @@ -1,5 +1,10 @@ use rustc_hir::def_id::DefId; -use rustc_middle::ty::{self, TyCtxt, fold_regions}; +use rustc_infer::infer::TyCtxtInferExt; +use rustc_infer::infer::canonical::query_response::make_query_region_constraints; +use rustc_infer::infer::resolve::OpportunisticRegionResolver; +use rustc_infer::traits::{Obligation, ObligationCause}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, fold_regions}; +use rustc_trait_selection::traits::{ObligationCtxt, with_replaced_escaping_bound_vars}; /// Return the set of types that should be taken into account when checking /// trait bounds on a coroutine's internal state. This properly replaces @@ -30,8 +35,57 @@ pub(crate) fn coroutine_hidden_types<'tcx>( }), ); + let assumptions = compute_assumptions(tcx, def_id, bound_tys); + ty::EarlyBinder::bind(ty::Binder::bind_with_vars( - ty::CoroutineWitnessTypes { types: bound_tys }, + ty::CoroutineWitnessTypes { types: bound_tys, assumptions }, tcx.mk_bound_variable_kinds(&vars), )) } + +fn compute_assumptions<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: DefId, + bound_tys: &'tcx ty::List<Ty<'tcx>>, +) -> &'tcx ty::List<ty::ArgOutlivesPredicate<'tcx>> { + let infcx = tcx.infer_ctxt().build(ty::TypingMode::Analysis { + defining_opaque_types_and_generators: ty::List::empty(), + }); + with_replaced_escaping_bound_vars(&infcx, &mut vec![None], bound_tys, |bound_tys| { + let param_env = tcx.param_env(def_id); + let ocx = ObligationCtxt::new(&infcx); + + ocx.register_obligations(bound_tys.iter().map(|ty| { + Obligation::new( + tcx, + ObligationCause::dummy(), + param_env, + ty::ClauseKind::WellFormed(ty.into()), + ) + })); + let _errors = ocx.select_all_or_error(); + + let region_obligations = infcx.take_registered_region_obligations(); + let region_assumptions = infcx.take_registered_region_assumptions(); + let region_constraints = infcx.take_and_reset_region_constraints(); + + let outlives = make_query_region_constraints( + tcx, + region_obligations, + ®ion_constraints, + region_assumptions, + ) + .outlives + .fold_with(&mut OpportunisticRegionResolver::new(&infcx)); + + tcx.mk_outlives_from_iter( + outlives + .into_iter() + .map(|(o, _)| o) + // FIXME(higher_ranked_auto): We probably should deeply resolve these before + // filtering out infers which only correspond to unconstrained infer regions + // which we can sometimes get. + .filter(|o| !o.has_infer()), + ) + }) +} |
