diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2014-12-31 14:42:06 -0500 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2014-12-31 14:42:06 -0500 |
| commit | 0a2d531b94f4c49ecc0b190b1feb438e27c3e882 (patch) | |
| tree | 567d9511b82c9ed2632f1ed80b2c51ab04dc6d50 | |
| parent | 67dab2af81ba64023c526dc96315863a9f7e9e40 (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.rs | 47 | ||||
| -rw-r--r-- | src/librustc_trans/trans/monomorphize.rs | 7 |
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, ¶m_env, tcx) { + let vtable = drain_fulfillment_cx(span, &infcx, ¶m_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, ¶m_env, &mut fulfill_cx, &result); result } |
