提交 2a0b3d62 编写于 作者: N Niko Matsakis

introduce `Normalizable` trait for things directly normalizable

上级 de7e941e
...@@ -72,9 +72,10 @@ ...@@ -72,9 +72,10 @@
use syntax_pos::symbol::InternedString; use syntax_pos::symbol::InternedString;
use traits::query::{ use traits::query::{
CanonicalProjectionGoal, CanonicalTyGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpSubtypeGoal, 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; use ty::subst::Substs;
// erase!() just makes tokens go away. It's used to specify which macro argument // erase!() just makes tokens go away. It's used to specify which macro argument
...@@ -652,6 +653,10 @@ pub fn fingerprint_needed_for_crate_hash(self) -> bool { ...@@ -652,6 +653,10 @@ pub fn fingerprint_needed_for_crate_hash(self) -> bool {
[] TypeOpEq(CanonicalTypeOpEqGoal<'tcx>), [] TypeOpEq(CanonicalTypeOpEqGoal<'tcx>),
[] TypeOpSubtype(CanonicalTypeOpSubtypeGoal<'tcx>), [] TypeOpSubtype(CanonicalTypeOpSubtypeGoal<'tcx>),
[] TypeOpProvePredicate(CanonicalTypeOpProvePredicateGoal<'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>) }, [] SubstituteNormalizeAndTestPredicates { key: (DefId, &'tcx Substs<'tcx>) },
......
...@@ -41,6 +41,9 @@ ...@@ -41,6 +41,9 @@
pub type CanonicalTypeOpProvePredicateGoal<'tcx> = pub type CanonicalTypeOpProvePredicateGoal<'tcx> =
Canonical<'tcx, type_op::prove_predicate::ProvePredicate<'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)] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct NoSolution; pub struct NoSolution;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use infer::canonical::{Canonical, CanonicalizedQueryResult}; use infer::canonical::{Canonical, CanonicalizedQueryResult, QueryResult};
use ty::{self, ParamEnv, Ty, TyCtxt}; use ty::{self, ParamEnv, Ty, TyCtxt};
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
...@@ -45,6 +45,12 @@ fn perform_query( ...@@ -45,6 +45,12 @@ fn perform_query(
) -> CanonicalizedQueryResult<'gcx, ()> { ) -> CanonicalizedQueryResult<'gcx, ()> {
tcx.type_op_eq(canonicalized).unwrap() tcx.type_op_eq(canonicalized).unwrap()
} }
fn upcast_result(
v: &'a CanonicalizedQueryResult<'gcx, ()>,
) -> &'a Canonical<'tcx, QueryResult<'tcx, ()>> {
v
}
} }
BraceStructTypeFoldableImpl! { BraceStructTypeFoldableImpl! {
......
...@@ -9,15 +9,17 @@ ...@@ -9,15 +9,17 @@
// except according to those terms. // except according to those terms.
use infer::canonical::query_result; 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 infer::{InferCtxt, InferOk, InferResult};
use std::fmt;
use std::rc::Rc;
use syntax::codemap::DUMMY_SP;
use traits::{ObligationCause, TraitEngine}; use traits::{ObligationCause, TraitEngine};
use ty::error::TypeError; use ty::error::TypeError;
use ty::fold::TypeFoldable; use ty::fold::TypeFoldable;
use ty::{Lift, ParamEnv, TyCtxt}; use ty::{Lift, ParamEnv, TyCtxt};
use std::fmt;
use std::rc::Rc;
use syntax::codemap::DUMMY_SP;
pub mod custom; pub mod custom;
pub mod eq; pub mod eq;
...@@ -98,17 +100,12 @@ fn fully_perform_nontrivial( ...@@ -98,17 +100,12 @@ fn fully_perform_nontrivial(
} }
} }
type Lifted<'gcx, T> = <T as Lift<'gcx>>::Lifted;
pub trait QueryTypeOp<'gcx: 'tcx, 'tcx>: TypeFoldable<'tcx> + Lift<'gcx> { pub trait QueryTypeOp<'gcx: 'tcx, 'tcx>: TypeFoldable<'tcx> + Lift<'gcx> {
type QueryResult: TypeFoldable<'tcx> + Lift<'gcx>; type QueryResult: TypeFoldable<'tcx> + Lift<'gcx>;
/// Micro-optimization: returns `Ok(x)` if we can trivially /// Micro-optimization: returns `Ok(x)` if we can trivially
/// produce the output, else returns `Err(self)` back. /// produce the output, else returns `Err(self)` back.
fn trivial_noop( fn trivial_noop(self, tcx: TyCtxt<'_, 'gcx, 'tcx>) -> Result<Self::QueryResult, Self>;
self,
tcx: TyCtxt<'_, 'gcx, 'tcx>,
) -> Result<Lifted<'gcx, Self::QueryResult>, Self>;
fn param_env(&self) -> ParamEnv<'tcx>; fn param_env(&self) -> ParamEnv<'tcx>;
...@@ -116,14 +113,24 @@ fn perform_query( ...@@ -116,14 +113,24 @@ fn perform_query(
tcx: TyCtxt<'_, 'gcx, 'tcx>, tcx: TyCtxt<'_, 'gcx, 'tcx>,
canonicalized: Canonicalized<'gcx, Self>, canonicalized: Canonicalized<'gcx, Self>,
) -> CanonicalizedQueryResult<'gcx, Self::QueryResult>; ) -> 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 impl<'gcx: 'tcx, 'tcx, Q> TypeOp<'gcx, 'tcx> for Q
where where
Q: QueryTypeOp<'gcx, 'tcx>, 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> { fn trivial_noop(self, tcx: TyCtxt<'_, 'gcx, 'tcx>) -> Result<Self::Output, Self> {
QueryTypeOp::trivial_noop(self, tcx) QueryTypeOp::trivial_noop(self, tcx)
...@@ -152,7 +159,7 @@ fn perform(self, infcx: &InferCtxt<'_, 'gcx, 'tcx>) -> InferResult<'tcx, Self::O ...@@ -152,7 +159,7 @@ fn perform(self, infcx: &InferCtxt<'_, 'gcx, 'tcx>) -> InferResult<'tcx, Self::O
&ObligationCause::dummy(), &ObligationCause::dummy(),
param_env, param_env,
&canonical_var_values, &canonical_var_values,
&canonical_result, Q::upcast_result(&canonical_result),
) )
} }
} }
...@@ -8,17 +8,15 @@ ...@@ -8,17 +8,15 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use infer::{InferCtxt, InferOk, InferResult}; use infer::canonical::{Canonical, Canonicalized, CanonicalizedQueryResult, QueryResult};
use traits::query::NoSolution;
use traits::{Normalized, ObligationCause};
use ty::fold::TypeFoldable;
use ty::{ParamEnv, TyCtxt};
use std::fmt; 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> { pub struct Normalize<'tcx, T> {
param_env: ParamEnv<'tcx>, pub param_env: ParamEnv<'tcx>,
value: T, pub value: T,
} }
impl<'tcx, T> Normalize<'tcx, T> impl<'tcx, T> Normalize<'tcx, T>
...@@ -30,13 +28,13 @@ pub fn new(param_env: ParamEnv<'tcx>, value: T) -> Self { ...@@ -30,13 +28,13 @@ pub fn new(param_env: ParamEnv<'tcx>, value: T) -> Self {
} }
} }
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 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() { if !self.value.has_projections() {
Ok(self.value) Ok(self.value)
} else { } else {
...@@ -44,13 +42,126 @@ fn trivial_noop(self, _tcx: TyCtxt<'_, 'gcx, 'tcx>) -> Result<Self::Output, Self ...@@ -44,13 +42,126 @@ fn trivial_noop(self, _tcx: TyCtxt<'_, 'gcx, 'tcx>) -> Result<Self::Output, Self
} }
} }
fn perform(self, infcx: &InferCtxt<'_, 'gcx, 'tcx>) -> InferResult<'tcx, Self::Output> { fn param_env(&self) -> ParamEnv<'tcx> {
let Normalized { value, obligations } = infcx self.param_env
.at(&ObligationCause::dummy(), self.param_env) }
.normalize(&self.value)
.unwrap_or_else(|NoSolution| { fn perform_query(
bug!("normalization of `{:?}` failed", self.value,); tcx: TyCtxt<'_, 'gcx, 'tcx>,
}); canonicalized: Canonicalized<'gcx, Self>,
Ok(InferOk { value, obligations }) ) -> 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 @@ ...@@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use infer::canonical::{Canonical, CanonicalizedQueryResult}; use infer::canonical::{Canonical, CanonicalizedQueryResult, QueryResult};
use ty::{ParamEnv, Predicate, TyCtxt}; use ty::{ParamEnv, Predicate, TyCtxt};
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
...@@ -18,11 +18,11 @@ pub struct ProvePredicate<'tcx> { ...@@ -18,11 +18,11 @@ pub struct ProvePredicate<'tcx> {
} }
impl<'tcx> ProvePredicate<'tcx> { impl<'tcx> ProvePredicate<'tcx> {
pub fn new( pub fn new(param_env: ParamEnv<'tcx>, predicate: Predicate<'tcx>) -> Self {
param_env: ParamEnv<'tcx>, ProvePredicate {
predicate: Predicate<'tcx>, param_env,
) -> Self { predicate,
ProvePredicate { param_env, predicate } }
} }
} }
...@@ -43,6 +43,12 @@ fn perform_query( ...@@ -43,6 +43,12 @@ fn perform_query(
) -> CanonicalizedQueryResult<'gcx, ()> { ) -> CanonicalizedQueryResult<'gcx, ()> {
tcx.type_op_prove_predicate(canonicalized).unwrap() tcx.type_op_prove_predicate(canonicalized).unwrap()
} }
fn upcast_result(
v: &'a CanonicalizedQueryResult<'gcx, ()>,
) -> &'a Canonical<'tcx, QueryResult<'tcx, ()>> {
v
}
} }
BraceStructTypeFoldableImpl! { BraceStructTypeFoldableImpl! {
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use infer::canonical::{Canonical, CanonicalizedQueryResult}; use infer::canonical::{Canonical, CanonicalizedQueryResult, QueryResult};
use ty::{ParamEnv, Ty, TyCtxt}; use ty::{ParamEnv, Ty, TyCtxt};
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
...@@ -49,6 +49,12 @@ fn perform_query( ...@@ -49,6 +49,12 @@ fn perform_query(
) -> CanonicalizedQueryResult<'gcx, ()> { ) -> CanonicalizedQueryResult<'gcx, ()> {
tcx.type_op_subtype(canonicalized).unwrap() tcx.type_op_subtype(canonicalized).unwrap()
} }
fn upcast_result(
v: &'a CanonicalizedQueryResult<'gcx, ()>,
) -> &'a Canonical<'tcx, QueryResult<'tcx, ()>> {
v
}
} }
BraceStructTypeFoldableImpl! { BraceStructTypeFoldableImpl! {
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
use mir::interpret::{GlobalId, ConstValue}; use mir::interpret::{GlobalId, ConstValue};
use traits::query::{ use traits::query::{
CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal, CanonicalTypeOpEqGoal, CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal, CanonicalTypeOpEqGoal,
CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpSubtypeGoal, CanonicalTypeOpNormalizeGoal, CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpSubtypeGoal,
}; };
use ty::{self, ParamEnvAnd, Ty, TyCtxt}; use ty::{self, ParamEnvAnd, Ty, TyCtxt};
use ty::subst::Substs; use ty::subst::Substs;
...@@ -123,6 +123,36 @@ fn describe(_tcx: TyCtxt, goal: CanonicalTypeOpProvePredicateGoal<'tcx>) -> Stri ...@@ -123,6 +123,36 @@ fn describe(_tcx: TyCtxt, goal: CanonicalTypeOpProvePredicateGoal<'tcx>) -> Stri
} }
} }
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> { impl<'tcx> QueryDescription<'tcx> for queries::is_copy_raw<'tcx> {
fn describe(_tcx: TyCtxt, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> String { fn describe(_tcx: TyCtxt, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> String {
format!("computing whether `{}` is `Copy`", env.value) format!("computing whether `{}` is `Copy`", env.value)
......
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
use traits::{self, Vtable}; use traits::{self, Vtable};
use traits::query::{CanonicalPredicateGoal, CanonicalProjectionGoal, use traits::query::{CanonicalPredicateGoal, CanonicalProjectionGoal,
CanonicalTyGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpSubtypeGoal, CanonicalTyGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpSubtypeGoal,
CanonicalTypeOpProvePredicateGoal, NoSolution}; CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpNormalizeGoal, NoSolution};
use traits::query::dropck_outlives::{DtorckConstraint, DropckOutlivesResult}; use traits::query::dropck_outlives::{DtorckConstraint, DropckOutlivesResult};
use traits::query::normalize::NormalizationResult; use traits::query::normalize::NormalizationResult;
use traits::specialization_graph; use traits::specialization_graph;
...@@ -447,7 +447,7 @@ ...@@ -447,7 +447,7 @@
CanonicalPredicateGoal<'tcx> CanonicalPredicateGoal<'tcx>
) -> Result<traits::EvaluationResult, traits::OverflowError>, ) -> 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( [] fn type_op_eq: TypeOpEq(
CanonicalTypeOpEqGoal<'tcx> CanonicalTypeOpEqGoal<'tcx>
) -> Result< ) -> Result<
...@@ -455,7 +455,7 @@ ...@@ -455,7 +455,7 @@
NoSolution, 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( [] fn type_op_subtype: TypeOpSubtype(
CanonicalTypeOpSubtypeGoal<'tcx> CanonicalTypeOpSubtypeGoal<'tcx>
) -> Result< ) -> Result<
...@@ -463,7 +463,7 @@ ...@@ -463,7 +463,7 @@
NoSolution, 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( [] fn type_op_prove_predicate: TypeOpProvePredicate(
CanonicalTypeOpProvePredicateGoal<'tcx> CanonicalTypeOpProvePredicateGoal<'tcx>
) -> Result< ) -> Result<
...@@ -471,6 +471,38 @@ ...@@ -471,6 +471,38 @@
NoSolution, 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: [] fn substitute_normalize_and_test_predicates:
substitute_normalize_and_test_predicates_node((DefId, &'tcx Substs<'tcx>)) -> bool, 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>, ...@@ -1031,6 +1031,10 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
DepKind::TypeOpEq | DepKind::TypeOpEq |
DepKind::TypeOpSubtype | DepKind::TypeOpSubtype |
DepKind::TypeOpProvePredicate | DepKind::TypeOpProvePredicate |
DepKind::TypeOpNormalizeTy |
DepKind::TypeOpNormalizePredicate |
DepKind::TypeOpNormalizePolyFnSig |
DepKind::TypeOpNormalizeFnSig |
DepKind::SubstituteNormalizeAndTestPredicates | DepKind::SubstituteNormalizeAndTestPredicates |
DepKind::InstanceDefSizeEstimate | DepKind::InstanceDefSizeEstimate |
DepKind::ProgramClausesForEnv | DepKind::ProgramClausesForEnv |
......
...@@ -286,9 +286,10 @@ fn sanitize_constant(&mut self, constant: &Constant<'tcx>, location: Location) { ...@@ -286,9 +286,10 @@ fn sanitize_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
let instantiated_predicates = let instantiated_predicates =
tcx.predicates_of(def_id).instantiate(tcx, substs); tcx.predicates_of(def_id).instantiate(tcx, substs);
let predicates = type_checker.normalize_and_prove_instantiated_predicates(
type_checker.normalize(instantiated_predicates.predicates, location); instantiated_predicates,
type_checker.prove_predicates(predicates, location); location,
);
} }
value.ty value.ty
...@@ -1526,9 +1527,7 @@ fn prove_aggregate_predicates( ...@@ -1526,9 +1527,7 @@ fn prove_aggregate_predicates(
AggregateKind::Array(_) | AggregateKind::Tuple => ty::InstantiatedPredicates::empty(), AggregateKind::Array(_) | AggregateKind::Tuple => ty::InstantiatedPredicates::empty(),
}; };
let predicates = self.normalize(instantiated_predicates.predicates, location); self.normalize_and_prove_instantiated_predicates(instantiated_predicates, location);
debug!("prove_aggregate_predicates: predicates={:?}", predicates);
self.prove_predicates(predicates, location);
} }
fn prove_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>, location: Location) { fn prove_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>, location: Location) {
...@@ -1540,12 +1539,22 @@ fn prove_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>, location: Location) ...@@ -1540,12 +1539,22 @@ fn prove_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>, location: Location)
); );
} }
fn prove_predicates( fn normalize_and_prove_instantiated_predicates(
&mut self, &mut self,
predicates: impl IntoIterator<Item = ty::Predicate<'tcx>> + Clone, instantiated_predicates: ty::InstantiatedPredicates<'tcx>,
location: Location, 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 { for predicate in predicates {
debug!( debug!(
"prove_predicates(predicate={:?}, location={:?})", "prove_predicates(predicate={:?}, location={:?})",
...@@ -1560,6 +1569,19 @@ fn prove_predicates( ...@@ -1560,6 +1569,19 @@ fn prove_predicates(
} }
} }
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>) { fn typeck_mir(&mut self, mir: &Mir<'tcx>) {
self.last_span = mir.span; self.last_span = mir.span;
debug!("run_on_mir: {:?}", mir.span); debug!("run_on_mir: {:?}", mir.span);
...@@ -1588,7 +1610,7 @@ fn typeck_mir(&mut self, mir: &Mir<'tcx>) { ...@@ -1588,7 +1610,7 @@ fn typeck_mir(&mut self, mir: &Mir<'tcx>) {
fn normalize<T>(&mut self, value: T, location: impl ToLocations) -> T fn normalize<T>(&mut self, value: T, location: impl ToLocations) -> T
where where
T: fmt::Debug + TypeFoldable<'tcx>, T: type_op::normalize::Normalizable<'gcx, 'tcx>,
{ {
debug!("normalize(value={:?}, location={:?})", value, location); debug!("normalize(value={:?}, location={:?})", value, location);
let param_env = self.param_env; let param_env = self.param_env;
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
mod normalize_erasing_regions; mod normalize_erasing_regions;
pub mod lowering; pub mod lowering;
mod type_op_eq; mod type_op_eq;
mod type_op_normalize;
mod type_op_prove_predicate; mod type_op_prove_predicate;
mod type_op_subtype; mod type_op_subtype;
...@@ -53,6 +54,10 @@ pub fn provide(p: &mut Providers) { ...@@ -53,6 +54,10 @@ pub fn provide(p: &mut Providers) {
type_op_eq: type_op_eq::type_op_eq, type_op_eq: type_op_eq::type_op_eq,
type_op_prove_predicate: type_op_prove_predicate::type_op_prove_predicate, type_op_prove_predicate: type_op_prove_predicate::type_op_prove_predicate,
type_op_subtype: type_op_subtype::type_op_subtype, 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 ..*p
}; };
} }
// 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))
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册