mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
Move canonicalization code around
This commit is contained in:
parent
7f89c7c32d
commit
a61616a016
@ -1,7 +1,6 @@
|
|||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_infer::infer::at::ToTrace;
|
use rustc_infer::infer::at::ToTrace;
|
||||||
use rustc_infer::infer::canonical::query_response::make_query_region_constraints;
|
use rustc_infer::infer::canonical::CanonicalVarValues;
|
||||||
use rustc_infer::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarValues};
|
|
||||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||||
use rustc_infer::infer::{
|
use rustc_infer::infer::{
|
||||||
DefineOpaqueTypes, InferCtxt, InferOk, LateBoundRegionConversionTime, TyCtxtInferExt,
|
DefineOpaqueTypes, InferCtxt, InferOk, LateBoundRegionConversionTime, TyCtxtInferExt,
|
||||||
@ -9,9 +8,7 @@ use rustc_infer::infer::{
|
|||||||
use rustc_infer::traits::query::NoSolution;
|
use rustc_infer::traits::query::NoSolution;
|
||||||
use rustc_infer::traits::ObligationCause;
|
use rustc_infer::traits::ObligationCause;
|
||||||
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
|
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
|
||||||
use rustc_middle::traits::solve::{
|
use rustc_middle::traits::solve::{CanonicalGoal, Certainty, MaybeCause, QueryResult};
|
||||||
CanonicalGoal, Certainty, ExternalConstraints, ExternalConstraintsData, MaybeCause, QueryResult,
|
|
||||||
};
|
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
|
self, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
|
||||||
TypeVisitor,
|
TypeVisitor,
|
||||||
@ -21,11 +18,12 @@ use std::ops::ControlFlow;
|
|||||||
|
|
||||||
use crate::traits::specialization_graph;
|
use crate::traits::specialization_graph;
|
||||||
|
|
||||||
use super::canonical::{CanonicalizeMode, Canonicalizer};
|
|
||||||
use super::search_graph::{self, OverflowHandler};
|
use super::search_graph::{self, OverflowHandler};
|
||||||
use super::SolverMode;
|
use super::SolverMode;
|
||||||
use super::{search_graph::SearchGraph, Goal};
|
use super::{search_graph::SearchGraph, Goal};
|
||||||
|
|
||||||
|
mod canonical;
|
||||||
|
|
||||||
pub struct EvalCtxt<'a, 'tcx> {
|
pub struct EvalCtxt<'a, 'tcx> {
|
||||||
/// The inference context that backs (mostly) inference and placeholder terms
|
/// The inference context that backs (mostly) inference and placeholder terms
|
||||||
/// instantiated while solving goals.
|
/// instantiated while solving goals.
|
||||||
@ -414,7 +412,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
|||||||
if let &ty::Infer(ty::TyVar(vid)) = ty.kind() {
|
if let &ty::Infer(ty::TyVar(vid)) = ty.kind() {
|
||||||
match self.infcx.probe_ty_var(vid) {
|
match self.infcx.probe_ty_var(vid) {
|
||||||
Ok(value) => bug!("resolved var in query: {goal:?} {value:?}"),
|
Ok(value) => bug!("resolved var in query: {goal:?} {value:?}"),
|
||||||
Err(universe) => universe == self.universe(),
|
Err(universe) => universe == self.infcx.universe(),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
@ -424,7 +422,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
|||||||
if let ty::ConstKind::Infer(ty::InferConst::Var(vid)) = ct.kind() {
|
if let ty::ConstKind::Infer(ty::InferConst::Var(vid)) = ct.kind() {
|
||||||
match self.infcx.probe_const_var(vid) {
|
match self.infcx.probe_const_var(vid) {
|
||||||
Ok(value) => bug!("resolved var in query: {goal:?} {value:?}"),
|
Ok(value) => bug!("resolved var in query: {goal:?} {value:?}"),
|
||||||
Err(universe) => universe == self.universe(),
|
Err(universe) => universe == self.infcx.universe(),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
@ -566,22 +564,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
|||||||
self.infcx.fresh_substs_for_item(DUMMY_SP, def_id)
|
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(
|
pub(super) fn translate_substs(
|
||||||
&self,
|
&self,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
@ -621,35 +603,4 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
|||||||
crate::traits::wf::unnormalized_obligations(self.infcx, param_env, arg)
|
crate::traits::wf::unnormalized_obligations(self.infcx, param_env, arg)
|
||||||
.map(|obligations| obligations.into_iter().map(|obligation| obligation.into()))
|
.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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -8,20 +8,19 @@
|
|||||||
/// section of the [rustc-dev-guide][c].
|
/// section of the [rustc-dev-guide][c].
|
||||||
///
|
///
|
||||||
/// [c]: https://rustc-dev-guide.rust-lang.org/solve/canonicalization.html
|
/// [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::{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::CanonicalVarValues;
|
||||||
use rustc_infer::infer::canonical::{CanonicalExt, QueryRegionConstraints};
|
use rustc_infer::infer::canonical::{CanonicalExt, QueryRegionConstraints};
|
||||||
use rustc_infer::traits::query::NoSolution;
|
use rustc_middle::traits::query::NoSolution;
|
||||||
use rustc_infer::traits::solve::ExternalConstraintsData;
|
use rustc_middle::traits::solve::{ExternalConstraints, ExternalConstraintsData};
|
||||||
use rustc_middle::ty::{self, GenericArgKind};
|
use rustc_middle::ty::{self, GenericArgKind};
|
||||||
|
use rustc_span::DUMMY_SP;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
mod canonicalize;
|
|
||||||
|
|
||||||
impl<'tcx> EvalCtxt<'_, 'tcx> {
|
impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||||
/// Canonicalizes the goal remembering the original values
|
/// Canonicalizes the goal remembering the original values
|
||||||
/// for each bound variable.
|
/// for each bound variable.
|
||||||
@ -30,7 +29,12 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
|||||||
goal: Goal<'tcx, ty::Predicate<'tcx>>,
|
goal: Goal<'tcx, ty::Predicate<'tcx>>,
|
||||||
) -> (Vec<ty::GenericArg<'tcx>>, CanonicalGoal<'tcx>) {
|
) -> (Vec<ty::GenericArg<'tcx>>, CanonicalGoal<'tcx>) {
|
||||||
let mut orig_values = Default::default();
|
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)
|
(orig_values, canonical_goal)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,7 +45,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
|||||||
/// - `external_constraints`: additional constraints which aren't expressable
|
/// - `external_constraints`: additional constraints which aren't expressable
|
||||||
/// using simple unification of inference variables.
|
/// using simple unification of inference variables.
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[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,
|
&mut self,
|
||||||
certainty: Certainty,
|
certainty: Certainty,
|
||||||
) -> QueryResult<'tcx> {
|
) -> QueryResult<'tcx> {
|
||||||
@ -51,7 +55,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
|||||||
let external_constraints = self.compute_external_query_constraints()?;
|
let external_constraints = self.compute_external_query_constraints()?;
|
||||||
|
|
||||||
let response = Response { var_values: self.var_values, external_constraints, certainty };
|
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 },
|
CanonicalizeMode::Response { max_input_universe: self.max_input_universe },
|
||||||
&mut Default::default(),
|
&mut Default::default(),
|
||||||
response,
|
response,
|
||||||
@ -59,6 +64,26 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
|||||||
Ok(canonical)
|
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
|
/// After calling a canonical query, we apply the constraints returned
|
||||||
/// by the query using this function.
|
/// by the query using this function.
|
||||||
///
|
///
|
||||||
@ -98,10 +123,10 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
|||||||
// FIXME: Longterm canonical queries should deal with all placeholders
|
// FIXME: Longterm canonical queries should deal with all placeholders
|
||||||
// created inside of the query directly instead of returning them to the
|
// created inside of the query directly instead of returning them to the
|
||||||
// caller.
|
// caller.
|
||||||
let prev_universe = self.universe();
|
let prev_universe = self.infcx.universe();
|
||||||
let universes_created_in_query = response.max_universe.index() + 1;
|
let universes_created_in_query = response.max_universe.index() + 1;
|
||||||
for _ in 0..universes_created_in_query {
|
for _ in 0..universes_created_in_query {
|
||||||
self.create_next_universe();
|
self.infcx.create_next_universe();
|
||||||
}
|
}
|
||||||
|
|
||||||
let var_values = response.value.var_values;
|
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
|
// 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
|
// exist at all (see the FIXME at the start of this method), we have to deal with
|
||||||
// them for now.
|
// 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())
|
ty::UniverseIndex::from(prev_universe.index() + idx.index())
|
||||||
})
|
})
|
||||||
} else if info.is_existential() {
|
} else if info.is_existential() {
|
||||||
@ -158,7 +183,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
|||||||
if let Some(v) = opt_values[index] {
|
if let Some(v) = opt_values[index] {
|
||||||
v
|
v
|
||||||
} else {
|
} else {
|
||||||
self.instantiate_canonical_var(info, |_| prev_universe)
|
self.infcx.instantiate_canonical_var(DUMMY_SP, info, |_| prev_universe)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// For placeholders which were already part of the input, we simply map this
|
// For placeholders which were already part of the input, we simply map this
|
@ -15,8 +15,7 @@ use rustc_hir::def_id::DefId;
|
|||||||
use rustc_infer::infer::canonical::{Canonical, CanonicalVarValues};
|
use rustc_infer::infer::canonical::{Canonical, CanonicalVarValues};
|
||||||
use rustc_infer::traits::query::NoSolution;
|
use rustc_infer::traits::query::NoSolution;
|
||||||
use rustc_middle::traits::solve::{
|
use rustc_middle::traits::solve::{
|
||||||
CanonicalGoal, CanonicalResponse, Certainty, ExternalConstraintsData, Goal, QueryResult,
|
CanonicalResponse, Certainty, ExternalConstraintsData, Goal, QueryResult, Response,
|
||||||
Response,
|
|
||||||
};
|
};
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
@ -24,7 +23,7 @@ use rustc_middle::ty::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
mod assembly;
|
mod assembly;
|
||||||
mod canonical;
|
mod canonicalize;
|
||||||
mod eval_ctxt;
|
mod eval_ctxt;
|
||||||
mod fulfill;
|
mod fulfill;
|
||||||
mod project_goals;
|
mod project_goals;
|
||||||
|
Loading…
Reference in New Issue
Block a user