Skip to content

Commit 984a8ef

Browse files
committed
Only flag the error for placeholder-existential failures if there is
actually an existential.
1 parent 0a281ca commit 984a8ef

File tree

3 files changed

+48
-33
lines changed

3 files changed

+48
-33
lines changed

compiler/rustc_borrowck/src/handle_placeholders.rs

Lines changed: 42 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use crate::ty::VarianceDiagInfo;
2020
use crate::type_check::free_region_relations::UniversalRegionRelations;
2121
use crate::type_check::{Locations, MirTypeckRegionConstraints};
2222
use crate::universal_regions::UniversalRegions;
23-
use crate::{BorrowckInferCtxt, NllRegionVariableOrigin, bug};
23+
use crate::{BorrowckInferCtxt, NllRegionVariableOrigin};
2424

2525
/// A set of outlives constraints after rewriting to remove
2626
/// higher-kinded constraints.
@@ -122,10 +122,12 @@ impl PlaceholderReachability {
122122
pub(crate) struct RegionTracker {
123123
reachable_placeholders: PlaceholderReachability,
124124

125-
/// The largest universe nameable from this SCC.
126-
/// It is the smallest nameable universes of all
127-
/// existential regions reachable from it. Small Rvids are preferred.
128-
max_nameable_universe: (UniverseIndex, RegionVid),
125+
/// The smallest max nameable universe of all
126+
/// regions reachable from this SCC.
127+
min_max_nameable_universe: UniverseIndex,
128+
129+
/// The existential region with the smallest universe, if any.
130+
min_universe_existential: Option<(UniverseIndex, RegionVid)>,
129131

130132
/// The representative Region Variable Id for this SCC.
131133
pub(crate) representative: Representative,
@@ -146,7 +148,15 @@ impl RegionTracker {
146148

147149
Self {
148150
reachable_placeholders,
149-
max_nameable_universe: (definition.universe, rvid),
151+
min_universe_existential: if matches!(
152+
definition.origin,
153+
NllRegionVariableOrigin::Existential { .. }
154+
) {
155+
Some((definition.universe, rvid))
156+
} else {
157+
None
158+
},
159+
min_max_nameable_universe: definition.universe,
150160
representative: Representative::new(rvid, definition),
151161
}
152162
}
@@ -155,7 +165,8 @@ impl RegionTracker {
155165
/// largest nameable universe of any reachable region, or
156166
/// `max_nameable(r) = min (max_nameable(r') for r' reachable from r)`
157167
pub(crate) fn max_nameable_universe(self) -> UniverseIndex {
158-
self.max_nameable_universe.0
168+
// Note that this is stricter than it might need to be!
169+
self.min_max_nameable_universe
159170
}
160171

161172
pub(crate) fn max_placeholder_universe_reached(self) -> UniverseIndex {
@@ -166,19 +177,19 @@ impl RegionTracker {
166177
}
167178
}
168179

169-
/// Determine if the tracked universes of the two SCCs are compatible.
180+
/// Determine if the universe constraints of the members of two SCCs are compatible.
170181
pub(crate) fn universe_compatible_with(&self, other: Self) -> bool {
171182
// HACK: We first check whether we can name the highest existential universe
172183
// of `other`. This only exists to avoid errors in case that scc already
173184
// depends on a placeholder it cannot name itself.
174-
self.max_nameable_universe().can_name(other.max_nameable_universe())
175-
|| other.reachable_placeholders.can_be_named_by(self.max_nameable_universe())
185+
self.min_max_nameable_universe.can_name(other.min_max_nameable_universe)
186+
|| other.reachable_placeholders.can_be_named_by(self.min_max_nameable_universe)
176187
}
177188

178189
/// If this SCC reaches a placeholder it can't name, return it.
179190
fn unnameable_placeholder(&self) -> Option<(UniverseIndex, RegionVid)> {
180191
self.reachable_placeholders.max_universe().filter(|&(placeholder_universe, _)| {
181-
!self.max_nameable_universe().can_name(placeholder_universe)
192+
!self.min_max_nameable_universe.can_name(placeholder_universe)
182193
})
183194
}
184195

@@ -193,7 +204,12 @@ impl RegionTracker {
193204
return None;
194205
};
195206

196-
let (reachable_lowest_max_u, reachable_lowest_max_u_rvid) = self.max_nameable_universe;
207+
let Some((reachable_lowest_max_u, reachable_lowest_max_u_rvid)) =
208+
self.min_universe_existential
209+
else {
210+
debug!("SCC universe wasn't lowered by an existential; skipping.");
211+
return None;
212+
};
197213

198214
(!self.reachable_placeholders.can_be_named_by(reachable_lowest_max_u))
199215
.then_some(reachable_lowest_max_u_rvid)
@@ -226,14 +242,20 @@ impl scc::Annotation for RegionTracker {
226242

227243
Self {
228244
representative: self.representative.min(other.representative),
229-
max_nameable_universe: self.max_nameable_universe.min(other.max_nameable_universe),
230-
reachable_placeholders: self.reachable_placeholders.merge(other.reachable_placeholders),
245+
..self.merge_reached(other)
231246
}
232247
}
233248

249+
#[inline(always)]
234250
fn merge_reached(self, other: Self) -> Self {
235251
Self {
236-
max_nameable_universe: self.max_nameable_universe.min(other.max_nameable_universe),
252+
min_universe_existential: self
253+
.min_universe_existential
254+
.xor(other.min_universe_existential)
255+
.or_else(|| self.min_universe_existential.min(other.min_universe_existential)),
256+
min_max_nameable_universe: self
257+
.min_max_nameable_universe
258+
.min(other.min_max_nameable_universe),
237259
reachable_placeholders: self.reachable_placeholders.merge(other.reachable_placeholders),
238260
representative: self.representative,
239261
}
@@ -442,19 +464,7 @@ fn rewrite_placeholder_outlives<'tcx>(
442464
variance_info: VarianceDiagInfo::None,
443465
from_closure: false,
444466
});
445-
} else if !(annotation.reaches_existential_that_cannot_name_us().is_some()
446-
|| annotation.reaches_other_placeholder(annotation.representative.rvid()).is_some())
447-
{
448-
// The SCC's representative is not nameable from some region
449-
// that ends up in the SCC. This means there is nothing for us to do.
450-
// However, this is only possible under circumstances that produce
451-
// errors, so we make sure that we catch them here. Otherwise,
452-
// there might actually be soundness issues!
453-
bug!(
454-
"Universe of SCC {scc:?} should have been lowered by an existential or at least another placeholder but was lowered by {:?}, which is neither.",
455-
annotation.max_nameable_universe
456-
);
457-
};
467+
}
458468
}
459469
added_constraints
460470
}
@@ -486,12 +496,12 @@ fn find_placeholder_mismatch_errors<'tcx>(
486496
let scc = sccs.scc(rvid);
487497
let annotation = annotations.scc_to_annotation[scc];
488498

