Don't hang when there's an infinite loop of outlives obligations
This commit is contained in:
parent
7d1fda7b40
commit
a371059933
2 changed files with 87 additions and 62 deletions
|
@ -154,74 +154,93 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
|
||||||
} = *self;
|
} = *self;
|
||||||
|
|
||||||
let mut outlives_predicates = vec![(predicate, constraint_category)];
|
let mut outlives_predicates = vec![(predicate, constraint_category)];
|
||||||
while let Some((ty::OutlivesPredicate(k1, r2), constraint_category)) =
|
for iteration in 0.. {
|
||||||
outlives_predicates.pop()
|
if outlives_predicates.is_empty() {
|
||||||
{
|
break;
|
||||||
match k1.unpack() {
|
}
|
||||||
GenericArgKind::Lifetime(r1) => {
|
|
||||||
let r1_vid = self.to_region_vid(r1);
|
|
||||||
let r2_vid = self.to_region_vid(r2);
|
|
||||||
self.add_outlives(r1_vid, r2_vid, constraint_category);
|
|
||||||
}
|
|
||||||
|
|
||||||
GenericArgKind::Type(mut t1) => {
|
if !self.tcx.recursion_limit().value_within_limit(iteration) {
|
||||||
// Normalize the type we receive from a `TypeOutlives` obligation
|
bug!(
|
||||||
// in the new trait solver.
|
"FIXME(-Znext-solver): Overflowed when processing region obligations: {outlives_predicates:#?}"
|
||||||
if infcx.next_trait_solver() {
|
);
|
||||||
let result = CustomTypeOp::new(
|
}
|
||||||
|ocx| {
|
|
||||||
match deeply_normalize(
|
|
||||||
ocx.infcx.at(
|
|
||||||
&ObligationCause::dummy_with_span(self.span),
|
|
||||||
param_env,
|
|
||||||
),
|
|
||||||
t1,
|
|
||||||
) {
|
|
||||||
Ok(normalized_ty) => {
|
|
||||||
t1 = normalized_ty;
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
infcx.err_ctxt().report_fulfillment_errors(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
let mut next_outlives_predicates = vec![];
|
||||||
},
|
for (ty::OutlivesPredicate(k1, r2), constraint_category) in outlives_predicates {
|
||||||
"normalize type outlives obligation",
|
match k1.unpack() {
|
||||||
)
|
GenericArgKind::Lifetime(r1) => {
|
||||||
.fully_perform(infcx, self.span);
|
let r1_vid = self.to_region_vid(r1);
|
||||||
|
let r2_vid = self.to_region_vid(r2);
|
||||||
match result {
|
self.add_outlives(r1_vid, r2_vid, constraint_category);
|
||||||
Ok(TypeOpOutput { output: (), constraints, .. }) => {
|
|
||||||
if let Some(constraints) = constraints {
|
|
||||||
assert!(
|
|
||||||
constraints.member_constraints.is_empty(),
|
|
||||||
"FIXME(-Znext-solver): How do I handle these?"
|
|
||||||
);
|
|
||||||
outlives_predicates
|
|
||||||
.extend(constraints.outlives.iter().copied());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(_) => {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// we don't actually use this for anything, but
|
GenericArgKind::Type(mut t1) => {
|
||||||
// the `TypeOutlives` code needs an origin.
|
// Normalize the type we receive from a `TypeOutlives` obligation
|
||||||
let origin = infer::RelateParamBound(DUMMY_SP, t1, None);
|
// in the new trait solver.
|
||||||
|
if infcx.next_trait_solver() {
|
||||||
|
let result = CustomTypeOp::new(
|
||||||
|
|ocx| {
|
||||||
|
match deeply_normalize(
|
||||||
|
ocx.infcx.at(
|
||||||
|
&ObligationCause::dummy_with_span(self.span),
|
||||||
|
param_env,
|
||||||
|
),
|
||||||
|
t1,
|
||||||
|
) {
|
||||||
|
Ok(normalized_ty) => {
|
||||||
|
t1 = normalized_ty;
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
infcx.err_ctxt().report_fulfillment_errors(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TypeOutlives::new(
|
Ok(())
|
||||||
&mut *self,
|
},
|
||||||
tcx,
|
"normalize type outlives obligation",
|
||||||
region_bound_pairs,
|
)
|
||||||
Some(implicit_region_bound),
|
.fully_perform(infcx, self.span);
|
||||||
known_type_outlives_obligations,
|
|
||||||
)
|
match result {
|
||||||
.type_must_outlive(origin, t1, r2, constraint_category);
|
Ok(TypeOpOutput { output: (), constraints, .. }) => {
|
||||||
|
if let Some(constraints) = constraints {
|
||||||
|
assert!(
|
||||||
|
constraints.member_constraints.is_empty(),
|
||||||
|
"no member constraints expected from normalizing: {:#?}",
|
||||||
|
constraints.member_constraints
|
||||||
|
);
|
||||||
|
next_outlives_predicates
|
||||||
|
.extend(constraints.outlives.iter().copied());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(_) => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// we don't actually use this for anything, but
|
||||||
|
// the `TypeOutlives` code needs an origin.
|
||||||
|
let origin = infer::RelateParamBound(DUMMY_SP, t1, None);
|
||||||
|
|
||||||
|
TypeOutlives::new(
|
||||||
|
&mut *self,
|
||||||
|
tcx,
|
||||||
|
region_bound_pairs,
|
||||||
|
Some(implicit_region_bound),
|
||||||
|
known_type_outlives_obligations,
|
||||||
|
)
|
||||||
|
.type_must_outlive(
|
||||||
|
origin,
|
||||||
|
t1,
|
||||||
|
r2,
|
||||||
|
constraint_category,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
GenericArgKind::Const(_) => unreachable!(),
|
||||||
}
|
}
|
||||||
|
|
||||||
GenericArgKind::Const(_) => unreachable!(),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
outlives_predicates = next_outlives_predicates;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -154,12 +154,18 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||||
.map_err(|e| (e, SubregionOrigin::AscribeUserTypeProvePredicate(DUMMY_SP)))?;
|
.map_err(|e| (e, SubregionOrigin::AscribeUserTypeProvePredicate(DUMMY_SP)))?;
|
||||||
|
|
||||||
// Must loop since the process of normalizing may itself register region obligations.
|
// Must loop since the process of normalizing may itself register region obligations.
|
||||||
loop {
|
for iteration in 0.. {
|
||||||
let my_region_obligations = self.take_registered_region_obligations();
|
let my_region_obligations = self.take_registered_region_obligations();
|
||||||
if my_region_obligations.is_empty() {
|
if my_region_obligations.is_empty() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !self.tcx.recursion_limit().value_within_limit(iteration) {
|
||||||
|
bug!(
|
||||||
|
"FIXME(-Znext-solver): Overflowed when processing region obligations: {my_region_obligations:#?}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
for RegionObligation { sup_type, sub_region, origin } in my_region_obligations {
|
for RegionObligation { sup_type, sub_region, origin } in my_region_obligations {
|
||||||
let sup_type = deeply_normalize_ty(sup_type, origin.clone())
|
let sup_type = deeply_normalize_ty(sup_type, origin.clone())
|
||||||
.map_err(|e| (e, origin.clone()))?;
|
.map_err(|e| (e, origin.clone()))?;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue