Skip to content

Commit

Permalink
Don't ICE when logging unusual types
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Aaron1011 committed Jan 23, 2019
1 parent 19f8958 commit fc0c883
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 30 deletions.
2 changes: 1 addition & 1 deletion src/librustc_codegen_llvm/type_of.rs
Expand Up @@ -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)
{
Expand Down
8 changes: 4 additions & 4 deletions src/librustc_codegen_ssa/mono_item.rs
Expand Up @@ -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());

Expand Down Expand Up @@ -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());
}
Expand All @@ -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());

Expand All @@ -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());
}
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_mir/monomorphize/collector.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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>,
Expand Down
56 changes: 35 additions & 21 deletions src/librustc_mir/monomorphize/item.rs
Expand Up @@ -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()
Expand All @@ -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
}
}
Expand Down Expand Up @@ -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"),
Expand All @@ -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() {
Expand All @@ -281,25 +288,25 @@ 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('&');
if mutbl == hir::MutMutable {
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, ..) => {
Expand All @@ -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 '_");
Expand Down Expand Up @@ -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();
Expand All @@ -357,15 +365,15 @@ 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 }, _) |
ty::Closure(def_id, ClosureSubsts { ref substs }) => {
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(..) |
Expand All @@ -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);
}
}
}
}
Expand Down Expand Up @@ -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();
Expand All @@ -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(", ");
}

Expand All @@ -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(", ");
}

Expand All @@ -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);
}
}
4 changes: 2 additions & 2 deletions src/librustc_mir/monomorphize/partitioning.rs
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit fc0c883

Please sign in to comment.