Skip to content
Merged
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
70 changes: 38 additions & 32 deletions compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ use tracing::{debug, instrument};
use super::explain_borrow::{BorrowExplanation, LaterUseKind};
use super::{DescribePlaceOpt, RegionName, RegionNameSource, UseSpans};
use crate::borrow_set::{BorrowData, TwoPhaseActivation};
use crate::consumers::OutlivesConstraint;
use crate::diagnostics::conflict_errors::StorageDeadOrDrop::LocalStorageDead;
use crate::diagnostics::{CapturedMessageOpt, call_kind, find_all_local_uses};
use crate::{InitializationRequiringAction, MirBorrowckCtxt, WriteKind, borrowck_errors};
Expand Down Expand Up @@ -3076,40 +3077,48 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
),
(
Some(name),
BorrowExplanation::MustBeValidFor {
category:
category @ (ConstraintCategory::Return(_)
| ConstraintCategory::CallArgument(_)
| ConstraintCategory::OpaqueType),
from_closure: false,
ref region_name,
span,
..
},
) if borrow_spans.for_coroutine() || borrow_spans.for_closure() => self
.report_escaping_closure_capture(
BorrowExplanation::MustBeValidFor { ref best_blame, ref region_name, .. },
) if let OutlivesConstraint {
category:
category @ (ConstraintCategory::Return(_)
| ConstraintCategory::CallArgument(_)
| ConstraintCategory::OpaqueType),
from_closure: false,
span,
..
} = best_blame.constraint()
&& (borrow_spans.for_coroutine() || borrow_spans.for_closure()) =>
{
self.report_escaping_closure_capture(
borrow_spans,
borrow_span,
region_name,
category,
span,
*category,
*span,
&format!("`{name}`"),
"function",
),
)
}
(
name,
BorrowExplanation::MustBeValidFor {
category: ConstraintCategory::Assignment,
from_closure: false,
ref best_blame,
region_name:
RegionName {
source: RegionNameSource::AnonRegionFromUpvar(upvar_span, upvar_name),
..
},
span,
..
},
) => self.report_escaping_data(borrow_span, &name, upvar_span, upvar_name, span),
) if let OutlivesConstraint {
category: ConstraintCategory::Assignment,
from_closure: false,
span,
..
} = best_blame.constraint() =>
{
self.report_escaping_data(borrow_span, &name, upvar_span, upvar_name, *span)
}
(Some(name), explanation) => self.report_local_value_does_not_live_long_enough(
location,
&name,
Expand Down Expand Up @@ -3143,18 +3152,14 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
explanation: BorrowExplanation<'tcx>,
) -> Diag<'infcx> {
let borrow_span = borrow_spans.var_or_use_path_span();
if let BorrowExplanation::MustBeValidFor {
category,
span,
ref opt_place_desc,
from_closure: false,
..
} = explanation
if let BorrowExplanation::MustBeValidFor { best_blame, opt_place_desc, .. } = &explanation
&& let OutlivesConstraint { category, span, from_closure: false, .. } =
best_blame.constraint()
&& let Err(diag) = self.try_report_cannot_return_reference_to_local(
borrow,
borrow_span,
span,
category,
*span,
*category,
opt_place_desc.as_ref(),
)
{
Expand Down Expand Up @@ -3356,14 +3361,15 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
proper_span: Span,
explanation: BorrowExplanation<'tcx>,
) -> Diag<'infcx> {
if let BorrowExplanation::MustBeValidFor { category, span, from_closure: false, .. } =
explanation
if let BorrowExplanation::MustBeValidFor { ref best_blame, .. } = explanation
&& let OutlivesConstraint { category, span, from_closure: false, .. } =
best_blame.constraint()
{
if let Err(diag) = self.try_report_cannot_return_reference_to_local(
borrow,
proper_span,
span,
category,
*span,
*category,
None,
) {
return diag;
Expand Down
27 changes: 10 additions & 17 deletions compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use super::{RegionName, UseSpans, find_use};
use crate::borrow_set::BorrowData;
use crate::constraints::OutlivesConstraint;
use crate::nll::ConstraintDescription;
use crate::region_infer::{BlameConstraint, Cause};
use crate::region_infer::{BestBlame, Cause};
use crate::{MirBorrowckCtxt, WriteKind};

#[derive(Debug)]
Expand All @@ -35,12 +35,9 @@ pub(crate) enum BorrowExplanation<'tcx> {
should_note_order: bool,
},
MustBeValidFor {
category: ConstraintCategory<'tcx>,
from_closure: bool,
span: Span,
best_blame: BestBlame<'tcx>,
region_name: RegionName,
opt_place_desc: Option<String>,
path: Vec<OutlivesConstraint<'tcx>>,
},
Unexplained,
}
Expand Down Expand Up @@ -376,13 +373,13 @@ impl<'tcx> BorrowExplanation<'tcx> {
}
}
BorrowExplanation::MustBeValidFor {
category,
span,
ref best_blame,
ref region_name,
ref opt_place_desc,
from_closure: _,
ref path,
} => {
let OutlivesConstraint { category, span, .. } = *best_blame.constraint();
let path = best_blame.path();

region_name.highlight_region_name(err);

if let Some(desc) = opt_place_desc {
Expand All @@ -403,8 +400,8 @@ impl<'tcx> BorrowExplanation<'tcx> {
);
};

cx.add_placeholder_from_predicate_note(err, &path);
cx.add_sized_or_copy_bound_info(err, category, &path);
cx.add_placeholder_from_predicate_note(err, path);
cx.add_sized_or_copy_bound_info(err, category, path);

if let ConstraintCategory::Cast {
is_raw_ptr_dyn_type_cast: _,
Expand Down Expand Up @@ -689,22 +686,18 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
// Here, under NLL: no cause was found. Under polonius: no cause was found, or a
// boring local was found, which we ignore like NLLs do to match its diagnostics.
if let Some(region) = self.regioncx.to_error_region_vid(borrow_region_vid) {
let (blame_constraint, path) = self.regioncx.best_blame_constraint(
let best_blame = self.regioncx.best_blame_constraint(
borrow_region_vid,
NllRegionVariableOrigin::FreeRegion,
region,
);
let BlameConstraint { category, from_closure, span, .. } = blame_constraint;

if let Some(region_name) = self.give_region_a_name(region) {
let opt_place_desc = self.describe_place(borrow.borrowed_place.as_ref());
BorrowExplanation::MustBeValidFor {
category,
from_closure,
span,
best_blame,
region_name,
opt_place_desc,
path,
}
} else {
debug!("Could not generate a region name");
Expand Down
21 changes: 10 additions & 11 deletions compiler/rustc_borrowck/src/diagnostics/region_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ use rustc_trait_selection::traits::{Obligation, ObligationCtxt};
use tracing::{debug, instrument, trace};

use super::{LIMITATION_NOTE, OutlivesSuggestionBuilder, RegionName, RegionNameSource};
use crate::consumers::RegionInferenceContext;
use crate::consumers::{OutlivesConstraint, RegionInferenceContext};
use crate::nll::ConstraintDescription;
use crate::region_infer::{BlameConstraint, TypeTest};
use crate::region_infer::TypeTest;
use crate::session_diagnostics::{
FnMutError, FnMutReturnTypeErr, GenericDoesNotLiveLongEnough, LifetimeOutliveErr,
LifetimeReturnCategoryErr, RequireStaticErr, VarHereDenote,
Expand Down Expand Up @@ -414,9 +414,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
};

// Find the code to blame for the fact that `longer_fr` outlives `error_fr`.
let (blame_constraint, path) =
self.regioncx.best_blame_constraint(longer_fr, origin_longer, error_vid);
let cause = blame_constraint.to_obligation_cause_from_path(&path);
let best_blame = self.regioncx.best_blame_constraint(longer_fr, origin_longer, error_vid);
let cause = best_blame.to_obligation_cause();

// FIXME these methods should have better names, and also probably not be this generic.
// FIXME note that we *throw away* the error element here! We probably want to
Expand Down Expand Up @@ -447,9 +446,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
) {
debug!("report_region_error(fr={:?}, outlived_fr={:?})", fr, outlived_fr);

let (blame_constraint, path) =
self.regioncx.best_blame_constraint(fr, fr_origin, outlived_fr);
let BlameConstraint { category, span, variance_info, .. } = blame_constraint;
let best_blame = self.regioncx.best_blame_constraint(fr, fr_origin, outlived_fr);
let OutlivesConstraint { category, span, variance_info, .. } = *best_blame.constraint();
let path = best_blame.path();

debug!("report_region_error: category={:?} {:?} {:?}", category, span, variance_info);

Expand Down Expand Up @@ -563,10 +562,10 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
}
}

self.add_placeholder_from_predicate_note(&mut diag, &path);
self.add_sized_or_copy_bound_info(&mut diag, category, &path);
self.add_placeholder_from_predicate_note(&mut diag, path);
self.add_sized_or_copy_bound_info(&mut diag, category, path);

for constraint in &path {
for constraint in path {
if let ConstraintCategory::Cast { is_raw_ptr_dyn_type_cast: true, .. } =
constraint.category
{
Expand Down
63 changes: 33 additions & 30 deletions compiler/rustc_borrowck/src/region_infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1285,9 +1285,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
return RegionRelationCheckResult::Error;
}

let blame_constraint = self
.best_blame_constraint(longer_fr, NllRegionVariableOrigin::FreeRegion, shorter_fr)
.0;
let best_blame = self.best_blame_constraint(
longer_fr,
NllRegionVariableOrigin::FreeRegion,
shorter_fr,
);
let OutlivesConstraint { category, span, .. } = best_blame.constraint();

// Grow `shorter_fr` until we find some non-local regions.
// We will always find at least one: `'static`. We'll call
Expand Down Expand Up @@ -1346,8 +1349,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
propagated_outlives_requirements.push(ClosureOutlivesRequirement {
subject: ClosureOutlivesSubject::Region(fr_minus),
outlived_free_region: fr_plus,
blame_span: blame_constraint.span,
category: blame_constraint.category,
blame_span: *span,
category: *category,
});
}
return RegionRelationCheckResult::Propagated;
Expand Down Expand Up @@ -1614,7 +1617,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
from_region: RegionVid,
from_region_origin: NllRegionVariableOrigin<'tcx>,
to_region: RegionVid,
) -> (BlameConstraint<'tcx>, Vec<OutlivesConstraint<'tcx>>) {
) -> BestBlame<'tcx> {
assert!(from_region != to_region, "Trying to blame a region for itself!");

let path = self.constraint_path_between_regions(from_region, to_region).unwrap();
Expand Down Expand Up @@ -1787,40 +1790,34 @@ impl<'tcx> RegionInferenceContext<'tcx> {

debug!(?best_choice, ?blame_source);

let best_constraint = if let Some(next) = path.get(best_choice + 1)
let best_blame_idx = if let Some(next) = path.get(best_choice + 1)
&& matches!(path[best_choice].category, ConstraintCategory::Return(_))
&& next.category == ConstraintCategory::OpaqueType
{
// The return expression is being influenced by the return type being
// impl Trait, point at the return type and not the return expr.
*next
best_choice + 1
} else if path[best_choice].category == ConstraintCategory::Return(ReturnConstraint::Normal)
&& let Some(field) = path.iter().find_map(|p| {
if let ConstraintCategory::ClosureUpvar(f) = p.category { Some(f) } else { None }
})
{
path[best_choice].category =
ConstraintCategory::Return(ReturnConstraint::ClosureUpvar(field));
path[best_choice]
best_choice
} else {
path[best_choice]
best_choice
};

assert!(
!matches!(
best_constraint.category,
path[best_blame_idx].category,
ConstraintCategory::OutlivesUnnameablePlaceholder(_)
),
"Illegal placeholder constraint blamed; should have redirected to other region relation"
);

let blame_constraint = BlameConstraint {
category: best_constraint.category,
from_closure: best_constraint.from_closure,
span: best_constraint.span,
variance_info: best_constraint.variance_info,
};
(blame_constraint, path)
BestBlame { path, idx: best_blame_idx }
}

pub(crate) fn universe_info(&self, universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
Expand Down Expand Up @@ -1895,21 +1892,19 @@ impl<'tcx> RegionInferenceContext<'tcx> {
}

#[derive(Clone, Debug)]
pub(crate) struct BlameConstraint<'tcx> {
pub category: ConstraintCategory<'tcx>,
pub from_closure: bool,
pub span: Span,
pub variance_info: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
pub(crate) struct BestBlame<'tcx> {
/// See docs on [`RegionInferenceContext::best_blame_constraint`] for what this is.
path: Vec<OutlivesConstraint<'tcx>>,
/// Index into `path` of the constraint most relevant to report to users.
idx: usize,
}

impl<'tcx> BlameConstraint<'tcx> {
pub(crate) fn to_obligation_cause_from_path(
&self,
path: &[OutlivesConstraint<'tcx>],
) -> ObligationCause<'tcx> {
impl<'tcx> BestBlame<'tcx> {
pub(crate) fn to_obligation_cause(&self) -> ObligationCause<'tcx> {
// FIXME - determine what we should do if we encounter multiple
// `ConstraintCategory::Predicate` constraints. Currently, we just pick the first one.
let cause_code = path
let cause_code = self
.path
.iter()
.find_map(|constraint| {
if let ConstraintCategory::Predicate(predicate_span) = constraint.category {
Expand All @@ -1923,6 +1918,14 @@ impl<'tcx> BlameConstraint<'tcx> {
})
.unwrap_or_else(|| ObligationCauseCode::Misc);

ObligationCause::new(self.span, CRATE_DEF_ID, cause_code.clone())
ObligationCause::new(self.constraint().span, CRATE_DEF_ID, cause_code.clone())
}

pub(crate) fn constraint(&self) -> &OutlivesConstraint<'tcx> {
&self.path[self.idx]
}

pub(crate) fn path(&self) -> &[OutlivesConstraint<'tcx>] {
&self.path
}
}
Loading