From 92f94765ec2202ccda84a7da97c4d415ffb9b070 Mon Sep 17 00:00:00 2001
From: Niko Matsakis <niko@alum.mit.edu>
Date: Sat, 31 Jan 2015 06:33:41 -0500
Subject: [PATCH] Adjust the handling of trait obligations and defaults to
 account for upvar inference.  Upvar inference can cause some obligations to
 be deferred, notably things like `F : Sized` where `F` is a closure type, or
 `F : FnMut`. Adjust the ordering therefore so that we process all traits and
 apply fallback, do upvar inference, and only then start reporting errors for
 outstanding obligations.

---
 src/librustc_typeck/check/mod.rs    | 3 ++-
 src/librustc_typeck/check/vtable.rs | 9 +++++++--
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 285b4fdf2e8..c58377fc87b 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -493,8 +493,9 @@ fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
             let fcx = check_fn(ccx, fn_ty.unsafety, id, &fn_sig,
                                decl, id, body, &inh);
 
-            vtable::select_all_fcx_obligations_or_error(&fcx);
+            vtable::select_all_fcx_obligations_and_apply_defaults(&fcx);
             upvar::closure_analyze_fn(&fcx, id, decl, body);
+            vtable::select_all_fcx_obligations_or_error(&fcx);
             regionck::regionck_fn(&fcx, id, decl, body);
             writeback::resolve_type_vars_in_fn(&fcx, decl, body);
         }
diff --git a/src/librustc_typeck/check/vtable.rs b/src/librustc_typeck/check/vtable.rs
index 9d8eaf98569..9921a331fa4 100644
--- a/src/librustc_typeck/check/vtable.rs
+++ b/src/librustc_typeck/check/vtable.rs
@@ -277,15 +277,20 @@ fn check_object_type_binds_all_associated_types<'tcx>(tcx: &ty::ctxt<'tcx>,
     }
 }
 
-pub fn select_all_fcx_obligations_or_error(fcx: &FnCtxt) {
+pub fn select_all_fcx_obligations_and_apply_defaults(fcx: &FnCtxt) {
     debug!("select_all_fcx_obligations_or_error");
 
     fcx.inh.deferred_resolutions.borrow_mut()
                                 .retain(|r| !r.attempt_resolution(fcx));
-
     select_fcx_obligations_where_possible(fcx);
     fcx.default_type_parameters();
+    select_fcx_obligations_where_possible(fcx);
+}
 
+pub fn select_all_fcx_obligations_or_error(fcx: &FnCtxt) {
+    debug!("select_all_fcx_obligations_or_error");
+
+    select_all_fcx_obligations_and_apply_defaults(fcx);
     let mut fulfillment_cx = fcx.inh.fulfillment_cx.borrow_mut();
     let r = fulfillment_cx.select_all_or_error(fcx.infcx(), fcx);
     match r {