Skip to content

Commit fafae23

Browse files
Deduce outlives obligations from WF of coroutine interior types
1 parent fc52758 commit fafae23

File tree

3 files changed

+60
-3
lines changed

3 files changed

+60
-3
lines changed

compiler/rustc_middle/src/query/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -988,7 +988,7 @@ rustc_queries! {
988988
}
989989

990990
query coroutine_hidden_types(
991-
def_id: DefId
991+
def_id: DefId,
992992
) -> ty::EarlyBinder<'tcx, ty::Binder<'tcx, ty::CoroutineWitnessTypes<TyCtxt<'tcx>>>> {
993993
desc { "looking up the hidden types stored across await points in a coroutine" }
994994
}

compiler/rustc_middle/src/ty/context.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3112,6 +3112,17 @@ impl<'tcx> TyCtxt<'tcx> {
31123112
T::collect_and_apply(iter, |xs| self.mk_bound_variable_kinds(xs))
31133113
}
31143114

3115+
pub fn mk_outlives_from_iter<I, T>(self, iter: I) -> T::Output
3116+
where
3117+
I: Iterator<Item = T>,
3118+
T: CollectAndApply<
3119+
ty::OutlivesPredicate<'tcx, ty::GenericArg<'tcx>>,
3120+
&'tcx ty::List<ty::OutlivesPredicate<'tcx, ty::GenericArg<'tcx>>>,
3121+
>,
3122+
{
3123+
T::collect_and_apply(iter, |xs| self.mk_outlives(xs))
3124+
}
3125+
31153126
/// Emit a lint at `span` from a lint struct (some type that implements `LintDiagnostic`,
31163127
/// typically generated by `#[derive(LintDiagnostic)]`).
31173128
#[track_caller]

compiler/rustc_traits/src/coroutine_witnesses.rs

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
use rustc_hir::def_id::DefId;
2-
use rustc_middle::ty::{self, TyCtxt, fold_regions};
2+
use rustc_infer::infer::TyCtxtInferExt;
3+
use rustc_infer::infer::canonical::query_response::make_query_region_constraints;
4+
use rustc_infer::traits::{Obligation, ObligationCause};
5+
use rustc_middle::ty::{self, Ty, TyCtxt, fold_regions};
6+
use rustc_trait_selection::traits::{ObligationCtxt, with_replaced_escaping_bound_vars};
37

48
/// Return the set of types that should be taken into account when checking
59
/// trait bounds on a coroutine's internal state. This properly replaces
@@ -29,8 +33,50 @@ pub(crate) fn coroutine_hidden_types<'tcx>(
2933
ty
3034
}),
3135
);
36+
37+
let assumptions = compute_assumptions(tcx, def_id, bound_tys);
38+
3239
ty::EarlyBinder::bind(ty::Binder::bind_with_vars(
33-
ty::CoroutineWitnessTypes { types: bound_tys, assumptions: ty::List::empty() },
40+
ty::CoroutineWitnessTypes { types: bound_tys, assumptions },
3441
tcx.mk_bound_variable_kinds(&vars),
3542
))
3643
}
44+
45+
fn compute_assumptions<'tcx>(
46+
tcx: TyCtxt<'tcx>,
47+
def_id: DefId,
48+
bound_tys: &'tcx ty::List<Ty<'tcx>>,
49+
) -> &'tcx ty::List<ty::OutlivesPredicate<'tcx, ty::GenericArg<'tcx>>> {
50+
let infcx = tcx.infer_ctxt().build(ty::TypingMode::Analysis {
51+
defining_opaque_types_and_generators: ty::List::empty(),
52+
});
53+
with_replaced_escaping_bound_vars(&infcx, &mut vec![None], bound_tys, |bound_tys| {
54+
let param_env = tcx.param_env(def_id);
55+
let ocx = ObligationCtxt::new(&infcx);
56+
57+
ocx.register_obligations(bound_tys.iter().map(|ty| {
58+
Obligation::new(
59+
tcx,
60+
ObligationCause::dummy(),
61+
param_env,
62+
ty::ClauseKind::WellFormed(ty.into()),
63+
)
64+
}));
65+
let _errors = ocx.select_all_or_error();
66+
67+
let region_obligations = infcx.take_registered_region_obligations();
68+
let region_constraints = infcx.take_and_reset_region_constraints();
69+
tcx.mk_outlives_from_iter(
70+
make_query_region_constraints(
71+
tcx,
72+
region_obligations
73+
.iter()
74+
.map(|r_o| (r_o.sup_type, r_o.sub_region, r_o.origin.to_constraint_category())),
75+
&region_constraints,
76+
)
77+
.outlives
78+
.into_iter()
79+
.map(|(o, _)| o),
80+
)
81+
})
82+
}

0 commit comments

Comments
 (0)