about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2018-06-19 18:32:43 -0400
committerNiko Matsakis <niko@alum.mit.edu>2018-06-26 13:18:27 -0400
commit82169b6134b34f17b0e7c247dbd92bb6949951c0 (patch)
treeb88687335417912da041d4ceb8cbd61c7f6b794b
parenta583269af57e6acce6d9c2ffe4c0ce2b4f2e1ab9 (diff)
downloadrust-82169b6134b34f17b0e7c247dbd92bb6949951c0.tar.gz
rust-82169b6134b34f17b0e7c247dbd92bb6949951c0.zip
convert query-type-op to create query-region-constraint directly
-rw-r--r--src/librustc/infer/canonical/query_result.rs85
-rw-r--r--src/librustc/traits/query/type_op/custom.rs57
-rw-r--r--src/librustc/traits/query/type_op/eq.rs12
-rw-r--r--src/librustc/traits/query/type_op/mod.rs170
-rw-r--r--src/librustc/traits/query/type_op/normalize.rs10
-rw-r--r--src/librustc/traits/query/type_op/outlives.rs12
-rw-r--r--src/librustc/traits/query/type_op/prove_predicate.rs10
-rw-r--r--src/librustc/traits/query/type_op/subtype.rs10
8 files changed, 179 insertions, 187 deletions
diff --git a/src/librustc/infer/canonical/query_result.rs b/src/librustc/infer/canonical/query_result.rs
index d512bb5268d..8a3784fe088 100644
--- a/src/librustc/infer/canonical/query_result.rs
+++ b/src/librustc/infer/canonical/query_result.rs
@@ -17,7 +17,6 @@
 //!
 //! [c]: https://rust-lang-nursery.github.io/rustc-guide/traits/canonicalization.html
 
