about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2018-06-11 10:33:37 -0400
committerNiko Matsakis <niko@alum.mit.edu>2018-06-26 10:59:40 -0400
commit71ce2e7eb6d941def725e85b8e9a23c75472ec62 (patch)
tree388a86b22734c8a3088f86a63ac7aa06c8138fb0
parent1acffada44df88112d23941cd96ea120ea4b8daf (diff)
downloadrust-71ce2e7eb6d941def725e85b8e9a23c75472ec62.tar.gz
rust-71ce2e7eb6d941def725e85b8e9a23c75472ec62.zip
make `Eq` a true query
-rw-r--r--src/librustc/dep_graph/dep_node.rs6
-rw-r--r--src/librustc/traits/query/mod.rs3
-rw-r--r--src/librustc/traits/query/type_op/eq.rs32
-rw-r--r--src/librustc/ty/query/config.rs10
-rw-r--r--src/librustc/ty/query/keys.rs29
-rw-r--r--src/librustc/ty/query/mod.rs10
-rw-r--r--src/librustc/ty/query/plumbing.rs1
-rw-r--r--src/librustc_traits/lib.rs2
-rw-r--r--src/librustc_traits/type_op_eq.rs35
9 files changed, 80 insertions, 48 deletions
diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs
index 3a152ccd0c9..efaebfd0610 100644
--- a/src/librustc/dep_graph/dep_node.rs
+++ b/src/librustc/dep_graph/dep_node.rs
@@ -70,8 +70,9 @@ use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
 use std::fmt;
 use std::hash::Hash;
 use syntax_pos::symbol::InternedString;
-use traits::query::{CanonicalProjectionGoal,
-                    CanonicalTyGoal, CanonicalPredicateGoal};
+use traits::query::{
+    CanonicalProjectionGoal, CanonicalTyGoal, CanonicalTypeOpEqGoal, CanonicalPredicateGoal,
+};
 use ty::{TyCtxt, Instance, InstanceDef, ParamEnv, ParamEnvAnd, PolyTraitRef, Ty};
 use ty::subst::Substs;
 
@@ -647,6 +648,7 @@ define_dep_nodes!( <'tcx>
     [] NormalizeTyAfterErasingRegions(ParamEnvAnd<'tcx, Ty<'tcx>>),
     [] DropckOutlives(CanonicalTyGoal<'tcx>),
     [] EvaluateObligation(CanonicalPredicateGoal<'tcx>),
+    [] TypeOpEq(CanonicalTypeOpEqGoal<'tcx>),
 
     [] SubstituteNormalizeAndTestPredicates { key: (DefId, &'tcx Substs<'tcx>) },
 
diff --git a/src/librustc/traits/query/mod.rs b/src/librustc/traits/query/mod.rs
index 7181a94acff..3ee0c0cdd0b 100644
--- a/src/librustc/traits/query/mod.rs
+++ b/src/librustc/traits/query/mod.rs
@@ -32,6 +32,9 @@ pub type CanonicalTyGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, Ty<'tcx>>
 pub type CanonicalPredicateGoal<'tcx> =
     Canonical<'tcx, ty::ParamEnvAnd<'tcx, ty::Predicate<'tcx>>>;
 
+pub type CanonicalTypeOpEqGoal<'tcx> =
+    Canonical<'tcx, type_op::eq::Eq<'tcx>>;
+
 #[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 9dad9fa4e0a..8925fa12f03 100644
--- a/src/librustc/traits/query/type_op/eq.rs
+++ b/src/librustc/traits/query/type_op/eq.rs
@@ -8,17 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use infer::canonical::{CanonicalizedQueryResult, Canonical};
-use traits::query::NoSolution;
-use traits::{FulfillmentContext, ObligationCause};
+use infer::canonical::{Canonical, CanonicalizedQueryResult};
 use ty::{self, ParamEnv, Ty, TyCtxt};
-use syntax::codemap::DUMMY_SP;
 
-#[derive(Copy, Clone, Debug)]
+#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
 pub struct Eq<'tcx> {
-    param_env: ParamEnv<'tcx>,
-    a: Ty<'tcx>,
-    b: Ty<'tcx>,
+    pub param_env: ParamEnv<'tcx>,
+    pub a: Ty<'tcx>,
+    pub b: Ty<'tcx>,
 }
 
 impl<'tcx> Eq<'tcx> {
@@ -46,20 +43,7 @@ impl<'gcx: 'tcx, 'tcx> super::QueryTypeOp<'gcx, 'tcx> for Eq<'tcx> {
         tcx: TyCtxt<'_, 'gcx, 'tcx>,
         canonicalized: Canonical<'gcx, Eq<'gcx>>,
     ) -> CanonicalizedQueryResult<'gcx, ()> {
-        let tcx = tcx.global_tcx();
-        tcx.infer_ctxt()
-            .enter(|ref infcx| {
-                let (Eq { param_env, a, b }, canonical_inference_vars) =
-                    infcx.instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &canonicalized);
-                let fulfill_cx = &mut FulfillmentContext::new();
-                let obligations = match infcx.at(&ObligationCause::dummy(), param_env).eq(a, b) {
-                    Ok(v) => v.into_obligations(),
-                    Err(_) => return Err(NoSolution),
-                };
-                fulfill_cx.register_predicate_obligations(infcx, obligations);
-                infcx.make_canonicalized_query_result(canonical_inference_vars, (), fulfill_cx)
-            })
-            .unwrap()
+        tcx.type_op_eq(canonicalized).unwrap()
     }
 }
 
@@ -79,3 +63,7 @@ BraceStructLiftImpl! {
         b,
     }
 }
