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:
commit
a6fa7de8e7
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>,
|
||||||
|
|
|
@ -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 ¶meter_type in sig.inputs() {
|
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.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,11 +384,15 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
|
||||||
ty::Param(_) |
|
ty::Param(_) |
|
||||||
ty::GeneratorWitness(_) |
|
ty::GeneratorWitness(_) |
|
||||||
ty::Opaque(..) => {
|
ty::Opaque(..) => {
|
||||||
|
if debug {
|
||||||
|
output.push_str(&format!("`{:?}`", t));
|
||||||
|
} else {
|
||||||
bug!("DefPathBasedNames: Trying to create type name for \
|
bug!("DefPathBasedNames: Trying to create type name for \
|
||||||
unexpected type: {:?}", t);
|
unexpected type: {:?}", t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn push_def_path(&self,
|
pub fn push_def_path(&self,
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue