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 => { ty::Str => {
let mut name = String::with_capacity(32); let mut name = String::with_capacity(32);
let printer = DefPathBasedNames::new(cx.tcx, true, true); 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 }) if let (&ty::Adt(def, _), &layout::Variants::Single { index })
= (&layout.ty.sty, &layout.variants) = (&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> { pub trait MonoItemExt<'a, 'tcx: 'a>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> {
fn define<Bx: BuilderMethods<'a, 'tcx>>(&self, cx: &'a Bx::CodegenCx) { fn define<Bx: BuilderMethods<'a, 'tcx>>(&self, cx: &'a Bx::CodegenCx) {
debug!("BEGIN IMPLEMENTING '{} ({})' in cgu {}", debug!("BEGIN IMPLEMENTING '{} ({})' in cgu {}",
self.to_string(cx.tcx()), self.to_string(cx.tcx(), true),
self.to_raw_string(), self.to_raw_string(),
cx.codegen_unit().name()); cx.codegen_unit().name());
@ -45,7 +45,7 @@ pub trait MonoItemExt<'a, 'tcx: 'a>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> {
} }
debug!("END IMPLEMENTING '{} ({})' in cgu {}", debug!("END IMPLEMENTING '{} ({})' in cgu {}",
self.to_string(cx.tcx()), self.to_string(cx.tcx(), true),
self.to_raw_string(), self.to_raw_string(),
cx.codegen_unit().name()); cx.codegen_unit().name());
} }
@ -57,7 +57,7 @@ pub trait MonoItemExt<'a, 'tcx: 'a>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> {
visibility: Visibility visibility: Visibility
) { ) {
debug!("BEGIN PREDEFINING '{} ({})' in cgu {}", debug!("BEGIN PREDEFINING '{} ({})' in cgu {}",
self.to_string(cx.tcx()), self.to_string(cx.tcx(), true),
self.to_raw_string(), self.to_raw_string(),
cx.codegen_unit().name()); cx.codegen_unit().name());
@ -76,7 +76,7 @@ pub trait MonoItemExt<'a, 'tcx: 'a>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> {
} }
debug!("END PREDEFINING '{} ({})' in cgu {}", debug!("END PREDEFINING '{} ({})' in cgu {}",
self.to_string(cx.tcx()), self.to_string(cx.tcx(), true),
self.to_raw_string(), self.to_raw_string(),
cx.codegen_unit().name()); 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. // We've been here already, no need to search again.
return; 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 mut neighbors = Vec::new();
let recursion_depth_reset; 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); 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>, 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)) 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() { return match *self.as_mono_item() {
MonoItem::Fn(instance) => { MonoItem::Fn(instance) => {
to_string_internal(tcx, "fn ", instance) to_string_internal(tcx, "fn ", instance, debug)
}, },
MonoItem::Static(def_id) => { MonoItem::Static(def_id) => {
let instance = Instance::new(def_id, tcx.intern_substs(&[])); let instance = Instance::new(def_id, tcx.intern_substs(&[]));
to_string_internal(tcx, "static ", instance) to_string_internal(tcx, "static ", instance, debug)
}, },
MonoItem::GlobalAsm(..) => { MonoItem::GlobalAsm(..) => {
"global_asm".to_string() "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>, fn to_string_internal<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
prefix: &str, prefix: &str,
instance: Instance<'tcx>) instance: Instance<'tcx>,
debug: bool)
-> String { -> String {
let mut result = String::with_capacity(32); let mut result = String::with_capacity(32);
result.push_str(prefix); result.push_str(prefix);
let printer = DefPathBasedNames::new(tcx, false, false); 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 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 { match t.sty {
ty::Bool => output.push_str("bool"), ty::Bool => output.push_str("bool"),
ty::Char => output.push_str("char"), 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::Float(ast::FloatTy::F64) => output.push_str("f64"),
ty::Adt(adt_def, substs) => { ty::Adt(adt_def, substs) => {
self.push_def_path(adt_def.did, output); 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) => { ty::Tuple(component_types) => {
output.push('('); output.push('(');
for &component_type in component_types { for &component_type in component_types {
self.push_type_name(component_type, output); self.push_type_name(component_type, output, debug);
output.push_str(", "); output.push_str(", ");
} }
if !component_types.is_empty() { if !component_types.is_empty() {
@ -281,7 +288,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
hir::MutMutable => output.push_str("mut "), 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) => { ty::Ref(_, inner_type, mutbl) => {
output.push('&'); output.push('&');
@ -289,17 +296,17 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
output.push_str("mut "); output.push_str("mut ");
} }
self.push_type_name(inner_type, output); self.push_type_name(inner_type, output, debug);
}, },
ty::Array(inner_type, len) => { ty::Array(inner_type, len) => {
output.push('['); 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(); write!(output, "; {}", len.unwrap_usize(self.tcx)).unwrap();
output.push(']'); output.push(']');
}, },
ty::Slice(inner_type) => { ty::Slice(inner_type) => {
output.push('['); output.push('[');
self.push_type_name(inner_type, output); self.push_type_name(inner_type, output, debug);
output.push(']'); output.push(']');
}, },
ty::Dynamic(ref trait_data, ..) => { ty::Dynamic(ref trait_data, ..) => {
@ -309,6 +316,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
principal.skip_binder().substs, principal.skip_binder().substs,
trait_data.projection_bounds(), trait_data.projection_bounds(),
output, output,
debug
); );
} else { } else {
output.push_str("dyn '_"); output.push_str("dyn '_");
@ -338,7 +346,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
if !sig.inputs().is_empty() { if !sig.inputs().is_empty() {
for &parameter_type in sig.inputs() { 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.push_str(", ");
} }
output.pop(); output.pop();
@ -357,7 +365,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
if !sig.output().is_unit() { if !sig.output().is_unit() {
output.push_str(" -> "); 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 }, _) | ty::Generator(def_id, GeneratorSubsts { ref substs }, _) |
@ -365,7 +373,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
self.push_def_path(def_id, output); self.push_def_path(def_id, output);
let generics = self.tcx.generics_of(self.tcx.closure_base_def_id(def_id)); let generics = self.tcx.generics_of(self.tcx.closure_base_def_id(def_id));
let substs = substs.truncate_to(self.tcx, generics); 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::Error |
ty::Bound(..) | ty::Bound(..) |
@ -376,8 +384,12 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
ty::Param(_) | ty::Param(_) |
ty::GeneratorWitness(_) | ty::GeneratorWitness(_) |
ty::Opaque(..) => { 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); unexpected type: {:?}", t);
}
} }
} }
} }
@ -412,7 +424,8 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
fn push_type_params<I>(&self, fn push_type_params<I>(&self,
substs: &Substs<'tcx>, substs: &Substs<'tcx>,
projections: I, projections: I,
output: &mut String) output: &mut String,
debug: bool)
where I: Iterator<Item=ty::PolyExistentialProjection<'tcx>> where I: Iterator<Item=ty::PolyExistentialProjection<'tcx>>
{ {
let mut projections = projections.peekable(); let mut projections = projections.peekable();
@ -423,7 +436,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
output.push('<'); output.push('<');
for type_parameter in substs.types() { for type_parameter in substs.types() {
self.push_type_name(type_parameter, output); self.push_type_name(type_parameter, output, debug);
output.push_str(", "); 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(); let name = &self.tcx.associated_item(projection.item_def_id).ident.as_str();
output.push_str(name); output.push_str(name);
output.push_str("="); output.push_str("=");
self.push_type_name(projection.ty, output); self.push_type_name(projection.ty, output, debug);
output.push_str(", "); output.push_str(", ");
} }
@ -444,8 +457,9 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
pub fn push_instance_as_string(&self, pub fn push_instance_as_string(&self,
instance: Instance<'tcx>, instance: Instance<'tcx>,
output: &mut String) { output: &mut String,
debug: bool) {
self.push_def_path(instance.def_id(), output); 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>"); .unwrap_or("<no hash>");
debug!(" - {} [{:?}] [{}]", debug!(" - {} [{:?}] [{}]",
mono_item.to_string(tcx), mono_item.to_string(tcx, true),
linkage, linkage,
symbol_hash); symbol_hash);
} }
@ -971,7 +971,7 @@ fn collect_and_partition_mono_items<'a, 'tcx>(
let mut item_keys: Vec<_> = items let mut item_keys: Vec<_> = items
.iter() .iter()
.map(|i| { .map(|i| {
let mut output = i.to_string(tcx); let mut output = i.to_string(tcx, false);
output.push_str(" @@"); output.push_str(" @@");
let mut empty = Vec::new(); let mut empty = Vec::new();
let cgus = item_to_cgus.get_mut(i).unwrap_or(&mut empty); let cgus = item_to_cgus.get_mut(i).unwrap_or(&mut empty);