diff options
| author | Eduard-Mihai Burtescu <edy.burt@gmail.com> | 2020-04-17 03:55:39 +0300 |
|---|---|---|
| committer | Eduard-Mihai Burtescu <edy.burt@gmail.com> | 2020-04-17 05:18:32 +0300 |
| commit | eccb28e3d67460f77331eb5ecceab36181831946 (patch) | |
| tree | 0be938445b6fb8cc8f28ae44a81dd9c1f3554eb8 | |
| parent | aabed9322e78b280d54fe7a90bb088932731d967 (diff) | |
| download | rust-eccb28e3d67460f77331eb5ecceab36181831946.tar.gz rust-eccb28e3d67460f77331eb5ecceab36181831946.zip | |
ty/print: pretty-print constant aggregates (arrays, tuples and ADTs).
7 files changed, 72 insertions, 25 deletions
diff --git a/src/librustc_middle/query/mod.rs b/src/librustc_middle/query/mod.rs index 3ddb290fc8d..1b94966c347 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 0cabd201a95..85c05515bd7 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 d5566b9d761..753c64d6c32 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::<bool>::Some(const true); // bb0[3]: scope 0 at $DIR/discriminant.rs:6:34: 6:44 -+ _3 = const {transmute(0x01): std::option::Option<bool>}; // bb0[3]: scope 0 at $DIR/discriminant.rs:6:34: 6:44 ++ _3 = const std::option::Option::<bool>::Some(true); // bb0[3]: scope 0 at $DIR/discriminant.rs:6:34: 6:44 // ty::Const - // + ty: bool + // + ty: std::option::Option<bool> 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 bdd9c020c95..1d8e945f87a 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::<bool>::Some(const true); // bb0[3]: scope 0 at $DIR/discriminant.rs:6:34: 6:44 -+ _3 = const {transmute(0x01): std::option::Option<bool>}; // bb0[3]: scope 0 at $DIR/discriminant.rs:6:34: 6:44 ++ _3 = const std::option::Option::<bool>::Some(true); // bb0[3]: scope 0 at $DIR/discriminant.rs:6:34: 6:44 // ty::Const - // + ty: bool + // + ty: std::option::Option<bool> 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 6983e94ff8d..7f2f7cdb176 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<u32>); // bb0[2]: scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43 - (*_2) = const std::vec::Vec::<u32>::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<u32>) = 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::<u32>; // bb0[4]: scope 2 at $SRC_DIR/liballoc/vec.rs:LL:COL ++ ((*_4).0: alloc::raw_vec::RawVec<u32>) = const alloc::raw_vec::RawVec::<u32> { ptr: std::ptr::Unique::<u32> { pointer: {0x4 as *const u32}, _marker: std::marker::PhantomData::<u32> }, 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<u32> {std::vec::Vec::<u32>::new} - // + val: Value(Scalar(<ZST>)) 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 38ab9ce9926..b968b33ac52 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<u32>); // bb0[2]: scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43 - (*_2) = const std::vec::Vec::<u32>::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<u32>) = 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::<u32>; // bb0[4]: scope 2 at $SRC_DIR/liballoc/vec.rs:LL:COL ++ ((*_4).0: alloc::raw_vec::RawVec<u32>) = const alloc::raw_vec::RawVec::<u32> { ptr: std::ptr::Unique::<u32> { pointer: {0x4 as *const u32}, _marker: std::marker::PhantomData::<u32> }, 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<u32> {std::vec::Vec::<u32>::new} - // + val: Value(Scalar(<ZST>)) 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 8613a812a83..855ead7ea05 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(<ZST>)) @@ -39,7 +39,7 @@ - // mir::Constant - // + span: $DIR/simplify-locals-removes-unused-consts.rs:13:25: 13:27 - // + literal: Const { ty: (), val: Value(Scalar(<ZST>)) } -- _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(<ZST>)) @@ -68,7 +68,7 @@ - // + literal: Const { ty: (), val: Value(Scalar(<ZST>)) } - 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(<ZST>)) @@ -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 |
