Skip to content

Commit

Permalink
Auto merge of #102618 - aliemjay:simplify-closure-promote, r=compiler…
Browse files Browse the repository at this point in the history
…-errors

rework applying closure requirements in borrowck

Previously the promoted closure constraints were registered under the category `ConstraintCategory::ClosureBounds` in `type_check::prove_closure_bounds()` and then mapped back their original category in `regions_infer::best_blame_constraint` using the complicated map `closure_bounds_mapping`.

Now we're registering promoted constraints under their original category and span earlier in `type_check::prove_closure_bounds`.

See commit messages.

Fixes #99245
  • Loading branch information
bors committed Nov 6, 2022
2 parents a4ab2e0 + 02f78fd commit e30fb6a
Show file tree
Hide file tree
Showing 26 changed files with 173 additions and 349 deletions.
1 change: 1 addition & 0 deletions compiler/rustc_borrowck/src/constraints/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ impl<'s, 'tcx, D: ConstraintGraphDirecton> Iterator for Edges<'s, 'tcx, D> {
span: DUMMY_SP,
category: ConstraintCategory::Internal,
variance_info: VarianceDiagInfo::default(),
from_closure: false,
})
} else {
None
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_borrowck/src/constraints/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ pub struct OutlivesConstraint<'tcx> {

/// Variance diagnostic information
pub variance_info: VarianceDiagInfo<'tcx>,

/// If this constraint is promoted from closure requirements.
pub from_closure: bool,
}

