From eccb28e3d67460f77331eb5ecceab36181831946 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 17 Apr 2020 03:55:39 +0300 Subject: [PATCH] ty/print: pretty-print constant aggregates (arrays, tuples and ADTs). --- src/librustc_middle/query/mod.rs | 2 +- src/librustc_middle/ty/print/pretty.rs | 79 +++++++++++++++---- .../32bit/rustc.main.ConstProp.diff | 2 +- .../64bit/rustc.main.ConstProp.diff | 2 +- .../32bit/rustc.main.Inline.diff | 2 +- .../64bit/rustc.main.Inline.diff | 2 +- .../rustc.main.SimplifyLocals.diff | 8 +- 7 files changed, 72 insertions(+), 25 deletions(-) diff --git a/src/librustc_middle/query/mod.rs b/src/librustc_middle/query/mod.rs index 3ddb290fc8d1..1b94966c3477 100644 --- a/src/librustc_middle/query/mod.rs +++ b/src/librustc_middle/query/mod.rs @@ -574,7 +574,7 @@ rustc_queries! { desc { "extract field of const" } } - /// Destructure a constant ADT or array into its variant indent and its + /// Destructure a constant ADT or array into its variant index and its /// field values. query destructure_const( key: ty::ParamEnvAnd<'tcx, &'tcx ty::Const<'tcx>> diff --git a/src/librustc_middle/ty/print/pretty.rs b/src/librustc_middle/ty/print/pretty.rs index 0cabd201a95b..85c05515bd73 100644 --- a/src/librustc_middle/ty/print/pretty.rs +++ b/src/librustc_middle/ty/print/pretty.rs @@ -9,7 +9,7 @@ use rustc_apfloat::Float; use rustc_ast::ast; use rustc_attr::{SignedInt, UnsignedInt}; use rustc_hir as hir; -use rustc_hir::def::{DefKind, Namespace}; +use rustc_hir::def::{CtorKind, DefKind, Namespace}; use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData}; use rustc_span::symbol::{kw, Symbol}; @@ -1037,19 +1037,6 @@ pub trait PrettyPrinter<'tcx>: } // For function type zsts just printing the path is enough (Scalar::Raw { size: 0, .. }, ty::FnDef(d, s)) => p!(print_value_path(*d, s)), - // Empty tuples are frequently occurring, so don't print the fallback. - (Scalar::Raw { size: 0, .. }, ty::Tuple(ts)) if ts.is_empty() => p!(write("()")), - // Zero element arrays have a trivial representation. - ( - Scalar::Raw { size: 0, .. }, - ty::Array( - _, - ty::Const { - val: ty::ConstKind::Value(ConstValue::Scalar(Scalar::Raw { data: 0, .. })), - .. - }, - ), - ) => p!(write("[]")), // Nontrivial types with scalar bit representation (Scalar::Raw { data, size }, _) => { let print = |mut this: Self| { @@ -1118,14 +1105,14 @@ pub trait PrettyPrinter<'tcx>: define_scoped_cx!(self); if self.tcx().sess.verbose() { - p!(write("ConstValue({:?}: {:?})", ct, ty)); + p!(write("ConstValue({:?}: ", ct), print(ty), write(")")); return Ok(self); } let u8_type = self.tcx().types.u8; match (ct, &ty.kind) { - (ConstValue::Scalar(scalar), _) => self.pretty_print_const_scalar(scalar, ty, print_ty), + // Byte/string slices, printed as (byte) string literals. ( ConstValue::Slice { data, start, end }, ty::Ref(_, ty::TyS { kind: ty::Slice(t), .. }, _), @@ -1159,6 +1146,66 @@ pub trait PrettyPrinter<'tcx>: p!(pretty_print_byte_str(byte_str)); Ok(self) } + + // Aggregates, printed as array/tuple/struct/variant construction syntax. + // + // NB: the `has_param_types_or_consts` check ensures that we can use + // the `destructure_const` query with an empty `ty::ParamEnv` without + // introducing ICEs (e.g. via `layout_of`) from missing bounds. + // E.g. `transmute([0usize; 2]): (u8, *mut T)` needs to know `T: Sized` + // to be able to destructure the tuple into `(0u8, *mut T) + // + // FIXME(eddyb) for `--emit=mir`/`-Z dump-mir`, we should provide the + // correct `ty::ParamEnv` to allow printing *all* constant values. + (_, ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) if !ty.has_param_types_or_consts() => { + let contents = self.tcx().destructure_const( + ty::ParamEnv::reveal_all() + .and(self.tcx().mk_const(ty::Const { val: ty::ConstKind::Value(ct), ty })), + ); + let fields = contents.fields.iter().copied(); + + match ty.kind { + ty::Array(..) => { + p!(write("["), comma_sep(fields), write("]")); + } + ty::Tuple(..) => { + p!(write("("), comma_sep(fields)); + if contents.fields.len() == 1 { + p!(write(",")); + } + p!(write(")")); + } + ty::Adt(def, substs) => { + let variant_def = &def.variants[contents.variant]; + p!(print_value_path(variant_def.def_id, substs)); + + match variant_def.ctor_kind { + CtorKind::Const => {} + CtorKind::Fn => { + p!(write("("), comma_sep(fields), write(")")); + } + CtorKind::Fictive => { + p!(write(" {{ ")); + let mut first = true; + for (field_def, field) in variant_def.fields.iter().zip(fields) { + if !first { + p!(write(", ")); + } + p!(write("{}: ", field_def.ident), print(field)); + first = false; + } + p!(write(" }}")); + } + } + } + _ => unreachable!(), + } + + Ok(self) + } + + (ConstValue::Scalar(scalar), _) => self.pretty_print_const_scalar(scalar, ty, print_ty), + // FIXME(oli-obk): also pretty print arrays and other aggregate constants by reading // their fields instead of just dumping the memory. _ => { diff --git a/src/test/mir-opt/const_prop/discriminant/32bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/discriminant/32bit/rustc.main.ConstProp.diff index d5566b9d761d..753c64d6c329 100644 --- a/src/test/mir-opt/const_prop/discriminant/32bit/rustc.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/discriminant/32bit/rustc.main.ConstProp.diff @@ -16,7 +16,7 @@ StorageLive(_2); // bb0[1]: scope 0 at $DIR/discriminant.rs:6:13: 6:64 StorageLive(_3); // bb0[2]: scope 0 at $DIR/discriminant.rs:6:34: 6:44 - _3 = std::option::Option::::Some(const true); // bb0[3]: scope 0 at $DIR/discriminant.rs:6:34: 6:44 -+ _3 = const {transmute(0x01): std::option::Option}; // bb0[3]: scope 0 at $DIR/discriminant.rs:6:34: 6:44 ++ _3 = const std::option::Option::::Some(true); // bb0[3]: scope 0 at $DIR/discriminant.rs:6:34: 6:44 // ty::Const - // + ty: bool + // + ty: std::option::Option diff --git a/src/test/mir-opt/const_prop/discriminant/64bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/discriminant/64bit/rustc.main.ConstProp.diff index bdd9c020c955..1d8e945f87a6 100644 --- a/src/test/mir-opt/const_prop/discriminant/64bit/rustc.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/discriminant/64bit/rustc.main.ConstProp.diff @@ -16,7 +16,7 @@ StorageLive(_2); // bb0[1]: scope 0 at $DIR/discriminant.rs:6:13: 6:64 StorageLive(_3); // bb0[2]: scope 0 at $DIR/discriminant.rs:6:34: 6:44 - _3 = std::option::Option::::Some(const true); // bb0[3]: scope 0 at $DIR/discriminant.rs:6:34: 6:44 -+ _3 = const {transmute(0x01): std::option::Option}; // bb0[3]: scope 0 at $DIR/discriminant.rs:6:34: 6:44 ++ _3 = const std::option::Option::::Some(true); // bb0[3]: scope 0 at $DIR/discriminant.rs:6:34: 6:44 // ty::Const - // + ty: bool + // + ty: std::option::Option diff --git a/src/test/mir-opt/inline/inline-into-box-place/32bit/rustc.main.Inline.diff b/src/test/mir-opt/inline/inline-into-box-place/32bit/rustc.main.Inline.diff index 6983e94ff8d7..7f2f7cdb1766 100644 --- a/src/test/mir-opt/inline/inline-into-box-place/32bit/rustc.main.Inline.diff +++ b/src/test/mir-opt/inline/inline-into-box-place/32bit/rustc.main.Inline.diff @@ -19,7 +19,7 @@ _2 = Box(std::vec::Vec); // bb0[2]: scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43 - (*_2) = const std::vec::Vec::::new() -> [return: bb2, unwind: bb4]; // bb0[3]: scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 + _4 = &mut (*_2); // bb0[3]: scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 -+ ((*_4).0: alloc::raw_vec::RawVec) = const ByRef { alloc: Allocation { bytes: [4, 0, 0, 0, 0, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), undef_mask: UndefMask { blocks: [255], len: Size { raw: 8 } }, size: Size { raw: 8 }, align: Align { pow2: 2 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }: alloc::raw_vec::RawVec::; // bb0[4]: scope 2 at $SRC_DIR/liballoc/vec.rs:LL:COL ++ ((*_4).0: alloc::raw_vec::RawVec) = const alloc::raw_vec::RawVec:: { ptr: std::ptr::Unique:: { pointer: {0x4 as *const u32}, _marker: std::marker::PhantomData:: }, cap: 0usize, alloc: std::alloc::Global }; // bb0[4]: scope 2 at $SRC_DIR/liballoc/vec.rs:LL:COL // ty::Const - // + ty: fn() -> std::vec::Vec {std::vec::Vec::::new} - // + val: Value(Scalar()) diff --git a/src/test/mir-opt/inline/inline-into-box-place/64bit/rustc.main.Inline.diff b/src/test/mir-opt/inline/inline-into-box-place/64bit/rustc.main.Inline.diff index 38ab9ce9926c..b968b33ac527 100644 --- a/src/test/mir-opt/inline/inline-into-box-place/64bit/rustc.main.Inline.diff +++ b/src/test/mir-opt/inline/inline-into-box-place/64bit/rustc.main.Inline.diff @@ -19,7 +19,7 @@ _2 = Box(std::vec::Vec); // bb0[2]: scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43 - (*_2) = const std::vec::Vec::::new() -> [return: bb2, unwind: bb4]; // bb0[3]: scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 + _4 = &mut (*_2); // bb0[3]: scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 -+ ((*_4).0: alloc::raw_vec::RawVec) = const ByRef { alloc: Allocation { bytes: [4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), undef_mask: UndefMask { blocks: [65535], len: Size { raw: 16 } }, size: Size { raw: 16 }, align: Align { pow2: 3 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }: alloc::raw_vec::RawVec::; // bb0[4]: scope 2 at $SRC_DIR/liballoc/vec.rs:LL:COL ++ ((*_4).0: alloc::raw_vec::RawVec) = const alloc::raw_vec::RawVec:: { ptr: std::ptr::Unique:: { pointer: {0x4 as *const u32}, _marker: std::marker::PhantomData:: }, cap: 0usize, alloc: std::alloc::Global }; // bb0[4]: scope 2 at $SRC_DIR/liballoc/vec.rs:LL:COL // ty::Const - // + ty: fn() -> std::vec::Vec {std::vec::Vec::::new} - // + val: Value(Scalar()) diff --git a/src/test/mir-opt/simplify-locals-removes-unused-consts/rustc.main.SimplifyLocals.diff b/src/test/mir-opt/simplify-locals-removes-unused-consts/rustc.main.SimplifyLocals.diff index 8613a812a834..855ead7ea055 100644 --- a/src/test/mir-opt/simplify-locals-removes-unused-consts/rustc.main.SimplifyLocals.diff +++ b/src/test/mir-opt/simplify-locals-removes-unused-consts/rustc.main.SimplifyLocals.diff @@ -24,7 +24,7 @@ - StorageLive(_2); // bb0[1]: scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:13:21: 13:23 - _2 = const (); // bb0[2]: scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:13:21: 13:23 + StorageLive(_1); // bb0[0]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:5: 14:22 -+ _1 = const use_zst(const {transmute(()): ((), ())}) -> bb1; // bb0[1]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:5: 14:22 ++ _1 = const use_zst(const ((), ())) -> bb1; // bb0[1]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:5: 14:22 // ty::Const - // + ty: () - // + val: Value(Scalar()) @@ -39,7 +39,7 @@ - // mir::Constant - // + span: $DIR/simplify-locals-removes-unused-consts.rs:13:25: 13:27 - // + literal: Const { ty: (), val: Value(Scalar()) } -- _1 = const {transmute(()): ((), ())}; // bb0[5]: scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:13:20: 13:28 +- _1 = const ((), ()); // bb0[5]: scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:13:20: 13:28 - // ty::Const - // + ty: ((), ()) - // + val: Value(Scalar()) @@ -68,7 +68,7 @@ - // + literal: Const { ty: (), val: Value(Scalar()) } - StorageDead(_7); // bb0[14]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:20: 14:21 - StorageDead(_6); // bb0[15]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:20: 14:21 -- _4 = const use_zst(const {transmute(()): ((), ())}) -> bb1; // bb0[16]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:5: 14:22 +- _4 = const use_zst(const ((), ())) -> bb1; // bb0[16]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:5: 14:22 - // ty::Const // + ty: fn(((), ())) {use_zst} // + val: Value(Scalar()) @@ -88,7 +88,7 @@ - StorageLive(_8); // bb1[1]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:5: 16:35 - StorageLive(_10); // bb1[2]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:12: 16:30 - StorageLive(_11); // bb1[3]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:12: 16:28 -- _11 = const {transmute(0x28): Temp}; // bb1[4]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:12: 16:28 +- _11 = const Temp { x: 40u8 }; // bb1[4]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:12: 16:28 + StorageDead(_1); // bb1[0]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:22: 14:23 + StorageLive(_2); // bb1[1]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:5: 16:35 + _2 = const use_u8(const 42u8) -> bb2; // bb1[2]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:5: 16:35