Skip to content
Draft
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
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,8 @@ fn try_extract_error_from_fulfill_cx<'a, 'tcx>(
// already run, but there's no point using `span_delayed_bug`
// when we're going to emit an error here anyway.
let _errors = ocx.evaluate_obligations_error_on_ambiguity();
let region_constraints = ocx.infcx.with_region_constraints(|r| r.clone());
// FIXME(-Zassumptions-on-binders): do something here for abby_constraints?
let region_constraints = ocx.infcx.with_region_constraints(|r, _| r.clone());
try_extract_error_from_region_constraints(
ocx.infcx,
generic_param_scope,
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_borrowck/src/handle_placeholders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,9 @@ pub(crate) fn compute_sccs_applying_placeholder_outlives_constraints<'tcx>(
mut outlives_constraints,
universe_causes,
type_tests,
solver_constraints,
} = constraints;
assert!(solver_constraints.is_true(), "solver constraints were not lowered to NLL");

let fr_static = universal_regions.fr_static;
let compute_sccs =
Expand Down
9 changes: 6 additions & 3 deletions compiler/rustc_borrowck/src/type_check/canonical.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,12 @@ where
let TypeOpOutput { output, constraints: query_constraints, error_info } =
op.fully_perform(infcx, infcx.root_def_id, locations.span(body))?;
if cfg!(debug_assertions) {
let data = infcx.take_and_reset_region_constraints();
if !data.is_empty() {
panic!("leftover region constraints: {data:#?}");
let (legacy_constraints, abby_constraints) = infcx.take_and_reset_region_constraints();
if !legacy_constraints.is_empty() {
panic!("leftover region constraints: {legacy_constraints:#?}");
}
if !abby_constraints.get_constraint().is_true() {
panic!("leftover region constraints: {abby_constraints:#?}");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {

#[instrument(skip(self), level = "debug")]
pub(super) fn convert_all(&mut self, query_constraints: &QueryRegionConstraints<'tcx>) {
let QueryRegionConstraints { constraints, assumptions } = query_constraints;
let QueryRegionConstraints { constraints, assumptions, solver_constraints } =
query_constraints;
let assumptions =
elaborate::elaborate_outlives_assumptions(self.infcx.tcx, assumptions.iter().copied());

Expand All @@ -76,6 +77,9 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
self.convert(predicate, category, &assumptions);
});
}

self.constraints
.register_solver_constraint(solver_constraints.clone().with_spans(self.span));
}

/// Given an instance of the closure type, this method instantiates the "extra" requirements
Expand Down
13 changes: 13 additions & 0 deletions compiler/rustc_borrowck/src/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use rustc_infer::infer::outlives::env::RegionBoundPairs;
use rustc_infer::infer::region_constraints::RegionConstraintData;
use rustc_infer::infer::{
BoundRegionConversionTime, InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin,
SolverRegionConstraint,
};
use rustc_infer::traits::{Obligation, ObligationCause, PredicateObligations};
use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
Expand Down Expand Up @@ -111,6 +112,7 @@ pub(crate) fn type_check<'tcx>(
outlives_constraints: OutlivesConstraintSet::default(),
type_tests: Vec::default(),
universe_causes: FxIndexMap::default(),
solver_constraints: Default::default(),
};

let CreateResult {
Expand Down Expand Up @@ -171,6 +173,8 @@ pub(crate) fn type_check<'tcx>(
let polonius_context = typeck.polonius_context;

if infcx.tcx.assumptions_on_binders() {
let constraint = mem::take(&mut typeck.constraints.solver_constraints);
assert!(infcx.tcx.assumptions_on_binders());
let mut converter = constraint_conversion::ConstraintConversion::new(
typeck.infcx,
typeck.universal_regions,
Expand All @@ -182,6 +186,7 @@ pub(crate) fn type_check<'tcx>(
typeck.constraints,
);
typeck.infcx.destructure_solver_region_constraints_for_borrowck(
constraint,
&mut converter,
typeck.known_type_outlives_obligations,
typeck.region_bound_pairs,
Expand Down Expand Up @@ -290,9 +295,17 @@ pub(crate) struct MirTypeckRegionConstraints<'tcx> {
pub(crate) universe_causes: FxIndexMap<ty::UniverseIndex, UniverseInfo<'tcx>>,

pub(crate) type_tests: Vec<TypeTest<'tcx>>,

/// Constraints from completed AoB type operations, lowered once all bounds are available.
pub(crate) solver_constraints: SolverRegionConstraint<'tcx>,
}

impl<'tcx> MirTypeckRegionConstraints<'tcx> {
pub(crate) fn register_solver_constraint(&mut self, constraint: SolverRegionConstraint<'tcx>) {
let prev = mem::take(&mut self.solver_constraints);
self.solver_constraints = SolverRegionConstraint::build_and(prev, constraint);
}

/// Creates a `Region` for a given `PlaceholderRegion`, or returns the
/// region that corresponds to a previously created one.
pub(crate) fn placeholder_region(
Expand Down
59 changes: 32 additions & 27 deletions compiler/rustc_infer/src/infer/canonical/query_response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,13 +146,15 @@ impl<'tcx> InferCtxt<'tcx> {
let region_obligations = self.take_registered_region_obligations();
let region_assumptions = self.take_registered_region_assumptions();
debug!(?region_obligations);
let region_constraints = self.with_region_constraints(|region_constraints| {
make_query_region_constraints(
region_obligations,
region_constraints,
region_assumptions,
)
});
let region_constraints =
self.with_region_constraints(|legacy_constraints, abby_constraints| {
make_query_region_constraints(
region_obligations,
legacy_constraints,
region_assumptions,
abby_constraints.get_constraint().without_spans(),
)
});
debug!(?region_constraints);

let opaque_types = self
Expand Down Expand Up @@ -195,9 +197,9 @@ impl<'tcx> InferCtxt<'tcx> {
let InferOk { value: result_args, obligations } =
self.query_response_instantiation(cause, param_env, original_values, query_response)?;

for QueryRegionConstraint { constraint, visible_for_leak_check: vis, .. } in
&query_response.value.region_constraints.constraints
{
let QueryRegionConstraints { constraints, assumptions, solver_constraints } =
&query_response.value.region_constraints;
for QueryRegionConstraint { constraint, visible_for_leak_check: vis, .. } in constraints {
let constraint = instantiate_value(self.tcx, &result_args, *constraint);
match constraint {
ty::RegionConstraint::Outlives(clause) => {
Expand All @@ -209,11 +211,14 @@ impl<'tcx> InferCtxt<'tcx> {
}
}

for assumption in &query_response.value.region_constraints.assumptions {
for assumption in assumptions {
let assumption = instantiate_value(self.tcx, &result_args, *assumption);
self.register_region_assumption(assumption);
}

let constraint = instantiate_value(self.tcx, &result_args, solver_constraints.clone());
self.register_solver_region_constraint(constraint.with_spans(cause.span));

let user_result: R =
query_response.instantiate_projected(self.tcx, &result_args, |q_r| q_r.value.clone());

Expand Down Expand Up @@ -324,27 +329,26 @@ impl<'tcx> InferCtxt<'tcx> {
}
}

let QueryRegionConstraints { constraints, assumptions, solver_constraints } =
&query_response.value.region_constraints;

// ...also include the other query region constraints from the query.
output_query_region_constraints.constraints.extend(
query_response.value.region_constraints.constraints.iter().filter_map(|&r_c| {
let r_c = instantiate_value(self.tcx, &result_args, r_c);
output_query_region_constraints.constraints.extend(constraints.iter().filter_map(|&r_c| {
let r_c = instantiate_value(self.tcx, &result_args, r_c);

// Screen out `'a: 'a` or `'a == 'a` cases.
if r_c.constraint.is_trivial() { None } else { Some(r_c) }
}),
);
// Screen out `'a: 'a` or `'a == 'a` cases.
if r_c.constraint.is_trivial() { None } else { Some(r_c) }
}));

// FIXME(higher_ranked_auto): Optimize this to instantiate all assumptions
// at once, rather than calling `instantiate_value` repeatedly which may
// create more universes.
output_query_region_constraints.assumptions.extend(
query_response
.value
.region_constraints
.assumptions
.iter()
.map(|&r_c| instantiate_value(self.tcx, &result_args, r_c)),
);
output_query_region_constraints
.assumptions
.extend(assumptions.iter().map(|&r_c| instantiate_value(self.tcx, &result_args, r_c)));

let constraint = instantiate_value(self.tcx, &result_args, solver_constraints.clone());
output_query_region_constraints.add_solver_constraint(constraint);

let user_result: R =
query_response.instantiate_projected(self.tcx, &result_args, |q_r| q_r.value.clone());
Expand Down Expand Up @@ -618,6 +622,7 @@ pub fn make_query_region_constraints<'tcx>(
outlives_obligations: Vec<TypeOutlivesConstraint<'tcx>>,
region_constraints: &RegionConstraintData<'tcx>,
assumptions: Vec<ty::ArgOutlivesClause<'tcx>>,
solver_constraints: ty::region_constraint::RegionConstraint<TyCtxt<'tcx>>,
) -> QueryRegionConstraints<'tcx> {
let RegionConstraintData { constraints, verifys } = region_constraints;

Expand Down Expand Up @@ -662,5 +667,5 @@ pub fn make_query_region_constraints<'tcx>(
))
.collect();

QueryRegionConstraints { constraints, assumptions }
QueryRegionConstraints { constraints, assumptions, solver_constraints }
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use rustc_index::IndexVec;
use rustc_type_ir::RegionVid;

use super::Data;
use crate::infer::SubregionOrigin;
use crate::infer::region_constraints::{Constraint, ConstraintKind, RegionConstraintData};
use crate::infer::region_constraints::{Constraint, ConstraintKind};

/// Selects either out-edges or in-edges for [`IndexedConstraintEdges::adjacent_edges`].
#[derive(Clone, Copy, Debug)]
Expand All @@ -13,24 +14,23 @@ pub(super) enum EdgeDirection {

/// Type alias for the pairs stored in [`RegionConstraintData::constraints`],
/// which we are indexing.
type ConstraintPair<'data, 'tcx> = (Constraint<'tcx>, &'data SubregionOrigin<'tcx>);
type ConstraintPair<'tcx> = (Constraint<'tcx>, SubregionOrigin<'tcx>);

/// An index from region variables to their corresponding constraint edges,
/// used on some error paths.
pub(super) struct IndexedConstraintEdges<'data, 'tcx> {
out_edges: IndexVec<RegionVid, Vec<ConstraintPair<'data, 'tcx>>>,
in_edges: IndexVec<RegionVid, Vec<ConstraintPair<'data, 'tcx>>>,
pub(super) struct IndexedConstraintEdges<'tcx> {
out_edges: IndexVec<RegionVid, Vec<ConstraintPair<'tcx>>>,
in_edges: IndexVec<RegionVid, Vec<ConstraintPair<'tcx>>>,
}

impl<'data, 'tcx> IndexedConstraintEdges<'data, 'tcx> {
pub(super) fn build_index(num_vars: usize, data: &'data RegionConstraintData<'tcx>) -> Self {
impl<'tcx> IndexedConstraintEdges<'tcx> {
pub(super) fn build_index<D: Data<'tcx>>(num_vars: usize, data: &D) -> Self {
let mut out_edges = IndexVec::from_fn_n(|_| vec![], num_vars);
let mut in_edges = IndexVec::from_fn_n(|_| vec![], num_vars);

for pair @ (c, _) in data
.constraints
.iter()
.flat_map(|(c, origin)| c.iter_outlives().map(move |c| (c, origin)))
.constraints()
.flat_map(|(c, origin)| c.iter_outlives().map(move |c| (c, origin.clone())))
{
// Only push a var out-edge for `VarSub...` constraints.
match c.kind {
Expand All @@ -51,10 +51,9 @@ impl<'data, 'tcx> IndexedConstraintEdges<'data, 'tcx> {
// (It's unclear whether this is important or not.)

for pair @ (c, _) in data
.constraints
.iter()
.constraints()
.rev()
.flat_map(|(c, origin)| c.iter_outlives().map(move |c| (c, origin)))
.flat_map(|(c, origin)| c.iter_outlives().map(move |c| (c, origin.clone())))
{
// Only push a var in-edge for `...SubVar` constraints.
match c.kind {
Expand All @@ -79,7 +78,7 @@ impl<'data, 'tcx> IndexedConstraintEdges<'data, 'tcx> {
&self,
region_vid: RegionVid,
dir: EdgeDirection,
) -> &[ConstraintPair<'data, 'tcx>] {
) -> &[ConstraintPair<'tcx>] {
let edges = match dir {
EdgeDirection::Out => &self.out_edges,
EdgeDirection::In => &self.in_edges,
Expand Down
Loading
Loading