+
+impl_stable_hash_for! {
+    struct Eq<'tcx> { param_env, a, b }
+}
diff --git a/src/librustc/ty/query/config.rs b/src/librustc/ty/query/config.rs
index cc00e9a00ab..d02eac6f212 100644
--- a/src/librustc/ty/query/config.rs
+++ b/src/librustc/ty/query/config.rs
@@ -12,7 +12,9 @@ use dep_graph::SerializedDepNodeIndex;
 use dep_graph::DepNode;
 use hir::def_id::{CrateNum, DefId, DefIndex};
 use mir::interpret::{GlobalId, ConstValue};
-use traits::query::{CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal};
+use traits::query::{
+    CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal, CanonicalTypeOpEqGoal,
+};
 use ty::{self, ParamEnvAnd, Ty, TyCtxt};
 use ty::subst::Substs;
 use ty::query::queries;
@@ -102,6 +104,12 @@ impl<'tcx> QueryDescription<'tcx> for queries::evaluate_obligation<'tcx> {
     }
 }
 
+impl<'tcx> QueryDescription<'tcx> for queries::type_op_eq<'tcx> {
+    fn describe(_tcx: TyCtxt, goal: CanonicalTypeOpEqGoal<'tcx>) -> String {
+        format!("evaluating `type_op_eq` `{:?}`", 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)
diff --git a/src/librustc/ty/query/keys.rs b/src/librustc/ty/query/keys.rs
index 279d5ebb990..cad3a658682 100644
--- a/src/librustc/ty/query/keys.rs
+++ b/src/librustc/ty/query/keys.rs
@@ -10,8 +10,8 @@
 
 //! Defines the set of legal keys that can be used in queries.
 
+use infer::canonical::Canonical;
 use hir::def_id::{CrateNum, DefId, LOCAL_CRATE, DefIndex};
-use traits::query::{CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal};
 use ty::{self, Ty, TyCtxt};
 use ty::subst::Substs;
 use ty::fast_reject::SimplifiedType;
@@ -190,27 +190,12 @@ impl Key for InternedString {
     }
 }
 
