Skip to content
18 changes: 12 additions & 6 deletions compiler/rustc_infer/src/infer/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,13 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {

fn get_solver_region_constraint(
&self,
) -> rustc_type_ir::region_constraint::RegionConstraint<TyCtxt<'tcx>> {
) -> rustc_type_ir::region_constraint::CanonicalFormRegionConstraint<TyCtxt<'tcx>> {
self.inner.borrow().solver_region_constraint_storage.get_constraint()
}

fn overwrite_solver_region_constraint(
&self,
constraint: rustc_type_ir::region_constraint::RegionConstraint<TyCtxt<'tcx>>,
constraint: rustc_type_ir::region_constraint::CanonicalFormRegionConstraint<TyCtxt<'tcx>>,
) {
let mut inner = self.inner.borrow_mut();
use rustc_data_structures::undo_log::UndoLogs;
Expand Down Expand Up @@ -330,15 +330,21 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {

fn register_solver_region_constraint(
&self,
c: rustc_type_ir::region_constraint::RegionConstraint<TyCtxt<'tcx>>,
c: rustc_type_ir::region_constraint::CanonicalFormRegionConstraint<TyCtxt<'tcx>>,
) {
let mut inner = self.inner.borrow_mut();
use rustc_data_structures::undo_log::UndoLogs;

let old_constraint = inner.solver_region_constraint_storage.get_constraint();
let new_constraint =
rustc_type_ir::region_constraint::CanonicalFormRegionConstraint::new_and(
c,
old_constraint.clone(),
);

use crate::infer::UndoLog;
let previous_was_and = inner.solver_region_constraint_storage.is_and();
inner.undo_log.push(UndoLog::PushSolverRegionConstraint { previous_was_and });
inner.solver_region_constraint_storage.push(c);
inner.undo_log.push(UndoLog::OverwriteSolverRegionConstraint { old_constraint });
inner.solver_region_constraint_storage.overwrite_solver_region_constraint(new_constraint);
}

fn register_ty_outlives(&self, ty: Ty<'tcx>, r: ty::Region<'tcx>, span: Span) {
Expand Down
41 changes: 3 additions & 38 deletions compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1810,58 +1810,23 @@ impl<'tcx> InferCtxt<'tcx> {
}

type SolverRegionConstraint<'tcx> =
rustc_type_ir::region_constraint::RegionConstraint<TyCtxt<'tcx>>;
rustc_type_ir::region_constraint::CanonicalFormRegionConstraint<TyCtxt<'tcx>>;

#[derive(Clone, Debug)]
struct SolverRegionConstraintStorage<'tcx>(SolverRegionConstraint<'tcx>);

impl<'tcx> SolverRegionConstraintStorage<'tcx> {
fn new() -> Self {
SolverRegionConstraintStorage(SolverRegionConstraint::And(Box::new([])))
SolverRegionConstraintStorage(SolverRegionConstraint::new_true())
}

fn get_constraint(&self) -> SolverRegionConstraint<'tcx> {
self.0.clone()
}

fn is_and(&self) -> bool {
self.0.is_and()
}

fn pop(&mut self, previous_was_and: bool) -> Option<SolverRegionConstraint<'tcx>> {
match &mut self.0 {
SolverRegionConstraint::And(and) => {
let mut and = core::mem::take(and).into_iter().collect::<Vec<_>>();
let popped = and.pop()?;
if previous_was_and {
self.0 = SolverRegionConstraint::And(and.into_boxed_slice());
} else {
assert_eq!(and.len(), 1);
self.0 = and.pop().unwrap();
}
Some(popped)
}
_ => unreachable!(),
}
}

#[instrument(level = "debug")]
fn push(&mut self, constraint: SolverRegionConstraint<'tcx>) {
match core::mem::replace(&mut self.0, SolverRegionConstraint::new_true()) {
SolverRegionConstraint::And(and) => {
let and =
and.into_iter().chain([constraint]).collect::<Vec<_>>().into_boxed_slice();
self.0 = SolverRegionConstraint::And(and);
}
previous => {
self.0 = SolverRegionConstraint::And(Box::new([previous, constraint]));
}
}
}

#[instrument(level = "debug", skip(self))]
fn overwrite_solver_region_constraint(&mut self, constraint: SolverRegionConstraint<'tcx>) {
self.0 = constraint;
self.0 = constraint
}
}

