about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2018-06-11 10:50:16 -0400
committerNiko Matsakis <niko@alum.mit.edu>2018-06-26 10:59:40 -0400
commit4beea9943b541e9165bfcbba8b15f9008a7434d1 (patch)
tree02cd122369f3fc93e01e51fe8f641787035104bd
parent71ce2e7eb6d941def725e85b8e9a23c75472ec62 (diff)
downloadrust-4beea9943b541e9165bfcbba8b15f9008a7434d1.tar.gz
rust-4beea9943b541e9165bfcbba8b15f9008a7434d1.zip
make `Subtype` a true query
-rw-r--r--src/librustc/dep_graph/dep_node.rs4
-rw-r--r--src/librustc/traits/query/mod.rs3
-rw-r--r--src/librustc/traits/query/type_op/subtype.rs51
-rw-r--r--src/librustc/ty/query/config.rs7
-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_subtype.rs35
8 files changed, 98 insertions, 15 deletions
diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs
index efaebfd0610..6f0b794129b 100644
--- a/src/librustc/dep_graph/dep_node.rs
+++ b/src/librustc/dep_graph/dep_node.rs
@@ -71,7 +71,8 @@ use std::fmt;
 use std::hash::Hash;
 use syntax_pos::symbol::InternedString;
 use traits::query::{
-    CanonicalProjectionGoal, CanonicalTyGoal, CanonicalTypeOpEqGoal, CanonicalPredicateGoal,
+    CanonicalProjectionGoal, CanonicalTyGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpSubtypeGoal,
+    CanonicalPredicateGoal,
 };
 use ty::{TyCtxt, Instance, InstanceDef, ParamEnv, ParamEnvAnd, PolyTraitRef, Ty};
 use ty::subst::Substs;
