summary refs log tree commit diff
path: root/src/librustc/traits
diff options
context:
space:
mode:
Diffstat (limited to 'src/librustc/traits')
-rw-r--r--src/librustc/traits/project.rs2
-rw-r--r--src/librustc/traits/query/evaluate_obligation.rs32
-rw-r--r--src/librustc/traits/select.rs5
-rw-r--r--src/librustc/traits/structural_impls.rs2
4 files changed, 30 insertions, 11 deletions
diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs
index e50f59cbc82..d5e887f2424 100644
--- a/src/librustc/traits/project.rs
+++ b/src/librustc/traits/project.rs
@@ -894,7 +894,7 @@ fn project_type<'cx, 'gcx, 'tcx>(
     let recursion_limit = *selcx.tcx().sess.recursion_limit.get();
     if obligation.recursion_depth >= recursion_limit {
         debug!("project: overflow!");
-        selcx.infcx().report_overflow_error(&obligation, true);
+        return Err(ProjectionTyError::TraitSelectionError(SelectionError::Overflow));
     }
 
     let obligation_trait_ref = &obligation.predicate.trait_ref(selcx.tcx());
diff --git a/src/librustc/traits/query/evaluate_obligation.rs b/src/librustc/traits/query/evaluate_obligation.rs
index 6bd92678362..f573b1ef45e 100644
--- a/src/librustc/traits/query/evaluate_obligation.rs
+++ b/src/librustc/traits/query/evaluate_obligation.rs
@@ -20,7 +20,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
         &self,
         obligation: &PredicateObligation<'tcx>,
     ) -> bool {
-        self.evaluate_obligation(obligation).may_apply()
+        self.evaluate_obligation_no_overflow(obligation).may_apply()
     }
 
     /// Evaluates whether the predicate can be satisfied in the given
@@ -30,28 +30,44 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
         &self,
         obligation: &PredicateObligation<'tcx>,
     ) -> bool {
-        self.evaluate_obligation(obligation) == EvaluationResult::EvaluatedToOk
+        self.evaluate_obligation_no_overflow(obligation) == EvaluationResult::EvaluatedToOk
     }
 
-    // Helper function that canonicalizes and runs the query, as well as handles
-    // overflow.
-    fn evaluate_obligation(
+    /// Evaluate a given predicate, capturing overflow and propagating it back.
+    pub fn evaluate_obligation(
         &self,
         obligation: &PredicateObligation<'tcx>,
-    ) -> EvaluationResult {
+    ) -> Result<EvaluationResult, OverflowError> {
         let mut _orig_values = SmallVec::new();
         let c_pred = self.canonicalize_query(&obligation.param_env.and(obligation.predicate),
                                              &mut _orig_values);
         // Run canonical query. If overflow occurs, rerun from scratch but this time
         // in standard trait query mode so that overflow is handled appropriately
         // within `SelectionContext`.
-        match self.tcx.global_tcx().evaluate_obligation(c_pred) {
+        self.tcx.global_tcx().evaluate_obligation(c_pred)
+    }
+
+    // Helper function that canonicalizes and runs the query. If an
+    // overflow results, we re-run it in the local context so we can
+    // report a nice error.
+    fn evaluate_obligation_no_overflow(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+    ) -> EvaluationResult {
+        match self.evaluate_obligation(obligation) {
             Ok(result) => result,
             Err(OverflowError) => {
                 let mut selcx =
                     SelectionContext::with_query_mode(&self, TraitQueryMode::Standard);
                 selcx.evaluate_obligation_recursively(obligation)
-                     .expect("Overflow should be caught earlier in standard query mode")
+                    .unwrap_or_else(|r| {
+                        span_bug!(
+                            obligation.cause.span,
+                            "Overflow should be caught earlier in standard query mode: {:?}, {:?}",
+                            obligation,
+                            r,
+                        )
+                    })
             }
         }
     }
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index 232ef108537..706d038812e 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -1376,7 +1376,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
         let tcx = self.tcx();
         let trait_ref = cache_fresh_trait_pred.skip_binder().trait_ref;
         if self.can_use_global_caches(param_env) {
-            if let Some(trait_ref) = tcx.lift_to_global(&trait_ref) {
+            if let Err(Overflow) = candidate {
+                // Don't cache overflow globally; we only produce this
+                // in certain modes.
+            } else if let Some(trait_ref) = tcx.lift_to_global(&trait_ref) {
                 if let Some(candidate) = tcx.lift_to_global(&candidate) {
                     debug!(
                         "insert_candidate_cache(trait_ref={:?}, candidate={:?}) global",
diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs
index 10e930d1c92..6b0b1c35a7e 100644
--- a/src/librustc/traits/structural_impls.rs
+++ b/src/librustc/traits/structural_impls.rs
@@ -175,7 +175,7 @@ impl<'a, 'tcx> Lift<'tcx> for traits::SelectionError<'a> {
             super::ConstEvalFailure(ref err) => tcx.lift(&**err).map(|err| super::ConstEvalFailure(
                 err.into(),
             )),
-            super::Overflow => bug!(), // FIXME: ape ConstEvalFailure?
+            super::Overflow => Some(super::Overflow),
         }
     }
 }