about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2018-06-08 09:29:41 -0400
committerNiko Matsakis <niko@alum.mit.edu>2018-06-26 10:49:24 -0400
commitdfd33f593218aa47030e3d9abc12bf19c3c7525d (patch)
treec14e04662228b64646013cc4ab0cb4465c1970f2 /src
parenta1811cef764ebae9715947066c19ea171b7927f1 (diff)
downloadrust-dfd33f593218aa47030e3d9abc12bf19c3c7525d.tar.gz
rust-dfd33f593218aa47030e3d9abc12bf19c3c7525d.zip
move `make_query_response` into method on infcx
Diffstat (limited to 'src')
-rw-r--r--src/librustc/infer/canonical/query_result.rs131
-rw-r--r--src/librustc_traits/dropck_outlives.rs27
-rw-r--r--src/librustc_traits/lib.rs1
-rw-r--r--src/librustc_traits/normalize_projection_ty.rs4
-rw-r--r--src/librustc_traits/util.rs123
5 files changed, 148 insertions, 138 deletions
diff --git a/src/librustc/infer/canonical/query_result.rs b/src/librustc/infer/canonical/query_result.rs
index b1eed05c2a2..aff9136bad0 100644
--- a/src/librustc/infer/canonical/query_result.rs
+++ b/src/librustc/infer/canonical/query_result.rs
@@ -17,11 +17,16 @@
 //!
 //! [c]: https://rust-lang-nursery.github.io/rustc-guide/traits/canonicalization.html
 
-use infer::canonical::{Canonical, CanonicalVarValues, QueryRegionConstraint, QueryResult};
 use infer::canonical::substitute::substitute_value;
+use infer::canonical::{
+    Canonical, CanonicalVarValues, Canonicalize, Certainty, QueryRegionConstraint, QueryResult,
+};
+use infer::region_constraints::{Constraint, RegionConstraintData};
 use infer::{InferCtxt, InferOk, InferResult};
 use rustc_data_structures::indexed_vec::Idx;
 use std::fmt::Debug;
+use traits::query::NoSolution;
+use traits::{FulfillmentContext, TraitEngine};
 use traits::{Obligation, ObligationCause, PredicateObligation};
 use ty::fold::TypeFoldable;
 use ty::subst::{Kind, UnpackedKind};
@@ -29,7 +34,131 @@ use ty::{self, CanonicalVar};
 
 use rustc_data_structures::indexed_vec::IndexVec;
 
+type CanonicalizedQueryResult<'gcx, 'tcx, T> =
+    <QueryResult<'tcx, T> as Canonicalize<'gcx, 'tcx>>::Canonicalized;
+
 impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
