From d798b53e6e6cc3c5e27c1bc64365284df9784efc Mon Sep 17 00:00:00 2001 From: Aidan Cully Date: Sun, 15 Feb 2015 12:45:00 -0500 Subject: [PATCH] Resolve issue #22187 (ICE compiling libcore with RUST_LOG=debug). The issue is that the Repr logic assumes that any trait_defs to be represented will be non-local. This will not be the case when compiling libcore: the compiler has a default predicate on many types that they will be Sized, and the Sized trait is defined in libcore. If we allow that a Repr'ed trait_def must come from a foreign crate, then, because the Repr logic can be used while the trait_defs table is being built, there will be a chance that a trait_def lookup will fail on Repr. Handle both of these issues by defining a new try_lookup_trait_def for use by the Repr logic that will attempt to look up a trait_def in the local crate, and returns success/failure in an Option<>. Callers are then responsible for making sure the trait_def is actually present in defining the representation. --- src/librustc/util/ppaux.rs | 45 +++++++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 60b422b3769d5..9b40c3181d351 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -674,12 +674,16 @@ impl<'tcx> UserString<'tcx> for TraitAndProjections<'tcx> { fn user_string(&self, tcx: &ctxt<'tcx>) -> String { let &(ref trait_ref, ref projection_bounds) = self; let base = ty::item_path_str(tcx, trait_ref.def_id); - parameterized(tcx, - &base, - trait_ref.substs, - trait_ref.def_id, - &projection_bounds[..], - || ty::lookup_trait_def(tcx, trait_ref.def_id).generics.clone()) + if let Some(trait_def) = try_lookup_trait_def(tcx, trait_ref.def_id) { + parameterized(tcx, + &base, + trait_ref.substs, + trait_ref.def_id, + &projection_bounds[..], + || trait_def.generics.clone()) + } else { + format!("local_trait_not_ready({:?})", trait_ref.def_id) + } } } @@ -807,8 +811,12 @@ impl<'tcx> Repr<'tcx> for ty::TraitRef<'tcx> { // to enumerate the `for<...>` etc because the debruijn index // tells you everything you need to know. let base = ty::item_path_str(tcx, self.def_id); - parameterized(tcx, &base, self.substs, self.def_id, &[], - || ty::lookup_trait_def(tcx, self.def_id).generics.clone()) + if let Some(trait_def) = try_lookup_trait_def(tcx, self.def_id) { + parameterized(tcx, &base, self.substs, self.def_id, &[], + || trait_def.generics.clone()) + } else { + format!("local_trait_not_ready({:?})", self.def_id) + } } } @@ -1275,8 +1283,12 @@ impl<'tcx, T> UserString<'tcx> for ty::Binder impl<'tcx> UserString<'tcx> for ty::TraitRef<'tcx> { fn user_string(&self, tcx: &ctxt<'tcx>) -> String { let path_str = ty::item_path_str(tcx, self.def_id); - parameterized(tcx, &path_str, self.substs, self.def_id, &[], - || ty::lookup_trait_def(tcx, self.def_id).generics.clone()) + if let Some(trait_def) = try_lookup_trait_def(tcx, self.def_id) { + parameterized(tcx, &path_str, self.substs, self.def_id, &[], + || trait_def.generics.clone()) + } else { + format!("local_trait_not_ready({:?})", self.def_id) + } } } @@ -1532,3 +1544,16 @@ impl<'tcx> Repr<'tcx> for ast::Unsafety { format!("{:?}", *self) } } + +// Wrapper around lookup_trait_def that can handle when the trait is +// defined in the local crate. Returns Option<_> because this function +// can be called while the trait_defs map is being built, so that +// looking up the trait_def in the local crate can sometimes fail. +fn try_lookup_trait_def<'tcx>(tcx: &ctxt<'tcx>, did: ast::DefId) + -> Option>> { + if did.krate == ast::LOCAL_CRATE { + tcx.trait_defs.borrow().get(&did).map(|r| r.clone()) + } else { + Some(ty::lookup_trait_def(tcx, did)) + } +}