diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2018-06-11 11:56:06 -0400 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2018-06-26 10:59:40 -0400 |
| commit | 2a0b3d6224768119f1d2e9850488c3d184362c1c (patch) | |
| tree | d4d7a21fe7af5c37d28bdc6e30b894ad6433b038 /src/librustc/traits | |
| parent | de7e941e4eafdc73f4d68c6cdbb8c49224e5a90b (diff) | |
| download | rust-2a0b3d6224768119f1d2e9850488c3d184362c1c.tar.gz rust-2a0b3d6224768119f1d2e9850488c3d184362c1c.zip | |
introduce `Normalizable` trait for things directly normalizable
Diffstat (limited to 'src/librustc/traits')
| -rw-r--r-- | src/librustc/traits/query/mod.rs | 3 | ||||
| -rw-r--r-- | src/librustc/traits/query/type_op/eq.rs | 8 | ||||
| -rw-r--r-- | src/librustc/traits/query/type_op/mod.rs | 33 | ||||
| -rw-r--r-- | src/librustc/traits/query/type_op/normalize.rs | 151 | ||||
| -rw-r--r-- | src/librustc/traits/query/type_op/prove_predicate.rs | 18 | ||||
| -rw-r--r-- | src/librustc/traits/query/type_op/subtype.rs | 8 |
6 files changed, 180 insertions, 41 deletions
diff --git a/src/librustc/traits/query/mod.rs b/src/librustc/traits/query/mod.rs index aa0b524af06..dddd05db668 100644 --- a/src/librustc/traits/query/mod.rs +++ b/src/librustc/traits/query/mod.rs @@ -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; diff --git a/src/librustc/traits/query/type_op/eq.rs b/src/librustc/traits/query/type_op/eq.rs index 8925fa12f03..348283d1af3 100644 --- a/src/librustc/traits/query/type_op/eq.rs +++ b/src/librustc/traits/query/type_op/eq.rs @@ -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! { diff --git a/src/librustc/traits/query/type_op/mod.rs b/src/librustc/traits/query/type_op/mod.rs index 6cda9ea1518..cddb648f04f 100644 --- a/src/librustc/traits/query/type_op/mod.rs +++ b/src/librustc/traits/query/type_op/mod.rs @@ -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), ) } } diff --git a/src/librustc/traits/query/type_op/normalize.rs b/src/librustc/traits/query/type_op/normalize.rs index a363f6f213c..d63997fe40c 100644 --- a/src/librustc/traits/query/type_op/normalize.rs +++ b/src/librustc/traits/query/type_op/normalize.rs @@ -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 } } diff --git a/src/librustc/traits/query/type_op/prove_predicate.rs b/src/librustc/traits/query/type_op/prove_predicate.rs index 193dd1c7c84..866ebd0cc12 100644 --- a/src/librustc/traits/query/type_op/prove_predicate.rs +++ b/src/librustc/traits/query/type_op/prove_predicate.rs @@ -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! { diff --git a/src/librustc/traits/query/type_op/subtype.rs b/src/librustc/traits/query/type_op/subtype.rs index 01f9386bec4..a0fb2c2763d 100644 --- a/src/librustc/traits/query/type_op/subtype.rs +++ b/src/librustc/traits/query/type_op/subtype.rs @@ -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! { |
