Skip to content

Commit 3c75d58

Browse files
Auto merge of #143545 - compiler-errors:coroutine-obl, r=<try>
[experiment] Consider WF of coroutine witness when proving outlives assumptions This needs to be majorly cleaned up --- cc #110338 Consider, for example: ```rust use std::future::Future; trait Client { type Connecting<'a>: Future + Send where Self: 'a; fn connect(&'_ self) -> Self::Connecting<'_>; } fn call_connect<C>(c: &'_ C) -> impl Future + Send where C: Client + Send + Sync, { async move { c.connect().await } } ```
2 parents e43d139 + a7ec91c commit 3c75d58

File tree

28 files changed

+232
-125
lines changed

28 files changed

+232
-125
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_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: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,8 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
162162
type BoundRegion = ty::BoundRegion;
163163
type PlaceholderRegion = ty::PlaceholderRegion;
164164

165+
type RegionAssumptions = &'tcx ty::List<ty::OutlivesPredicate<'tcx, ty::GenericArg<'tcx>>>;
166+
165167
type ParamEnv = ty::ParamEnv<'tcx>;
166168
type Predicate = Predicate<'tcx>;
167169

@@ -874,6 +876,7 @@ pub struct CtxtInterners<'tcx> {
874876
offset_of: InternedSet<'tcx, List<(VariantIdx, FieldIdx)>>,
875877
valtree: InternedSet<'tcx, ty::ValTreeKind<'tcx>>,
876878
patterns: InternedSet<'tcx, List<ty::Pattern<'tcx>>>,
879+
outlives: InternedSet<'tcx, List<ty::OutlivesPredicate<'tcx, ty::GenericArg<'tcx>>>>,
877880
}
878881

879882
impl<'tcx> CtxtInterners<'tcx> {
@@ -911,6 +914,7 @@ impl<'tcx> CtxtInterners<'tcx> {
911914
offset_of: InternedSet::with_capacity(N),
912915
valtree: InternedSet::with_capacity(N),
913916
patterns: InternedSet::with_capacity(N),
917+
outlives: InternedSet::with_capacity(N),
914918
}
915919
}
916920

@@ -2692,6 +2696,7 @@ slice_interners!(
26922696
captures: intern_captures(&'tcx ty::CapturedPlace<'tcx>),
26932697
offset_of: pub mk_offset_of((VariantIdx, FieldIdx)),
26942698
patterns: pub mk_patterns(Pattern<'tcx>),
2699+
outlives: pub mk_outlives(ty::OutlivesPredicate<'tcx, ty::GenericArg<'tcx>>),
26952700
);
26962701

26972702
impl<'tcx> TyCtxt<'tcx> {
@@ -3107,6 +3112,17 @@ impl<'tcx> TyCtxt<'tcx> {
31073112
T::collect_and_apply(iter, |xs| self.mk_bound_variable_kinds(xs))
31083113
}
31093114

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+
31103126
/// Emit a lint at `span` from a lint struct (some type that implements `LintDiagnostic`,
31113127
/// typically generated by `#[derive(LintDiagnostic)]`).
31123128
#[track_caller]

0 commit comments

Comments
 (0)