Skip to content

Commit 9613c58

Browse files
Consider outlives assumptions
1 parent 4bb495a commit 9613c58

File tree

23 files changed

+157
-122
lines changed

23 files changed

+157
-122
lines changed

compiler/rustc_borrowck/src/type_check/constraint_conversion.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,13 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
7070

7171
#[instrument(skip(self), level = "debug")]
7272
pub(super) fn convert_all(&mut self, query_constraints: &QueryRegionConstraints<'tcx>) {
73-
let QueryRegionConstraints { outlives } = query_constraints;
73+
let QueryRegionConstraints { outlives, assumptions } = query_constraints;
7474

7575
for &(predicate, constraint_category) in outlives {
76+
if assumptions.contains(&predicate) {
77+
continue;
78+
}
79+
7680
self.convert(predicate, constraint_category);
7781
}
7882
}
@@ -270,7 +274,8 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
270274
match self.param_env.and(DeeplyNormalize { value: ty }).fully_perform(self.infcx, self.span)
271275
{
272276
Ok(TypeOpOutput { output: ty, constraints, .. }) => {
273-
if let Some(QueryRegionConstraints { outlives }) = constraints {
277+
// FIXME(higher_ranked_auto): WTF
278+
if let Some(QueryRegionConstraints { outlives, assumptions: _ }) = constraints {
274279
next_outlives_predicates.extend(outlives.iter().copied());
275280
}
276281
ty

compiler/rustc_borrowck/src/type_check/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,11 @@ pub(crate) fn type_check<'tcx>(
131131
pre_obligations.is_empty(),
132132
"there should be no incoming region obligations = {pre_obligations:#?}",
133133
);
134+
let pre_assumptions = infcx.take_registered_region_assumptions();
135+
assert!(
136+
pre_assumptions.is_empty(),
137+
"there should be no incoming region assumptions = {pre_assumptions:#?}",
138+
);
134139

135140
debug!(?normalized_inputs_and_output);
136141

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

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ impl<'tcx> InferCtxt<'tcx> {
115115
}
116116

117117
let region_obligations = self.take_registered_region_obligations();
118+
let region_assumptions = self.take_registered_region_assumptions();
118119
debug!(?region_obligations);
119120
let region_constraints = self.with_region_constraints(|region_constraints| {
120121
make_query_region_constraints(
@@ -123,6 +124,7 @@ impl<'tcx> InferCtxt<'tcx> {
123124
.iter()
124125
.map(|r_o| (r_o.sup_type, r_o.sub_region, r_o.origin.to_constraint_category())),
125126
region_constraints,
127+
region_assumptions,
126128
)
127129
});
128130
debug!(?region_constraints);
@@ -174,6 +176,11 @@ impl<'tcx> InferCtxt<'tcx> {
174176
self.register_outlives_constraint(predicate, cause);
175177
}
176178

179+
for assumption in &query_response.value.region_constraints.assumptions {
180+
let assumption = instantiate_value(self.tcx, &result_args, *assumption);
181+
self.register_region_assumption(assumption);
182+
}
183+
177184
let user_result: R =
178185
query_response.instantiate_projected(self.tcx, &result_args, |q_r| q_r.value.clone());
179186

@@ -297,6 +304,16 @@ impl<'tcx> InferCtxt<'tcx> {
297304
}),
298305
);
299306

307+
// FIXME(higher_ranked_auto): Optimize?
308+
output_query_region_constraints.assumptions.extend(
309+
query_response
310+
.value
311+
.region_constraints
312+
.assumptions
313+
.iter()
314+
.map(|&r_c| instantiate_value(self.tcx, &result_args, r_c)),
315+
);
316+
300317
let user_result: R =
301318
query_response.instantiate_projected(self.tcx, &result_args, |q_r| q_r.value.clone());
302319

@@ -572,6 +589,7 @@ pub fn make_query_region_constraints<'tcx>(
572589
tcx: TyCtxt<'tcx>,
573590
outlives_obligations: impl Iterator<Item = (Ty<'tcx>, ty::Region<'tcx>, ConstraintCategory<'tcx>)>,
574591
region_constraints: &RegionConstraintData<'tcx>,
592+
assumptions: Vec<ty::OutlivesPredicate<'tcx, ty::GenericArg<'tcx>>>,
575593
) -> QueryRegionConstraints<'tcx> {
576594
let RegionConstraintData { constraints, verifys } = region_constraints;
577595

@@ -604,5 +622,5 @@ pub fn make_query_region_constraints<'tcx>(
604622
}))
605623
.collect();
606624