@@ -649,6 +650,7 @@ define_dep_nodes!( <'tcx>
     [] DropckOutlives(CanonicalTyGoal<'tcx>),
     [] EvaluateObligation(CanonicalPredicateGoal<'tcx>),
     [] TypeOpEq(CanonicalTypeOpEqGoal<'tcx>),
+    [] TypeOpSubtype(CanonicalTypeOpSubtypeGoal<'tcx>),
 
     [] SubstituteNormalizeAndTestPredicates { key: (DefId, &'tcx Substs<'tcx>) },
 
diff --git a/src/librustc/traits/query/mod.rs b/src/librustc/traits/query/mod.rs
index 3ee0c0cdd0b..47f55b7e5e4 100644
--- a/src/librustc/traits/query/mod.rs
+++ b/src/librustc/traits/query/mod.rs
@@ -35,6 +35,9 @@ pub type CanonicalPredicateGoal<'tcx> =
 pub type CanonicalTypeOpEqGoal<'tcx> =
     Canonical<'tcx, type_op::eq::Eq<'tcx>>;
 
+pub type CanonicalTypeOpSubtypeGoal<'tcx> =
+    Canonical<'tcx, type_op::subtype::Subtype<'tcx>>;
+
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
 pub struct NoSolution;
 
diff --git a/src/librustc/traits/query/type_op/subtype.rs b/src/librustc/traits/query/type_op/subtype.rs
index e9adabc8b08..01f9386bec4 100644
--- a/src/librustc/traits/query/type_op/subtype.rs
+++ b/src/librustc/traits/query/type_op/subtype.rs
@@ -8,15 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use infer::{InferCtxt, InferResult};
-use traits::ObligationCause;
+use infer::canonical::{Canonical, CanonicalizedQueryResult};
 use ty::{ParamEnv, Ty, TyCtxt};
 
-#[derive(Debug)]
+#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
 pub struct Subtype<'tcx> {
-    param_env: ParamEnv<'tcx>,
-    sub: Ty<'tcx>,
-    sup: Ty<'tcx>,
+    pub param_env: ParamEnv<'tcx>,
+    pub sub: Ty<'tcx>,
+    pub sup: Ty<'tcx>,
 }
 
 impl<'tcx> Subtype<'tcx> {
@@ -29,10 +28,10 @@ impl<'tcx> Subtype<'tcx> {
     }
 }
 
-impl<'gcx, 'tcx> super::TypeOp<'gcx, 'tcx> for Subtype<'tcx> {
-    type Output = ();
+impl<'gcx: 'tcx, 'tcx> super::QueryTypeOp<'gcx, 'tcx> for Subtype<'tcx> {
+    type QueryResult = ();
 
-    fn trivial_noop(self, _tcx: TyCtxt<'_, 'gcx, 'tcx>) -> Result<Self::Output, Self> {
+    fn trivial_noop(self, _tcx: TyCtxt<'_, 'gcx, 'tcx>) -> Result<(), Self> {
         if self.sub == self.sup {
             Ok(())
         } else {
@@ -40,9 +39,35 @@ impl<'gcx, 'tcx> super::TypeOp<'gcx, 'tcx> for Subtype<'tcx> {
         }
     }
 
-    fn perform(self, infcx: &InferCtxt<'_, 'gcx, 'tcx>) -> InferResult<'tcx, Self::Output> {
-        infcx
-            .at(&ObligationCause::dummy(), self.param_env)
-            .sup(self.sup, self.sub)
+    fn param_env(&self) -> ParamEnv<'tcx> {
+        self.param_env
     }
+
+    fn perform_query(
+        tcx: TyCtxt<'_, 'gcx, 'tcx>,
+        canonicalized: Canonical<'gcx, Subtype<'gcx>>,
+    ) -> CanonicalizedQueryResult<'gcx, ()> {
+        tcx.type_op_subtype(canonicalized).unwrap()
+    }
+}
+
+BraceStructTypeFoldableImpl! {
+    impl<'tcx> TypeFoldable<'tcx> for Subtype<'tcx> {
+        param_env,
+        sub,
+        sup,
+    }
+}
+
+BraceStructLiftImpl! {
+    impl<'a, 'tcx> Lift<'tcx> for Subtype<'a> {
+        type Lifted = Subtype<'tcx>;
+        param_env,
+        sub,
+        sup,
+    }
+}
+
+impl_stable_hash_for! {
+    struct Subtype<'tcx> { param_env, sub, sup }
 }
diff --git a/src/librustc/ty/query/config.rs b/src/librustc/ty/query/config.rs
index d02eac6f212..bccdec27099 100644
--- a/src/librustc/ty/query/config.rs
+++ b/src/librustc/ty/query/config.rs
@@ -14,6 +14,7 @@ use hir::def_id::{CrateNum, DefId, DefIndex};
 use mir::interpret::{GlobalId, ConstValue};
 use traits::query::{
     CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal, CanonicalTypeOpEqGoal,
+    CanonicalTypeOpSubtypeGoal,
 };
 use ty::{self, ParamEnvAnd, Ty, TyCtxt};
 use ty::subst::Substs;
@@ -110,6 +111,12 @@ impl<'tcx> QueryDescription<'tcx> for queries::type_op_eq<'tcx> {
     }
 }
 
+impl<'tcx> QueryDescription<'tcx> for queries::type_op_subtype<'tcx> {
+    fn describe(_tcx: TyCtxt, goal: CanonicalTypeOpSubtypeGoal<'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/mod.rs b/src/librustc/ty/query/mod.rs
index d5cd37fd98a..e848fa2c347 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, CanonicalTypeOpEqGoal, NoSolution};
+                    CanonicalTyGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpSubtypeGoal, NoSolution};
 use traits::query::dropck_outlives::{DtorckConstraint, DropckOutlivesResult};
 use traits::query::normalize::NormalizationResult;
 use traits::specialization_graph;
@@ -454,6 +454,14 @@ define_queries! { <'tcx>
         NoSolution,
     >,
 
+    /// Do not call this query directly: invoke `infcx.at().subtype()` instead.
+    [] fn type_op_subtype: TypeOpSubtype(
+        CanonicalTypeOpSubtypeGoal<'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 51695b113d5..2380764252b 100644
--- a/src/librustc/ty/query/plumbing.rs
+++ b/src/librustc/ty/query/plumbing.rs
@@ -1029,6 +1029,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
         DepKind::DropckOutlives |
         DepKind::EvaluateObligation |
         DepKind::TypeOpEq |
+        DepKind::TypeOpSubtype |
         DepKind::SubstituteNormalizeAndTestPredicates |
         DepKind::InstanceDefSizeEstimate |
         DepKind::ProgramClausesForEnv |
diff --git a/src/librustc_traits/lib.rs b/src/librustc_traits/lib.rs
index dae960c9aa3..671e352c0e4 100644
--- a/src/librustc_traits/lib.rs
+++ b/src/librustc_traits/lib.rs
@@ -35,6 +35,7 @@ mod normalize_projection_ty;
 mod normalize_erasing_regions;
 pub mod lowering;
 mod type_op_eq;
+mod type_op_subtype;
 
 use rustc::ty::query::Providers;
 
@@ -49,6 +50,7 @@ pub fn provide(p: &mut Providers) {
         program_clauses_for_env: lowering::program_clauses_for_env,
         evaluate_obligation: evaluate_obligation::evaluate_obligation,
         type_op_eq: type_op_eq::type_op_eq,
+        type_op_subtype: type_op_subtype::type_op_subtype,
         ..*p
     };
 }
diff --git a/src/librustc_traits/type_op_subtype.rs b/src/librustc_traits/type_op_subtype.rs
new file mode 100644
index 00000000000..1fa5ec915f2
--- /dev/null
+++ b/src/librustc_traits/type_op_subtype.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::subtype::Subtype;
+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_subtype<'tcx>(
+    tcx: TyCtxt<'_, 'tcx, 'tcx>,
+    canonicalized: Canonical<'tcx, Subtype<'tcx>>,
+) -> Result<Lrc<Canonical<'tcx, QueryResult<'tcx, ()>>>, NoSolution> {
+    let tcx = tcx.global_tcx();
+    tcx.infer_ctxt().enter(|ref infcx| {
+        let (Subtype { param_env, sub, sup }, 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).sup(sup, sub) {
+            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)
+    })
+}