Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 17 additions & 16 deletions compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ use rustc_traits::{type_op_ascribe_user_type_with_span, type_op_prove_predicate_
use tracing::{debug, instrument};

use crate::MirBorrowckCtxt;
use crate::region_infer::values::RegionElement;
use crate::session_diagnostics::{
HigherRankedErrorCause, HigherRankedLifetimeError, HigherRankedSubtypeError,
};
Expand All @@ -49,11 +48,12 @@ impl<'tcx> UniverseInfo<'tcx> {
UniverseInfo::RelateTys { expected, found }
}

/// Report an error where an element erroneously made its way into `placeholder`.
pub(crate) fn report_erroneous_element(
&self,
mbcx: &mut MirBorrowckCtxt<'_, '_, 'tcx>,
placeholder: ty::PlaceholderRegion<'tcx>,
error_element: RegionElement<'tcx>,
error_element: Option<ty::PlaceholderRegion<'tcx>>,
cause: ObligationCause<'tcx>,
) {
match *self {
Expand Down Expand Up @@ -153,10 +153,17 @@ pub(crate) trait TypeOpInfo<'tcx> {
&self,
mbcx: &mut MirBorrowckCtxt<'_, '_, 'tcx>,
placeholder: ty::PlaceholderRegion<'tcx>,
error_element: RegionElement<'tcx>,
error_element: Option<ty::PlaceholderRegion<'tcx>>,
cause: ObligationCause<'tcx>,
) {
let tcx = mbcx.infcx.tcx;

// FIXME: this logic is convoluted and strange, and
// we should probably just use the placeholders we get
// as arguments! However, upstream error reporting code
// needs adaptations for that to work (this universe is
// neither the assigned one, nor the calculated one but
// some base-shifted one for some reason?).
let base_universe = self.base_universe();
debug!(?base_universe);

Expand All @@ -172,19 +179,13 @@ pub(crate) trait TypeOpInfo<'tcx> {
ty::Placeholder::new(adjusted_universe.into(), placeholder.bound),
);

let error_region =
if let RegionElement::PlaceholderRegion(error_placeholder) = error_element {
let adjusted_universe =
error_placeholder.universe.as_u32().checked_sub(base_universe.as_u32());
adjusted_universe.map(|adjusted| {
ty::Region::new_placeholder(
tcx,
ty::Placeholder::new(adjusted.into(), error_placeholder.bound),
)
})
} else {
None
};
// FIXME: one day this should just be error_element, but see above about the adjusted universes. At that point, this method can probably be removed entirely.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// FIXME: one day this should just be error_element, but see above about the adjusted universes. At that point, this method can probably be removed entirely.
// FIXME: one day this should just be error_element,
// but see above about the adjusted universes. At that point,
// this method can probably be removed entirely.

let error_region = error_element.and_then(|e| {
let adjusted_universe = e.universe.as_u32().checked_sub(base_universe.as_u32());
adjusted_universe.map(|adjusted| {
ty::Region::new_placeholder(tcx, ty::Placeholder::new(adjusted.into(), e.bound))
})
});

debug!(?placeholder_region);

Expand Down
115 changes: 39 additions & 76 deletions compiler/rustc_borrowck/src/diagnostics/region_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ use tracing::{debug, instrument, trace};

use super::{OutlivesSuggestionBuilder, RegionName, RegionNameSource};
use crate::nll::ConstraintDescription;
use crate::region_infer::values::RegionElement;
use crate::region_infer::{BlameConstraint, TypeTest};
use crate::session_diagnostics::{
FnMutError, FnMutReturnTypeErr, GenericDoesNotLiveLongEnough, LifetimeOutliveErr,
Expand Down Expand Up @@ -104,15 +103,9 @@ pub(crate) enum RegionErrorKind<'tcx> {
/// A generic bound failure for a type test (`T: 'a`).
TypeTestError { type_test: TypeTest<'tcx> },

/// Higher-ranked subtyping error.
BoundUniversalRegionError {
/// The placeholder free region.
longer_fr: RegionVid,
/// The region element that erroneously must be outlived by `longer_fr`.
error_element: RegionElement<'tcx>,
/// The placeholder region.
placeholder: ty::PlaceholderRegion<'tcx>,
},
/// 'p outlives 'r, which does not hold. 'p is always a placeholder
/// and 'r is some other region.
PlaceholderOutlivesIllegalRegion { longer_fr: RegionVid, illegally_outlived_r: RegionVid },

/// Any other lifetime error.
RegionError {
Expand Down Expand Up @@ -205,60 +198,47 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
let tcx = self.infcx.tcx;

// find generic associated types in the given region 'lower_bound'
let gat_id_and_generics = self
let scc = self.regioncx.constraint_sccs().scc(lower_bound);
let Some(gat_hir_id) = self
.regioncx
.placeholders_contained_in(lower_bound)
.map(|placeholder| {
if let Some(id) = placeholder.bound.kind.get_id()
&& let Some(placeholder_id) = id.as_local()
&& let gat_hir_id = tcx.local_def_id_to_hir_id(placeholder_id)
&& let Some(generics_impl) =
tcx.parent_hir_node(tcx.parent_hir_id(gat_hir_id)).generics()
{
Some((gat_hir_id, generics_impl))
} else {
None
}
})
.collect::<Vec<_>>();
debug!(?gat_id_and_generics);
.placeholder_representative(scc)
.and_then(|placeholder| placeholder.bound.kind.get_id())
.and_then(|id| id.as_local())
.map(|local| self.infcx.tcx.local_def_id_to_hir_id(local))
else {
return;
};

// Look for the where-bound which introduces the placeholder.
// As we're using the HIR, we need to handle both `for<'a> T: Trait<'a>`
// and `T: for<'a> Trait`<'a>.
let mut hrtb_bounds = vec![];
gat_id_and_generics.iter().flatten().for_each(|&(gat_hir_id, generics)| {
for pred in generics.predicates {
let BoundPredicate(WhereBoundPredicate { bound_generic_params, bounds, .. }) =
pred.kind
else {
continue;
};
if bound_generic_params
.iter()
.rfind(|bgp| tcx.local_def_id_to_hir_id(bgp.def_id) == gat_hir_id)
.is_some()
{
for bound in *bounds {
hrtb_bounds.push(bound);
}
} else {
for bound in *bounds {
if let Trait(trait_bound) = bound {
if trait_bound
.bound_generic_params
.iter()
.rfind(|bgp| tcx.local_def_id_to_hir_id(bgp.def_id) == gat_hir_id)
.is_some()
{
hrtb_bounds.push(bound);
return;
}
}
}

// FIXME(amandasystems) we can probably flatten this.
for pred in self
.infcx
.tcx
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why use self.infcx.tcx instead of just tcx?

.parent_hir_node(self.infcx.tcx.parent_hir_id(gat_hir_id))
.generics()
.map(|gen_impl| gen_impl.predicates)
.into_iter()
.flatten()
{
let BoundPredicate(WhereBoundPredicate { bound_generic_params, bounds, .. }) =
pred.kind
else {
continue;
};
if bound_generic_params
.iter()
.rfind(|bgp| self.infcx.tcx.local_def_id_to_hir_id(bgp.def_id) == gat_hir_id)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
.rfind(|bgp| self.infcx.tcx.local_def_id_to_hir_id(bgp.def_id) == gat_hir_id)
.rfind(|bgp| tcx.local_def_id_to_hir_id(bgp.def_id) == gat_hir_id)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
.rfind(|bgp| self.infcx.tcx.local_def_id_to_hir_id(bgp.def_id) == gat_hir_id)
.rfind(|bgp| tcx.local_def_id_to_hir_id(bgp.def_id) == gat_hir_id)

.is_some()
{
for bound in *bounds {
hrtb_bounds.push(bound);
}
}
});
}
debug!(?hrtb_bounds);

let mut suggestions = vec![];
Expand Down Expand Up @@ -361,28 +341,11 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
}
}

RegionErrorKind::BoundUniversalRegionError {
RegionErrorKind::PlaceholderOutlivesIllegalRegion {
longer_fr,
placeholder,
error_element,
illegally_outlived_r,
} => {
let error_vid = self.regioncx.region_from_element(longer_fr, &error_element);

// Find the code to blame for the fact that `longer_fr` outlives `error_fr`.
let cause = self
.regioncx
.best_blame_constraint(
longer_fr,
NllRegionVariableOrigin::Placeholder(placeholder),
error_vid,
)
.0
.cause;

let universe = placeholder.universe;
let universe_info = self.regioncx.universe_info(universe);

universe_info.report_erroneous_element(self, placeholder, error_element, cause);
self.report_erroneous_rvid_reaches_placeholder(longer_fr, illegally_outlived_r)
}

RegionErrorKind::RegionError { fr_origin, longer_fr, shorter_fr, is_reported } => {
Expand Down
Loading
Loading