Move canonicalization code around

This commit is contained in:
Michael Goulet 2023-03-24 17:27:06 +00:00
parent 7f89c7c32d
commit a61616a016
4 changed files with 47 additions and 72 deletions

View File

@ -1,7 +1,6 @@
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,
@ -9,9 +8,7 @@ use rustc_infer::infer::{
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,
@ -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.
@ -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
@ -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
@ -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>,
@ -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)
}
}

View File

@ -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.
@ -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)
}
@ -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> {
@ -51,7 +55,8 @@ 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,
@ -59,6 +64,26 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
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.
///
@ -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;
@ -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() {
@ -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

View File

@ -15,8 +15,7 @@ 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::{
@ -24,7 +23,7 @@ use rustc_middle::ty::{
};
mod assembly;
mod canonical;
mod canonicalize;
mod eval_ctxt;
mod fulfill;
mod project_goals;