Skip to content

Commit

Permalink
ty/print: pretty-print constant aggregates (arrays, tuples and ADTs).
Browse files Browse the repository at this point in the history
  • Loading branch information
eddyb committed Apr 17, 2020
1 parent aabed93 commit eccb28e
Show file tree
Hide file tree
Showing 7 changed files with 72 additions and 25 deletions.
2 changes: 1 addition & 1 deletion src/librustc_middle/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>>
Expand Down
79 changes: 63 additions & 16 deletions src/librustc_middle/ty/print/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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| {
Expand Down Expand Up @@ -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), .. }, _),
Expand Down Expand Up @@ -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.
_ => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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>))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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>))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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>))
Expand All @@ -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>))
Expand Down Expand Up @@ -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>))
Expand All @@ -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
Expand Down

0 comments on commit eccb28e

Please sign in to comment.