Rollup merge of #57865 - Aaron1011:fix/debug-ice, r=estebank

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:
Mazdak Farrokhzad 2019-01-25 01:37:03 +01:00 committed by GitHub
commit a6fa7de8e7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 44 additions and 30 deletions

View File

@ -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)
{

View File

@ -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());
}

View File

@ -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>,

View File

@ -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 &parameter_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);
}
}

View File

@ -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);