+    /// This method is meant to be invoked as the final step of a canonical query
+    /// implementation. It is given:
+    ///
+    /// - the instantiated variables `inference_vars` created from the query key
+    /// - the result `answer` of the query
+    /// - a fulfillment context `fulfill_cx` that may contain various obligations which
+    ///   have yet to be proven.
+    ///
+    /// Given this, the function will process the obligations pending
+    /// in `fulfill_cx`:
+    ///
+    /// - If all the obligations can be proven successfully, it will
+    ///   package up any resulting region obligations (extracted from
+    ///   `infcx`) along with the fully resolved value `answer` into a
+    ///   query result (which is then itself canonicalized).
+    /// - If some obligations can be neither proven nor disproven, then
+    ///   the same thing happens, but the resulting query is marked as ambiguous.
+    /// - Finally, if any of the obligations result in a hard error,
+    ///   then `Err(NoSolution)` is returned.
+    pub fn make_canonicalized_query_result<T>(
+        &self,
+        inference_vars: CanonicalVarValues<'tcx>,
+        answer: T,
+        fulfill_cx: &mut FulfillmentContext<'tcx>,
+    ) -> Result<CanonicalizedQueryResult<'gcx, 'tcx, T>, NoSolution>
+    where
+        T: Debug,
+        QueryResult<'tcx, T>: Canonicalize<'gcx, 'tcx>,
+    {
+        let tcx = self.tcx;
+
+        debug!(
+            "make_query_response(\
+             inference_vars={:?}, \
+             answer={:?})",
+            inference_vars, answer,
+        );
+
+        // Select everything, returning errors.
+        let true_errors = match fulfill_cx.select_where_possible(self) {
+            Ok(()) => vec![],
+            Err(errors) => errors,
+        };
+        debug!("true_errors = {:#?}", true_errors);
+
+        if !true_errors.is_empty() {
+            // FIXME -- we don't indicate *why* we failed to solve
+            debug!("make_query_response: true_errors={:#?}", true_errors);
+            return Err(NoSolution);
+        }
+
+        // Anything left unselected *now* must be an ambiguity.
+        let ambig_errors = match fulfill_cx.select_all_or_error(self) {
+            Ok(()) => vec![],
+            Err(errors) => errors,
+        };
+        debug!("ambig_errors = {:#?}", ambig_errors);
+
+        let region_obligations = self.take_registered_region_obligations();
+
+        let region_constraints = self.with_region_constraints(|region_constraints| {
+            let RegionConstraintData {
+                constraints,
+                verifys,
+                givens,
+            } = region_constraints;
+
+            assert!(verifys.is_empty());
+            assert!(givens.is_empty());
+
+            let mut outlives: Vec<_> = constraints
+            .into_iter()
+            .map(|(k, _)| match *k {
+                // Swap regions because we are going from sub (<=) to outlives
+                // (>=).
+                Constraint::VarSubVar(v1, v2) => ty::OutlivesPredicate(
+                    tcx.mk_region(ty::ReVar(v2)).into(),
+                    tcx.mk_region(ty::ReVar(v1)),
+                ),
+                Constraint::VarSubReg(v1, r2) => {
+                    ty::OutlivesPredicate(r2.into(), tcx.mk_region(ty::ReVar(v1)))
+                }
+                Constraint::RegSubVar(r1, v2) => {
+                    ty::OutlivesPredicate(tcx.mk_region(ty::ReVar(v2)).into(), r1)
+                }
+                Constraint::RegSubReg(r1, r2) => ty::OutlivesPredicate(r2.into(), r1),
+            })
+            .map(ty::Binder::dummy) // no bound regions in the code above
+            .collect();
+
+            outlives.extend(
+                region_obligations
+                    .into_iter()
+                    .map(|(_, r_o)| ty::OutlivesPredicate(r_o.sup_type.into(), r_o.sub_region))
+                    .map(ty::Binder::dummy), // no bound regions in the code above
+            );
+
+            outlives
+        });
+
+        let certainty = if ambig_errors.is_empty() {
+            Certainty::Proven
+        } else {
+            Certainty::Ambiguous
+        };
+
+        let (canonical_result, _) = self.canonicalize_response(&QueryResult {
+            var_values: inference_vars,
+            region_constraints,
+            certainty,
+            value: answer,
+        });
+
+        debug!(
+            "make_query_response: canonical_result = {:#?}",
+            canonical_result
+        );
+
+        Ok(canonical_result)
+    }
+
     /// Given the (canonicalized) result to a canonical query,
     /// instantiates the result so it can be used, plugging in the
     /// values from the canonical query. (Note that the result may
diff --git a/src/librustc_traits/dropck_outlives.rs b/src/librustc_traits/dropck_outlives.rs
index 219c6b9aefb..cd49aa2241b 100644
--- a/src/librustc_traits/dropck_outlives.rs
+++ b/src/librustc_traits/dropck_outlives.rs
@@ -8,17 +8,16 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use rustc::infer::canonical::{Canonical, QueryResult};
 use rustc::hir::def_id::DefId;
-use rustc::traits::{FulfillmentContext, Normalized, ObligationCause};
+use rustc::infer::canonical::{Canonical, QueryResult};
+use rustc::traits::query::dropck_outlives::{DropckOutlivesResult, DtorckConstraint};
 use rustc::traits::query::{CanonicalTyGoal, NoSolution};
-use rustc::traits::query::dropck_outlives::{DtorckConstraint, DropckOutlivesResult};
-use rustc::ty::{self, ParamEnvAnd, Ty, TyCtxt};
+use rustc::traits::{FulfillmentContext, Normalized, ObligationCause};
 use rustc::ty::subst::{Subst, Substs};
