Don't ICE when logging unusual types
MonoItemExt#to_string is used for both debug logging and LLVM symbol name generation. When debugging, we want to print out any type we encounter, even if it's something weird like GeneratorWitness. However, during codegen, we still want to error if we encounter an unexpected type when generating a name. To resolve this issue, this commit introduces a new 'debug' parameter to the relevant methods. When set to 'true', it allows any type to be printed - when set to 'false', it 'bug!'s when encountering an unexpected type. This prevents an ICE when enabling debug logging (via RUST_LOG) while running rustc on generator-related code.
This commit is contained in:
parent
19f8958f82
commit
fc0c8839f7
5 changed files with 44 additions and 30 deletions
|
@ -55,7 +55,7 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
|
|||
ty::Str => {
|
||||
let mut name = String::with_capacity(32);
|
||||
let printer = DefPathBasedNames::new(cx.tcx, true, true);
|
||||
printer.push_type_name(layout.ty, &mut name);
|
||||
printer.push_type_name(layout.ty, &mut name, false);
|
||||
if let (&ty::Adt(def, _), &layout::Variants::Single { index })
|
||||
= (&layout.ty.sty, &layout.variants)
|
||||
{
|
||||
|
|
|
@ -13,7 +13,7 @@ pub use rustc_mir::monomorphize::item::MonoItemExt as BaseMonoItemExt;
|
|||
pub trait MonoItemExt<'a, 'tcx: 'a>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> {
|
||||
fn define<Bx: BuilderMethods<'a, 'tcx>>(&self, cx: &'a Bx::CodegenCx) {
|
||||
debug!("BEGIN IMPLEMENTING '{} ({})' in cgu {}",
|
||||
self.to_string(cx.tcx()),
|
||||
self.to_string(cx.tcx(), true),
|
||||
self.to_raw_string(),
|
||||
cx.codegen_unit().name());
|
||||
|
||||
|
@ -45,7 +45,7 @@ pub trait MonoItemExt<'a, 'tcx: 'a>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> {
|
|||
}
|
||||
|
||||
debug!("END IMPLEMENTING '{} ({})' in cgu {}",
|
||||
self.to_string(cx.tcx()),
|
||||
self.to_string(cx.tcx(), true),
|
||||
self.to_raw_string(),
|
||||
cx.codegen_unit().name());
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ pub trait MonoItemExt<'a, 'tcx: 'a>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> {
|
|||
visibility: Visibility
|
||||
) {
|
||||
debug!("BEGIN PREDEFINING '{} ({})' in cgu {}",
|
||||
self.to_string(cx.tcx()),
|
||||
self.to_string(cx.tcx(), true),
|
||||
self.to_raw_string(),
|
||||
cx.codegen_unit().name());
|
||||
|
||||
|
@ -76,7 +76,7 @@ pub trait MonoItemExt<'a, 'tcx: 'a>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> {
|
|||
}
|
||||
|
||||
debug!("END PREDEFINING '{} ({})' in cgu {}",
|
||||
self.to_string(cx.tcx()),
|
||||
self.to_string(cx.tcx(), true),
|
||||
self.to_raw_string(),
|
||||
cx.codegen_unit().name());
|
||||
}
|
||||
|
|
|
@ -355,7 +355,7 @@ fn collect_items_rec<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
// We've been here already, no need to search again.
|
||||
return;
|
||||
}
|
||||
debug!("BEGIN collect_items_rec({})", starting_point.to_string(tcx));
|
||||
debug!("BEGIN collect_items_rec({})", starting_point.to_string(tcx, true));
|
||||
|
||||
let mut neighbors = Vec::new();
|
||||
let recursion_depth_reset;
|
||||
|
@ -409,7 +409,7 @@ fn collect_items_rec<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
recursion_depths.insert(def_id, depth);
|
||||
}
|
||||
|
||||
debug!("END collect_items_rec({})", starting_point.to_string(tcx));
|
||||
debug!("END collect_items_rec({})", starting_point.to_string(tcx, true));
|
||||
}
|
||||
|
||||
fn record_accesses<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
|
|
|
@ -159,14 +159,14 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug {
|
|||
tcx.substitute_normalize_and_test_predicates((def_id, &substs))
|
||||
}
|
||||
|
||||
fn to_string(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> String {
|
||||
fn to_string(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, debug: bool) -> String {
|
||||
return match *self.as_mono_item() {
|
||||
MonoItem::Fn(instance) => {
|
||||
to_string_internal(tcx, "fn ", instance)
|
||||
to_string_internal(tcx, "fn ", instance, debug)
|
||||
},
|
||||
MonoItem::Static(def_id) => {
|
||||
let instance = Instance::new(def_id, tcx.intern_substs(&[]));
|
||||
to_string_internal(tcx, "static ", instance)
|
||||
to_string_internal(tcx, "static ", instance, debug)
|
||||
},
|
||||
MonoItem::GlobalAsm(..) => {
|
||||
"global_asm".to_string()
|
||||
|
@ -175,12 +175,13 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug {
|
|||
|
||||
fn to_string_internal<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
prefix: &str,
|
||||
instance: Instance<'tcx>)
|
||||
instance: Instance<'tcx>,
|
||||
debug: bool)
|
||||
-> String {
|
||||
let mut result = String::with_capacity(32);
|
||||
result.push_str(prefix);
|
||||
let printer = DefPathBasedNames::new(tcx, false, false);
|
||||
printer.push_instance_as_string(instance, &mut result);
|
||||
printer.push_instance_as_string(instance, &mut result, debug);
|
||||
result
|
||||
}
|
||||
}
|
||||
|
@ -238,7 +239,13 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String) {
|
||||
// Pushes the type name of the specified type to the provided string.
|
||||
// If 'debug' is true, printing normally unprintable types is allowed
|
||||
// (e.g. ty::GeneratorWitness). This parameter should only be set when
|
||||
// this method is being used for logging purposes (e.g. with debug! or info!)
|
||||
// When being used for codegen purposes, 'debug' should be set to 'false'
|
||||
// in order to catch unexpected types that should never end up in a type name
|
||||
pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String, debug: bool) {
|
||||
match t.sty {
|
||||
ty::Bool => output.push_str("bool"),
|
||||
ty::Char => output.push_str("char"),
|
||||
|
@ -260,12 +267,12 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
|
|||
ty::Float(ast::FloatTy::F64) => output.push_str("f64"),
|
||||
ty::Adt(adt_def, substs) => {
|
||||
self.push_def_path(adt_def.did, output);
|
||||
self.push_type_params(substs, iter::empty(), output);
|
||||
self.push_type_params(substs, iter::empty(), output, debug);
|
||||
},
|
||||
ty::Tuple(component_types) => {
|
||||
output.push('(');
|
||||
for &component_type in component_types {
|
||||
self.push_type_name(component_type, output);
|
||||
self.push_type_name(component_type, output, debug);
|
||||
output.push_str(", ");
|
||||
}
|
||||
if !component_types.is_empty() {
|
||||
|
@ -281,7 +288,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
|
|||
hir::MutMutable => output.push_str("mut "),
|
||||
}
|
||||
|
||||
self.push_type_name(inner_type, output);
|
||||
self.push_type_name(inner_type, output, debug);
|
||||
},
|
||||
ty::Ref(_, inner_type, mutbl) => {
|
||||
output.push('&');
|
||||
|
@ -289,17 +296,17 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
|
|||
output.push_str("mut ");
|
||||
}
|
||||
|
||||
self.push_type_name(inner_type, output);
|
||||
self.push_type_name(inner_type, output, debug);
|
||||
},
|
||||
ty::Array(inner_type, len) => {
|
||||
output.push('[');
|
||||
self.push_type_name(inner_type, output);
|
||||
self.push_type_name(inner_type, output, debug);
|
||||
write!(output, "; {}", len.unwrap_usize(self.tcx)).unwrap();
|
||||
output.push(']');
|
||||
},
|
||||
ty::Slice(inner_type) => {
|
||||
output.push('[');
|
||||
self.push_type_name(inner_type, output);
|
||||
self.push_type_name(inner_type, output, debug);
|
||||
output.push(']');
|
||||
},
|
||||
ty::Dynamic(ref trait_data, ..) => {
|
||||
|
@ -309,6 +316,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
|
|||
principal.skip_binder().substs,
|
||||
trait_data.projection_bounds(),
|
||||
output,
|
||||
debug
|
||||
);
|
||||
} else {
|
||||
output.push_str("dyn '_");
|
||||
|
@ -338,7 +346,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
|
|||
|
||||
if !sig.inputs().is_empty() {
|
||||
for ¶meter_type in sig.inputs() {
|
||||
self.push_type_name(parameter_type, output);
|
||||
self.push_type_name(parameter_type, output, debug);
|
||||
output.push_str(", ");
|
||||
}
|
||||
output.pop();
|
||||
|
@ -357,7 +365,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
|
|||
|
||||
if !sig.output().is_unit() {
|
||||
output.push_str(" -> ");
|
||||
self.push_type_name(sig.output(), output);
|
||||
self.push_type_name(sig.output(), output, debug);
|
||||
}
|
||||
},
|
||||
ty::Generator(def_id, GeneratorSubsts { ref substs }, _) |
|
||||
|
@ -365,7 +373,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
|
|||
self.push_def_path(def_id, output);
|
||||
let generics = self.tcx.generics_of(self.tcx.closure_base_def_id(def_id));
|
||||
let substs = substs.truncate_to(self.tcx, generics);
|
||||
self.push_type_params(substs, iter::empty(), output);
|
||||
self.push_type_params(substs, iter::empty(), output, debug);
|
||||
}
|
||||
ty::Error |
|
||||
ty::Bound(..) |
|
||||
|
@ -376,8 +384,12 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
|
|||
ty::Param(_) |
|
||||
ty::GeneratorWitness(_) |
|
||||
ty::Opaque(..) => {
|
||||
bug!("DefPathBasedNames: Trying to create type name for \
|
||||
if debug {
|
||||
output.push_str(&format!("`{:?}`", t));
|
||||
} else {
|
||||
bug!("DefPathBasedNames: Trying to create type name for \
|
||||
unexpected type: {:?}", t);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -412,7 +424,8 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
|
|||
fn push_type_params<I>(&self,
|
||||
substs: &Substs<'tcx>,
|
||||
projections: I,
|
||||
output: &mut String)
|
||||
output: &mut String,
|
||||
debug: bool)
|
||||
where I: Iterator<Item=ty::PolyExistentialProjection<'tcx>>
|
||||
{
|
||||
let mut projections = projections.peekable();
|
||||
|
@ -423,7 +436,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
|
|||
output.push('<');
|
||||
|
||||
for type_parameter in substs.types() {
|
||||
self.push_type_name(type_parameter, output);
|
||||
self.push_type_name(type_parameter, output, debug);
|
||||
output.push_str(", ");
|
||||
}
|
||||
|
||||
|
@ -432,7 +445,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
|
|||
let name = &self.tcx.associated_item(projection.item_def_id).ident.as_str();
|
||||
output.push_str(name);
|
||||
output.push_str("=");
|
||||
self.push_type_name(projection.ty, output);
|
||||
self.push_type_name(projection.ty, output, debug);
|
||||
output.push_str(", ");
|
||||
}
|
||||
|
||||
|
@ -444,8 +457,9 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
|
|||
|
||||
pub fn push_instance_as_string(&self,
|
||||
instance: Instance<'tcx>,
|
||||
output: &mut String) {
|
||||
output: &mut String,
|
||||
debug: bool) {
|
||||
self.push_def_path(instance.def_id(), output);
|
||||
self.push_type_params(instance.substs, iter::empty(), output);
|
||||
self.push_type_params(instance.substs, iter::empty(), output, debug);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -879,7 +879,7 @@ fn debug_dump<'a, 'b, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
.unwrap_or("<no hash>");
|
||||
|
||||
debug!(" - {} [{:?}] [{}]",
|
||||
mono_item.to_string(tcx),
|
||||
mono_item.to_string(tcx, true),
|
||||
linkage,
|
||||
symbol_hash);
|
||||
}
|
||||
|
@ -971,7 +971,7 @@ fn collect_and_partition_mono_items<'a, 'tcx>(
|
|||
let mut item_keys: Vec<_> = items
|
||||
.iter()
|
||||
.map(|i| {
|
||||
let mut output = i.to_string(tcx);
|
||||
let mut output = i.to_string(tcx, false);
|
||||
output.push_str(" @@");
|
||||
let mut empty = Vec::new();
|
||||
let cgus = item_to_cgus.get_mut(i).unwrap_or(&mut empty);
|
||||
|
|
Loading…
Reference in a new issue