mirror of
https://github.com/rust-lang/rust.git
synced 2025-11-07 08:26:14 +00:00
92 lines
3.6 KiB
Rust
92 lines
3.6 KiB
Rust
use rustc_hir::def_id::DefId;
|
|
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
|
|
/// `ReErased` with new existential bound lifetimes.
|
|
pub(crate) fn coroutine_hidden_types<'tcx>(
|
|
tcx: TyCtxt<'tcx>,
|
|
def_id: DefId,
|
|
) -> ty::EarlyBinder<'tcx, ty::Binder<'tcx, ty::CoroutineWitnessTypes<TyCtxt<'tcx>>>> {
|
|
let coroutine_layout = tcx.mir_coroutine_witnesses(def_id);
|
|
let mut vars = vec![];
|
|
let bound_tys = tcx.mk_type_list_from_iter(
|
|
coroutine_layout
|
|
.as_ref()
|
|
.map_or_else(|| [].iter(), |l| l.field_tys.iter())
|
|
.filter(|decl| !decl.ignore_for_traits)
|
|
.map(|decl| {
|
|
let ty = fold_regions(tcx, decl.ty, |re, debruijn| {
|
|
assert_eq!(re, tcx.lifetimes.re_erased);
|
|
let var = ty::BoundVar::from_usize(vars.len());
|
|
vars.push(ty::BoundVariableKind::Region(ty::BoundRegionKind::Anon));
|
|
ty::Region::new_bound(
|
|
tcx,
|
|
debruijn,
|
|
ty::BoundRegion { var, kind: ty::BoundRegionKind::Anon },
|
|
)
|
|
});
|
|
ty
|
|
}),
|
|
);
|
|
|
|
let assumptions = compute_assumptions(tcx, def_id, bound_tys);
|
|
|
|
ty::EarlyBinder::bind(ty::Binder::bind_with_vars(
|
|
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()),
|
|
)
|
|
})
|
|
}
|