+use rustc::ty::{self, ParamEnvAnd, Ty, TyCtxt};
 use rustc::util::nodemap::FxHashSet;
 use rustc_data_structures::sync::Lrc;
 use syntax::codemap::{Span, DUMMY_SP};
-use util;
 
 crate fn dropck_outlives<'tcx>(
     tcx: TyCtxt<'_, 'tcx, 'tcx>,
@@ -36,7 +35,10 @@ crate fn dropck_outlives<'tcx>(
             canonical_inference_vars,
         ) = infcx.instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &goal);
 
-        let mut result = DropckOutlivesResult { kinds: vec![], overflows: vec![] };
+        let mut result = DropckOutlivesResult {
+            kinds: vec![],
+            overflows: vec![],
+        };
 
         // A stack of types left to process. Each round, we pop
         // something from the stack and invoke
@@ -135,7 +137,7 @@ crate fn dropck_outlives<'tcx>(
 
         debug!("dropck_outlives: result = {:#?}", result);
 
-        util::make_query_response(infcx, canonical_inference_vars, result, fulfill_cx)
+        infcx.make_canonicalized_query_result(canonical_inference_vars, result, fulfill_cx)
     })
 }
 
@@ -184,7 +186,8 @@ fn dtorck_constraint_for_ty<'a, 'gcx, 'tcx>(
             dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ety)
         }
 
-        ty::TyTuple(tys) => tys.iter()
+        ty::TyTuple(tys) => tys
+            .iter()
             .map(|ty| dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ty))
             .collect(),
 
@@ -222,7 +225,10 @@ fn dtorck_constraint_for_ty<'a, 'gcx, 'tcx>(
                 dtorck_types: vec![],
                 overflows: vec![],
             };
-            debug!("dtorck_constraint: generator {:?} => {:?}", def_id, constraint);
+            debug!(
+                "dtorck_constraint: generator {:?} => {:?}",
+                def_id, constraint
+            );
 
             Ok(constraint)
         }
@@ -291,7 +297,8 @@ crate fn adt_dtorck_constraint<'a, 'tcx>(
         return Ok(result);
     }
 
-    let mut result = def.all_fields()
+    let mut result = def
+        .all_fields()
         .map(|field| tcx.type_of(field.did))
         .map(|fty| dtorck_constraint_for_ty(tcx, span, fty, 0, fty))
         .collect::<Result<DtorckConstraint, NoSolution>>()?;
diff --git a/src/librustc_traits/lib.rs b/src/librustc_traits/lib.rs
index c3135439204..830aa93c3c3 100644
--- a/src/librustc_traits/lib.rs
+++ b/src/librustc_traits/lib.rs
@@ -33,7 +33,6 @@ mod dropck_outlives;
 mod evaluate_obligation;
 mod normalize_projection_ty;
 mod normalize_erasing_regions;
-mod util;
 pub mod lowering;
 
 use rustc::ty::query::Providers;
diff --git a/src/librustc_traits/normalize_projection_ty.rs b/src/librustc_traits/normalize_projection_ty.rs
index a9ac53972e4..a9c4fef9f7d 100644
--- a/src/librustc_traits/normalize_projection_ty.rs
+++ b/src/librustc_traits/normalize_projection_ty.rs
@@ -15,7 +15,6 @@ use rustc::ty::{ParamEnvAnd, TyCtxt};
 use rustc_data_structures::sync::Lrc;
 use syntax::ast::DUMMY_NODE_ID;
 use syntax_pos::DUMMY_SP;
-use util;
 use std::sync::atomic::Ordering;
 
 crate fn normalize_projection_ty<'tcx>(
@@ -43,8 +42,7 @@ crate fn normalize_projection_ty<'tcx>(
 
         // Now that we have fulfilled as much as we can, create a solution
         // from what we've learned.
