Skip to content

Commit

Permalink
Move canonicalization code around
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed Mar 29, 2023
1 parent 7f89c7c commit a61616a
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 72 deletions.
61 changes: 6 additions & 55 deletions compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
use rustc_hir::def_id::DefId;
use rustc_infer::infer::at::ToTrace;
use rustc_infer::infer::canonical::query_response::make_query_region_constraints;
use rustc_infer::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarValues};
use rustc_infer::infer::canonical::CanonicalVarValues;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::{
DefineOpaqueTypes, InferCtxt, InferOk, LateBoundRegionConversionTime, TyCtxtInferExt,
};
use rustc_infer::traits::query::NoSolution;
use rustc_infer::traits::ObligationCause;
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
use rustc_middle::traits::solve::{
CanonicalGoal, Certainty, ExternalConstraints, ExternalConstraintsData, MaybeCause, QueryResult,
};
use rustc_middle::traits::solve::{CanonicalGoal, Certainty, MaybeCause, QueryResult};
use rustc_middle::ty::{
self, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
TypeVisitor,
Expand All @@ -21,11 +18,12 @@ use std::ops::ControlFlow;

use crate::traits::specialization_graph;

use super::canonical::{CanonicalizeMode, Canonicalizer};
use super::search_graph::{self, OverflowHandler};
use super::SolverMode;
use super::{search_graph::SearchGraph, Goal};

mod canonical;

pub struct EvalCtxt<'a, 'tcx> {
/// The inference context that backs (mostly) inference and placeholder terms
/// instantiated while solving goals.
Expand Down Expand Up @@ -414,7 +412,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
if let &ty::Infer(ty::TyVar(vid)) = ty.kind() {
match self.infcx.probe_ty_var(vid) {
Ok(value) => bug!("resolved var in query: {goal:?} {value:?}"),
Err(universe) => universe == self.universe(),
Err(universe) => universe == self.infcx.universe(),
}
} else {
false
Expand All @@ -424,7 +422,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
if let ty::ConstKind::Infer(ty::InferConst::Var(vid)) = ct.kind() {
match self.infcx.probe_const_var(vid) {
Ok(value) => bug!("resolved var in query: {goal:?} {value:?}"),
Err(universe) => universe == self.universe(),
Err(universe) => universe == self.infcx.universe(),
}
} else {
false
Expand Down Expand Up @@ -566,22 +564,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
self.infcx.fresh_substs_for_item(DUMMY_SP, def_id)
}

pub(super) fn universe(&self) -> ty::UniverseIndex {
self.infcx.universe()
}

pub(super) fn create_next_universe(&self) -> ty::UniverseIndex {
self.infcx.create_next_universe()
}

pub(super) fn instantiate_canonical_var(
&self,
cv_info: CanonicalVarInfo<'tcx>,
universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex,
) -> ty::GenericArg<'tcx> {
self.infcx.instantiate_canonical_var(DUMMY_SP, cv_info, universe_map)
}

pub(super) fn translate_substs(
&self,
param_env: ty::ParamEnv<'tcx>,
Expand Down Expand Up @@ -621,35 +603,4 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
crate::traits::wf::unnormalized_obligations(self.infcx, param_env, arg)
.map(|obligations| obligations.into_iter().map(|obligation| obligation.into()))
}

#[instrument(level = "debug", skip(self), ret)]
pub(super) fn compute_external_query_constraints(
&self,
) -> Result<ExternalConstraints<'tcx>, NoSolution> {
// Cannot use `take_registered_region_obligations` as we may compute the response
// inside of a `probe` whenever we have multiple choices inside of the solver.
let region_obligations = self.infcx.inner.borrow().region_obligations().to_owned();
let region_constraints = self.infcx.with_region_constraints(|region_constraints| {
make_query_region_constraints(
self.tcx(),
region_obligations
.iter()
.map(|r_o| (r_o.sup_type, r_o.sub_region, r_o.origin.to_constraint_category())),
region_constraints,
)
});
let opaque_types = self.infcx.clone_opaque_types_for_query_response();
Ok(self
.tcx()
.mk_external_constraints(ExternalConstraintsData { region_constraints, opaque_types }))
}

pub(super) fn canonicalize<T: TypeFoldable<TyCtxt<'tcx>>>(
&self,
canonicalize_mode: CanonicalizeMode,
variables: &mut Vec<ty::GenericArg<'tcx>>,
value: T,
) -> Canonical<'tcx, T> {
Canonicalizer::canonicalize(self.infcx, canonicalize_mode, variables, value)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,19 @@
/// section of the [rustc-dev-guide][c].
///
/// [c]: https://rustc-dev-guide.rust-lang.org/solve/canonicalization.html
pub use self::canonicalize::{CanonicalizeMode, Canonicalizer};