-impl<'tcx> Key for CanonicalProjectionGoal<'tcx> {
-    fn query_crate(&self) -> CrateNum {
-        LOCAL_CRATE
-    }
-
-    fn default_span(&self, _tcx: TyCtxt) -> Span {
-        DUMMY_SP
-    }
-}
-
-impl<'tcx> Key for CanonicalTyGoal<'tcx> {
-    fn query_crate(&self) -> CrateNum {
-        LOCAL_CRATE
-    }
-
-    fn default_span(&self, _tcx: TyCtxt) -> Span {
-        DUMMY_SP
-    }
-}
-
-impl<'tcx> Key for CanonicalPredicateGoal<'tcx> {
+/// Canonical query goals correspond to abstract trait operations that
+/// are not tied to any crate in particular.
+impl<'tcx, T> Key for Canonical<'tcx, T>
+where
+    T: Debug + Hash + Clone + Eq,
+{
     fn query_crate(&self) -> CrateNum {
         LOCAL_CRATE
     }
diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs
index f19bc01e198..d5cd37fd98a 100644
--- a/src/librustc/ty/query/mod.rs
+++ b/src/librustc/ty/query/mod.rs
@@ -34,7 +34,7 @@ use session::{CompileResult, CrateDisambiguator};
 use session::config::OutputFilenames;
 use traits::{self, Vtable};
 use traits::query::{CanonicalPredicateGoal, CanonicalProjectionGoal,
-                    CanonicalTyGoal, NoSolution};
+                    CanonicalTyGoal, CanonicalTypeOpEqGoal, NoSolution};
 use traits::query::dropck_outlives::{DtorckConstraint, DropckOutlivesResult};
 use traits::query::normalize::NormalizationResult;
 use traits::specialization_graph;
@@ -446,6 +446,14 @@ define_queries! { <'tcx>
         CanonicalPredicateGoal<'tcx>
     ) -> Result<traits::EvaluationResult, traits::OverflowError>,
 
+    /// Do not call this query directly: invoke `infcx.eq()` instead.
+    [] fn type_op_eq: TypeOpEq(
+        CanonicalTypeOpEqGoal<'tcx>
+    ) -> Result<
+        Lrc<Canonical<'tcx, canonical::QueryResult<'tcx, ()>>>,
+        NoSolution,
+    >,
+
     [] fn substitute_normalize_and_test_predicates:
         substitute_normalize_and_test_predicates_node((DefId, &'tcx Substs<'tcx>)) -> bool,
 
diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs
index 4679c265d58..51695b113d5 100644
--- a/src/librustc/ty/query/plumbing.rs
+++ b/src/librustc/ty/query/plumbing.rs
@@ -1028,6 +1028,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
         DepKind::NormalizeTyAfterErasingRegions |
         DepKind::DropckOutlives |
         DepKind::EvaluateObligation |
+        DepKind::TypeOpEq |
         DepKind::SubstituteNormalizeAndTestPredicates |
         DepKind::InstanceDefSizeEstimate |
         DepKind::ProgramClausesForEnv |
diff --git a/src/librustc_traits/lib.rs b/src/librustc_traits/lib.rs
index 830aa93c3c3..dae960c9aa3 100644
--- a/src/librustc_traits/lib.rs
+++ b/src/librustc_traits/lib.rs
@@ -34,6 +34,7 @@ mod evaluate_obligation;
 mod normalize_projection_ty;
 mod normalize_erasing_regions;
 pub mod lowering;
+mod type_op_eq;
 
 use rustc::ty::query::Providers;
 
@@ -47,6 +48,7 @@ pub fn provide(p: &mut Providers) {
         program_clauses_for: lowering::program_clauses_for,
         program_clauses_for_env: lowering::program_clauses_for_env,
         evaluate_obligation: evaluate_obligation::evaluate_obligation,
+        type_op_eq: type_op_eq::type_op_eq,
         ..*p
     };
 }
diff --git a/src/librustc_traits/type_op_eq.rs b/src/librustc_traits/type_op_eq.rs
new file mode 100644
index 00000000000..b73bee46486
--- /dev/null
+++ b/src/librustc_traits/type_op_eq.rs
@@ -0,0 +1,35 @@
+// 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::traits::query::type_op::eq::Eq;
+use rustc::traits::query::NoSolution;
+use rustc::traits::{FulfillmentContext, ObligationCause};
+use rustc::ty::TyCtxt;
+use rustc_data_structures::sync::Lrc;
+use syntax::codemap::DUMMY_SP;
+
+crate fn type_op_eq<'tcx>(
+    tcx: TyCtxt<'_, 'tcx, 'tcx>,
+    canonicalized: Canonical<'tcx, Eq<'tcx>>,
+) -> Result<Lrc<Canonical<'tcx, QueryResult<'tcx, ()>>>, NoSolution> {
+    let tcx = tcx.global_tcx();
+    tcx.infer_ctxt().enter(|ref infcx| {
+        let (Eq { param_env, a, b }, canonical_inference_vars) =
+            infcx.instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &canonicalized);
+        let fulfill_cx = &mut FulfillmentContext::new();
+        let obligations = match infcx.at(&ObligationCause::dummy(), param_env).eq(a, b) {
+            Ok(v) => v.into_obligations(),
+            Err(_) => return Err(NoSolution),
+        };
+        fulfill_cx.register_predicate_obligations(infcx, obligations);
+        infcx.make_canonicalized_query_result(canonical_inference_vars, (), fulfill_cx)
+    })
+}