607-
QueryRegionConstraints { outlives }
625+
QueryRegionConstraints { outlives, assumptions }
608626
}

compiler/rustc_infer/src/infer/mod.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,9 @@ pub struct InferCtxtInner<'tcx> {
149149
/// that all type inference variables have been bound and so forth.
150150
region_obligations: Vec<TypeOutlivesConstraint<'tcx>>,
151151

152+
/// UwU
153+
region_assumptions: Vec<ty::OutlivesPredicate<'tcx, ty::GenericArg<'tcx>>>,
154+
152155
/// Caches for opaque type inference.
153156
opaque_type_storage: OpaqueTypeStorage<'tcx>,
154157
}
@@ -164,7 +167,8 @@ impl<'tcx> InferCtxtInner<'tcx> {
164167
int_unification_storage: Default::default(),
165168
float_unification_storage: Default::default(),
166169
region_constraint_storage: Some(Default::default()),
167-
region_obligations: vec![],
170+
region_obligations: Default::default(),
171+
region_assumptions: Default::default(),
168172
opaque_type_storage: Default::default(),
169173
}
170174
}
@@ -174,6 +178,11 @@ impl<'tcx> InferCtxtInner<'tcx> {
174178
&self.region_obligations
175179
}
176180

181+
#[inline]
182+
pub fn region_assumptions(&self) -> &[ty::OutlivesPredicate<'tcx, ty::GenericArg<'tcx>>] {
183+
&self.region_assumptions
184+
}
185+
177186
#[inline]
178187
pub fn projection_cache(&mut self) -> traits::ProjectionCache<'_, 'tcx> {
179188
self.projection_cache.with_log(&mut self.undo_log)

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ impl<'tcx> InferCtxt<'tcx> {
6060
assert!(
6161
self.tainted_by_errors().is_some() || inner.region_obligations.is_empty(),
6262
"region_obligations not empty: {:#?}",
63-
inner.region_obligations
63+
inner.region_obligations,
6464
);
6565
assert!(!UndoLogs::<UndoLog<'_>>::in_snapshot(&inner.undo_log));
6666
inner.region_constraint_storage.take().expect("regions already resolved")
@@ -93,6 +93,11 @@ impl<'tcx> InferCtxt<'tcx> {
9393
"region_obligations not empty: {:#?}",
9494
self.inner.borrow().region_obligations
9595
);
96+
assert!(
97+
self.inner.borrow().region_assumptions.is_empty(),
98+
"region_assumptions not empty: {:#?}",
99+
self.inner.borrow().region_assumptions
100+
);
96101

97102
self.inner.borrow_mut().unwrap_region_constraints().take_and_reset_data()
98103
}

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,21 @@ impl<'tcx> InferCtxt<'tcx> {
169169
std::mem::take(&mut self.inner.borrow_mut().region_obligations)
170170
}
171171

172+
pub fn register_region_assumption(
173+
&self,
174+
assumption: ty::OutlivesPredicate<'tcx, ty::GenericArg<'tcx>>,
175+
) {
176+
let mut inner = self.inner.borrow_mut();
177+
inner.undo_log.push(UndoLog::PushRegionAssumption);
178+
inner.region_assumptions.push(assumption);
179+
}
180+
181+
pub fn take_registered_region_assumptions(
182+
&self,
183+
) -> Vec<ty::OutlivesPredicate<'tcx, ty::GenericArg<'tcx>>> {
184+
std::mem::take(&mut self.inner.borrow_mut().region_assumptions)
185+
}
186+
172187
/// Process the region obligations that must be proven (during
173188
/// `regionck`) for the given `body_id`, given information about
174189
/// the region bounds in scope and so forth.
@@ -189,6 +204,7 @@ impl<'tcx> InferCtxt<'tcx> {
189204
-> Result<PolyTypeOutlivesPredicate<'tcx>, NoSolution>,
190205
) -> Result<(), (PolyTypeOutlivesPredicate<'tcx>, SubregionOrigin<'tcx>)> {
191206
assert!(!self.in_snapshot(), "cannot process registered region obligations in a snapshot");
207+
let assumptions = self.take_registered_region_assumptions();
192208

193209
// Must loop since the process of normalizing may itself register region obligations.
194210
for iteration in 0.. {
@@ -207,6 +223,10 @@ impl<'tcx> InferCtxt<'tcx> {
207223
}
208224

209225
for TypeOutlivesConstraint { sup_type, sub_region, origin } in my_region_obligations {
226+
if assumptions.contains(&ty::OutlivesPredicate(sup_type.into(), sub_region)) {
227+
continue;
228+
}
229+
210230
let outlives = ty::Binder::dummy(ty::OutlivesPredicate(sup_type, sub_region));
211231
let ty::OutlivesPredicate(sup_type, sub_region) =
212232
deeply_normalize_ty(outlives, origin.clone())

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ pub(crate) enum UndoLog<'tcx> {
2727
RegionUnificationTable(sv::UndoLog<ut::Delegate<RegionVidKey<'tcx>>>),
2828
ProjectionCache(traits::UndoLog<'tcx>),
2929
PushTypeOutlivesConstraint,
30+
PushRegionAssumption,
3031
}
3132

3233
macro_rules! impl_from {
@@ -75,6 +76,9 @@ impl<'tcx> Rollback<UndoLog<'tcx>> for InferCtxtInner<'tcx> {
7576
UndoLog::PushTypeOutlivesConstraint => {
7677
self.region_obligations.pop();
7778
}
79+
UndoLog::PushRegionAssumption => {
80+
self.region_assumptions.pop();
81+
}
7882
}
7983
}
8084
}

compiler/rustc_middle/src/infer/canonical.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,13 +81,14 @@ pub struct QueryResponse<'tcx, R> {
8181
#[derive(HashStable, TypeFoldable, TypeVisitable)]
8282
pub struct QueryRegionConstraints<'tcx> {
8383
pub outlives: Vec<QueryOutlivesConstraint<'tcx>>,
84+
pub assumptions: Vec<ty::OutlivesPredicate<'tcx, ty::GenericArg<'tcx>>>,
8485
}
8586

8687
impl QueryRegionConstraints<'_> {
87-
/// Represents an empty (trivially true) set of region
88-
/// constraints.
88+
/// Represents an empty (trivially true) set of region constraints.
89+
// FIXME(higher_ranked_auto): This could still just be true if there are only assumptions?
8990
pub fn is_empty(&self) -> bool {
90-
self.outlives.is_empty()
91+
self.outlives.is_empty() && self.assumptions.is_empty()
9192
}
9293
}
9394

compiler/rustc_trait_selection/src/solve/delegate.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,13 +212,15 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
212212
// Cannot use `take_registered_region_obligations` as we may compute the response
213213
// inside of a `probe` whenever we have multiple choices inside of the solver.
214214
let region_obligations = self.0.inner.borrow().region_obligations().to_owned();
215+
let region_assumptions = self.0.inner.borrow().region_assumptions().to_owned();
215216
let region_constraints = self.0.with_region_constraints(|region_constraints| {
216217
make_query_region_constraints(
217218
self.tcx,
218219
region_obligations
219220
.iter()
220221
.map(|r_o| (r_o.sup_type, r_o.sub_region, r_o.origin.to_constraint_category())),
221222
region_constraints,
223+
region_assumptions,
222224
)
223225
});
224226

compiler/rustc_trait_selection/src/traits/coherence.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,7 @@ fn impl_intersection_has_negative_obligation(
461461
// requirements, when proving the negated where clauses below.
462462
drop(equate_obligations);
463463
drop(infcx.take_registered_region_obligations());
464+
drop(infcx.take_registered_region_assumptions());
464465
drop(infcx.take_and_reset_region_constraints());
465466

466467
plug_infer_with_placeholders(

0 commit comments

Comments
 (0)