Change:
} } <ins> /// Normalizes the parameter environment, reporting errors if they occur. </ins> pub fn normalize_param_env_or_error<'a,'tcx>(unnormalized_env: ty::ParameterEnvironment<'a,'tcx>, cause: ObligationCause<'tcx>) -> ty::ParameterEnvironment<'a,'tcx> { <del> match normalize_param_env(&unnormalized_env, cause) { Ok(p) => p, </del> <ins> // I'm not wild about reporting errors here; I'd prefer to // have the errors get reported at a defined place (e.g., // during typeck). Instead I have all parameter // environments, in effect, going through this function // and hence potentially reporting errors. This ensurse of // course that we never forget to normalize (the // alternative seemed like it would involve a lot of // manual invocations of this fn -- and then we'd have to // deal with the errors at each of those sites). // // In any case, in practice, typeck constructs all the // parameter environments once for every fn as it goes, // and errors will get reported then; so after typeck we // can be sure that no errors should occur. let tcx = unnormalized_env.tcx; let span = cause.span; let body_id = cause.body_id; debug!("normalize_param_env_or_error(unnormalized_env={})", unnormalized_env.repr(tcx)); let infcx = infer::new_infer_ctxt(tcx); let predicates = match fully_normalize(&infcx, &unnormalized_env, cause, &unnormalized_env.caller_bounds) { Ok(predicates) => predicates, </ins> Err(errors) => { <del> // I'm not wild about reporting errors here; I'd prefer to // have the errors get reported at a defined place (e.g., // during typeck). Instead I have all parameter // environments, in effect, going through this function // and hence potentially reporting errors. This ensurse of // course that we never forget to normalize (the // alternative seemed like it would involve a lot of // manual invocations of this fn -- and then we'd have to // deal with the errors at each of those sites). // // In any case, in practice, typeck constructs all the // parameter environments once for every fn as it goes, // and errors will get reported then; so after typeck we // can be sure that no errors should occur. let infcx = infer::new_infer_ctxt(unnormalized_env.tcx); </del> report_fulfillment_errors(&infcx, &errors); <del> // Normalized failed? use what they gave us, it's better than nothing. unnormalized_env </del> <ins> return unnormalized_env; // an unnormalized env is better than nothing </ins> } <del> } } pub fn normalize_param_env<'a,'tcx>(param_env: &ty::ParameterEnvironment<'a,'tcx>, cause: ObligationCause<'tcx>) -> Result<ty::ParameterEnvironment<'a,'tcx>, Vec<FulfillmentError<'tcx>>> { let tcx = param_env.tcx; debug!("normalize_param_env(param_env={})", param_env.repr(tcx)); </del> <ins> }; </ins> <del> let infcx = infer::new_infer_ctxt(tcx); let predicates = try!(fully_normalize(&infcx, param_env, cause, &param_env.caller_bounds)); </del> <ins> infcx.resolve_regions_and_report_errors(body_id); let predicates = match infcx.fully_resolve(&predicates) { Ok(predicates) => predicates, Err(fixup_err) => { // If we encounter a fixup error, it means that some type // variable wound up unconstrained. I actually don't know // if this can happen, and I certainly don't expect it to // happen often, but if it did happen it probably // represents a legitimate failure due to some kind of // unconstrained variable, and it seems better not to ICE, // all things considered. let err_msg = fixup_err_to_string(fixup_err); tcx.sess.span_err(span, &err_msg); return unnormalized_env; // an unnormalized env is better than nothing } }; </ins> <del> debug!("normalize_param_env: predicates={}", </del> <ins> debug!("normalize_param_env_or_error: predicates={}", </ins> predicates.repr(tcx)); <del> Ok(param_env.with_caller_bounds(predicates)) </del> <ins> unnormalized_env.with_caller_bounds(predicates) </ins> } pub fn fully_normalize<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,

Discussion:
Attempting to compile with and yields the following ICE:
Reduced test case: Still ICEs with The ICE goes away if the on the is changed to a bare instead of a reference.
Slightly different test case: EDIT: Nevermind, it's the same but uses a closure instead of the more general .
I have bisected this issue to rust-lang/rust (from )
A workaround would be simply:
This doesn't help much if you need to call methods that are on the trait (which was on the original code).
cc me
This is blocking collect-rs from compiling.
This is interesting. The culprit is : it registers obligations from implementation's methods into an hybrid parameter environment which has trait's methods in it. In the example given in this issue, when the associate type is projected out, the implementation's method acquires an extra lifetime variable. The trait's method doesn't have it so the lifetime resolution fails in an ICE later on. I'm not sure how to fix that though.
This compiles so at first glance it looks like a viable workaround: But if one tries to really use as an , compiler panics on an assertion failure:
Getting this with some hashing code.

will output something along the lines of: Start hash BYTES: [69, 84, 87, 87, 100, 57, 118, 102, 80, 97, 122, 56, 100, 116, 80, 82, 74, 78, 104, 116, 109, 51, 88, 54, 56, 98, 56, 97, 66, 119, 105, 116, 90, 114, 50, 83, 107, 99, 51, 52, 89, 121, 121, 112, 86, 116, 57, 66, 120, 87, 86, 112, 88, 55, 66, 49, 76, 90, 86, 48, 49, 53, 56, 53, 52, 48, 56, 56, 49, 53, 54, 48, 51] lyra2 finished: CfV9jehQVXsVnx6Vrg5f9VgHVkWeatbrFGxKVz2knfEc Starting argon thread 'certificate::tests::checkcertdiff' panicked at 'index out of bounds: the len is 0 but the index is 31',