]> git.lizzy.rs Git - rust.git/commitdiff
expose `evaluate_obligation` that captures overflow, use in rustdoc
authorNiko Matsakis <niko@alum.mit.edu>
Thu, 13 Sep 2018 18:59:01 +0000 (14:59 -0400)
committerNiko Matsakis <niko@alum.mit.edu>
Thu, 13 Sep 2018 18:59:01 +0000 (14:59 -0400)
src/librustc/traits/query/evaluate_obligation.rs
src/librustdoc/clean/blanket_impl.rs

index 1a906b5da6f322220a6271d0f4fdf041b4926b51..f573b1ef45e9c677238982d3867de5f8a63c333c 100644 (file)
@@ -20,7 +20,7 @@ pub fn predicate_may_hold(
         &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,22 +30,31 @@ pub fn predicate_must_hold(
         &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 =
index e7e371cd5678569fafbbc64bf074eaf495daf8df..3d591a702aaa9134542374a965c9534665d36589 100644 (file)
@@ -103,11 +103,20 @@ pub fn get_blanket_impls<F>(
                         // FIXME(eddyb) ignoring `obligations` might cause false positives.
                         drop(obligations);
 
-                        let may_apply = infcx.predicate_may_hold(&traits::Obligation::new(
-                            cause.clone(),
-                            param_env,
-                            trait_ref.to_predicate(),
-                        ));
+                        debug!(
+                            "invoking predicate_may_hold: {:?}",
+                            trait_ref,
+                        );
+                        let may_apply = match infcx.evaluate_obligation(
+                            &traits::Obligation::new(
+                                cause.clone(),
+                                param_env,
+                                trait_ref.to_predicate(),
+                            ),
+                        ) {
+                            Ok(eval_result) => eval_result.may_apply(),
+                            Err(traits::OverflowError) => true, // overflow doesn't mean yes *or* no
+                        };
                         if !may_apply {
                             return
                         }