-use either::Either;
 use infer::canonical::substitute::substitute_value;
 use infer::canonical::{
     Canonical, CanonicalVarKind, CanonicalVarValues, CanonicalizedQueryResult, Certainty,
@@ -29,7 +28,6 @@ use rustc_data_structures::indexed_vec::Idx;
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc_data_structures::sync::Lrc;
 use std::fmt::Debug;
-use std::iter::once;
 use syntax::ast;
 use traits::query::NoSolution;
 use traits::{FulfillmentContext, TraitEngine};
@@ -191,9 +189,11 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
     pub fn instantiate_nll_query_result_and_region_obligations<R>(
         &self,
         cause: &ObligationCause<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
         original_values: &CanonicalVarValues<'tcx>,
         query_result: &Canonical<'tcx, QueryResult<'tcx, R>>,
-    ) -> Vec<QueryRegionConstraint<'tcx>>
+        output_query_region_constraints: &mut Vec<QueryRegionConstraint<'tcx>>,
+    ) -> InferResult<'tcx, R>
     where
         R: Debug + TypeFoldable<'tcx>,
     {
@@ -210,52 +210,59 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
         // Compute `QueryRegionConstraint` values that unify each of
         // the original values `v_o` that was canonicalized into a
         // variable...
-        let qrc_from_unify = original_values.var_values.iter_enumerated().flat_map(
-            |(index, original_value)| {
-                // ...with the value `v_r` of that variable from the query.
-                let result_value =
-                    query_result
-                        .substitute_projected(self.tcx, &result_subst, |v| &v.var_values[index]);
-                match (original_value.unpack(), result_value.unpack()) {
-                    (
-                        UnpackedKind::Lifetime(ty::ReErased),
-                        UnpackedKind::Lifetime(ty::ReErased),
-                    ) => {
-                        // no action needed
-                        Either::Left(None.into_iter())
-                    }
+        let mut obligations = vec![];
+
+        for (index, original_value) in original_values.var_values.iter_enumerated() {
+            // ...with the value `v_r` of that variable from the query.
+            let result_value = query_result
+                .substitute_projected(self.tcx, &result_subst, |v| &v.var_values[index]);
+            match (original_value.unpack(), result_value.unpack()) {
+                (UnpackedKind::Lifetime(ty::ReErased), UnpackedKind::Lifetime(ty::ReErased)) => {
+                    // no action needed
+                }
 
-                    (UnpackedKind::Lifetime(v_o), UnpackedKind::Lifetime(v_r)) => {
-                        // To make `v_o = v_r`, we emit `v_o: v_r` and `v_r: v_o`.
-                        Either::Right(
-                            once(ty::OutlivesPredicate(v_o.into(), v_r))
-                                .chain(once(ty::OutlivesPredicate(v_r.into(), v_o)))
-                                .map(ty::Binder::dummy),
-                        )
+                (UnpackedKind::Lifetime(v_o), UnpackedKind::Lifetime(v_r)) => {
+                    // To make `v_o = v_r`, we emit `v_o: v_r` and `v_r: v_o`.
+                    if v_o != v_r {
+                        output_query_region_constraints
+                            .push(ty::Binder::dummy(ty::OutlivesPredicate(v_o.into(), v_r)));
+                        output_query_region_constraints
+                            .push(ty::Binder::dummy(ty::OutlivesPredicate(v_r.into(), v_o)));
                     }
+                }
 
-                    (UnpackedKind::Type(_), _) | (_, UnpackedKind::Type(_)) => {
-                        // in NLL queries, we do not expect `type` results.
-                        bug!(
-                            "unexpected type in NLL query: cannot unify {:?} and {:?}",
-                            original_value,
-                            result_value,
-                        );
-                    }
+                (UnpackedKind::Type(v1), UnpackedKind::Type(v2)) => {
+                    let ok = self.at(cause, param_env).eq(v1, v2)?;
+                    obligations.extend(ok.into_obligations());
                 }
-            },
-        );
+
+                _ => {
+                    bug!(
+                        "kind mismatch, cannot unify {:?} and {:?}",
+                        original_value,
+                        result_value
+                    );
+                }
+            }
+        }
 
         // ...also include the other query region constraints from the query.
-        let qrc_from_result = query_result.value.region_constraints.iter().map(|r_c| {
-            r_c.map_bound(|ty::OutlivesPredicate(k1, r2)| {
+        output_query_region_constraints.reserve(query_result.value.region_constraints.len());
+        for r_c in query_result.value.region_constraints.iter() {
+            output_query_region_constraints.push(r_c.map_bound(|ty::OutlivesPredicate(k1, r2)| {
                 let k1 = substitute_value(self.tcx, &result_subst, &k1);
                 let r2 = substitute_value(self.tcx, &result_subst, &r2);
                 ty::OutlivesPredicate(k1, r2)
-            })
-        });
+            }));
+        }
 
-        qrc_from_unify.chain(qrc_from_result).collect()
+        let user_result: R =
+            query_result.substitute_projected(self.tcx, &result_subst, |q_r| &q_r.value);
+
+        Ok(InferOk {
+            value: user_result,
+            obligations,
+        })
     }
 
     /// Given the original values and the (canonicalized) result from
diff --git a/src/librustc/traits/query/type_op/custom.rs b/src/librustc/traits/query/type_op/custom.rs
index d3bc81a09a9..90ea276a094 100644
--- a/src/librustc/traits/query/type_op/custom.rs
+++ b/src/librustc/traits/query/type_op/custom.rs
@@ -9,9 +9,14 @@
 // except according to those terms.
 
 use infer::{InferCtxt, InferOk};
-use traits::query::Fallible;
-use ty::TyCtxt;
 use std::fmt;
+use traits::query::Fallible;
+
+use infer::canonical::query_result;
+use infer::canonical::QueryRegionConstraint;
+use std::rc::Rc;
+use syntax::codemap::DUMMY_SP;
+use traits::{ObligationCause, TraitEngine};
 
 pub struct CustomTypeOp<F, G> {
     closure: F,
@@ -38,12 +43,18 @@ where
 {
     type Output = R;
 
-    fn trivial_noop(self, _tcx: TyCtxt<'_, 'gcx, 'tcx>) -> Result<Self::Output, Self> {
-        Err(self)
-    }
+    /// Processes the operation and all resulting obligations,
+    /// returning the final result along with any region constraints
+    /// (they will be given over to the NLL region solver).
+    fn fully_perform(
+        self,
+        infcx: &InferCtxt<'_, 'gcx, 'tcx>,
+    ) -> Fallible<(Self::Output, Option<Rc<Vec<QueryRegionConstraint<'tcx>>>>)> {
+        if cfg!(debug_assertions) {
+            info!("fully_perform({:?})", self);
+        }
 
-    fn perform(self, infcx: &InferCtxt<'_, 'gcx, 'tcx>) -> Fallible<InferOk<'tcx, R>> {
-        Ok((self.closure)(infcx)?)
+        scrape_region_constraints(infcx, || Ok((self.closure)(infcx)?))
     }
 }
 
@@ -55,3 +66,35 @@ where
         write!(f, "{}", (self.description)())
     }
 }
+
+/// Executes `op` and then scrapes out all the "old style" region
+/// constraints that result, creating query-region-constraints.
+fn scrape_region_constraints<'gcx, 'tcx, R>(
+    infcx: &InferCtxt<'_, 'gcx, 'tcx>,
+    op: impl FnOnce() -> Fallible<InferOk<'tcx, R>>,
+) -> Fallible<(R, Option<Rc<Vec<QueryRegionConstraint<'tcx>>>>)> {
+    let mut fulfill_cx = TraitEngine::new(infcx.tcx);
+    let dummy_body_id = ObligationCause::dummy().body_id;
+    let InferOk { value, obligations } = infcx.commit_if_ok(|_| op())?;
+    debug_assert!(obligations.iter().all(|o| o.cause.body_id == dummy_body_id));
+    fulfill_cx.register_predicate_obligations(infcx, obligations);
+    if let Err(e) = fulfill_cx.select_all_or_error(infcx) {
+        infcx.tcx.sess.diagnostic().delay_span_bug(
+            DUMMY_SP,
+            &format!("errors selecting obligation during MIR typeck: {:?}", e),
+        );
+    }
+
+    let region_obligations = infcx.take_registered_region_obligations();
+
+    let region_constraint_data = infcx.take_and_reset_region_constraints();
+
+    let outlives =
+        query_result::make_query_outlives(infcx.tcx, region_obligations, &region_constraint_data);
+
+    if outlives.is_empty() {
+        Ok((value, None))
+    } else {
+        Ok((value, Some(Rc::new(outlives))))
+    }
+}
diff --git a/src/librustc/traits/query/type_op/eq.rs b/src/librustc/traits/query/type_op/eq.rs
index b70a5307097..04d256a93e1 100644
--- a/src/librustc/traits/query/type_op/eq.rs
+++ b/src/librustc/traits/query/type_op/eq.rs
@@ -10,7 +10,7 @@
 
 use infer::canonical::{Canonical, CanonicalizedQueryResult, QueryResult};
 use traits::query::Fallible;
-use ty::{self, ParamEnv, Ty, TyCtxt};
+use ty::{ParamEnv, Ty, TyCtxt};
 
 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
 pub struct Eq<'tcx> {
@@ -29,7 +29,7 @@ impl<'gcx: 'tcx, 'tcx> super::QueryTypeOp<'gcx, 'tcx> for Eq<'tcx> {
     type QueryKey = Self;
     type QueryResult = ();
 
-    fn trivial_noop(self, _tcx: TyCtxt<'_, 'gcx, 'tcx>) -> Result<Self::QueryResult, Self> {
+    fn prequery(self, _tcx: TyCtxt<'_, 'gcx, 'tcx>) -> Result<Self::QueryResult, Self> {
         if self.a == self.b {
             Ok(())
         } else {
@@ -37,12 +37,8 @@ impl<'gcx: 'tcx, 'tcx> super::QueryTypeOp<'gcx, 'tcx> for Eq<'tcx> {
         }
     }
 
-    fn into_query_key(self) -> Self {
-        self
-    }
-
-    fn param_env(&self) -> ty::ParamEnv<'tcx> {
-        self.param_env
+    fn param_env(key: &Self::QueryKey) -> ParamEnv<'tcx> {
+        key.param_env
     }
 
     fn perform_query(
diff --git a/src/librustc/traits/query/type_op/mod.rs b/src/librustc/traits/query/type_op/mod.rs
index 41d33338db4..16280885c12 100644
--- a/src/librustc/traits/query/type_op/mod.rs
+++ b/src/librustc/traits/query/type_op/mod.rs
@@ -8,16 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use infer::canonical::query_result;
 use infer::canonical::{
     Canonical, Canonicalized, CanonicalizedQueryResult, QueryRegionConstraint, QueryResult,
 };
 use infer::{InferCtxt, InferOk};
 use std::fmt;
 use std::rc::Rc;
-use syntax::codemap::DUMMY_SP;
 use traits::query::Fallible;
-use traits::{ObligationCause, TraitEngine};
+use traits::ObligationCause;
 use ty::fold::TypeFoldable;
 use ty::{Lift, ParamEnv, TyCtxt};
 
@@ -31,89 +29,25 @@ pub mod subtype;
 pub trait TypeOp<'gcx, 'tcx>: Sized + fmt::Debug {
     type Output;
 
-    /// 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<Self::Output, Self>;
-
-    /// Given an infcx, performs **the kernel** of the operation: this does the
-    /// key action and then, optionally, returns a set of obligations which must be proven.
-    ///
-    /// This method is not meant to be invoked directly: instead, one
-    /// should use `fully_perform`, which will take those resulting
-    /// obligations and prove them, and then process the combined
-    /// results into region obligations which are returned.
-    fn perform(
-        self,
-        infcx: &InferCtxt<'_, 'gcx, 'tcx>,
-    ) -> Fallible<InferOk<'tcx, Self::Output>>;
-
     /// Processes the operation and all resulting obligations,
     /// returning the final result along with any region constraints
     /// (they will be given over to the NLL region solver).
     fn fully_perform(
         self,
         infcx: &InferCtxt<'_, 'gcx, 'tcx>,
-    ) -> Fallible<(Self::Output, Option<Rc<Vec<QueryRegionConstraint<'tcx>>>>)> {
-        match self.trivial_noop(infcx.tcx) {
-            Ok(r) => Ok((r, None)),
-            Err(op) => op.fully_perform_nontrivial(infcx),
-        }
-    }
-
-    /// Helper for `fully_perform` that handles the nontrivial cases.
-    #[inline(never)] // just to help with profiling
-    fn fully_perform_nontrivial(
-        self,
-        infcx: &InferCtxt<'_, 'gcx, 'tcx>,
-    ) -> Fallible<(Self::Output, Option<Rc<Vec<QueryRegionConstraint<'tcx>>>>)> {
-        if cfg!(debug_assertions) {
-            info!(
-                "fully_perform_op_and_get_region_constraint_data({:?})",
-                self
-            );
-        }
-
-        let mut fulfill_cx = TraitEngine::new(infcx.tcx);
-        let dummy_body_id = ObligationCause::dummy().body_id;
-        let InferOk { value, obligations } = infcx.commit_if_ok(|_| self.perform(infcx))?;
-        debug_assert!(obligations.iter().all(|o| o.cause.body_id == dummy_body_id));
-        fulfill_cx.register_predicate_obligations(infcx, obligations);
-        if let Err(e) = fulfill_cx.select_all_or_error(infcx) {
-            infcx.tcx.sess.diagnostic().delay_span_bug(
-                DUMMY_SP,
-                &format!("errors selecting obligation during MIR typeck: {:?}", e),
-            );
-        }
-
-        let region_obligations = infcx.take_registered_region_obligations();
-
-        let region_constraint_data = infcx.take_and_reset_region_constraints();
-
-        let outlives = query_result::make_query_outlives(
-            infcx.tcx,
-            region_obligations,
-            &region_constraint_data,
-        );
-
-        if outlives.is_empty() {
-            Ok((value, None))
-        } else {
-            Ok((value, Some(Rc::new(outlives))))
-        }
-    }
+    ) -> Fallible<(Self::Output, Option<Rc<Vec<QueryRegionConstraint<'tcx>>>>)>;
 }
 
 pub trait QueryTypeOp<'gcx: 'tcx, 'tcx>: fmt::Debug + Sized {
     type QueryKey: 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<Self::QueryResult, Self>;
-
-    fn into_query_key(self) -> Self::QueryKey;
+    /// Either converts `self` directly into a `QueryResult` (for
+    /// simple cases) or into a `QueryKey` (for more complex cases
+    /// where we actually have work to do).
+    fn prequery(self, tcx: TyCtxt<'_, 'gcx, 'tcx>) -> Result<Self::QueryResult, Self::QueryKey>;
 
-    fn param_env(&self) -> ParamEnv<'tcx>;
+    fn param_env(key: &Self::QueryKey) -> ParamEnv<'tcx>;
 
     fn perform_query(
         tcx: TyCtxt<'_, 'gcx, 'tcx>,
@@ -130,6 +64,51 @@ pub trait QueryTypeOp<'gcx: 'tcx, 'tcx>: fmt::Debug + Sized {
     fn upcast_result(
         lifted_query_result: &'a CanonicalizedQueryResult<'gcx, Self::QueryResult>,
     ) -> &'a Canonical<'tcx, QueryResult<'tcx, Self::QueryResult>>;
+
+    fn fully_perform_into(
+        self,
+        infcx: &InferCtxt<'_, 'gcx, 'tcx>,
+        output_query_region_constraints: &mut Vec<QueryRegionConstraint<'tcx>>,
+    ) -> Fallible<Self::QueryResult> {
+        match QueryTypeOp::prequery(self, infcx.tcx) {
+            Ok(result) => Ok(result),
+            Err(query_key) => {
+                // FIXME(#33684) -- We need to use
+                // `canonicalize_hr_query_hack` here because of things
+                // like the subtype query, which go awry around
+                // `'static` otherwise.
+                let (canonical_self, canonical_var_values) =
+                    infcx.canonicalize_hr_query_hack(&query_key);
+                let canonical_result = Self::perform_query(infcx.tcx, canonical_self)?;
+                let canonical_result = Self::upcast_result(&canonical_result);
+
+                let param_env = Self::param_env(&query_key);
+
+                let InferOk { value, obligations } = infcx
+                    .instantiate_nll_query_result_and_region_obligations(
+                        &ObligationCause::dummy(),
+                        param_env,
+                        &canonical_var_values,
+                        canonical_result,
+                        output_query_region_constraints,
+                    )?;
+
+                // Typically, instantiating NLL query results does not
+                // create obligations. However, in some cases there
+                // are unresolved type variables, and unify them *can*
+                // create obligations. In that case, we have to go
+                // fulfill them. We do this via a (recursive) query.
+                for obligation in obligations {
+                    let () = prove_predicate::ProvePredicate::new(
+                        obligation.param_env,
+                        obligation.predicate,
+                    ).fully_perform_into(infcx, output_query_region_constraints)?;
+                }
+
+                Ok(value)
+            }
+        }
+    }
 }
 
 impl<'gcx: 'tcx, 'tcx, Q> TypeOp<'gcx, 'tcx> for Q
@@ -138,38 +117,21 @@ where
 {
     type Output = Q::QueryResult;
 
-    fn trivial_noop(self, tcx: TyCtxt<'_, 'gcx, 'tcx>) -> Result<Self::Output, Self> {
-        QueryTypeOp::trivial_noop(self, tcx)
-    }
-
-    fn perform(
+    fn fully_perform(
         self,
         infcx: &InferCtxt<'_, 'gcx, 'tcx>,
-    ) -> Fallible<InferOk<'tcx, Self::Output>> {
-        let param_env = self.param_env();
-
-        // FIXME(#33684) -- We need to use
-        // `canonicalize_hr_query_hack` here because of things like
-        // the subtype query, which go awry around `'static`
-        // otherwise.
-        let query_key = self.into_query_key();
-        let (canonical_self, canonical_var_values) = infcx.canonicalize_hr_query_hack(&query_key);
-        let canonical_result = Q::perform_query(infcx.tcx, canonical_self)?;
-
-        // FIXME: This is not the most efficient setup. The
-        // `instantiate_query_result_and_region_obligations` basically
-        // takes the `QueryRegionConstraint` values that we ultimately
-        // want to use and converts them into obligations. We return
-        // those to our caller, which will convert them into AST
-        // region constraints; we then convert *those* back into
-        // `QueryRegionConstraint` and ultimately into NLL
-        // constraints. We should cut out the middleman but that will
-        // take a bit of refactoring.
-        Ok(infcx.instantiate_query_result_and_region_obligations(
-            &ObligationCause::dummy(),
-            param_env,
-            &canonical_var_values,
-            Q::upcast_result(&canonical_result),
-        )?)
+    ) -> Fallible<(Self::Output, Option<Rc<Vec<QueryRegionConstraint<'tcx>>>>)> {
+        let mut qrc = vec![];
+        let r = Q::fully_perform_into(self, infcx, &mut qrc)?;
+
+        // Promote the final query-region-constraints into a
+        // (optional) ref-counted vector:
+        let opt_qrc = if qrc.is_empty() {
+            None
+        } else {
+            Some(Rc::new(qrc))
+        };
+
+        Ok((r, opt_qrc))
     }
 }
diff --git a/src/librustc/traits/query/type_op/normalize.rs b/src/librustc/traits/query/type_op/normalize.rs
index 8c5bbe05616..b72c887ba50 100644
--- a/src/librustc/traits/query/type_op/normalize.rs
+++ b/src/librustc/traits/query/type_op/normalize.rs
@@ -36,7 +36,7 @@ where
     type QueryKey = Self;
     type QueryResult = T;
 
-    fn trivial_noop(self, _tcx: TyCtxt<'_, 'gcx, 'tcx>) -> Result<T, Self> {
+    fn prequery(self, _tcx: TyCtxt<'_, 'gcx, 'tcx>) -> Result<T, Self> {
         if !self.value.has_projections() {
             Ok(self.value)
         } else {
@@ -44,12 +44,8 @@ where
         }
     }
 
-    fn into_query_key(self) -> Self {
-        self
-    }
-
-    fn param_env(&self) -> ParamEnv<'tcx> {
-        self.param_env
+    fn param_env(key: &Self::QueryKey) -> ParamEnv<'tcx> {
+        key.param_env
     }
 
     fn perform_query(
diff --git a/src/librustc/traits/query/type_op/outlives.rs b/src/librustc/traits/query/type_op/outlives.rs
index a6fbb165098..0254b901a8c 100644
--- a/src/librustc/traits/query/type_op/outlives.rs
+++ b/src/librustc/traits/query/type_op/outlives.rs
@@ -36,20 +36,16 @@ where
     type QueryKey = ParamEnvAnd<'tcx, Ty<'tcx>>;
     type QueryResult = DropckOutlivesResult<'tcx>;
 
-    fn trivial_noop(self, tcx: TyCtxt<'_, 'gcx, 'tcx>) -> Result<Self::QueryResult, Self> {
+    fn prequery(self, tcx: TyCtxt<'_, 'gcx, 'tcx>) -> Result<Self::QueryResult, Self::QueryKey> {
         if trivial_dropck_outlives(tcx, self.dropped_ty) {
             Ok(DropckOutlivesResult::default())
         } else {
-            Err(self)
+            Err(self.param_env.and(self.dropped_ty))
         }
     }
 
-    fn param_env(&self) -> ParamEnv<'tcx> {
-        self.param_env
-    }
-
-    fn into_query_key(self) -> Self::QueryKey {
-        self.param_env.and(self.dropped_ty)
+    fn param_env(key: &Self::QueryKey) -> ParamEnv<'tcx> {
+        key.param_env
     }
 
     fn perform_query(
diff --git a/src/librustc/traits/query/type_op/prove_predicate.rs b/src/librustc/traits/query/type_op/prove_predicate.rs
index 1d02fe9a113..b06ad32ff22 100644
--- a/src/librustc/traits/query/type_op/prove_predicate.rs
+++ b/src/librustc/traits/query/type_op/prove_predicate.rs
@@ -31,16 +31,12 @@ impl<'gcx: 'tcx, 'tcx> super::QueryTypeOp<'gcx, 'tcx> for ProvePredicate<'tcx> {
     type QueryKey = Self;
     type QueryResult = ();
 
-    fn trivial_noop(self, _tcx: TyCtxt<'_, 'gcx, 'tcx>) -> Result<Self::QueryResult, Self> {
+    fn prequery(self, _tcx: TyCtxt<'_, 'gcx, 'tcx>) -> Result<Self::QueryResult, Self::QueryKey> {
         Err(self)
     }
 
-    fn into_query_key(self) -> Self {
-        self
-    }
-
-    fn param_env(&self) -> ParamEnv<'tcx> {
-        self.param_env
+    fn param_env(key: &Self::QueryKey) -> ParamEnv<'tcx> {
+        key.param_env
     }
 
     fn perform_query(
diff --git a/src/librustc/traits/query/type_op/subtype.rs b/src/librustc/traits/query/type_op/subtype.rs
index 0842b78ce8b..bdc7dd9589b 100644
--- a/src/librustc/traits/query/type_op/subtype.rs
+++ b/src/librustc/traits/query/type_op/subtype.rs
@@ -33,7 +33,7 @@ impl<'gcx: 'tcx, 'tcx> super::QueryTypeOp<'gcx, 'tcx> for Subtype<'tcx> {
     type QueryKey = Self;
     type QueryResult = ();
 
-    fn trivial_noop(self, _tcx: TyCtxt<'_, 'gcx, 'tcx>) -> Result<(), Self> {
+    fn prequery(self, _tcx: TyCtxt<'_, 'gcx, 'tcx>) -> Result<(), Self::QueryKey> {
         if self.sub == self.sup {
             Ok(())
         } else {
@@ -41,12 +41,8 @@ impl<'gcx: 'tcx, 'tcx> super::QueryTypeOp<'gcx, 'tcx> for Subtype<'tcx> {
         }
     }
 
-    fn into_query_key(self) -> Self {
-        self
-    }
-
-    fn param_env(&self) -> ParamEnv<'tcx> {
-        self.param_env
+    fn param_env(key: &Self::QueryKey) -> ParamEnv<'tcx> {
+        key.param_env
     }
 
     fn perform_query(