use super::{CanonicalGoal, Certainty, EvalCtxt, Goal};
use super::{CanonicalResponse, QueryResult, Response};
use crate::solve::canonicalize::{CanonicalizeMode, Canonicalizer};
use crate::solve::{CanonicalResponse, QueryResult, Response};
use rustc_infer::infer::canonical::query_response::make_query_region_constraints;
use rustc_infer::infer::canonical::CanonicalVarValues;
use rustc_infer::infer::canonical::{CanonicalExt, QueryRegionConstraints};
use rustc_infer::traits::query::NoSolution;
use rustc_infer::traits::solve::ExternalConstraintsData;
use rustc_middle::traits::query::NoSolution;
use rustc_middle::traits::solve::{ExternalConstraints, ExternalConstraintsData};
use rustc_middle::ty::{self, GenericArgKind};
use rustc_span::DUMMY_SP;
use std::iter;
use std::ops::Deref;

mod canonicalize;

impl<'tcx> EvalCtxt<'_, 'tcx> {
/// Canonicalizes the goal remembering the original values
/// for each bound variable.
Expand All @@ -30,7 +29,12 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
goal: Goal<'tcx, ty::Predicate<'tcx>>,
) -> (Vec<ty::GenericArg<'tcx>>, CanonicalGoal<'tcx>) {
let mut orig_values = Default::default();
let canonical_goal = self.canonicalize(CanonicalizeMode::Input, &mut orig_values, goal);
let canonical_goal = Canonicalizer::canonicalize(
self.infcx,
CanonicalizeMode::Input,
&mut orig_values,
goal,
);
(orig_values, canonical_goal)
}

Expand All @@ -41,7 +45,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
/// - `external_constraints`: additional constraints which aren't expressable
/// using simple unification of inference variables.
#[instrument(level = "debug", skip(self))]
pub(super) fn evaluate_added_goals_and_make_canonical_response(
pub(in crate::solve) fn evaluate_added_goals_and_make_canonical_response(
&mut self,
certainty: Certainty,
) -> QueryResult<'tcx> {
Expand All @@ -51,14 +55,35 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
let external_constraints = self.compute_external_query_constraints()?;

let response = Response { var_values: self.var_values, external_constraints, certainty };
let canonical = self.canonicalize(
let canonical = Canonicalizer::canonicalize(
self.infcx,
CanonicalizeMode::Response { max_input_universe: self.max_input_universe },
&mut Default::default(),
response,
);
Ok(canonical)
}

#[instrument(level = "debug", skip(self), ret)]
fn compute_external_query_constraints(&self) -> Result<ExternalConstraints<'tcx>, NoSolution> {
// Cannot use `take_registered_region_obligations` as we may compute the response
// inside of a `probe` whenever we have multiple choices inside of the solver.
let region_obligations = self.infcx.inner.borrow().region_obligations().to_owned();
let region_constraints = self.infcx.with_region_constraints(|region_constraints| {
make_query_region_constraints(
self.tcx(),
region_obligations
.iter()
.map(|r_o| (r_o.sup_type, r_o.sub_region, r_o.origin.to_constraint_category())),
region_constraints,
)
});
let opaque_types = self.infcx.clone_opaque_types_for_query_response();
Ok(self
.tcx()
.mk_external_constraints(ExternalConstraintsData { region_constraints, opaque_types }))
}

/// After calling a canonical query, we apply the constraints returned
/// by the query using this function.
///
Expand Down Expand Up @@ -98,10 +123,10 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
// FIXME: Longterm canonical queries should deal with all placeholders
// created inside of the query directly instead of returning them to the
// caller.
let prev_universe = self.universe();
let prev_universe = self.infcx.universe();
let universes_created_in_query = response.max_universe.index() + 1;
for _ in 0..universes_created_in_query {
self.create_next_universe();
self.infcx.create_next_universe();
}

let var_values = response.value.var_values;
Expand Down Expand Up @@ -144,7 +169,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
// A variable from inside a binder of the query. While ideally these shouldn't
// exist at all (see the FIXME at the start of this method), we have to deal with
// them for now.
self.instantiate_canonical_var(info, |idx| {
self.infcx.instantiate_canonical_var(DUMMY_SP, info, |idx| {
ty::UniverseIndex::from(prev_universe.index() + idx.index())
})
} else if info.is_existential() {
Expand All @@ -158,7 +183,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
if let Some(v) = opt_values[index] {
v
} else {
self.instantiate_canonical_var(info, |_| prev_universe)
self.infcx.instantiate_canonical_var(DUMMY_SP, info, |_| prev_universe)
}
} else {
// For placeholders which were already part of the input, we simply map this
Expand Down
5 changes: 2 additions & 3 deletions compiler/rustc_trait_selection/src/solve/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,15 @@ use rustc_hir::def_id::DefId;
use rustc_infer::infer::canonical::{Canonical, CanonicalVarValues};
use rustc_infer::traits::query::NoSolution;
use rustc_middle::traits::solve::{
CanonicalGoal, CanonicalResponse, Certainty, ExternalConstraintsData, Goal, QueryResult,
Response,
CanonicalResponse, Certainty, ExternalConstraintsData, Goal, QueryResult, Response,
};
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::ty::{
CoercePredicate, RegionOutlivesPredicate, SubtypePredicate, TypeOutlivesPredicate,
};

mod assembly;
mod canonical;
mod canonicalize;
mod eval_ctxt;
mod fulfill;
mod project_goals;
Expand Down

0 comments on commit a61616a

Please sign in to comment.