-        util::make_query_response(
-            infcx,
+        infcx.make_canonicalized_query_result(
             canonical_inference_vars,
             NormalizationResult { normalized_ty: answer },
             fulfill_cx,
diff --git a/src/librustc_traits/util.rs b/src/librustc_traits/util.rs
deleted file mode 100644
index cdf20bdafad..00000000000
--- a/src/librustc_traits/util.rs
+++ /dev/null
@@ -1,123 +0,0 @@
-// 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::InferCtxt;
-use rustc::infer::canonical::{CanonicalVarValues, Canonicalize, Certainty, QueryResult};
-use rustc::infer::region_constraints::{Constraint, RegionConstraintData};
-use rustc::traits::{FulfillmentContext, TraitEngine};
-use rustc::traits::query::NoSolution;
-use rustc::ty;
-use std::fmt::Debug;
-
-/// The canonicalization form of `QueryResult<'tcx, T>`.
-type CanonicalizedQueryResult<'gcx, 'tcx, T> =
-    <QueryResult<'tcx, T> as Canonicalize<'gcx, 'tcx>>::Canonicalized;
-
-crate fn make_query_response<'gcx, 'tcx, T>(
-    infcx: &InferCtxt<'_, 'gcx, 'tcx>,
-    inference_vars: CanonicalVarValues<'tcx>,
-    answer: T,
-    fulfill_cx: &mut FulfillmentContext<'tcx>,
-) -> Result<CanonicalizedQueryResult<'gcx, 'tcx, T>, NoSolution>
-where
-    T: Debug,
-    QueryResult<'tcx, T>: Canonicalize<'gcx, 'tcx>,
-{
-    let tcx = infcx.tcx;
-
-    debug!(
-        "make_query_response(\
-         inference_vars={:?}, \
-         answer={:?})",
-        inference_vars, answer,
-    );
-
-    // Select everything, returning errors.
-    let true_errors = match fulfill_cx.select_where_possible(infcx) {
-        Ok(()) => vec![],
-        Err(errors) => errors,
-    };
-    debug!("true_errors = {:#?}", true_errors);
-
-    if !true_errors.is_empty() {
-        // FIXME -- we don't indicate *why* we failed to solve
-        debug!("make_query_response: true_errors={:#?}", true_errors);
-        return Err(NoSolution);
-    }
-
-    // Anything left unselected *now* must be an ambiguity.
-    let ambig_errors = match fulfill_cx.select_all_or_error(infcx) {
-        Ok(()) => vec![],
-        Err(errors) => errors,
-    };
-    debug!("ambig_errors = {:#?}", ambig_errors);
-
-    let region_obligations = infcx.take_registered_region_obligations();
-
-    let region_constraints = infcx.with_region_constraints(|region_constraints| {
-        let RegionConstraintData {
-            constraints,
-            verifys,
-            givens,
-        } = region_constraints;
-
-        assert!(verifys.is_empty());
-        assert!(givens.is_empty());
-
-        let mut outlives: Vec<_> = constraints
-            .into_iter()
-            .map(|(k, _)| match *k {
-                // Swap regions because we are going from sub (<=) to outlives
-                // (>=).
-                Constraint::VarSubVar(v1, v2) => ty::OutlivesPredicate(
-                    tcx.mk_region(ty::ReVar(v2)).into(),
-                    tcx.mk_region(ty::ReVar(v1)),
-                ),
-                Constraint::VarSubReg(v1, r2) => {
-                    ty::OutlivesPredicate(r2.into(), tcx.mk_region(ty::ReVar(v1)))
-                }
-                Constraint::RegSubVar(r1, v2) => {
-                    ty::OutlivesPredicate(tcx.mk_region(ty::ReVar(v2)).into(), r1)
-                }
-                Constraint::RegSubReg(r1, r2) => ty::OutlivesPredicate(r2.into(), r1),
-            })
-            .map(ty::Binder::dummy) // no bound regions in the code above
-            .collect();
-
-        outlives.extend(
-            region_obligations
-                .into_iter()
-                .map(|(_, r_o)| ty::OutlivesPredicate(r_o.sup_type.into(), r_o.sub_region))
-                .map(ty::Binder::dummy) // no bound regions in the code above
-        );
-
-        outlives
-    });
-
-    let certainty = if ambig_errors.is_empty() {
-        Certainty::Proven
-    } else {
-        Certainty::Ambiguous
-    };
-
-    let (canonical_result, _) = infcx.canonicalize_response(&QueryResult {
-        var_values: inference_vars,
-        region_constraints,
-        certainty,
-        value: answer,
-    });
-
-    debug!(
-        "make_query_response: canonical_result = {:#?}",
-        canonical_result
-    );
-
-    Ok(canonical_result)
-}