Skip to content

Commit 33f90f2

Browse files
committed
Check for upper bound universe errors more carefully
1 parent a9ca1ec commit 33f90f2

File tree

1 file changed

+26
-18
lines changed
  • src/librustc_infer/infer/lexical_region_resolve

1 file changed

+26
-18
lines changed

src/librustc_infer/infer/lexical_region_resolve/mod.rs

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,10 @@ pub fn resolve<'tcx>(
4949
let mut values = resolver.infer_variable_values(&mut errors);
5050
let re_erased = region_rels.tcx.lifetimes.re_erased;
5151

52-
values.values.iter_mut().for_each(|v| *v = VarValue::Value(re_erased));
52+
values.values.iter_mut().for_each(|v| match *v {
53+
VarValue::Value(ref mut r) => *r = re_erased,
54+
VarValue::ErrorValue => {}
55+
});
5356
(values, errors)
5457
}
5558
RegionckMode::Erase { suppress_errors: true } => {
@@ -290,8 +293,8 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
290293

291294
// Find all the "upper bounds" -- that is, each region `b` such that
292295
// `r0 <= b` must hold.
293-
let (member_upper_bounds, _) =
294-
self.collect_concrete_regions(graph, member_vid, OUTGOING, None);
296+
let (member_upper_bounds, ..) =
297+
self.collect_bounding_regions(graph, member_vid, OUTGOING, None);
295298

296299
// Get an iterator over the *available choice* -- that is,
297300
// each choice region `c` where `lb <= c` and `c <= ub` for all the
@@ -716,7 +719,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
716719
graph: &RegionGraph<'tcx>,
717720
errors: &mut Vec<RegionResolutionError<'tcx>>,
718721
) {
719-
debug!("collect_var_errors");
722+
debug!("collect_var_errors, var_data = {:#?}", var_data.values);
720723

721724
// This is the best way that I have found to suppress
722725
// duplicate and related errors. Basically we keep a set of
@@ -815,10 +818,10 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
815818
) {
816819
// Errors in expanding nodes result from a lower-bound that is
817820
// not contained by an upper-bound.
818-
let (mut lower_bounds, lower_dup) =
819-
self.collect_concrete_regions(graph, node_idx, INCOMING, Some(dup_vec));
820-
let (mut upper_bounds, upper_dup) =
821-
self.collect_concrete_regions(graph, node_idx, OUTGOING, Some(dup_vec));
821+
let (mut lower_bounds, lower_vid_bounds, lower_dup) =
822+
self.collect_bounding_regions(graph, node_idx, INCOMING, Some(dup_vec));
823+
let (mut upper_bounds, _, upper_dup) =
824+
self.collect_bounding_regions(graph, node_idx, OUTGOING, Some(dup_vec));
822825

823826
if lower_dup || upper_dup {
824827
return;
@@ -874,15 +877,22 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
874877
// If we have a scenario like `exists<'a> { forall<'b> { 'b:
875878
// 'a } }`, we wind up without any lower-bound -- all we have
876879
// are placeholders as upper bounds, but the universe of the
877-
// variable `'a` doesn't permit those placeholders.
880+
// variable `'a`, or some variable that `'a` has to outlive, doesn't
881+
// permit those placeholders.
882+
let min_universe = lower_vid_bounds
883+
.into_iter()
884+
.map(|vid| self.var_infos[vid].universe)
885+
.min()
886+
.expect("lower_vid_bounds should at least include `node_idx`");
887+
878888
for upper_bound in &upper_bounds {
879889
if let ty::RePlaceholder(p) = upper_bound.region {
880-
if node_universe.cannot_name(p.universe) {
890+
if min_universe.cannot_name(p.universe) {
881891
let origin = self.var_infos[node_idx].origin;
882892
errors.push(RegionResolutionError::UpperBoundUniverseConflict(
883893
node_idx,
884894
origin,
885-
node_universe,
895+
min_universe,
886896
upper_bound.origin.clone(),
887897
upper_bound.region,
888898
));
@@ -904,13 +914,13 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
904914
);
905915
}
906916

907-
fn collect_concrete_regions(
917+
fn collect_bounding_regions(
908918
&self,
909919
graph: &RegionGraph<'tcx>,
910920
orig_node_idx: RegionVid,
911921
dir: Direction,
912922
mut dup_vec: Option<&mut IndexVec<RegionVid, Option<RegionVid>>>,
913-
) -> (Vec<RegionAndOrigin<'tcx>>, bool) {
923+
) -> (Vec<RegionAndOrigin<'tcx>>, FxHashSet<RegionVid>, bool) {
914924
struct WalkState<'tcx> {
915925
set: FxHashSet<RegionVid>,
916926
stack: Vec<RegionVid>,
@@ -929,9 +939,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
929939
// direction specified
930940
process_edges(&self.data, &mut state, graph, orig_node_idx, dir);
931941

932-
while !state.stack.is_empty() {
933-
let node_idx = state.stack.pop().unwrap();
934-
942+
while let Some(node_idx) = state.stack.pop() {
935943
// check whether we've visited this node on some previous walk
936944
if let Some(dup_vec) = &mut dup_vec {
937945
if dup_vec[node_idx].is_none() {
@@ -949,8 +957,8 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
949957
process_edges(&self.data, &mut state, graph, node_idx, dir);
950958
}
951959

952-
let WalkState { result, dup_found, .. } = state;
953-
return (result, dup_found);
960+
let WalkState { result, dup_found, set, .. } = state;
961+
return (result, set, dup_found);
954962

955963
fn process_edges<'tcx>(
956964
this: &RegionConstraintData<'tcx>,

0 commit comments

Comments
 (0)