Expand Down
34 changes: 20 additions & 14 deletions compiler/rustc_infer/src/infer/outlives/obligations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ use rustc_middle::ty::{
TyCtxt, TypeVisitableExt, eager_resolve_vars,
};
use rustc_span::Span;
use rustc_type_ir::region_constraint::{self, LeafRegionConstraint};
use smallvec::smallvec;
use tracing::{debug, instrument};

Expand Down Expand Up @@ -232,7 +233,7 @@ impl<'tcx> InferCtxt<'tcx> {
region_outlives: TransitiveRelation<RegionVid>,
span: Span,
) {
let assumptions = rustc_type_ir::region_constraint::Assumptions::new(
let assumptions = region_constraint::Assumptions::new(
known_type_outlives.into_iter().cloned().collect(),
region_outlives.maybe_map(|r| Some(Region::new_var(self.tcx, r))).unwrap(),
);
Expand All @@ -254,19 +255,24 @@ impl<'tcx> InferCtxt<'tcx> {

let constraint = self.inner.borrow().solver_region_constraint_storage.get_constraint();
debug!(?constraint);
let constraint =
rustc_type_ir::region_constraint::destructure_type_outlives_constraints_in_root(
self,
constraint,
&assumptions,
);
let constraint = region_constraint::destructure_type_outlives_constraints_in_root(
self,
constraint,
&assumptions,
);
debug!(?constraint);
let constraint = rustc_type_ir::region_constraint::evaluate_solver_constraint(&constraint);
let constraint = region_constraint::propagate_ambiguity(constraint);
debug!(?constraint);

let mut constraints = vec![constraint];
while let Some(c) = constraints.pop() {
use rustc_type_ir::region_constraint::RegionConstraint::*;
// FIXME(-Zassumptions-on-binders): actually implement OR as an OR
for c in constraint.and_constraint.0.into_iter().chain(
constraint
.or_constraint
.0
.into_iter()
.flat_map(|and_constraint| and_constraint.0.into_iter()),
) {
use LeafRegionConstraint::*;

match c {
Ambiguity => {
Expand All @@ -281,9 +287,9 @@ impl<'tcx> InferCtxt<'tcx> {
category,
);
}
// FIXME(-Zassumptions-on-binders): actually implement OR as an OR
And(nested) | Or(nested) => constraints.extend(nested),
AliasTyOutlivesViaEnv(..) | PlaceholderTyOutlives(..) => unreachable!(),
AliasTyOutlivesViaEnv(..) | PlaceholderTyOutlives(..) => {
unreachable!()
}
}
}
}
Expand Down
9 changes: 0 additions & 9 deletions compiler/rustc_infer/src/infer/snapshot/undo_log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ pub(crate) enum UndoLog<'tcx> {
RegionUnificationTable(sv::UndoLog<ut::Delegate<RegionVidKey<'tcx>>>),
ProjectionCache(traits::UndoLog<'tcx>),
PushTypeOutlivesConstraint,
PushSolverRegionConstraint { previous_was_and: bool },
OverwriteSolverRegionConstraint { old_constraint: SolverRegionConstraint<'tcx> },
PushRegionAssumption,
PushHirTypeckPotentiallyRegionDependentGoal,
Expand Down Expand Up @@ -79,14 +78,6 @@ impl<'tcx> Rollback<UndoLog<'tcx>> for InferCtxtInner<'tcx> {
self.region_constraint_storage.as_mut().unwrap().unification_table.reverse(undo)
}
UndoLog::ProjectionCache(undo) => self.projection_cache.reverse(undo),
UndoLog::PushSolverRegionConstraint { previous_was_and } => {
let popped = self.solver_region_constraint_storage.pop(previous_was_and);
assert_matches!(
popped,
Some(_),
"pushed solver region constraint but could not pop it"
);
}
UndoLog::OverwriteSolverRegionConstraint { old_constraint } => {
self.solver_region_constraint_storage
.overwrite_solver_region_constraint(old_constraint);
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::ops::ControlFlow;
use rustc_macros::StableHash;
use rustc_type_ir::data_structures::HashSet;
use rustc_type_ir::inherent::*;
use rustc_type_ir::region_constraint::{RegionConstraint, evaluate_solver_constraint};
use rustc_type_ir::region_constraint::{self, CanonicalFormRegionConstraint};
use rustc_type_ir::relate::Relate;
use rustc_type_ir::relate::solver_relating::RelateExt;
use rustc_type_ir::search_graph::{CandidateHeadUsages, LowerAvailableDepth, PathKind};
Expand Down Expand Up @@ -1328,7 +1328,7 @@ where
args
}

pub(super) fn register_solver_region_constraint(&self, c: RegionConstraint<I>) {
pub(super) fn register_solver_region_constraint(&self, c: CanonicalFormRegionConstraint<I>) {
self.delegate.register_solver_region_constraint(c);
}

Expand Down Expand Up @@ -1664,11 +1664,11 @@ where
let constraint = self.delegate.get_solver_region_constraint();
debug_assert_eq!(
constraint,
evaluate_solver_constraint(&constraint.clone().canonical_form())
region_constraint::propagate_ambiguity(constraint.clone())
);
constraint
} else {
RegionConstraint::new_true()
CanonicalFormRegionConstraint::new_true()
})
} else {
ExternalRegionConstraints::Old(if let Certainty::Yes = certainty {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ use rustc_type_ir::outlives::{Component, push_outlives_components};
#[cfg(not(feature = "nightly"))]
use rustc_type_ir::region_constraint::TransitiveRelationBuilder;
use rustc_type_ir::region_constraint::{
Assumptions, RegionConstraint, eagerly_handle_placeholders_in_universe,
evaluate_solver_constraint,
And, Assumptions, LeafRegionConstraint, Or, eagerly_handle_placeholders_in_universe,
propagate_ambiguity,
};
use rustc_type_ir::{
AliasTy, Binder, ClauseKind, InferCtxtLike, Interner, OutlivesClause, Region, TypeVisitable,
Expand Down Expand Up @@ -137,8 +137,9 @@ where
.fold(constraint, |constraint, u| {
eagerly_handle_placeholders_in_universe(&**self.delegate, constraint, u)
});
let constraint = evaluate_solver_constraint(&constraint.canonical_form());
let constraint = propagate_ambiguity(constraint);

debug!("final constraint={:?}", constraint);
self.delegate.overwrite_solver_region_constraint(constraint.clone());

if constraint.is_false() {
Expand All @@ -154,36 +155,28 @@ where
/// type outlives constraints between the "components" of the type. E.g. `Foo<T, 'a>: 'b`
/// will be turned into `T: 'b, 'a: 'b`
#[instrument(level = "debug", skip(self), ret)]
pub(in crate::solve) fn destructure_type_outlives(
&mut self,
ty: I::Ty,
r: Region<I>,
) -> RegionConstraint<I> {
pub(in crate::solve) fn destructure_type_outlives(&mut self, ty: I::Ty, r: Region<I>) -> Or<I> {
let mut components = Default::default();
push_outlives_components(self.cx(), ty, &mut components);
self.destructure_components(&components, r)
}

fn destructure_components(
&mut self,
components: &[Component<I>],
r: Region<I>,
) -> RegionConstraint<I> {
RegionConstraint::And(
components.into_iter().map(|c| self.destructure_component(c, r)).collect(),
)
fn destructure_components(&mut self, components: &[Component<I>], r: Region<I>) -> Or<I> {
components
.into_iter()
.fold(Or::new_true(), |acc, c| Or::new_and(acc, self.destructure_component(c, r)))
}

fn destructure_component(&mut self, c: &Component<I>, r: Region<I>) -> RegionConstraint<I> {
fn destructure_component(&mut self, c: &Component<I>, r: Region<I>) -> Or<I> {
use Component::*;
use LeafRegionConstraint::*;
match c {
Region(c_r) => RegionConstraint::RegionOutlives(*c_r, r),
Region(c_r) => Or::new_leaf(RegionOutlives(*c_r, r)),
Placeholder(p) => {
RegionConstraint::PlaceholderTyOutlives(Ty::new_placeholder(self.cx(), *p), r)
Or::new_leaf(PlaceholderTyOutlives(Ty::new_placeholder(self.cx(), *p), r))
}
// The alias is either rigid or ambiguous in which case we'll return with ambiguity.
Alias(_, alias) => self.destructure_alias_outlives(*alias, r),
UnresolvedInferenceVariable(_) => RegionConstraint::Ambiguity,
UnresolvedInferenceVariable(_) => Or::new_ambig(),
Param(_) => panic!("Params should have been canonicalized to placeholders"),
EscapingAlias(components) => self.destructure_components(components, r),
}
Expand All @@ -197,18 +190,15 @@ where
/// 3. env assumptions. we defer handling `Alias<T, 'a>: 'b` via where clauses until
/// when exiting the current binder. See [`RegionConstraint::AliasTyOutlivesViaEnv`].
#[instrument(level = "debug", skip(self), ret)]
fn destructure_alias_outlives(
&mut self,
alias: AliasTy<I>,
r: Region<I>,
) -> RegionConstraint<I> {
fn destructure_alias_outlives(&mut self, alias: AliasTy<I>, r: Region<I>) -> Or<I> {
use LeafRegionConstraint::*;

let item_bounds =
rustc_type_ir::outlives::declared_bounds_from_definition(self.cx(), alias)
.map(|bound| RegionConstraint::RegionOutlives(bound, r));
let item_bound_outlives = RegionConstraint::Or(item_bounds.collect());
.map(|bound| And::new([RegionOutlives(bound, r)]));
let item_bound_outlives = Or::new(item_bounds);

let where_clause_outlives =
RegionConstraint::AliasTyOutlivesViaEnv(Binder::dummy((alias, r)));
let where_clause_outlives = Or::new_leaf(AliasTyOutlivesViaEnv(Binder::dummy((alias, r))));

let mut components = Default::default();
rustc_type_ir::outlives::compute_alias_components_recursive(
Expand All @@ -218,10 +208,7 @@ where
);
let components_outlives = self.destructure_components(&components, r);

RegionConstraint::Or(Box::new([
item_bound_outlives,
where_clause_outlives,
components_outlives,
]))
let assumption_outlives = Or::new_or(item_bound_outlives, where_clause_outlives);
Or::new_or(assumption_outlives, components_outlives)
}
}
12 changes: 10 additions & 2 deletions compiler/rustc_next_trait_solver/src/solve/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,12 @@ where
let ty = self.normalize(GoalSource::Misc, goal.param_env, ty::Unnormalized::new_wip(ty))?;

if self.cx().assumptions_on_binders() {
use rustc_type_ir::region_constraint::CanonicalFormRegionConstraint;

let constraint = self.destructure_type_outlives(ty, lt);
self.register_solver_region_constraint(constraint);
self.register_solver_region_constraint(CanonicalFormRegionConstraint::new_from_or(
constraint,
));
} else {
self.register_ty_outlives(ty, lt);
}
Expand All @@ -119,8 +123,12 @@ where
let ty::OutlivesClause(a, b) = goal.predicate;

if self.cx().assumptions_on_binders() {
use rustc_type_ir::region_constraint::{
CanonicalFormRegionConstraint, LeafRegionConstraint,
};

let constraint =
rustc_type_ir::region_constraint::RegionConstraint::RegionOutlives(a, b);
CanonicalFormRegionConstraint::new_leaf(LeafRegionConstraint::RegionOutlives(a, b));
self.register_solver_region_constraint(constraint);
} else {
self.register_region_outlives(a, b, VisibleForLeakCheck::Yes);
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_type_ir/src/infer_ctxt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -395,10 +395,10 @@ pub trait InferCtxtLike: Sized {
) -> Option<crate::region_constraint::Assumptions<Self::Interner>>;
fn get_solver_region_constraint(
&self,
) -> crate::region_constraint::RegionConstraint<Self::Interner>;
) -> crate::region_constraint::CanonicalFormRegionConstraint<Self::Interner>;
fn overwrite_solver_region_constraint(
&self,
constraint: crate::region_constraint::RegionConstraint<Self::Interner>,
constraint: crate::region_constraint::CanonicalFormRegionConstraint<Self::Interner>,
);

fn universe_of_ty(&self, ty: ty::TyVid) -> Option<ty::UniverseIndex>;
Expand Down Expand Up @@ -519,7 +519,7 @@ pub trait InferCtxtLike: Sized {

fn register_solver_region_constraint(
&self,
c: crate::region_constraint::RegionConstraint<Self::Interner>,
c: crate::region_constraint::CanonicalFormRegionConstraint<Self::Interner>,
);

fn register_ty_outlives(
Expand Down
Loading
Loading