]> git.lizzy.rs Git - rust.git/commitdiff
propagate sub-obligations better
authorNiko Matsakis <niko@alum.mit.edu>
Fri, 10 Mar 2017 10:19:49 +0000 (05:19 -0500)
committerNiko Matsakis <niko@alum.mit.edu>
Wed, 12 Apr 2017 00:32:46 +0000 (20:32 -0400)
The most interesting place is the hinting mechanism; once we start
having subtyping obligations, it's important to see those through.

src/librustc_typeck/check/method/probe.rs
src/librustc_typeck/check/mod.rs

index 8071fe3cc2806a834f40ad273a059ad7f4b9d74d..59dbbfe49f0a99848f3a712f02cd7fd808bf7eb5 100644 (file)
@@ -1149,19 +1149,16 @@ fn consider_probe(&self,
 
         self.probe(|_| {
             // First check that the self type can be related.
-            match self.sub_types(false,
-                                 &ObligationCause::dummy(),
-                                 self_ty,
-                                 probe.xform_self_ty) {
-                Ok(InferOk { obligations, value: () }) => {
-                    // FIXME(#32730) propagate obligations
-                    assert!(obligations.is_empty())
-                }
+            let sub_obligations = match self.sub_types(false,
+                                                       &ObligationCause::dummy(),
+                                                       self_ty,
+                                                       probe.xform_self_ty) {
+                Ok(InferOk { obligations, value: () }) => obligations,
                 Err(_) => {
                     debug!("--> cannot relate self-types");
                     return false;
                 }
-            }
+            };
 
             // If so, impls may carry other conditions (e.g., where
             // clauses) that must be considered. Make sure that those
@@ -1200,6 +1197,7 @@ fn consider_probe(&self,
             // Evaluate those obligations to see if they might possibly hold.
             let mut all_true = true;
             for o in obligations.iter()
+                .chain(sub_obligations.iter())
                 .chain(norm_obligations.iter())
                 .chain(ref_obligations.iter()) {
                 if !selcx.evaluate_obligation(o) {
index d300552af2caf5e53263bb20d87bd6aeccfd632a..77213b5a7436fddd249b30911adb92ea63f6c7bf 100644 (file)
@@ -90,7 +90,7 @@
 use rustc::infer::{self, InferCtxt, InferOk, RegionVariableOrigin};
 use rustc::infer::type_variable::{TypeVariableOrigin};
 use rustc::ty::subst::{Kind, Subst, Substs};
-use rustc::traits::{self, ObligationCause, ObligationCauseCode, Reveal};
+use rustc::traits::{self, FulfillmentContext, ObligationCause, ObligationCauseCode, Reveal};
 use rustc::ty::{ParamTy, ParameterEnvironment};
 use rustc::ty::{LvaluePreference, NoPreference, PreferMutLvalue};
 use rustc::ty::{self, Ty, TyCtxt, Visibility};
@@ -2552,11 +2552,30 @@ fn expected_inputs_for_expected_output(&self,
                 // No argument expectations are produced if unification fails.
                 let origin = self.misc(call_span);
                 let ures = self.sub_types(false, &origin, formal_ret, ret_ty);
+
                 // FIXME(#15760) can't use try! here, FromError doesn't default
                 // to identity so the resulting type is not constrained.
                 match ures {
-                    Ok(ok) => self.register_infer_ok_obligations(ok),
-                    Err(e) => return Err(e),
+                    Ok(ok) => {
+                        // Process any obligations locally as much as
+                        // we can.  We don't care if some things turn
+                        // out unconstrained or ambiguous, as we're
+                        // just trying to get hints here.
+                        let result = self.save_and_restore_obligations_in_snapshot_flag(|_| {
+                            let mut fulfill = FulfillmentContext::new();
+                            let ok = ok; // FIXME(#30046)
+                            for obligation in ok.obligations {
+                                fulfill.register_predicate_obligation(self, obligation);
+                            }
+                            fulfill.select_where_possible(self)
+                        });
+
+                        match result {
+                            Ok(()) => { }
+                            Err(_) => return Err(()),
+                        }
+                    }
+                    Err(_) => return Err(()),
                 }
 
                 // Record all the argument types, with the substitutions