about summary refs log tree commit diff
path: root/src/librustc/traits
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2018-06-11 11:56:06 -0400
committerNiko Matsakis <niko@alum.mit.edu>2018-06-26 10:59:40 -0400
commit2a0b3d6224768119f1d2e9850488c3d184362c1c (patch)
treed4d7a21fe7af5c37d28bdc6e30b894ad6433b038 /src/librustc/traits
parentde7e941e4eafdc73f4d68c6cdbb8c49224e5a90b (diff)
downloadrust-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.rs3
-rw-r--r--src/librustc/traits/query/type_op/eq.rs8
-rw-r--r--src/librustc/traits/query/type_op/mod.rs33
-rw-r--r--src/librustc/traits/query/type_op/normalize.rs151
-rw-r--r--src/librustc/traits/query/type_op/prove_predicate.rs18
-rw-r--r--src/librustc/traits/query/type_op/subtype.rs8
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! {