Skip to content

Commit 3e7dfaa

Browse files
Deduce outlives obligations from WF of coroutine interior types
1 parent 7976ca2 commit 3e7dfaa

File tree

3 files changed

+67
-3
lines changed

3 files changed

+67
-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: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
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::infer::resolve::OpportunisticRegionResolver;
5+
use rustc_infer::traits::{Obligation, ObligationCause};
6+
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, fold_regions};
7+
use rustc_trait_selection::traits::{ObligationCtxt, with_replaced_escaping_bound_vars};
38

49
/// Return the set of types that should be taken into account when checking
510
/// trait bounds on a coroutine's internal state. This properly replaces
@@ -29,8 +34,56 @@ pub(crate) fn coroutine_hidden_types<'tcx>(
2934
ty
3035
}),
3136
);
37+
38+
let assumptions = compute_assumptions(tcx, def_id, bound_tys);
39+
3240
ty::EarlyBinder::bind(ty::Binder::bind_with_vars(
33-
ty::CoroutineWitnessTypes { types: bound_tys, assumptions: ty::List::empty() },
41+
ty::CoroutineWitnessTypes { types: bound_tys, assumptions },
3442
tcx.mk_bound_variable_kinds(&vars),
3543
))
3644
}
45+
46+
fn compute_assumptions<'tcx>(
47+
tcx: TyCtxt<'tcx>,
48+
def_id: DefId,
49+
bound_tys: &'tcx ty::List<Ty<'tcx>>,
50+
) -> &'tcx ty::List<ty::OutlivesPredicate<'tcx, ty::GenericArg<'tcx>>> {
51+
let infcx = tcx.infer_ctxt().build(ty::TypingMode::Analysis {
52+
defining_opaque_types_and_generators: ty::List::empty(),
53+
});
54+
with_replaced_escaping_bound_vars(&infcx, &mut vec![None], bound_tys, |bound_tys| {
55+
let param_env = tcx.param_env(def_id);
56+
let ocx = ObligationCtxt::new(&infcx);
57+
58+
ocx.register_obligations(bound_tys.iter().map(|ty| {
59+
Obligation::new(
60+
tcx,
61+
ObligationCause::dummy(),
62+
param_env,
63+
ty::ClauseKind::WellFormed(ty.into()),
64+
)
65+
}));
66+
let _errors = ocx.select_all_or_error();
67+
68+
let region_obligations = infcx.take_registered_region_obligations();
69+
let region_constraints = infcx.take_and_reset_region_constraints();
70+
71+
let outlives = make_query_region_constraints(
72+
tcx,
73+
region_obligations,
74+
&region_constraints,
75+
)
76+
.outlives
77+
.fold_with(&mut OpportunisticRegionResolver::new(&infcx));
78+
79+
tcx.mk_outlives_from_iter(
80+
outlives
81+
.into_iter()
82+
.map(|(o, _)| o)
83+
// FIXME(higher_ranked_auto): We probably should deeply resolve these before
84+
// filtering out infers which only correspond to unconstrained infer regions
85+
// which we can sometimes get.
86+
.filter(|o| !o.has_infer()),
87+
)
88+
})
89+
}

0 commit comments

Comments
 (0)