Skip to content

Commit 1783887

Browse files
committed
Auto merge of #141392 - compiler-errors:query-outlives, r=lcnr
Avoid obligation construction dance with query region constraints And some renaming...
2 parents 95a2212 + 9d742ee commit 1783887

File tree

12 files changed

+73
-108
lines changed

12 files changed

+73
-108
lines changed

compiler/rustc_hir_analysis/src/check/wfcheck.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -742,7 +742,7 @@ fn ty_known_to_outlive<'tcx>(
742742
region: ty::Region<'tcx>,
743743
) -> bool {
744744
test_region_obligations(tcx, id, param_env, wf_tys, |infcx| {
745-
infcx.register_region_obligation(infer::RegionObligation {
745+
infcx.register_type_outlives_constraint_inner(infer::TypeOutlivesConstraint {
746746
sub_region: region,
747747
sup_type: ty,
748748
origin: infer::RelateParamBound(DUMMY_SP, ty, None),

compiler/rustc_infer/src/infer/canonical/query_response.rs

Lines changed: 8 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,20 @@ use std::iter;
1212

1313
use rustc_index::{Idx, IndexVec};
1414
use rustc_middle::arena::ArenaAllocatable;
15+
use rustc_middle::bug;
1516
use rustc_middle::mir::ConstraintCategory;
1617
use rustc_middle::ty::{self, BoundVar, GenericArg, GenericArgKind, Ty, TyCtxt, TypeFoldable};
17-
use rustc_middle::{bug, span_bug};
1818
use tracing::{debug, instrument};
1919

2020
use crate::infer::canonical::instantiate::{CanonicalExt, instantiate_value};
2121
use crate::infer::canonical::{
2222
Canonical, CanonicalQueryResponse, CanonicalVarValues, Certainty, OriginalQueryValues,
23-
QueryOutlivesConstraint, QueryRegionConstraints, QueryResponse,
23+
QueryRegionConstraints, QueryResponse,
2424
};
2525
use crate::infer::region_constraints::{Constraint, RegionConstraintData};
2626
use crate::infer::{DefineOpaqueTypes, InferCtxt, InferOk, InferResult, SubregionOrigin};
2727
use crate::traits::query::NoSolution;
28-
use crate::traits::{
29-
Obligation, ObligationCause, PredicateObligation, PredicateObligations, ScrubbedTraitError,
30-
TraitEngine,
31-
};
28+
use crate::traits::{ObligationCause, PredicateObligations, ScrubbedTraitError, TraitEngine};
3229

3330
impl<'tcx> InferCtxt<'tcx> {
3431
/// This method is meant to be invoked as the final step of a canonical query
@@ -169,15 +166,13 @@ impl<'tcx> InferCtxt<'tcx> {
169166
where
170167
R: Debug + TypeFoldable<TyCtxt<'tcx>>,
171168
{
172-
let InferOk { value: result_args, mut obligations } =
169+
let InferOk { value: result_args, obligations } =
173170
self.query_response_instantiation(cause, param_env, original_values, query_response)?;
174171

175-
obligations.extend(self.query_outlives_constraints_into_obligations(
176-
cause,
177-
param_env,
178-
&query_response.value.region_constraints.outlives,
179-
&result_args,
180-
));
172+
for (predicate, _category) in &query_response.value.region_constraints.outlives {
173+
let predicate = instantiate_value(self.tcx, &result_args, *predicate);
174+
self.register_outlives_constraint(predicate, cause);
175+
}
181176

182177
let user_result: R =
183178
query_response.instantiate_projected(self.tcx, &result_args, |q_r| q_r.value.clone());
@@ -525,47 +520,6 @@ impl<'tcx> InferCtxt<'tcx> {
525520
self.unify_canonical_vars(cause, param_env, original_values, instantiated_query_response)
526521
}
527522

528-
/// Converts the region constraints resulting from a query into an
529-
/// iterator of obligations.
530-
fn query_outlives_constraints_into_obligations(
531-
&self,
532-
cause: &ObligationCause<'tcx>,
533-
param_env: ty::ParamEnv<'tcx>,
534-
uninstantiated_region_constraints: &[QueryOutlivesConstraint<'tcx>],
535-
result_args: &CanonicalVarValues<'tcx>,
536-
) -> impl Iterator<Item = PredicateObligation<'tcx>> {
537-
uninstantiated_region_constraints.iter().map(move |&constraint| {
538-
let predicate = instantiate_value(self.tcx, result_args, constraint);
539-
self.query_outlives_constraint_to_obligation(predicate, cause.clone(), param_env)
540-
})
541-
}
542-
543-
pub fn query_outlives_constraint_to_obligation(
544-
&self,
545-
(predicate, _): QueryOutlivesConstraint<'tcx>,
546-
cause: ObligationCause<'tcx>,
547-
param_env: ty::ParamEnv<'tcx>,
548-
) -> Obligation<'tcx, ty::Predicate<'tcx>> {
549-
let ty::OutlivesPredicate(k1, r2) = predicate;
550-
551-
let atom = match k1.unpack() {
552-
GenericArgKind::Lifetime(r1) => ty::PredicateKind::Clause(
553-
ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(r1, r2)),
554-
),
555-
GenericArgKind::Type(t1) => ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(
556-
ty::OutlivesPredicate(t1, r2),
557-
)),
558-
GenericArgKind::Const(..) => {
559-
// Consts cannot outlive one another, so we don't expect to
560-
// encounter this branch.
561-
span_bug!(cause.span, "unexpected const outlives {:?}", predicate);
562-
}
563-
};
564-
let predicate = ty::Binder::dummy(atom);
565-
566-
Obligation::new(self.tcx, cause, param_env, predicate)
567-
}
568-
569523
/// Given two sets of values for the same set of canonical variables, unify them.
570524
/// The second set is produced lazily by supplying indices from the first set.
571525
fn unify_canonical_vars(

compiler/rustc_infer/src/infer/context.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
214214
}
215215

216216
fn register_ty_outlives(&self, ty: Ty<'tcx>, r: ty::Region<'tcx>, span: Span) {
217-
self.register_region_obligation_with_cause(ty, r, &ObligationCause::dummy_with_span(span));
217+
self.register_type_outlives_constraint(ty, r, &ObligationCause::dummy_with_span(span));
218218
}
219219

220220
type OpaqueTypeStorageEntries = OpaqueTypeStorageEntries;

compiler/rustc_infer/src/infer/mod.rs

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ pub struct InferCtxtInner<'tcx> {
150150
/// for each body-id in this map, which will process the
151151
/// obligations within. This is expected to be done 'late enough'
152152
/// that all type inference variables have been bound and so forth.
153-
region_obligations: Vec<RegionObligation<'tcx>>,
153+
region_obligations: Vec<TypeOutlivesConstraint<'tcx>>,
154154

155155
/// Caches for opaque type inference.
156156
opaque_type_storage: OpaqueTypeStorage<'tcx>,
@@ -173,7 +173,7 @@ impl<'tcx> InferCtxtInner<'tcx> {
173173
}
174174

175175
#[inline]
176-
pub fn region_obligations(&self) -> &[RegionObligation<'tcx>] {
176+
pub fn region_obligations(&self) -> &[TypeOutlivesConstraint<'tcx>] {
177177
&self.region_obligations
178178
}
179179

@@ -488,7 +488,7 @@ impl fmt::Display for FixupError {
488488

489489
/// See the `region_obligations` field for more information.
490490
#[derive(Clone, Debug)]
491-
pub struct RegionObligation<'tcx> {
491+
pub struct TypeOutlivesConstraint<'tcx> {
492492
pub sub_region: ty::Region<'tcx>,
493493
pub sup_type: Ty<'tcx>,
494494
pub origin: SubregionOrigin<'tcx>,
@@ -738,19 +738,6 @@ impl<'tcx> InferCtxt<'tcx> {
738738
})
739739
}
740740

741-
pub fn region_outlives_predicate(
742-
&self,
743-
cause: &traits::ObligationCause<'tcx>,
744-
predicate: ty::PolyRegionOutlivesPredicate<'tcx>,
745-
) {
746-
self.enter_forall(predicate, |ty::OutlivesPredicate(r_a, r_b)| {
747-
let origin = SubregionOrigin::from_obligation_cause(cause, || {
748-
RelateRegionParamBound(cause.span, None)
749-
});
750-
self.sub_regions(origin, r_b, r_a); // `b : a` ==> `a <= b`
751-
})
752-
}
753-
754741
/// Number of type variables created so far.
755742
pub fn num_ty_vars(&self) -> usize {
756743
self.inner.borrow_mut().type_variables().num_vars()

compiler/rustc_infer/src/infer/outlives/obligations.rs

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -76,23 +76,56 @@ use crate::infer::outlives::env::RegionBoundPairs;
7676
use crate::infer::outlives::verify::VerifyBoundCx;
7777
use crate::infer::resolve::OpportunisticRegionResolver;
7878
use crate::infer::snapshot::undo_log::UndoLog;
79-
use crate::infer::{self, GenericKind, InferCtxt, RegionObligation, SubregionOrigin, VerifyBound};
79+
use crate::infer::{
80+
self, GenericKind, InferCtxt, SubregionOrigin, TypeOutlivesConstraint, VerifyBound,
81+
};
8082
use crate::traits::{ObligationCause, ObligationCauseCode};
8183

8284
impl<'tcx> InferCtxt<'tcx> {
85+
pub fn register_outlives_constraint(
86+
&self,
87+
ty::OutlivesPredicate(arg, r2): ty::OutlivesPredicate<'tcx, ty::GenericArg<'tcx>>,
88+
cause: &ObligationCause<'tcx>,
89+
) {
90+
match arg.unpack() {
91+
ty::GenericArgKind::Lifetime(r1) => {
92+
self.register_region_outlives_constraint(ty::OutlivesPredicate(r1, r2), cause);
93+
}
94+
ty::GenericArgKind::Type(ty1) => {
95+
self.register_type_outlives_constraint(ty1, r2, cause);
96+
}
97+
ty::GenericArgKind::Const(_) => unreachable!(),
98+
}
99+
}
100+
101+
pub fn register_region_outlives_constraint(
102+
&self,
103+
ty::OutlivesPredicate(r_a, r_b): ty::RegionOutlivesPredicate<'tcx>,
104+
cause: &ObligationCause<'tcx>,
105+
) {
106+
let origin = SubregionOrigin::from_obligation_cause(cause, || {
107+
SubregionOrigin::RelateRegionParamBound(cause.span, None)
108+
});
109+
// `'a: 'b` ==> `'b <= 'a`
110+
self.sub_regions(origin, r_b, r_a);
111+
}
112+
83113
/// Registers that the given region obligation must be resolved
84114
/// from within the scope of `body_id`. These regions are enqueued
85115
/// and later processed by regionck, when full type information is
86116
/// available (see `region_obligations` field for more
87117
/// information).
88118
#[instrument(level = "debug", skip(self))]
89-
pub fn register_region_obligation(&self, obligation: RegionObligation<'tcx>) {
119+
pub fn register_type_outlives_constraint_inner(
120+
&self,
121+
obligation: TypeOutlivesConstraint<'tcx>,
122+
) {
90123
let mut inner = self.inner.borrow_mut();
91-
inner.undo_log.push(UndoLog::PushRegionObligation);
124+
inner.undo_log.push(UndoLog::PushTypeOutlivesConstraint);
92125
inner.region_obligations.push(obligation);
93126
}
94127

95-
pub fn register_region_obligation_with_cause(
128+
pub fn register_type_outlives_constraint(
96129
&self,
97130
sup_type: Ty<'tcx>,
98131
sub_region: Region<'tcx>,
@@ -124,11 +157,15 @@ impl<'tcx> InferCtxt<'tcx> {
124157
)
125158
});
126159

127-
self.register_region_obligation(RegionObligation { sup_type, sub_region, origin });
160+
self.register_type_outlives_constraint_inner(TypeOutlivesConstraint {
161+
sup_type,
162+
sub_region,
163+
origin,
164+
});
128165
}
129166

130167
/// Trait queries just want to pass back type obligations "as is"
131-
pub fn take_registered_region_obligations(&self) -> Vec<RegionObligation<'tcx>> {
168+
pub fn take_registered_region_obligations(&self) -> Vec<TypeOutlivesConstraint<'tcx>> {
132169
std::mem::take(&mut self.inner.borrow_mut().region_obligations)
133170
}
134171

@@ -166,7 +203,7 @@ impl<'tcx> InferCtxt<'tcx> {
166203
);
167204
}
168205

169-
for RegionObligation { sup_type, sub_region, origin } in my_region_obligations {
206+
for TypeOutlivesConstraint { sup_type, sub_region, origin } in my_region_obligations {
170207
let outlives = ty::Binder::dummy(ty::OutlivesPredicate(sup_type, sub_region));
171208
let ty::OutlivesPredicate(sup_type, sub_region) =
172209
deeply_normalize_ty(outlives, origin.clone())

compiler/rustc_infer/src/infer/snapshot/undo_log.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ pub(crate) enum UndoLog<'tcx> {
2626
RegionConstraintCollector(region_constraints::UndoLog<'tcx>),
2727
RegionUnificationTable(sv::UndoLog<ut::Delegate<RegionVidKey<'tcx>>>),
2828
ProjectionCache(traits::UndoLog<'tcx>),
29-
PushRegionObligation,
29+
PushTypeOutlivesConstraint,
3030
}
3131

3232
macro_rules! impl_from {
@@ -72,7 +72,7 @@ impl<'tcx> Rollback<UndoLog<'tcx>> for InferCtxtInner<'tcx> {
7272
self.region_constraint_storage.as_mut().unwrap().unification_table.reverse(undo)
7373
}
7474
UndoLog::ProjectionCache(undo) => self.projection_cache.reverse(undo),
75-
UndoLog::PushRegionObligation => {
75+
UndoLog::PushTypeOutlivesConstraint => {
7676
self.region_obligations.pop();
7777
}
7878
}

compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1024,7 +1024,7 @@ where
10241024
}
10251025

10261026
pub(super) fn register_region_outlives(&self, a: I::Region, b: I::Region) {
1027-
// `b : a` ==> `a <= b`
1027+
// `'a: 'b` ==> `'b <= 'a`
10281028
self.delegate.sub_regions(b, a, self.origin_span);
10291029
}
10301030

compiler/rustc_trait_selection/src/solve/delegate.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
7676
Some(HasChanged::No)
7777
}
7878
ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(outlives)) => {
79-
self.0.register_region_obligation_with_cause(
79+
self.0.register_type_outlives_constraint(
8080
outlives.0,
8181
outlives.1,
8282
&ObligationCause::dummy_with_span(span),

compiler/rustc_trait_selection/src/traits/auto_trait.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -726,7 +726,9 @@ impl<'tcx> AutoTraitFinder<'tcx> {
726726
}
727727
ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(binder)) => {
728728
let binder = bound_predicate.rebind(binder);
729-
selcx.infcx.region_outlives_predicate(&dummy_cause, binder)
729+
selcx.infcx.enter_forall(binder, |pred| {
730+
selcx.infcx.register_region_outlives_constraint(pred, &dummy_cause);
731+
});
730732
}
731733
ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(binder)) => {
732734
let binder = bound_predicate.rebind(binder);
@@ -735,14 +737,14 @@ impl<'tcx> AutoTraitFinder<'tcx> {
735737
binder.map_bound_ref(|pred| pred.0).no_bound_vars(),
736738
) {
737739
(None, Some(t_a)) => {
738-
selcx.infcx.register_region_obligation_with_cause(
740+
selcx.infcx.register_type_outlives_constraint(
739741
t_a,
740742
selcx.infcx.tcx.lifetimes.re_static,
741743
&dummy_cause,
742744
);
743745
}
744746
(Some(ty::OutlivesPredicate(t_a, r_b)), _) => {
745-
selcx.infcx.register_region_obligation_with_cause(
747+
selcx.infcx.register_type_outlives_constraint(
746748
t_a,
747749
r_b,
748750
&dummy_cause,

compiler/rustc_trait_selection/src/traits/fulfill.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
428428

429429
ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(data)) => {
430430
if infcx.considering_regions {
431-
infcx.region_outlives_predicate(&obligation.cause, Binder::dummy(data));
431+
infcx.register_region_outlives_constraint(data, &obligation.cause);
432432
}
433433

434434
ProcessResult::Changed(Default::default())
@@ -439,7 +439,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
439439
r_b,
440440
))) => {
441441
if infcx.considering_regions {
442-
infcx.register_region_obligation_with_cause(t_a, r_b, &obligation.cause);
442+
infcx.register_type_outlives_constraint(t_a, r_b, &obligation.cause);
443443
}
444444
ProcessResult::Changed(Default::default())
445445
}

compiler/rustc_trait_selection/src/traits/outlives_bounds.rs

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use rustc_span::def_id::LocalDefId;
99
use tracing::instrument;
1010

1111
use crate::infer::InferCtxt;
12-
use crate::traits::{ObligationCause, ObligationCtxt};
12+
use crate::traits::ObligationCause;
1313

1414
/// Implied bounds are region relationships that we deduce
1515
/// automatically. The idea is that (e.g.) a caller must check that a
@@ -79,24 +79,9 @@ fn implied_outlives_bounds<'a, 'tcx>(
7979

8080
if !constraints.is_empty() {
8181
let QueryRegionConstraints { outlives } = constraints;
82-
// Instantiation may have produced new inference variables and constraints on those
83-
// variables. Process these constraints.
84-
let ocx = ObligationCtxt::new(infcx);
8582
let cause = ObligationCause::misc(span, body_id);
86-
for &constraint in &outlives {
87-
ocx.register_obligation(infcx.query_outlives_constraint_to_obligation(
88-
constraint,
89-
cause.clone(),
90-
param_env,
91-
));
92-
}
93-
94-
let errors = ocx.select_all_or_error();
95-
if !errors.is_empty() {
96-
infcx.dcx().span_bug(
97-
span,
98-
"implied_outlives_bounds failed to solve obligations from instantiation",
99-
);
83+
for &(predicate, _) in &outlives {
84+
infcx.register_outlives_constraint(predicate, &cause);
10085
}
10186
};
10287

compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::ops::ControlFlow;
22

3-
use rustc_infer::infer::RegionObligation;
3+
use rustc_infer::infer::TypeOutlivesConstraint;
44
use rustc_infer::infer::canonical::CanonicalQueryInput;
55
use rustc_infer::traits::query::OutlivesBound;
66
use rustc_infer::traits::query::type_op::ImpliedOutlivesBounds;
@@ -141,7 +141,7 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>(
141141
&& !ocx.infcx.tcx.sess.opts.unstable_opts.no_implied_bounds_compat
142142
&& ty.visit_with(&mut ContainsBevyParamSet { tcx: ocx.infcx.tcx }).is_break()
143143
{
144-
for RegionObligation { sup_type, sub_region, .. } in
144+
for TypeOutlivesConstraint { sup_type, sub_region, .. } in
145145
ocx.infcx.take_registered_region_obligations()
146146
{
147147
let mut components = smallvec![];

0 commit comments

Comments
 (0)