Skip to content

Commit a36dc08

Browse files
correct filtering of regions + update comment
1 parent 8c66aab commit a36dc08

File tree

1 file changed

+29
-36
lines changed
  • compiler/rustc_borrowck/src/region_infer

1 file changed

+29
-36
lines changed

compiler/rustc_borrowck/src/region_infer/mod.rs

Lines changed: 29 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1290,44 +1290,37 @@ impl<'tcx> RegionInferenceContext<'tcx> {
12901290
// Grow `shorter_fr` until we find some non-local regions. (We
12911291
// always will.) We'll call them `shorter_fr+` -- they're ever
12921292
// so slightly larger than `shorter_fr`.
1293-
let shorter_fr_plusses =
1293+
let shorter_fr_plus =
12941294
self.universal_region_relations.non_local_upper_bounds(shorter_fr);
1295-
debug!(
1296-
"try_propagate_universal_region_error: shorter_fr_plus={:?}",
1297-
shorter_fr_plusses
1298-
);
12991295

1300-
let fr_static = self.universal_regions().fr_static;
1301-
let single_region = shorter_fr_plusses.len() == 1;
1302-
1303-
for shorter_fr_plus in shorter_fr_plusses {
1304-
// Don't propagate every `fr-: shorter_fr+`.
1305-
// A smaller "optimal subset" exists, since full propagation is overly conservative
1306-
// and can reject valid code. Consider this small example (`'b: 'a` == `a -> b`)
1307-
// were we try to propagate region error `'d: 'a`:
1308-
// a --> b --> d
1309-
// \
1310-
// \-> c
1311-
// Here `shorter_fr_plusses` == `['b, 'c]`.
1312-
// Propagating `'d: 'b` is correct and should happen; `'d: 'c` is redundant and can reject valid code.
1313-
// We can come closer to this "optimal subset" by checking if the `shorter_fr+` should be outlived by `fr-`.
1314-
// NOTE: [] is *not* a valid subset, so we check for that as well.
1315-
if single_region
1316-
|| shorter_fr_plus == fr_static // `fr-: 'static` should be propagated
1317-
|| self.eval_outlives(fr_minus, shorter_fr_plus)
1318-
{
1319-
debug!(
1320-
"try_propagate_universal_region_error: propagating {:?}: {:?}",
1321-
fr_minus, shorter_fr_plus,
1322-
);
1323-
// If that's the case, push the constraint `fr-: shorter_fr+`
1324-
propagated_outlives_requirements.push(ClosureOutlivesRequirement {
1325-
subject: ClosureOutlivesSubject::Region(fr_minus),
1326-
outlived_free_region: shorter_fr_plus,
1327-
blame_span: blame_constraint.cause.span,
1328-
category: blame_constraint.category,
1329-
});
1330-
}
1296+
// If any of the `shorter_fr+` regions are already outlived by `fr-`, we propagate only those.
1297+
// Otherwise, we might incorrectly reject valid code.
1298+
//
1299+
// Consider this example (`'b: 'a` == `a -> b`), where we try to propagate `'d: 'a`:
1300+
// a --> b --> d
1301+
// \
1302+
// \-> c
1303+
// Here, `shorter_fr+` of `'a` == `['b, 'c]`.
1304+
// Propagating `'d: 'b` is correct and should occur; `'d: 'c` is redundant because of `'d: 'b`
1305+
// and could reject valid code.
1306+
//
1307+
// So we filter `shorter_fr+` to regions already outlived by `fr-`, but if the filter yields an empty set,
1308+
// we fall back to the original one.
1309+
let subset: Vec<_> = shorter_fr_plus
1310+
.iter()
1311+
.filter(|&&fr_plus| self.eval_outlives(fr_minus, fr_plus))
1312+
.copied()
1313+
.collect();
1314+
let shorter_fr_plus = if subset.is_empty() { shorter_fr_plus } else { subset };
1315+
debug!("try_propagate_universal_region_error: shorter_fr_plus={:?}", shorter_fr_plus);
1316+
for fr in shorter_fr_plus {
1317+
// Push the constraint `fr-: shorter_fr+`
1318+
propagated_outlives_requirements.push(ClosureOutlivesRequirement {
1319+
subject: ClosureOutlivesSubject::Region(fr_minus),
1320+
outlived_free_region: fr,
1321+
blame_span: blame_constraint.cause.span,
1322+
category: blame_constraint.category,
1323+
});
13311324
}
13321325
return RegionRelationCheckResult::Propagated;
13331326
}

0 commit comments

Comments
 (0)