about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2015-01-12 10:19:47 -0500
committerNiko Matsakis <niko@alum.mit.edu>2015-01-28 05:15:24 -0500
commit47c2d3103874b2f07d91179fc13609904cd9639b (patch)
treefa61a2da7a4a5e5bf5bfb5bec661d57ba99919d9
parent25a27977fa1cbaddd4c2275881bee358eeaeb8a1 (diff)
downloadrust-47c2d3103874b2f07d91179fc13609904cd9639b.tar.gz
rust-47c2d3103874b2f07d91179fc13609904cd9639b.zip
Extract expectations from the projection obligation, which includes
all relevant information.
-rw-r--r--src/librustc_typeck/check/closure.rs88
1 files changed, 49 insertions, 39 deletions
diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs
index 2d7a7634472..bdae34e7878 100644
--- a/src/librustc_typeck/check/closure.rs
+++ b/src/librustc_typeck/check/closure.rs
@@ -34,7 +34,7 @@ pub fn check_expr_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
            expected.repr(fcx.tcx()));
 
     let expected_sig_and_kind = expected.to_option(fcx).and_then(|ty| {
-        deduce_closure_expectations_from_expected_type(fcx, ty)
+        deduce_expectations_from_expected_type(fcx, ty)
     });
 
     match opt_kind {
@@ -137,20 +137,21 @@ fn check_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
     fcx.inh.closures.borrow_mut().insert(expr_def_id, closure);
 }
 
-fn deduce_closure_expectations_from_expected_type<'a,'tcx>(
+fn deduce_expectations_from_expected_type<'a,'tcx>(
     fcx: &FnCtxt<'a,'tcx>,
     expected_ty: Ty<'tcx>)
     -> Option<(ty::FnSig<'tcx>,ty::ClosureKind)>
 {
     match expected_ty.sty {
         ty::ty_trait(ref object_type) => {
-            let trait_ref =
-                object_type.principal_trait_ref_with_self_ty(fcx.tcx(),
-                                                             fcx.tcx().types.err);
-            deduce_closure_expectations_from_trait_ref(fcx, &trait_ref)
+            let proj_bounds = object_type.projection_bounds_with_self_ty(fcx.tcx(),
+                                                                         fcx.tcx().types.err);
+            proj_bounds.iter()
+                       .filter_map(|pb| deduce_expectations_from_projection(fcx, pb))
+                       .next()
         }
         ty::ty_infer(ty::TyVar(vid)) => {
-            deduce_closure_expectations_from_obligations(fcx, vid)
+            deduce_expectations_from_obligations(fcx, vid)
         }
         _ => {
             None
@@ -158,15 +159,51 @@ fn deduce_closure_expectations_from_expected_type<'a,'tcx>(
     }
 }
 
-fn deduce_closure_expectations_from_trait_ref<'a,'tcx>(
+fn deduce_expectations_from_obligations<'a,'tcx>(
     fcx: &FnCtxt<'a,'tcx>,
-    trait_ref: &ty::PolyTraitRef<'tcx>)
+    expected_vid: ty::TyVid)
+    -> Option<(ty::FnSig<'tcx>, ty::ClosureKind)>
+{
+    let fulfillment_cx = fcx.inh.fulfillment_cx.borrow();
+    // Here `expected_ty` is known to be a type inference variable.
+
+    fulfillment_cx.pending_obligations()
+                  .iter()
+                  .filter_map(|obligation| {
+                      match obligation.predicate {
+                          ty::Predicate::Projection(ref proj_predicate) => {
+                              let trait_ref = proj_predicate.to_poly_trait_ref();
+                              let self_ty = fcx.infcx().shallow_resolve(trait_ref.self_ty());
+                              match self_ty.sty {
+                                  ty::ty_infer(ty::TyVar(v)) if expected_vid == v => {
+                                      deduce_expectations_from_projection(fcx, proj_predicate)
+                                  }
+                                  _ => {
+                                      None
+                                  }
+                              }
+                          }
+                          _ => {
+                              None
+                          }
+                      }
+                  })
+                  .next()
+}
+
+/// Given a projection like "<F as Fn(X)>::Result == Y", we can deduce
+/// everything we need to know about a closure.
+fn deduce_expectations_from_projection<'a,'tcx>(
+    fcx: &FnCtxt<'a,'tcx>,
+    projection: &ty::PolyProjectionPredicate<'tcx>)
     -> Option<(ty::FnSig<'tcx>, ty::ClosureKind)>
 {
     let tcx = fcx.tcx();
 
-    debug!("deduce_closure_expectations_from_object_type({})",
-           trait_ref.repr(tcx));
+    debug!("deduce_expectations_from_projection({})",
+           projection.repr(tcx));
+
+    let trait_ref = projection.to_poly_trait_ref();
 
     let kind = match tcx.lang_items.fn_trait_kind(trait_ref.def_id()) {
         Some(k) => k,
@@ -185,7 +222,7 @@ fn deduce_closure_expectations_from_trait_ref<'a,'tcx>(
     };
     debug!("input_tys {}", input_tys.repr(tcx));
 
-    let ret_param_ty = *trait_ref.substs().types.get(subst::TypeSpace, 1);
+    let ret_param_ty = projection.0.ty;
     let ret_param_ty = fcx.infcx().resolve_type_vars_if_possible(&ret_param_ty);
     debug!("ret_param_ty {}", ret_param_ty.repr(tcx));
 
@@ -199,30 +236,3 @@ fn deduce_closure_expectations_from_trait_ref<'a,'tcx>(
     return Some((fn_sig, kind));
 }
 
-fn deduce_closure_expectations_from_obligations<'a,'tcx>(
-    fcx: &FnCtxt<'a,'tcx>,
-    expected_vid: ty::TyVid)
-    -> Option<(ty::FnSig<'tcx>, ty::ClosureKind)>
-{
-    // Here `expected_ty` is known to be a type inference variable.
-    for obligation in fcx.inh.fulfillment_cx.borrow().pending_obligations().iter() {
-        match obligation.predicate {
-            ty::Predicate::Trait(ref trait_predicate) => {
-                let trait_ref = trait_predicate.to_poly_trait_ref();
-                let self_ty = fcx.infcx().shallow_resolve(trait_ref.self_ty());
-                match self_ty.sty {
-                    ty::ty_infer(ty::TyVar(v)) if expected_vid == v => { }
-                    _ => { continue; }
-                }
-
-                match deduce_closure_expectations_from_trait_ref(fcx, &trait_ref) {
-                    Some(e) => { return Some(e); }
-                    None => { }
-                }
-            }
-            _ => { }
-        }
-    }
-
-    None
-}