]> git.proxmox.com Git - rustc.git/blobdiff - compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
New upstream version 1.56.0~beta.4+dfsg1
[rustc.git] / compiler / rustc_trait_selection / src / traits / query / type_op / mod.rs
index fbff86618ade3172f15be2bbeb0259685ea84a8c..12ca3faeb379785e34b8f3b1c3e55ab6b3726743 100644 (file)
@@ -4,6 +4,7 @@ use crate::infer::canonical::{
 use crate::infer::{InferCtxt, InferOk};
 use crate::traits::query::Fallible;
 use crate::traits::ObligationCause;
+use rustc_infer::infer::canonical::Canonical;
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
 use std::fmt;
@@ -30,10 +31,18 @@ pub trait TypeOp<'tcx>: Sized + fmt::Debug {
     /// 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<'_, 'tcx>,
-    ) -> Fallible<(Self::Output, Option<Rc<QueryRegionConstraints<'tcx>>>)>;
+    fn fully_perform(self, infcx: &InferCtxt<'_, 'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>>;
+}
+
+/// The output from performing a type op
+pub struct TypeOpOutput<'tcx, Op: TypeOp<'tcx>> {
+    /// The output from the type op.
+    pub output: Op::Output,
+    /// Any region constraints from performing the type op.
+    pub constraints: Option<Rc<QueryRegionConstraints<'tcx>>>,
+    /// The canonicalized form of the query.
+    /// This for error reporting to be able to rerun the query.
+    pub canonicalized_query: Option<Canonical<'tcx, Op>>,
 }
 
 /// "Query type ops" are type ops that are implemented using a
@@ -45,7 +54,7 @@ pub trait TypeOp<'tcx>: Sized + fmt::Debug {
 /// which produces the resulting query region constraints.
 ///
 /// [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html
-pub trait QueryTypeOp<'tcx>: fmt::Debug + Sized + TypeFoldable<'tcx> + 'tcx {
+pub trait QueryTypeOp<'tcx>: fmt::Debug + Copy + TypeFoldable<'tcx> + 'tcx {
     type QueryResponse: TypeFoldable<'tcx>;
 
     /// Give query the option for a simple fast path that never
@@ -71,9 +80,9 @@ pub trait QueryTypeOp<'tcx>: fmt::Debug + Sized + TypeFoldable<'tcx> + 'tcx {
         query_key: ParamEnvAnd<'tcx, Self>,
         infcx: &InferCtxt<'_, 'tcx>,
         output_query_region_constraints: &mut QueryRegionConstraints<'tcx>,
-    ) -> Fallible<Self::QueryResponse> {
+    ) -> Fallible<(Self::QueryResponse, Option<Canonical<'tcx, ParamEnvAnd<'tcx, Self>>>)> {
         if let Some(result) = QueryTypeOp::try_fast_path(infcx.tcx, &query_key) {
-            return Ok(result);
+            return Ok((result, None));
         }
 
         // FIXME(#33684) -- We need to use
@@ -101,14 +110,14 @@ pub trait QueryTypeOp<'tcx>: fmt::Debug + Sized + TypeFoldable<'tcx> + 'tcx {
         // create obligations. In that case, we have to go
         // fulfill them. We do this via a (recursive) query.
         for obligation in obligations {
-            let () = ProvePredicate::fully_perform_into(
+            let ((), _) = ProvePredicate::fully_perform_into(
                 obligation.param_env.and(ProvePredicate::new(obligation.predicate)),
                 infcx,
                 output_query_region_constraints,
             )?;
         }
 
-        Ok(value)
+        Ok((value, Some(canonical_self)))
     }
 }
 
@@ -118,18 +127,16 @@ where
 {
     type Output = Q::QueryResponse;
 
-    fn fully_perform(
-        self,
-        infcx: &InferCtxt<'_, 'tcx>,
-    ) -> Fallible<(Self::Output, Option<Rc<QueryRegionConstraints<'tcx>>>)> {
+    fn fully_perform(self, infcx: &InferCtxt<'_, 'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>> {
         let mut region_constraints = QueryRegionConstraints::default();
-        let r = Q::fully_perform_into(self, infcx, &mut region_constraints)?;
+        let (output, canonicalized_query) =
+            Q::fully_perform_into(self, infcx, &mut region_constraints)?;
 
         // Promote the final query-region-constraints into a
         // (optional) ref-counted vector:
-        let opt_qrc =
+        let region_constraints =
             if region_constraints.is_empty() { None } else { Some(Rc::new(region_constraints)) };
 
-        Ok((r, opt_qrc))
+        Ok(TypeOpOutput { output, constraints: region_constraints, canonicalized_query })
     }
 }