Code change:
/// context it's calculated within. This is used by the `type_id` intrinsic. pub fn hash_crate_independent(tcx: &ctxt, ty: Ty, svh: &Svh) -> u64 { let mut state = sip::SipState::new(); <del> macro_rules! byte( ($b:expr) => { ($b as u8).hash(&mut state) } ); macro_rules! hash( ($e:expr) => { $e.hash(&mut state) } ); let region = |_state: &mut sip::SipState, r: Region| { match r { ReStatic => {} ReEmpty | ReEarlyBound(..) | ReLateBound(..) | ReFree(..) | ReScope(..) | ReInfer(..) => { tcx.sess.bug("non-static region found when hashing a type") </del> <ins> helper(tcx, ty, svh, &mut state); return state.result(); fn helper(tcx: &ctxt, ty: Ty, svh: &Svh, state: &mut sip::SipState) { macro_rules! byte( ($b:expr) => { ($b as u8).hash(state) } ); macro_rules! hash( ($e:expr) => { $e.hash(state) } ); let region = |state: &mut sip::SipState, r: Region| { match r { ReStatic => {} ReLateBound(db, BrAnon(i)) => { db.hash(state); i.hash(state); } ReEmpty | ReEarlyBound(..) | ReLateBound(..) | ReFree(..) | ReScope(..) | ReInfer(..) => { tcx.sess.bug("unexpected region found when hashing a type") } </ins> } <del> } }; let did = |state: &mut sip::SipState, did: DefId| { let h = if ast_util::is_local(did) { svh.clone() } else { tcx.sess.cstore.get_crate_hash(did.krate) </del> }; <del> h.as_str().hash(state); did.node.hash(state); }; let mt = |state: &mut sip::SipState, mt: mt| { mt.mutbl.hash(state); }; ty::walk_ty(ty, |ty| { match ty.sty { ty_bool => byte!(2), ty_char => byte!(3), ty_int(i) => { byte!(4); hash!(i); } ty_uint(u) => { byte!(5); hash!(u); } ty_float(f) => { byte!(6); hash!(f); } ty_str => { byte!(7); } ty_enum(d, _) => { byte!(8); did(&mut state, d); } ty_uniq(_) => { byte!(9); } ty_vec(_, Some(n)) => { byte!(10); n.hash(&mut state); } ty_vec(_, None) => { byte!(11); } ty_ptr(m) => { byte!(12); mt(&mut state, m); } ty_rptr(r, m) => { byte!(13); region(&mut state, r); mt(&mut state, m); } ty_bare_fn(ref b) => { byte!(14); hash!(b.unsafety); hash!(b.abi); </del> <ins> let did = |state: &mut sip::SipState, did: DefId| { let h = if ast_util::is_local(did) { svh.clone() } else { tcx.sess.cstore.get_crate_hash(did.krate) }; h.as_str().hash(state); did.node.hash(state); }; let mt = |state: &mut sip::SipState, mt: mt| { mt.mutbl.hash(state); }; let fn_sig = |state: &mut sip::SipState, sig: &FnSig| { let sig = anonymize_late_bound_regions(tcx, sig); for a in sig.inputs.iter() { helper(tcx, *a, svh, state); } if let ty::FnConverging(output) = sig.output { helper(tcx, output, svh, state); </ins> } <del> ty_closure(ref c) => { byte!(15); hash!(c.unsafety); hash!(c.onceness); hash!(c.bounds); match c.store { UniqTraitStore => byte!(0), RegionTraitStore(r, m) => { byte!(1) region(&mut state, r); assert_eq!(m, ast::MutMutable); </del> <ins> }; maybe_walk_ty(ty, |ty| { match ty.sty { ty_bool => byte!(2), ty_char => byte!(3), ty_int(i) => { byte!(4); hash!(i); } ty_uint(u) => { byte!(5); hash!(u); } ty_float(f) => { byte!(6); hash!(f); } ty_str => { byte!(7); } ty_enum(d, _) => { byte!(8); did(state, d); } ty_uniq(_) => { byte!(9); } ty_vec(_, Some(n)) => { byte!(10); n.hash(state); } ty_vec(_, None) => { byte!(11); } ty_ptr(m) => { byte!(12); mt(state, m); } ty_rptr(r, m) => { byte!(13); region(state, r); mt(state, m); } ty_bare_fn(ref b) => { byte!(14); hash!(b.unsafety); hash!(b.abi); fn_sig(state, &b.sig); return false; } ty_closure(ref c) => { byte!(15); hash!(c.unsafety); hash!(c.onceness); hash!(c.bounds); match c.store { UniqTraitStore => byte!(0), RegionTraitStore(r, m) => { byte!(1); region(state, r); assert_eq!(m, ast::MutMutable); } </ins> } <ins> fn_sig(state, &c.sig); return false; </ins> } <del> } ty_trait(box TyTrait { ref principal, bounds }) => { byte!(17); did(&mut state, principal.def_id); hash!(bounds); } ty_struct(d, _) => { byte!(18); did(&mut state, d); } ty_tup(ref inner) => { byte!(19); hash!(inner.len()); } ty_param(p) => { byte!(20); hash!(p.idx); did(&mut state, p.def_id); } ty_open(_) => byte!(22), ty_infer(_) => unreachable!(), ty_err => byte!(23), ty_unboxed_closure(d, r, _) => { byte!(24); did(&mut state, d); region(&mut state, r); } } }); </del> <ins> ty_trait(box TyTrait { ref principal, bounds }) => { byte!(17); did(state, principal.def_id); hash!(bounds); let principal = anonymize_late_bound_regions(tcx, principal); for subty in principal.substs.types.iter() { helper(tcx, *subty, svh, state); } </ins> <del> state.result() </del> <ins> return false; } ty_struct(d, _) => { byte!(18); did(state, d); } ty_tup(ref inner) => { byte!(19); hash!(inner.len()); } ty_param(p) => { byte!(20); hash!(p.idx); did(state, p.def_id); } ty_open(_) => byte!(22), ty_infer(_) => unreachable!(), ty_err => byte!(23), ty_unboxed_closure(d, r, _) => { byte!(24); did(state, d); region(state, r); } } true }); } </ins> } impl Variance {

Related discussion:
text: Backtrace:
Well, this is interesting. It's broken all the way back to 0.10. I think it's been a bug in the type id implementation since it first landed. Here's a smaller test case:
is there a particular reason explicitly checks that all regions it encounters are ? Trans doesn't seem to go out of its way to erase late-bound regions in fn type signatures, which results in this ICE. I could add a call to in trans to fix this, but it would be cheaper to just ignore regions during hashing.
Ended up catching me
It seems we actually want to take late-bound regions into account when hashing. For example, the following should hold: