From 4e4bdea0ae8b3b1995b002374db1a7b7639eb52d Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 10 Mar 2017 05:19:49 -0500 Subject: [PATCH] propagate sub-obligations better 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 | 16 +++++++-------- src/librustc_typeck/check/mod.rs | 25 ++++++++++++++++++++--- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 8071fe3cc28..59dbbfe49f0 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -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) { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index d300552af2c..77213b5a743 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -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 -- 2.44.0