Skip to content

Commit a9e1a79

Browse files
committed
Remove explicit tracking of placeholders from borrowcheck
1 parent 288ebd2 commit a9e1a79

34 files changed

Lines changed: 497 additions & 1085 deletions

compiler/rustc_borrowck/src/diagnostics/region_errors.rs

Lines changed: 39 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ use tracing::{debug, instrument, trace};
2929

3030
use super::{OutlivesSuggestionBuilder, RegionName, RegionNameSource};
3131
use crate::nll::ConstraintDescription;
32-
use crate::region_infer::values::RegionElement;
3332
use crate::region_infer::{BlameConstraint, TypeTest};
3433
use crate::session_diagnostics::{
3534
FnMutError, FnMutReturnTypeErr, GenericDoesNotLiveLongEnough, LifetimeOutliveErr,
@@ -104,38 +103,9 @@ pub(crate) enum RegionErrorKind<'tcx> {
104103
/// A generic bound failure for a type test (`T: 'a`).
105104
TypeTestError { type_test: TypeTest<'tcx> },
106105

107-
/// 'a outlives 'b, and both are placeholders.
108-
PlaceholderOutlivesPlaceholder {
109-
rvid_a: RegionVid,
110-
rvid_b: RegionVid,
111-
origin_a: ty::PlaceholderRegion<'tcx>,
112-
origin_b: ty::PlaceholderRegion<'tcx>,
113-
},
114-
115-
/// Indicates that a placeholder has a universe too large for one
116-
/// of its member existentials, or, equivalently, that there is
117-
/// a path through the outlives constraint graph from a placeholder
118-
/// to an existential region that cannot name it.
119-
PlaceholderOutlivesExistentialThatCannotNameIt {
120-
/// the placeholder that transitively outlives an
121-
/// existential that shouldn't leak into it
122-
longer_fr: RegionVid,
123-
/// The existential leaking into `longer_fr`.
124-
existential_that_cannot_name_longer: RegionVid,
125-
// `longer_fr`'s originating placeholder region.
126-
placeholder: ty::PlaceholderRegion<'tcx>,
127-
},
128-
129-
/// Higher-ranked subtyping error. A placeholder outlives
130-
/// either a location or a universal region.
131-
PlaceholderOutlivesLocationOrUniversal {
132-
/// The placeholder free region.
133-
longer_fr: RegionVid,
134-
/// The region element that erroneously must be outlived by `longer_fr`.
135-
error_element: RegionElement<'tcx>,
136-
/// The placeholder region.
137-
placeholder: ty::PlaceholderRegion<'tcx>,
138-
},
106+
/// 'p outlives 'r, which does not hold. 'p is always a placeholder
107+
/// and 'r is some other region.
108+
PlaceholderOutlivesIllegalRegion { longer_fr: RegionVid, illegally_outlived_r: RegionVid },
139109

140110
/// Any other lifetime error.
141111
RegionError {
@@ -228,60 +198,47 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
228198
let tcx = self.infcx.tcx;
229199

230200
// find generic associated types in the given region 'lower_bound'
231-
let gat_id_and_generics = self
201+
let scc = self.regioncx.constraint_sccs().scc(lower_bound);
202+
let Some(gat_hir_id) = self
232203
.regioncx
233-
.placeholders_contained_in(lower_bound)
234-
.map(|placeholder| {
235-
if let Some(id) = placeholder.bound.kind.get_id()
236-
&& let Some(placeholder_id) = id.as_local()
237-
&& let gat_hir_id = tcx.local_def_id_to_hir_id(placeholder_id)
238-
&& let Some(generics_impl) =
239-
tcx.parent_hir_node(tcx.parent_hir_id(gat_hir_id)).generics()
240-
{
241-
Some((gat_hir_id, generics_impl))
242-
} else {
243-
None
244-
}
245-
})
246-
.collect::<Vec<_>>();
247-
debug!(?gat_id_and_generics);
204+
.placeholder_representative(scc)
205+
.and_then(|placeholder| placeholder.bound.kind.get_id())
206+
.and_then(|id| id.as_local())
207+
.map(|local| self.infcx.tcx.local_def_id_to_hir_id(local))
208+
else {
209+
return;
210+
};
248211

249212
// Look for the where-bound which introduces the placeholder.
250213
// As we're using the HIR, we need to handle both `for<'a> T: Trait<'a>`
251214
// and `T: for<'a> Trait`<'a>.
252215
let mut hrtb_bounds = vec![];
253-
gat_id_and_generics.iter().flatten().for_each(|&(gat_hir_id, generics)| {
254-
for pred in generics.predicates {
255-
let BoundPredicate(WhereBoundPredicate { bound_generic_params, bounds, .. }) =
256-
pred.kind
257-
else {
258-
continue;
259-
};
260-
if bound_generic_params
261-
.iter()
262-
.rfind(|bgp| tcx.local_def_id_to_hir_id(bgp.def_id) == gat_hir_id)
263-
.is_some()
264-
{
265-
for bound in *bounds {
266-
hrtb_bounds.push(bound);
267-
}
268-
} else {
269-
for bound in *bounds {
270-
if let Trait(trait_bound) = bound {
271-
if trait_bound
272-
.bound_generic_params
273-
.iter()
274-
.rfind(|bgp| tcx.local_def_id_to_hir_id(bgp.def_id) == gat_hir_id)
275-
.is_some()
276-
{
277-
hrtb_bounds.push(bound);
278-
return;
279-
}
280-
}
281-
}
216+
217+
// FIXME(amandasystems) we can probably flatten this.
218+
for pred in self
219+
.infcx
220+
.tcx
221+
.parent_hir_node(self.infcx.tcx.parent_hir_id(gat_hir_id))
222+
.generics()
223+
.map(|gen_impl| gen_impl.predicates)
224+
.into_iter()
225+
.flatten()
226+
{
227+
let BoundPredicate(WhereBoundPredicate { bound_generic_params, bounds, .. }) =
228+
pred.kind
229+
else {
230+
continue;
231+
};
232+
if bound_generic_params
233+
.iter()
234+
.rfind(|bgp| self.infcx.tcx.local_def_id_to_hir_id(bgp.def_id) == gat_hir_id)
235+
.is_some()
236+
{
237+
for bound in *bounds {
238+
hrtb_bounds.push(bound);
282239
}
283240
}
284-
});
241+
}
285242
debug!(?hrtb_bounds);
286243

287244
let mut suggestions = vec![];
@@ -384,56 +341,13 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
384341
}
385342
}
386343

387-
RegionErrorKind::PlaceholderOutlivesLocationOrUniversal {
344+
RegionErrorKind::PlaceholderOutlivesIllegalRegion {
388345
longer_fr,
389-
placeholder,
390-
error_element,
391-
} => self.report_erroneous_rvid_reaches_placeholder(
392-
longer_fr,
393-
placeholder,
394-
self.regioncx.region_from_element(longer_fr, &error_element),
395-
),
396-
RegionErrorKind::PlaceholderOutlivesPlaceholder {
397-
rvid_a,
398-
rvid_b,
399-
origin_a,
400-
origin_b,
346+
illegally_outlived_r,
401347
} => {
402-
debug!(
403-
"Placeholder mismatch: {rvid_a:?} ({origin_a:?}) reaches {rvid_b:?} ({origin_b:?})"
404-
);
405-
406-
let cause = self
407-
.regioncx
408-
.best_blame_constraint(
409-
rvid_a,
410-
NllRegionVariableOrigin::Placeholder(origin_a),
411-
rvid_b,
412-
)
413-
.0
414-
.cause;
415-
416-
// FIXME We may be able to shorten the code path here, and immediately
417-
// report a `RegionResolutionError::UpperBoundUniverseConflict`, but
418-
// that's left for a future refactoring.
419-
self.regioncx.universe_info(origin_a.universe).report_erroneous_element(
420-
self,
421-
origin_a,
422-
Some(origin_b),
423-
cause,
424-
);
348+
self.report_erroneous_rvid_reaches_placeholder(longer_fr, illegally_outlived_r)
425349
}
426350

427-
RegionErrorKind::PlaceholderOutlivesExistentialThatCannotNameIt {
428-
longer_fr,
429-
existential_that_cannot_name_longer,
430-
placeholder,
431-
} => self.report_erroneous_rvid_reaches_placeholder(
432-
longer_fr,
433-
placeholder,
434-
existential_that_cannot_name_longer,
435-
),
436-
437351
RegionErrorKind::RegionError { fr_origin, longer_fr, shorter_fr, is_reported } => {
438352
if is_reported {
439353
self.report_region_error(

0 commit comments

Comments
 (0)