489-
if let Some(existential_that_cannot_name_rvid) =
490-
annotation.reaches_existential_that_cannot_name_us()
491-
{
499+
if let Some(cannot_name_rvid) = annotation.reaches_existential_that_cannot_name_us() {
500+
debug!("Existential {cannot_name_rvid:?} lowered our universe...");
501+
492502
errors_buffer.push(RegionErrorKind::PlaceholderOutlivesExistentialThatCannotNameIt {
493503
longer_fr: rvid,
494-
existential_that_cannot_name_longer: existential_that_cannot_name_rvid,
504+
existential_that_cannot_name_longer: cannot_name_rvid,
495505
placeholder: origin_a,
496506
})
497507
}

compiler/rustc_borrowck/src/nll.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,8 @@ pub(crate) fn compute_regions<'tcx>(
136136
&mut placeholder_errors,
137137
);
138138

139+
debug!("Placeholder errors: {placeholder_errors:?}");
140+
139141
// If requested, emit legacy polonius facts.
140142
polonius::legacy::emit_facts(
141143
&mut polonius_facts,
@@ -188,6 +190,7 @@ pub(crate) fn compute_regions<'tcx>(
188190

189191
let nll_errors = if region_inference_errors.is_empty() {
190192
// Only flag the higher-kinded bounds errors if there are no borrowck errors.
193+
debug!("No region inference errors, using placeholder errors: {placeholder_errors:?}");
191194
placeholder_errors
192195
} else {
193196
debug!("Errors already reported, skipping these: {placeholder_errors:?}");

compiler/rustc_borrowck/src/region_infer/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1566,7 +1566,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
15661566
from_region_origin: NllRegionVariableOrigin,
15671567
to_region: RegionVid,
15681568
) -> (BlameConstraint<'tcx>, Vec<OutlivesConstraint<'tcx>>) {
1569-
assert!(from_region != to_region, "Trying to blame a region for itself!");
1569+
if from_region == to_region {
1570+
bug!("Trying to blame {from_region:?} for itself!");
1571+
}
15701572

15711573
let path = self.constraint_path_between_regions(from_region, to_region).unwrap();
15721574

0 commit comments

Comments
 (0)