introduce Normalizable
trait for things directly normalizable
This commit is contained in:
parent
de7e941e4e
commit
2a0b3d6224
13 changed files with 362 additions and 57 deletions
|
@ -72,9 +72,10 @@ use std::hash::Hash;
|
|||
use syntax_pos::symbol::InternedString;
|
||||
use traits::query::{
|
||||
CanonicalProjectionGoal, CanonicalTyGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpSubtypeGoal,
|
||||
CanonicalPredicateGoal, CanonicalTypeOpProvePredicateGoal,
|
||||
CanonicalPredicateGoal, CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpNormalizeGoal,
|
||||
};
|
||||
use ty::{TyCtxt, Instance, InstanceDef, ParamEnv, ParamEnvAnd, PolyTraitRef, Ty};
|
||||
use ty::{TyCtxt, FnSig, Instance, InstanceDef,
|
||||
ParamEnv, ParamEnvAnd, Predicate, PolyFnSig, PolyTraitRef, Ty};
|
||||
use ty::subst::Substs;
|
||||
|
||||
// erase!() just makes tokens go away. It's used to specify which macro argument
|
||||
|
@ -652,6 +653,10 @@ define_dep_nodes!( <'tcx>
|
|||
[] TypeOpEq(CanonicalTypeOpEqGoal<'tcx>),
|
||||
[] TypeOpSubtype(CanonicalTypeOpSubtypeGoal<'tcx>),
|
||||
[] TypeOpProvePredicate(CanonicalTypeOpProvePredicateGoal<'tcx>),
|
||||
[] TypeOpNormalizeTy(CanonicalTypeOpNormalizeGoal<'tcx, Ty<'tcx>>),
|
||||
[] TypeOpNormalizePredicate(CanonicalTypeOpNormalizeGoal<'tcx, Predicate<'tcx>>),
|
||||
[] TypeOpNormalizePolyFnSig(CanonicalTypeOpNormalizeGoal<'tcx, PolyFnSig<'tcx>>),
|
||||
[] TypeOpNormalizeFnSig(CanonicalTypeOpNormalizeGoal<'tcx, FnSig<'tcx>>),
|
||||
|
||||
[] SubstituteNormalizeAndTestPredicates { key: (DefId, &'tcx Substs<'tcx>) },
|
||||
|
||||
|
|
|
@ -41,6 +41,9 @@ pub type CanonicalTypeOpSubtypeGoal<'tcx> =
|
|||
pub type CanonicalTypeOpProvePredicateGoal<'tcx> =
|
||||
Canonical<'tcx, type_op::prove_predicate::ProvePredicate<'tcx>>;
|
||||
|
||||
pub type CanonicalTypeOpNormalizeGoal<'tcx, T> =
|
||||
Canonical<'tcx, type_op::normalize::Normalize<'tcx, T>>;
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct NoSolution;
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use infer::canonical::{Canonical, CanonicalizedQueryResult};
|
||||
use infer::canonical::{Canonical, CanonicalizedQueryResult, QueryResult};
|
||||
use ty::{self, ParamEnv, Ty, TyCtxt};
|
||||
|
||||
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
|
||||
|
@ -45,6 +45,12 @@ impl<'gcx: 'tcx, 'tcx> super::QueryTypeOp<'gcx, 'tcx> for Eq<'tcx> {
|
|||
) -> CanonicalizedQueryResult<'gcx, ()> {
|
||||
tcx.type_op_eq(canonicalized).unwrap()
|
||||
}
|
||||
|
||||
fn upcast_result(
|
||||
v: &'a CanonicalizedQueryResult<'gcx, ()>,
|
||||
) -> &'a Canonical<'tcx, QueryResult<'tcx, ()>> {
|
||||
v
|
||||
}
|
||||
}
|
||||
|
||||
BraceStructTypeFoldableImpl! {
|
||||
|
|
|
@ -9,15 +9,17 @@
|
|||
// except according to those terms.
|
||||
|
||||
use infer::canonical::query_result;
|
||||
use infer::canonical::{Canonicalized, CanonicalizedQueryResult, QueryRegionConstraint};
|
||||
use infer::canonical::{
|
||||
Canonical, Canonicalized, CanonicalizedQueryResult, QueryRegionConstraint, QueryResult,
|
||||
};
|
||||
use infer::{InferCtxt, InferOk, InferResult};
|
||||
use std::fmt;
|
||||
use std::rc::Rc;
|
||||
use syntax::codemap::DUMMY_SP;
|
||||
use traits::{ObligationCause, TraitEngine};
|
||||
use ty::error::TypeError;
|
||||
use ty::fold::TypeFoldable;
|
||||
use ty::{Lift, ParamEnv, TyCtxt};
|
||||
use std::fmt;
|
||||
use std::rc::Rc;
|
||||
use syntax::codemap::DUMMY_SP;
|
||||
|
||||
pub mod custom;
|
||||
pub mod eq;
|
||||
|
@ -98,17 +100,12 @@ pub trait TypeOp<'gcx, 'tcx>: Sized + fmt::Debug {
|
|||
}
|
||||
}
|
||||
|
||||
type Lifted<'gcx, T> = <T as Lift<'gcx>>::Lifted;
|
||||
|
||||
pub trait QueryTypeOp<'gcx: 'tcx, 'tcx>: TypeFoldable<'tcx> + Lift<'gcx> {
|
||||
type QueryResult: TypeFoldable<'tcx> + Lift<'gcx>;
|
||||
|
||||
/// Micro-optimization: returns `Ok(x)` if we can trivially
|
||||
/// produce the output, else returns `Err(self)` back.
|
||||
fn trivial_noop(
|
||||
self,
|
||||
tcx: TyCtxt<'_, 'gcx, 'tcx>,
|
||||
) -> Result<Lifted<'gcx, Self::QueryResult>, Self>;
|
||||
fn trivial_noop(self, tcx: TyCtxt<'_, 'gcx, 'tcx>) -> Result<Self::QueryResult, Self>;
|
||||
|
||||
fn param_env(&self) -> ParamEnv<'tcx>;
|
||||
|
||||
|
@ -116,14 +113,24 @@ pub trait QueryTypeOp<'gcx: 'tcx, 'tcx>: TypeFoldable<'tcx> + Lift<'gcx> {
|
|||
tcx: TyCtxt<'_, 'gcx, 'tcx>,
|
||||
canonicalized: Canonicalized<'gcx, Self>,
|
||||
) -> CanonicalizedQueryResult<'gcx, Self::QueryResult>;
|
||||
|
||||
/// "Upcasts" a lifted query result (which is in the gcx lifetime)
|
||||
/// into the tcx lifetime. This is always just an identity cast,
|
||||
/// but the generic code does't realize it, so we have to push the
|
||||
/// operation into the impls that know more specifically what
|
||||
/// `QueryResult` is. This operation would (maybe) be nicer with
|
||||
/// something like HKTs or GATs, since then we could make
|
||||
/// `QueryResult` parametric and `'gcx` and `'tcx` etc.
|
||||
fn upcast_result(
|
||||
lifted_query_result: &'a CanonicalizedQueryResult<'gcx, Self::QueryResult>,
|
||||
) -> &'a Canonical<'tcx, QueryResult<'tcx, Self::QueryResult>>;
|
||||
}
|
||||
|
||||
impl<'gcx: 'tcx, 'tcx, Q> TypeOp<'gcx, 'tcx> for Q
|
||||
where
|
||||
Q: QueryTypeOp<'gcx, 'tcx>,
|
||||
Lifted<'gcx, Q::QueryResult>: TypeFoldable<'tcx>,
|
||||
{
|
||||
type Output = Lifted<'gcx, Q::QueryResult>;
|
||||
type Output = Q::QueryResult;
|
||||
|
||||
fn trivial_noop(self, tcx: TyCtxt<'_, 'gcx, 'tcx>) -> Result<Self::Output, Self> {
|
||||
QueryTypeOp::trivial_noop(self, tcx)
|
||||
|
@ -152,7 +159,7 @@ where
|
|||
&ObligationCause::dummy(),
|
||||
param_env,
|
||||
&canonical_var_values,
|
||||
&canonical_result,
|
||||
Q::upcast_result(&canonical_result),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,17 +8,15 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use infer::{InferCtxt, InferOk, InferResult};
|
||||
use traits::query::NoSolution;
|
||||
use traits::{Normalized, ObligationCause};
|
||||
use ty::fold::TypeFoldable;
|
||||
use ty::{ParamEnv, TyCtxt};
|
||||
use infer::canonical::{Canonical, Canonicalized, CanonicalizedQueryResult, QueryResult};
|
||||
use std::fmt;
|
||||
use ty::fold::TypeFoldable;
|
||||
use ty::{self, Lift, ParamEnv, Ty, TyCtxt};
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
|
||||
pub struct Normalize<'tcx, T> {
|
||||
param_env: ParamEnv<'tcx>,
|
||||
value: T,
|
||||
pub param_env: ParamEnv<'tcx>,
|
||||
pub value: T,
|
||||
}
|
||||
|
||||
impl<'tcx, T> Normalize<'tcx, T>
|
||||
|
@ -30,13 +28,13 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<'gcx, 'tcx, T> super::TypeOp<'gcx, 'tcx> for Normalize<'tcx, T>
|
||||
impl<'gcx: 'tcx, 'tcx, T> super::QueryTypeOp<'gcx, 'tcx> for Normalize<'tcx, T>
|
||||
where
|
||||
T: fmt::Debug + TypeFoldable<'tcx>,
|
||||
T: Normalizable<'gcx, 'tcx>,
|
||||
{
|
||||
type Output = T;
|
||||
type QueryResult = T;
|
||||
|
||||
fn trivial_noop(self, _tcx: TyCtxt<'_, 'gcx, 'tcx>) -> Result<Self::Output, Self> {
|
||||
fn trivial_noop(self, _tcx: TyCtxt<'_, 'gcx, 'tcx>) -> Result<T, Self> {
|
||||
if !self.value.has_projections() {
|
||||
Ok(self.value)
|
||||
} else {
|
||||
|
@ -44,13 +42,126 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
fn perform(self, infcx: &InferCtxt<'_, 'gcx, 'tcx>) -> InferResult<'tcx, Self::Output> {
|
||||
let Normalized { value, obligations } = infcx
|
||||
.at(&ObligationCause::dummy(), self.param_env)
|
||||
.normalize(&self.value)
|
||||
.unwrap_or_else(|NoSolution| {
|
||||
bug!("normalization of `{:?}` failed", self.value,);
|
||||
});
|
||||
Ok(InferOk { value, obligations })
|
||||
fn param_env(&self) -> ParamEnv<'tcx> {
|
||||
self.param_env
|
||||
}
|
||||
|
||||
fn perform_query(
|
||||
tcx: TyCtxt<'_, 'gcx, 'tcx>,
|
||||
canonicalized: Canonicalized<'gcx, Self>,
|
||||
) -> CanonicalizedQueryResult<'gcx, Self::QueryResult> {
|
||||
T::type_op_method(tcx, canonicalized)
|
||||
}
|
||||
|
||||
fn upcast_result(
|
||||
v: &'a CanonicalizedQueryResult<'gcx, T>,
|
||||
) -> &'a Canonical<'tcx, QueryResult<'tcx, T>> {
|
||||
T::upcast_result(v)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Normalizable<'gcx, 'tcx>: fmt::Debug + TypeFoldable<'tcx> + Lift<'gcx> {
|
||||
fn type_op_method(
|
||||
tcx: TyCtxt<'_, 'gcx, 'tcx>,
|
||||
canonicalized: Canonicalized<'gcx, Normalize<'gcx, Self>>,
|
||||
) -> CanonicalizedQueryResult<'gcx, Self>;
|
||||
|
||||
/// Convert from the `'gcx` (lifted) form of `Self` into the `tcx`
|
||||
/// form of `Self`.
|
||||
fn upcast_result(
|
||||
v: &'a CanonicalizedQueryResult<'gcx, Self>,
|
||||
) -> &'a Canonical<'tcx, QueryResult<'tcx, Self>>;
|
||||
}
|
||||
|
||||
impl Normalizable<'gcx, 'tcx> for Ty<'tcx>
|
||||
where
|
||||
'gcx: 'tcx,
|
||||
{
|
||||
fn type_op_method(
|
||||
tcx: TyCtxt<'_, 'gcx, 'tcx>,
|
||||
canonicalized: Canonicalized<'gcx, Normalize<'gcx, Self>>,
|
||||
) -> CanonicalizedQueryResult<'gcx, Self> {
|
||||
tcx.type_op_normalize_ty(canonicalized).unwrap()
|
||||
}
|
||||
|
||||
fn upcast_result(
|
||||
v: &'a CanonicalizedQueryResult<'gcx, Self>,
|
||||
) -> &'a Canonical<'tcx, QueryResult<'tcx, Self>> {
|
||||
v
|
||||
}
|
||||
}
|
||||
|
||||
impl Normalizable<'gcx, 'tcx> for ty::Predicate<'tcx>
|
||||
where
|
||||
'gcx: 'tcx,
|
||||
{
|
||||
fn type_op_method(
|
||||
tcx: TyCtxt<'_, 'gcx, 'tcx>,
|
||||
canonicalized: Canonicalized<'gcx, Normalize<'gcx, Self>>,
|
||||
) -> CanonicalizedQueryResult<'gcx, Self> {
|
||||
tcx.type_op_normalize_predicate(canonicalized).unwrap()
|
||||
}
|
||||
|
||||
fn upcast_result(
|
||||
v: &'a CanonicalizedQueryResult<'gcx, Self>,
|
||||
) -> &'a Canonical<'tcx, QueryResult<'tcx, Self>> {
|
||||
v
|
||||
}
|
||||
}
|
||||
|
||||
impl Normalizable<'gcx, 'tcx> for ty::PolyFnSig<'tcx>
|
||||
where
|
||||
'gcx: 'tcx,
|
||||
{
|
||||
fn type_op_method(
|
||||
tcx: TyCtxt<'_, 'gcx, 'tcx>,
|
||||
canonicalized: Canonicalized<'gcx, Normalize<'gcx, Self>>,
|
||||
) -> CanonicalizedQueryResult<'gcx, Self> {
|
||||
tcx.type_op_normalize_poly_fn_sig(canonicalized).unwrap()
|
||||
}
|
||||
|
||||
fn upcast_result(
|
||||
v: &'a CanonicalizedQueryResult<'gcx, Self>,
|
||||
) -> &'a Canonical<'tcx, QueryResult<'tcx, Self>> {
|
||||
v
|
||||
}
|
||||
}
|
||||
|
||||
impl Normalizable<'gcx, 'tcx> for ty::FnSig<'tcx>
|
||||
where
|
||||
'gcx: 'tcx,
|
||||
{
|
||||
fn type_op_method(
|
||||
tcx: TyCtxt<'_, 'gcx, 'tcx>,
|
||||
canonicalized: Canonicalized<'gcx, Normalize<'gcx, Self>>,
|
||||
) -> CanonicalizedQueryResult<'gcx, Self> {
|
||||
tcx.type_op_normalize_fn_sig(canonicalized).unwrap()
|
||||
}
|
||||
|
||||
fn upcast_result(
|
||||
v: &'a CanonicalizedQueryResult<'gcx, Self>,
|
||||
) -> &'a Canonical<'tcx, QueryResult<'tcx, Self>> {
|
||||
v
|
||||
}
|
||||
}
|
||||
|
||||
BraceStructTypeFoldableImpl! {
|
||||
impl<'tcx, T> TypeFoldable<'tcx> for Normalize<'tcx, T> {
|
||||
param_env,
|
||||
value,
|
||||
} where T: TypeFoldable<'tcx>,
|
||||
}
|
||||
|
||||
BraceStructLiftImpl! {
|
||||
impl<'a, 'tcx, T> Lift<'tcx> for Normalize<'a, T> {
|
||||
type Lifted = Normalize<'tcx, T::Lifted>;
|
||||
param_env,
|
||||
value,
|
||||
} where T: Lift<'tcx>,
|
||||
}
|
||||
|
||||
impl_stable_hash_for! {
|
||||
impl<'tcx, T> for struct Normalize<'tcx, T> {
|
||||
param_env, value
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use infer::canonical::{Canonical, CanonicalizedQueryResult};
|
||||
use infer::canonical::{Canonical, CanonicalizedQueryResult, QueryResult};
|
||||
use ty::{ParamEnv, Predicate, TyCtxt};
|
||||
|
||||
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
|
||||
|
@ -18,11 +18,11 @@ pub struct ProvePredicate<'tcx> {
|
|||
}
|
||||
|
||||
impl<'tcx> ProvePredicate<'tcx> {
|
||||
pub fn new(
|
||||
param_env: ParamEnv<'tcx>,
|
||||
predicate: Predicate<'tcx>,
|
||||
) -> Self {
|
||||
ProvePredicate { param_env, predicate }
|
||||
pub fn new(param_env: ParamEnv<'tcx>, predicate: Predicate<'tcx>) -> Self {
|
||||
ProvePredicate {
|
||||
param_env,
|
||||
predicate,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,6 +43,12 @@ impl<'gcx: 'tcx, 'tcx> super::QueryTypeOp<'gcx, 'tcx> for ProvePredicate<'tcx> {
|
|||
) -> CanonicalizedQueryResult<'gcx, ()> {
|
||||
tcx.type_op_prove_predicate(canonicalized).unwrap()
|
||||
}
|
||||
|
||||
fn upcast_result(
|
||||
v: &'a CanonicalizedQueryResult<'gcx, ()>,
|
||||
) -> &'a Canonical<'tcx, QueryResult<'tcx, ()>> {
|
||||
v
|
||||
}
|
||||
}
|
||||
|
||||
BraceStructTypeFoldableImpl! {
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use infer::canonical::{Canonical, CanonicalizedQueryResult};
|
||||
use infer::canonical::{Canonical, CanonicalizedQueryResult, QueryResult};
|
||||
use ty::{ParamEnv, Ty, TyCtxt};
|
||||
|
||||
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
|
||||
|
@ -49,6 +49,12 @@ impl<'gcx: 'tcx, 'tcx> super::QueryTypeOp<'gcx, 'tcx> for Subtype<'tcx> {
|
|||
) -> CanonicalizedQueryResult<'gcx, ()> {
|
||||
tcx.type_op_subtype(canonicalized).unwrap()
|
||||
}
|
||||
|
||||
fn upcast_result(
|
||||
v: &'a CanonicalizedQueryResult<'gcx, ()>,
|
||||
) -> &'a Canonical<'tcx, QueryResult<'tcx, ()>> {
|
||||
v
|
||||
}
|
||||
}
|
||||
|
||||
BraceStructTypeFoldableImpl! {
|
||||
|
|
|
@ -14,7 +14,7 @@ use hir::def_id::{CrateNum, DefId, DefIndex};
|
|||
use mir::interpret::{GlobalId, ConstValue};
|
||||
use traits::query::{
|
||||
CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal, CanonicalTypeOpEqGoal,
|
||||
CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpSubtypeGoal,
|
||||
CanonicalTypeOpNormalizeGoal, CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpSubtypeGoal,
|
||||
};
|
||||
use ty::{self, ParamEnvAnd, Ty, TyCtxt};
|
||||
use ty::subst::Substs;
|
||||
|
@ -123,6 +123,36 @@ impl<'tcx> QueryDescription<'tcx> for queries::type_op_prove_predicate<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::type_op_normalize_ty<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, goal: CanonicalTypeOpNormalizeGoal<'tcx, Ty<'tcx>>) -> String {
|
||||
format!("normalizing `{:?}`", goal)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::type_op_normalize_predicate<'tcx> {
|
||||
fn describe(
|
||||
_tcx: TyCtxt,
|
||||
goal: CanonicalTypeOpNormalizeGoal<'tcx, ty::Predicate<'tcx>>,
|
||||
) -> String {
|
||||
format!("normalizing `{:?}`", goal)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::type_op_normalize_poly_fn_sig<'tcx> {
|
||||
fn describe(
|
||||
_tcx: TyCtxt,
|
||||
goal: CanonicalTypeOpNormalizeGoal<'tcx, ty::PolyFnSig<'tcx>>,
|
||||
) -> String {
|
||||
format!("normalizing `{:?}`", goal)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::type_op_normalize_fn_sig<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, goal: CanonicalTypeOpNormalizeGoal<'tcx, ty::FnSig<'tcx>>) -> String {
|
||||
format!("normalizing `{:?}`", goal)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::is_copy_raw<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> String {
|
||||
format!("computing whether `{}` is `Copy`", env.value)
|
||||
|
|
|
@ -35,7 +35,7 @@ use session::config::OutputFilenames;
|
|||
use traits::{self, Vtable};
|
||||
use traits::query::{CanonicalPredicateGoal, CanonicalProjectionGoal,
|
||||
CanonicalTyGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpSubtypeGoal,
|
||||
CanonicalTypeOpProvePredicateGoal, NoSolution};
|
||||
CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpNormalizeGoal, NoSolution};
|
||||
use traits::query::dropck_outlives::{DtorckConstraint, DropckOutlivesResult};
|
||||
use traits::query::normalize::NormalizationResult;
|
||||
use traits::specialization_graph;
|
||||
|
@ -447,7 +447,7 @@ define_queries! { <'tcx>
|
|||
CanonicalPredicateGoal<'tcx>
|
||||
) -> Result<traits::EvaluationResult, traits::OverflowError>,
|
||||
|
||||
/// Do not call this query directly: invoke `infcx.eq()` instead.
|
||||
/// Do not call this query directly: part of the `Eq` type-op
|
||||
[] fn type_op_eq: TypeOpEq(
|
||||
CanonicalTypeOpEqGoal<'tcx>
|
||||
) -> Result<
|
||||
|
@ -455,7 +455,7 @@ define_queries! { <'tcx>
|
|||
NoSolution,
|
||||
>,
|
||||
|
||||
/// Do not call this query directly: invoke `infcx.at().subtype()` instead.
|
||||
/// Do not call this query directly: part of the `Subtype` type-op
|
||||
[] fn type_op_subtype: TypeOpSubtype(
|
||||
CanonicalTypeOpSubtypeGoal<'tcx>
|
||||
) -> Result<
|
||||
|
@ -463,7 +463,7 @@ define_queries! { <'tcx>
|
|||
NoSolution,
|
||||
>,
|
||||
|
||||
/// Do not call this query directly: invoke `infcx.at().prove_predicates()` instead.
|
||||
/// Do not call this query directly: part of the `ProvePredicate` type-op
|
||||
[] fn type_op_prove_predicate: TypeOpProvePredicate(
|
||||
CanonicalTypeOpProvePredicateGoal<'tcx>
|
||||
) -> Result<
|
||||
|
@ -471,6 +471,38 @@ define_queries! { <'tcx>
|
|||
NoSolution,
|
||||
>,
|
||||
|
||||
/// Do not call this query directly: part of the `Normalize` type-op
|
||||
[] fn type_op_normalize_ty: TypeOpNormalizeTy(
|
||||
CanonicalTypeOpNormalizeGoal<'tcx, Ty<'tcx>>
|
||||
) -> Result<
|
||||
Lrc<Canonical<'tcx, canonical::QueryResult<'tcx, Ty<'tcx>>>>,
|
||||
NoSolution,
|
||||
>,
|
||||
|
||||
/// Do not call this query directly: part of the `Normalize` type-op
|
||||
[] fn type_op_normalize_predicate: TypeOpNormalizePredicate(
|
||||
CanonicalTypeOpNormalizeGoal<'tcx, ty::Predicate<'tcx>>
|
||||
) -> Result<
|
||||
Lrc<Canonical<'tcx, canonical::QueryResult<'tcx, ty::Predicate<'tcx>>>>,
|
||||
NoSolution,
|
||||
>,
|
||||
|
||||
/// Do not call this query directly: part of the `Normalize` type-op
|
||||
[] fn type_op_normalize_poly_fn_sig: TypeOpNormalizePolyFnSig(
|
||||
CanonicalTypeOpNormalizeGoal<'tcx, ty::PolyFnSig<'tcx>>
|
||||
) -> Result<
|
||||
Lrc<Canonical<'tcx, canonical::QueryResult<'tcx, ty::PolyFnSig<'tcx>>>>,
|
||||
NoSolution,
|
||||
>,
|
||||
|
||||
/// Do not call this query directly: part of the `Normalize` type-op
|
||||
[] fn type_op_normalize_fn_sig: TypeOpNormalizeFnSig(
|
||||
CanonicalTypeOpNormalizeGoal<'tcx, ty::FnSig<'tcx>>
|
||||
) -> Result<
|
||||
Lrc<Canonical<'tcx, canonical::QueryResult<'tcx, ty::FnSig<'tcx>>>>,
|
||||
NoSolution,
|
||||
>,
|
||||
|
||||
[] fn substitute_normalize_and_test_predicates:
|
||||
substitute_normalize_and_test_predicates_node((DefId, &'tcx Substs<'tcx>)) -> bool,
|
||||
|
||||
|
|
|
@ -1031,6 +1031,10 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
|
|||
DepKind::TypeOpEq |
|
||||
DepKind::TypeOpSubtype |
|
||||
DepKind::TypeOpProvePredicate |
|
||||
DepKind::TypeOpNormalizeTy |
|
||||
DepKind::TypeOpNormalizePredicate |
|
||||
DepKind::TypeOpNormalizePolyFnSig |
|
||||
DepKind::TypeOpNormalizeFnSig |
|
||||
DepKind::SubstituteNormalizeAndTestPredicates |
|
||||
DepKind::InstanceDefSizeEstimate |
|
||||
DepKind::ProgramClausesForEnv |
|
||||
|
|
|
@ -286,9 +286,10 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
|
|||
|
||||
let instantiated_predicates =
|
||||
tcx.predicates_of(def_id).instantiate(tcx, substs);
|
||||
let predicates =
|
||||
type_checker.normalize(instantiated_predicates.predicates, location);
|
||||
type_checker.prove_predicates(predicates, location);
|
||||
type_checker.normalize_and_prove_instantiated_predicates(
|
||||
instantiated_predicates,
|
||||
location,
|
||||
);
|
||||
}
|
||||
|
||||
value.ty
|
||||
|
@ -1526,9 +1527,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
|||
AggregateKind::Array(_) | AggregateKind::Tuple => ty::InstantiatedPredicates::empty(),
|
||||
};
|
||||
|
||||
let predicates = self.normalize(instantiated_predicates.predicates, location);
|
||||
debug!("prove_aggregate_predicates: predicates={:?}", predicates);
|
||||
self.prove_predicates(predicates, location);
|
||||
self.normalize_and_prove_instantiated_predicates(instantiated_predicates, location);
|
||||
}
|
||||
|
||||
fn prove_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>, location: Location) {
|
||||
|
@ -1540,12 +1539,22 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
|||
);
|
||||
}
|
||||
|
||||
fn prove_predicates(
|
||||
fn normalize_and_prove_instantiated_predicates(
|
||||
&mut self,
|
||||
predicates: impl IntoIterator<Item = ty::Predicate<'tcx>> + Clone,
|
||||
instantiated_predicates: ty::InstantiatedPredicates<'tcx>,
|
||||
location: Location,
|
||||
) {
|
||||
for predicate in instantiated_predicates.predicates {
|
||||
let predicate = self.normalize(predicate, location);
|
||||
self.prove_predicate(predicate, location);
|
||||
}
|
||||
}
|
||||
|
||||
fn prove_predicates(
|
||||
&mut self,
|
||||
predicates: impl IntoIterator<Item = ty::Predicate<'tcx>>,
|
||||
location: Location,
|
||||
) {
|
||||
for predicate in predicates {
|
||||
debug!(
|
||||
"prove_predicates(predicate={:?}, location={:?})",
|
||||
|
@ -1560,6 +1569,19 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn prove_predicate(&mut self, predicate: ty::Predicate<'tcx>, location: Location) {
|
||||
debug!(
|
||||
"prove_predicate(predicate={:?}, location={:?})",
|
||||
predicate, location,
|
||||
);
|
||||
|
||||
let param_env = self.param_env;
|
||||
self.fully_perform_op(
|
||||
location.at_self(),
|
||||
type_op::prove_predicate::ProvePredicate::new(param_env, predicate),
|
||||
).unwrap()
|
||||
}
|
||||
|
||||
fn typeck_mir(&mut self, mir: &Mir<'tcx>) {
|
||||
self.last_span = mir.span;
|
||||
debug!("run_on_mir: {:?}", mir.span);
|
||||
|
@ -1588,7 +1610,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
|||
|
||||
fn normalize<T>(&mut self, value: T, location: impl ToLocations) -> T
|
||||
where
|
||||
T: fmt::Debug + TypeFoldable<'tcx>,
|
||||
T: type_op::normalize::Normalizable<'gcx, 'tcx>,
|
||||
{
|
||||
debug!("normalize(value={:?}, location={:?})", value, location);
|
||||
let param_env = self.param_env;
|
||||
|
|
|
@ -35,6 +35,7 @@ mod normalize_projection_ty;
|
|||
mod normalize_erasing_regions;
|
||||
pub mod lowering;
|
||||
mod type_op_eq;
|
||||
mod type_op_normalize;
|
||||
mod type_op_prove_predicate;
|
||||
mod type_op_subtype;
|
||||
|
||||
|
@ -53,6 +54,10 @@ pub fn provide(p: &mut Providers) {
|
|||
type_op_eq: type_op_eq::type_op_eq,
|
||||
type_op_prove_predicate: type_op_prove_predicate::type_op_prove_predicate,
|
||||
type_op_subtype: type_op_subtype::type_op_subtype,
|
||||
type_op_normalize_ty: type_op_normalize::type_op_normalize_ty,
|
||||
type_op_normalize_predicate: type_op_normalize::type_op_normalize_predicate,
|
||||
type_op_normalize_fn_sig: type_op_normalize::type_op_normalize_fn_sig,
|
||||
type_op_normalize_poly_fn_sig: type_op_normalize::type_op_normalize_poly_fn_sig,
|
||||
..*p
|
||||
};
|
||||
}
|
||||
|
|
68
src/librustc_traits/type_op_normalize.rs
Normal file
68
src/librustc_traits/type_op_normalize.rs
Normal file
|
@ -0,0 +1,68 @@
|
|||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use rustc::infer::canonical::{Canonical, QueryResult};
|
||||
use rustc::infer::InferCtxt;
|
||||
use rustc::traits::query::type_op::normalize::Normalize;
|
||||
use rustc::traits::query::NoSolution;
|
||||
use rustc::traits::{FulfillmentContext, Normalized, ObligationCause};
|
||||
use rustc::ty::{FnSig, Lift, PolyFnSig, Predicate, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use std::fmt;
|
||||
use syntax::codemap::DUMMY_SP;
|
||||
|
||||
fn type_op_normalize<'gcx, 'tcx, T>(
|
||||
infcx: &InferCtxt<'_, 'gcx, 'tcx>,
|
||||
canonicalized: Canonical<'tcx, Normalize<'tcx, T>>,
|
||||
) -> Result<Lrc<Canonical<'gcx, QueryResult<'gcx, <T as Lift<'gcx>>::Lifted>>>, NoSolution>
|
||||
where
|
||||
T: fmt::Debug + TypeFoldable<'tcx> + Lift<'gcx>,
|
||||
{
|
||||
let (Normalize { param_env, value }, canonical_inference_vars) =
|
||||
infcx.instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &canonicalized);
|
||||
let fulfill_cx = &mut FulfillmentContext::new();
|
||||
let Normalized { value, obligations } = infcx
|
||||
.at(&ObligationCause::dummy(), param_env)
|
||||
.normalize(&value)?;
|
||||
fulfill_cx.register_predicate_obligations(infcx, obligations);
|
||||
infcx.make_canonicalized_query_result(canonical_inference_vars, value, fulfill_cx)
|
||||
}
|
||||
|
||||
crate fn type_op_normalize_ty<'tcx>(
|
||||
tcx: TyCtxt<'_, 'tcx, 'tcx>,
|
||||
canonicalized: Canonical<'tcx, Normalize<'tcx, Ty<'tcx>>>,
|
||||
) -> Result<Lrc<Canonical<'tcx, QueryResult<'tcx, Ty<'tcx>>>>, NoSolution> {
|
||||
tcx.infer_ctxt()
|
||||
.enter(|ref infcx| type_op_normalize(infcx, canonicalized))
|
||||
}
|
||||
|
||||
crate fn type_op_normalize_predicate<'tcx>(
|
||||
tcx: TyCtxt<'_, 'tcx, 'tcx>,
|
||||
canonicalized: Canonical<'tcx, Normalize<'tcx, Predicate<'tcx>>>,
|
||||
) -> Result<Lrc<Canonical<'tcx, QueryResult<'tcx, Predicate<'tcx>>>>, NoSolution> {
|
||||
tcx.infer_ctxt()
|
||||
.enter(|ref infcx| type_op_normalize(infcx, canonicalized))
|
||||
}
|
||||
|
||||
crate fn type_op_normalize_fn_sig<'tcx>(
|
||||
tcx: TyCtxt<'_, 'tcx, 'tcx>,
|
||||
canonicalized: Canonical<'tcx, Normalize<'tcx, FnSig<'tcx>>>,
|
||||
) -> Result<Lrc<Canonical<'tcx, QueryResult<'tcx, FnSig<'tcx>>>>, NoSolution> {
|
||||
tcx.infer_ctxt()
|
||||
.enter(|ref infcx| type_op_normalize(infcx, canonicalized))
|
||||
}
|
||||
|
||||
crate fn type_op_normalize_poly_fn_sig<'tcx>(
|
||||
tcx: TyCtxt<'_, 'tcx, 'tcx>,
|
||||
canonicalized: Canonical<'tcx, Normalize<'tcx, PolyFnSig<'tcx>>>,
|
||||
) -> Result<Lrc<Canonical<'tcx, QueryResult<'tcx, PolyFnSig<'tcx>>>>, NoSolution> {
|
||||
tcx.infer_ctxt()
|
||||
.enter(|ref infcx| type_op_normalize(infcx, canonicalized))
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue