From 547d86307c6acd10520af96f8e2974522c50ac1e Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Fri, 19 Jun 2020 20:19:19 -0700 Subject: [PATCH] Improve GeneratorLayout debug output --- src/librustc_index/bit_set.rs | 18 +++++- src/librustc_middle/mir/query.rs | 60 ++++++++++++++++++- src/librustc_middle/ty/sty.rs | 1 - src/librustc_mir/util/pretty.rs | 2 +- ...ustc.main-{{closure}}.generator_drop.0.mir | 15 ++++- ...tc.main-{{closure}}.generator_resume.0.mir | 15 ++++- 6 files changed, 105 insertions(+), 6 deletions(-) diff --git a/src/librustc_index/bit_set.rs b/src/librustc_index/bit_set.rs index 46c38840516..cb8b30830c5 100644 --- a/src/librustc_index/bit_set.rs +++ b/src/librustc_index/bit_set.rs @@ -700,7 +700,7 @@ impl GrowableBitSet { /// /// All operations that involve a row and/or column index will panic if the /// index exceeds the relevant bound. -#[derive(Clone, Debug, Eq, PartialEq, RustcDecodable, RustcEncodable)] +#[derive(Clone, Eq, PartialEq, RustcDecodable, RustcEncodable)] pub struct BitMatrix { num_rows: usize, num_columns: usize, @@ -876,6 +876,22 @@ impl BitMatrix { } } +impl fmt::Debug for BitMatrix { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + /// Forces its contents to print in regular mode instead of alternate mode. + struct OneLinePrinter(T); + impl fmt::Debug for OneLinePrinter { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(fmt, "{:?}", self.0) + } + } + + write!(fmt, "BitMatrix({}x{}) ", self.num_rows, self.num_columns)?; + let items = self.rows().flat_map(|r| self.iter(r).map(move |c| (r, c))); + fmt.debug_set().entries(items.map(OneLinePrinter)).finish() + } +} + /// A fixed-column-size, variable-row-size 2D bit matrix with a moderately /// sparse representation. /// diff --git a/src/librustc_middle/mir/query.rs b/src/librustc_middle/mir/query.rs index b77b069befd..9ad79230a4f 100644 --- a/src/librustc_middle/mir/query.rs +++ b/src/librustc_middle/mir/query.rs @@ -10,6 +10,8 @@ use rustc_index::vec::IndexVec; use rustc_span::{Span, Symbol}; use rustc_target::abi::VariantIdx; use smallvec::SmallVec; +use std::cell::Cell; +use std::fmt::{self, Debug}; use super::{Field, SourceInfo}; @@ -58,7 +60,7 @@ rustc_index::newtype_index! { } /// The layout of generator state. -#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)] +#[derive(Clone, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)] pub struct GeneratorLayout<'tcx> { /// The type of every local stored inside the generator. pub field_tys: IndexVec>, @@ -77,6 +79,62 @@ pub struct GeneratorLayout<'tcx> { pub storage_conflicts: BitMatrix, } +impl Debug for GeneratorLayout<'_> { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + /// Prints an iterator of (key, value) tuples as a map. + struct MapPrinter<'a, K, V>(Cell + 'a>>>); + impl<'a, K, V> MapPrinter<'a, K, V> { + fn new(iter: impl Iterator + 'a) -> Self { + Self(Cell::new(Some(Box::new(iter)))) + } + } + impl<'a, K: Debug, V: Debug> Debug for MapPrinter<'a, K, V> { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_map().entries(self.0.take().unwrap()).finish() + } + } + + /// Prints the generator variant name. + struct GenVariantPrinter(VariantIdx); + impl From for GenVariantPrinter { + fn from(idx: VariantIdx) -> Self { + GenVariantPrinter(idx) + } + } + impl Debug for GenVariantPrinter { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + let variant_name = ty::GeneratorSubsts::variant_name(self.0); + if fmt.alternate() { + write!(fmt, "{:9}({:?})", variant_name, self.0) + } else { + write!(fmt, "{}", variant_name) + } + } + } + + /// Forces its contents to print in regular mode instead of alternate mode. + struct OneLinePrinter(T); + impl Debug for OneLinePrinter { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(fmt, "{:?}", self.0) + } + } + + fmt.debug_struct("GeneratorLayout") + .field("field_tys", &MapPrinter::new(self.field_tys.iter_enumerated())) + .field( + "variant_fields", + &MapPrinter::new( + self.variant_fields + .iter_enumerated() + .map(|(k, v)| (GenVariantPrinter(k), OneLinePrinter(v))), + ), + ) + .field("storage_conflicts", &self.storage_conflicts) + .finish() + } +} + #[derive(Debug, RustcEncodable, RustcDecodable, HashStable)] pub struct BorrowCheckResult<'tcx> { /// All the opaque types that are restricted to concrete types diff --git a/src/librustc_middle/ty/sty.rs b/src/librustc_middle/ty/sty.rs index 79fa06790bd..8f86d2ef522 100644 --- a/src/librustc_middle/ty/sty.rs +++ b/src/librustc_middle/ty/sty.rs @@ -522,7 +522,6 @@ impl<'tcx> GeneratorSubsts<'tcx> { /// Calls `f` with a reference to the name of the enumerator for the given /// variant `v`. - #[inline] pub fn variant_name(v: VariantIdx) -> Cow<'static, str> { match v.as_usize() { Self::UNRESUMED => Cow::from(Self::UNRESUMED_NAME), diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs index 02614044063..db45481e4fd 100644 --- a/src/librustc_mir/util/pretty.rs +++ b/src/librustc_mir/util/pretty.rs @@ -131,7 +131,7 @@ fn dump_matched_mir_node<'tcx, F>( } writeln!(file, " {} {}", disambiguator, pass_name)?; if let Some(ref layout) = body.generator_layout { - writeln!(file, "// generator_layout = {:?}", layout)?; + writeln!(file, "/* generator_layout = {:#?} */", layout)?; } writeln!(file)?; extra_data(PassWhere::BeforeCFG, &mut file)?; diff --git a/src/test/mir-opt/generator-drop-cleanup/rustc.main-{{closure}}.generator_drop.0.mir b/src/test/mir-opt/generator-drop-cleanup/rustc.main-{{closure}}.generator_drop.0.mir index b34d42155cc..3c77995eea8 100644 --- a/src/test/mir-opt/generator-drop-cleanup/rustc.main-{{closure}}.generator_drop.0.mir +++ b/src/test/mir-opt/generator-drop-cleanup/rustc.main-{{closure}}.generator_drop.0.mir @@ -1,5 +1,18 @@ // MIR for `main::{{closure}}#0` 0 generator_drop -// generator_layout = GeneratorLayout { field_tys: [std::string::String], variant_fields: [[], [], [], [_0]], variant_source_info: [SourceInfo { span: $DIR/generator-drop-cleanup.rs:10:15: 10:15 (#0), scope: scope[0] }, SourceInfo { span: $DIR/generator-drop-cleanup.rs:13:6: 13:6 (#0), scope: scope[0] }, SourceInfo { span: $DIR/generator-drop-cleanup.rs:13:6: 13:6 (#0), scope: scope[0] }, SourceInfo { span: $DIR/generator-drop-cleanup.rs:12:9: 12:14 (#0), scope: scope[1] }], storage_conflicts: BitMatrix { num_rows: 1, num_columns: 1, words: [1], marker: PhantomData } } +/* generator_layout = GeneratorLayout { + field_tys: { + _0: std::string::String, + }, + variant_fields: { + Unresumed(0): [], + Returned (1): [], + Panicked (2): [], + Suspend0 (3): [_0], + }, + storage_conflicts: BitMatrix(1x1) { + (_0, _0), + }, +} */ fn main::{{closure}}#0(_1: *mut [generator@$DIR/generator-drop-cleanup.rs:10:15: 13:6 {std::string::String, ()}]) -> () { let mut _0: (); // return place in scope 0 at $DIR/generator-drop-cleanup.rs:10:15: 13:6 diff --git a/src/test/mir-opt/generator-tiny/rustc.main-{{closure}}.generator_resume.0.mir b/src/test/mir-opt/generator-tiny/rustc.main-{{closure}}.generator_resume.0.mir index 2398e950145..bd6db11a7e7 100644 --- a/src/test/mir-opt/generator-tiny/rustc.main-{{closure}}.generator_resume.0.mir +++ b/src/test/mir-opt/generator-tiny/rustc.main-{{closure}}.generator_resume.0.mir @@ -1,5 +1,18 @@ // MIR for `main::{{closure}}#0` 0 generator_resume -// generator_layout = GeneratorLayout { field_tys: [HasDrop], variant_fields: [[], [], [], [_0]], variant_source_info: [SourceInfo { span: $DIR/generator-tiny.rs:19:16: 19:16 (#0), scope: scope[0] }, SourceInfo { span: $DIR/generator-tiny.rs:25:6: 25:6 (#0), scope: scope[0] }, SourceInfo { span: $DIR/generator-tiny.rs:25:6: 25:6 (#0), scope: scope[0] }, SourceInfo { span: $DIR/generator-tiny.rs:22:13: 22:18 (#0), scope: scope[1] }], storage_conflicts: BitMatrix { num_rows: 1, num_columns: 1, words: [1], marker: PhantomData } } +/* generator_layout = GeneratorLayout { + field_tys: { + _0: HasDrop, + }, + variant_fields: { + Unresumed(0): [], + Returned (1): [], + Panicked (2): [], + Suspend0 (3): [_0], + }, + storage_conflicts: BitMatrix(1x1) { + (_0, _0), + }, +} */ fn main::{{closure}}#0(_1: std::pin::Pin<&mut [generator@$DIR/generator-tiny.rs:19:16: 25:6 {u8, HasDrop, ()}]>, _2: u8) -> std::ops::GeneratorState<(), ()> { debug _x => _10; // in scope 0 at $DIR/generator-tiny.rs:19:17: 19:19