impl<'tcx> fmt::Debug for OutlivesConstraint<'tcx> {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_borrowck/src/diagnostics/region_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
// Try to convert the lower-bound region into something named we can print for the user.
let lower_bound_region = self.to_error_region(type_test.lower_bound);

let type_test_span = type_test.locations.span(&self.body);
let type_test_span = type_test.span;

if let Some(lower_bound_region) = lower_bound_region {
let generic_ty = type_test.generic_kind.to_ty(self.infcx.tcx);
Expand Down
2 changes: 0 additions & 2 deletions compiler/rustc_borrowck/src/nll.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,6 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
mut liveness_constraints,
outlives_constraints,
member_constraints,
closure_bounds_mapping,
universe_causes,
type_tests,
} = constraints;
Expand All @@ -264,7 +263,6 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
universal_region_relations,
outlives_constraints,
member_constraints,
closure_bounds_mapping,
universe_causes,
type_tests,
liveness_constraints,
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_borrowck/src/region_infer/dump_mir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
let mut constraints: Vec<_> = self.constraints.outlives().iter().collect();
constraints.sort_by_key(|c| (c.sup, c.sub));
for constraint in &constraints {
let OutlivesConstraint { sup, sub, locations, category, span, variance_info: _ } =
constraint;
let OutlivesConstraint { sup, sub, locations, category, span, .. } = constraint;
let (name, arg) = match locations {
Locations::All(span) => {
("All", tcx.sess.source_map().span_to_embeddable_string(*span))
Expand Down
162 changes: 17 additions & 145 deletions compiler/rustc_borrowck/src/region_infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@ use rustc_data_structures::frozen::Frozen;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::graph::scc::Sccs;
use rustc_errors::Diagnostic;
use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
use rustc_hir::def_id::CRATE_DEF_ID;
use rustc_hir::CRATE_HIR_ID;
use rustc_index::vec::IndexVec;
use rustc_infer::infer::canonical::QueryOutlivesConstraint;
use rustc_infer::infer::outlives::test_type_match;
use rustc_infer::infer::region_constraints::{GenericKind, VarInfos, VerifyBound, VerifyIfEq};
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin};
Expand All @@ -19,9 +18,7 @@ use rustc_middle::mir::{
};
use rustc_middle::traits::ObligationCause;
use rustc_middle::traits::ObligationCauseCode;
use rustc_middle::ty::{
self, subst::SubstsRef, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitable,
};
use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitable};
use rustc_span::Span;

use crate::{
Expand Down Expand Up @@ -89,10 +86,6 @@ pub struct RegionInferenceContext<'tcx> {
/// `member_region_scc`.
member_constraints_applied: Vec<AppliedMemberConstraint>,

/// Map closure bounds to a `Span` that should be used for error reporting.
closure_bounds_mapping:
FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory<'tcx>, Span)>>,

/// Map universe indexes to information on why we created it.
universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>,

Expand Down Expand Up @@ -221,8 +214,8 @@ pub struct TypeTest<'tcx> {
/// The region `'x` that the type must outlive.
pub lower_bound: RegionVid,

/// Where did this constraint arise and why?
pub locations: Locations,
/// The span to blame.
pub span: Span,

/// A test which, if met by the region `'x`, proves that this type
/// constraint is satisfied.
Expand Down Expand Up @@ -265,10 +258,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
outlives_constraints: OutlivesConstraintSet<'tcx>,
member_constraints_in: MemberConstraintSet<'tcx, RegionVid>,
closure_bounds_mapping: FxHashMap<
Location,
FxHashMap<(RegionVid, RegionVid), (ConstraintCategory<'tcx>, Span)>,
>,
universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
type_tests: Vec<TypeTest<'tcx>>,
liveness_constraints: LivenessValues<RegionVid>,
Expand Down Expand Up @@ -310,7 +299,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
rev_scc_graph: None,
member_constraints,
member_constraints_applied: Vec::new(),
closure_bounds_mapping,
universe_causes,
scc_universes,
scc_representatives,
Expand Down Expand Up @@ -882,13 +870,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
if deduplicate_errors.insert((
erased_generic_kind,
type_test.lower_bound,
type_test.locations,
type_test.span,
)) {
debug!(
"check_type_test: reporting error for erased_generic_kind={:?}, \
lower_bound_region={:?}, \
type_test.locations={:?}",
erased_generic_kind, type_test.lower_bound, type_test.locations,
type_test.span={:?}",
erased_generic_kind, type_test.lower_bound, type_test.span,
);

errors_buffer.push(RegionErrorKind::TypeTestError { type_test: type_test.clone() });
Expand Down Expand Up @@ -931,7 +919,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
) -> bool {
let tcx = infcx.tcx;

let TypeTest { generic_kind, lower_bound, locations, verify_bound: _ } = type_test;
let TypeTest { generic_kind, lower_bound, span: _, verify_bound: _ } = type_test;

let generic_ty = generic_kind.to_ty(tcx);
let Some(subject) = self.try_promote_type_test_subject(infcx, generic_ty) else {
Expand Down Expand Up @@ -959,7 +947,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
propagated_outlives_requirements.push(ClosureOutlivesRequirement {
subject,
outlived_free_region: static_r,
blame_span: locations.span(body),
blame_span: type_test.span,
category: ConstraintCategory::Boring,
});

Expand Down Expand Up @@ -1011,7 +999,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
let requirement = ClosureOutlivesRequirement {
subject,
outlived_free_region: upper_bound,
blame_span: locations.span(body),
blame_span: type_test.span,
category: ConstraintCategory::Boring,
};
debug!("try_promote_type_test: pushing {:#?}", requirement);
Expand Down Expand Up @@ -1804,18 +1792,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
}
}

pub(crate) fn retrieve_closure_constraint_info(
&self,
constraint: OutlivesConstraint<'tcx>,
) -> Option<(ConstraintCategory<'tcx>, Span)> {
match constraint.locations {
Locations::All(_) => None,
Locations::Single(loc) => {
self.closure_bounds_mapping[&loc].get(&(constraint.sup, constraint.sub)).copied()
}
}
}

/// Finds a good `ObligationCause` to blame for the fact that `fr1` outlives `fr2`.
pub(crate) fn find_outlives_blame_span(
&self,
Expand Down Expand Up @@ -1921,6 +1897,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
span: p_c.definition_span,
category: ConstraintCategory::OpaqueType,
variance_info: ty::VarianceDiagInfo::default(),
from_closure: false,
};
handle_constraint(constraint);
}
Expand Down Expand Up @@ -2066,31 +2043,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
// Classify each of the constraints along the path.
let mut categorized_path: Vec<BlameConstraint<'tcx>> = path
.iter()
.map(|constraint| {
let (category, span, from_closure, cause_code) =
if constraint.category == ConstraintCategory::ClosureBounds {
if let Some((category, span)) =
self.retrieve_closure_constraint_info(*constraint)
{
(category, span, true, ObligationCauseCode::MiscObligation)
} else {
(
constraint.category,
constraint.span,
false,
ObligationCauseCode::MiscObligation,
)
}
} else {
(constraint.category, constraint.span, false, cause_code.clone())
};
BlameConstraint {
category,
from_closure,
cause: ObligationCause::new(span, CRATE_HIR_ID, cause_code),
variance_info: constraint.variance_info,
outlives_constraint: *constraint,
}
.map(|constraint| BlameConstraint {
category: constraint.category,
from_closure: constraint.from_closure,
cause: ObligationCause::new(constraint.span, CRATE_HIR_ID, cause_code.clone()),
variance_info: constraint.variance_info,
outlives_constraint: *constraint,
})
.collect();
debug!("categorized_path={:#?}", categorized_path);
Expand Down Expand Up @@ -2274,92 +2232,6 @@ impl<'tcx> RegionDefinition<'tcx> {
}
}

pub trait ClosureRegionRequirementsExt<'tcx> {
fn apply_requirements(
&self,
tcx: TyCtxt<'tcx>,
closure_def_id: DefId,
closure_substs: SubstsRef<'tcx>,
) -> Vec<QueryOutlivesConstraint<'tcx>>;
}

impl<'tcx> ClosureRegionRequirementsExt<'tcx> for ClosureRegionRequirements<'tcx> {
/// Given an instance T of the closure type, this method
/// instantiates the "extra" requirements that we computed for the
/// closure into the inference context. This has the effect of
/// adding new outlives obligations to existing variables.
///
/// As described on `ClosureRegionRequirements`, the extra
/// requirements are expressed in terms of regionvids that index
/// into the free regions that appear on the closure type. So, to
/// do this, we first copy those regions out from the type T into
/// a vector. Then we can just index into that vector to extract
/// out the corresponding region from T and apply the
/// requirements.
fn apply_requirements(
&self,
tcx: TyCtxt<'tcx>,
closure_def_id: DefId,
closure_substs: SubstsRef<'tcx>,
) -> Vec<QueryOutlivesConstraint<'tcx>> {
debug!(
"apply_requirements(closure_def_id={:?}, closure_substs={:?})",
closure_def_id, closure_substs
);

// Extract the values of the free regions in `closure_substs`
// into a vector. These are the regions that we will be
// relating to one another.
let closure_mapping = &UniversalRegions::closure_mapping(
tcx,
closure_substs,
self.num_external_vids,
closure_def_id.expect_local(),
);
debug!("apply_requirements: closure_mapping={:?}", closure_mapping);

// Create the predicates.
self.outlives_requirements
.iter()
.map(|outlives_requirement| {
let outlived_region = closure_mapping[outlives_requirement.outlived_free_region];

match outlives_requirement.subject {
ClosureOutlivesSubject::Region(region) => {
let region = closure_mapping[region];
debug!(
"apply_requirements: region={:?} \
outlived_region={:?} \
outlives_requirement={:?}",
region, outlived_region, outlives_requirement,
);
(
ty::Binder::dummy(ty::OutlivesPredicate(
region.into(),
outlived_region,
)),
ConstraintCategory::BoringNoLocation,
)
}

ClosureOutlivesSubject::Ty(ty) => {
debug!(
"apply_requirements: ty={:?} \
outlived_region={:?} \
outlives_requirement={:?}",
ty, outlived_region, outlives_requirement,
);
(
ty::Binder::dummy(ty::OutlivesPredicate(ty.into(), outlived_region)),
ConstraintCategory::BoringNoLocation,
)
}
}
})
.collect()
}
}

#[derive(Clone, Debug)]
pub struct BlameConstraint<'tcx> {
pub category: ConstraintCategory<'tcx>,
Expand Down
Loading

0 comments on commit e30fb6a

Please sign in to comment.