about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2014-12-31 14:42:06 -0500
committerNiko Matsakis <niko@alum.mit.edu>2014-12-31 14:42:06 -0500
commit0a2d531b94f4c49ecc0b190b1feb438e27c3e882 (patch)
tree567d9511b82c9ed2632f1ed80b2c51ab04dc6d50
parent67dab2af81ba64023c526dc96315863a9f7e9e40 (diff)
Teach trans to drain fulfillment context. japaric encountered problems
due to this but we were not able to isolate a smaller test case.
-rw-r--r--src/librustc_trans/trans/common.rs47
-rw-r--r--src/librustc_trans/trans/monomorphize.rs7
2 files changed, 36 insertions, 18 deletions
diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs
index 1b00a77fe51..7c2585becea 100644
--- a/src/librustc_trans/trans/common.rs
+++ b/src/librustc_trans/trans/common.rs
@@ -954,28 +954,47 @@ pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
     // Currently, we use a fulfillment context to completely resolve
     // all nested obligations. This is because they can inform the
-    // inference of the impl's type parameters. However, in principle,
-    // we only need to do this until the impl's type parameters are
-    // fully bound. It could be a slight optimization to stop
-    // iterating early.
+    // inference of the impl's type parameters.
     let mut fulfill_cx = traits::FulfillmentContext::new();
     let vtable = selection.map_move_nested(|predicate| {
         fulfill_cx.register_predicate_obligation(&infcx, predicate);
     });
-    match fulfill_cx.select_all_or_error(&infcx, &param_env, tcx) {
+    let vtable = drain_fulfillment_cx(span, &infcx, &param_env, &mut fulfill_cx, &vtable);
+
+    info!("Cache miss: {}", trait_ref.repr(ccx.tcx()));
+    ccx.trait_cache().borrow_mut().insert(trait_ref,
+                                          vtable.clone());
+
+    vtable
+}
+
+pub fn drain_fulfillment_cx<'a,'tcx,T>(span: Span,
+                                       infcx: &infer::InferCtxt<'a,'tcx>,
+                                       param_env: &ty::ParameterEnvironment<'tcx>,
+                                       fulfill_cx: &mut traits::FulfillmentContext<'tcx>,
+                                       result: &T)
+                                       -> T
+    where T : TypeFoldable<'tcx> + Repr<'tcx>
+{
+    debug!("drain_fulfillment_cx(result={})",
+           result.repr(infcx.tcx));
+
+    // In principle, we only need to do this so long as `result`
+    // contains unbound type parameters. It could be a slight
+    // optimization to stop iterating early.
+    match fulfill_cx.select_all_or_error(infcx, param_env, infcx.tcx) {
         Ok(()) => { }
         Err(errors) => {
             if errors.iter().all(|e| e.is_overflow()) {
                 // See Ok(None) case above.
-                ccx.sess().span_fatal(
+                infcx.tcx.sess.span_fatal(
                     span,
                     "reached the recursion limit during monomorphization");
             } else {
-                tcx.sess.span_bug(
+                infcx.tcx.sess.span_bug(
                     span,
-                    format!("Encountered errors `{}` fulfilling `{}` during trans",
-                            errors.repr(tcx),
-                            trait_ref.repr(tcx))[]);
+                    format!("Encountered errors `{}` fulfilling during trans",
+                            errors.repr(infcx.tcx))[]);
             }
         }
     }
@@ -985,13 +1004,7 @@ pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     // sort of overkill because we do not expect there to be any
     // unbound type variables, hence no `TyFresh` types should ever be
     // inserted.
-    let vtable = vtable.fold_with(&mut infcx.freshener());
-
-    info!("Cache miss: {}", trait_ref.repr(ccx.tcx()));
-    ccx.trait_cache().borrow_mut().insert(trait_ref,
-                                          vtable.clone());
-
-    vtable
+    result.fold_with(&mut infcx.freshener())
 }
 
 // Key used to lookup values supplied for type parameters in an expr.
diff --git a/src/librustc_trans/trans/monomorphize.rs b/src/librustc_trans/trans/monomorphize.rs
index c693c6ea428..fdcb232e125 100644
--- a/src/librustc_trans/trans/monomorphize.rs
+++ b/src/librustc_trans/trans/monomorphize.rs
@@ -31,6 +31,7 @@ use syntax::ast;
 use syntax::ast_map;
 use syntax::ast_util::{local_def, PostExpansionMethod};
 use syntax::attr;
+use syntax::codemap::DUMMY_SP;
 use std::hash::{sip, Hash};
 
 pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
@@ -331,7 +332,11 @@ pub fn normalize_associated_type<'tcx,T>(tcx: &ty::ctxt<'tcx>, value: &T) -> T
            result.repr(tcx),
            obligations.repr(tcx));
 
-    assert_eq!(obligations.len(), 0); // TODO not good enough
+    let mut fulfill_cx = traits::FulfillmentContext::new();
+    for obligation in obligations.into_iter() {
+        fulfill_cx.register_predicate_obligation(&infcx, obligation);
+    }
+    let result = drain_fulfillment_cx(DUMMY_SP, &infcx, &param_env, &mut fulfill_cx, &result);
 
     result
 }