Skip to content

Commit eccb28e

Browse files
committed
ty/print: pretty-print constant aggregates (arrays, tuples and ADTs).
1 parent aabed93 commit eccb28e

File tree

7 files changed

+72
-25
lines changed

7 files changed

+72
-25
lines changed

src/librustc_middle/query/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -574,7 +574,7 @@ rustc_queries! {
574574
desc { "extract field of const" }
575575
}
576576

577-
/// Destructure a constant ADT or array into its variant indent and its
577+
/// Destructure a constant ADT or array into its variant index and its
578578
/// field values.
579579
query destructure_const(
580580
key: ty::ParamEnvAnd<'tcx, &'tcx ty::Const<'tcx>>

src/librustc_middle/ty/print/pretty.rs

+63-16
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use rustc_apfloat::Float;
99
use rustc_ast::ast;
1010
use rustc_attr::{SignedInt, UnsignedInt};
1111
use rustc_hir as hir;
12-
use rustc_hir::def::{DefKind, Namespace};
12+
use rustc_hir::def::{CtorKind, DefKind, Namespace};
1313
use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
1414
use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
1515
use rustc_span::symbol::{kw, Symbol};
@@ -1037,19 +1037,6 @@ pub trait PrettyPrinter<'tcx>:
10371037
}
10381038
// For function type zsts just printing the path is enough
10391039
(Scalar::Raw { size: 0, .. }, ty::FnDef(d, s)) => p!(print_value_path(*d, s)),
1040-
// Empty tuples are frequently occurring, so don't print the fallback.
1041-
(Scalar::Raw { size: 0, .. }, ty::Tuple(ts)) if ts.is_empty() => p!(write("()")),
1042-
// Zero element arrays have a trivial representation.
1043-
(
1044-
Scalar::Raw { size: 0, .. },
1045-
ty::Array(
1046-
_,
1047-
ty::Const {
1048-
val: ty::ConstKind::Value(ConstValue::Scalar(Scalar::Raw { data: 0, .. })),
1049-
..
1050-
},
1051-
),
1052-
) => p!(write("[]")),
10531040
// Nontrivial types with scalar bit representation
10541041
(Scalar::Raw { data, size }, _) => {
10551042
let print = |mut this: Self| {
@@ -1118,14 +1105,14 @@ pub trait PrettyPrinter<'tcx>:
11181105
define_scoped_cx!(self);
11191106

11201107
if self.tcx().sess.verbose() {
1121-
p!(write("ConstValue({:?}: {:?})", ct, ty));
1108+
p!(write("ConstValue({:?}: ", ct), print(ty), write(")"));
11221109
return Ok(self);
11231110
}
11241111

11251112
let u8_type = self.tcx().types.u8;
11261113

11271114
match (ct, &ty.kind) {
1128-
(ConstValue::Scalar(scalar), _) => self.pretty_print_const_scalar(scalar, ty, print_ty),
1115+
// Byte/string slices, printed as (byte) string literals.
11291116
(
11301117
ConstValue::Slice { data, start, end },
11311118
ty::Ref(_, ty::TyS { kind: ty::Slice(t), .. }, _),
@@ -1159,6 +1146,66 @@ pub trait PrettyPrinter<'tcx>:
11591146
p!(pretty_print_byte_str(byte_str));
11601147
Ok(self)
11611148
}
1149+
1150+
// Aggregates, printed as array/tuple/struct/variant construction syntax.
1151+
//
1152+
// NB: the `has_param_types_or_consts` check ensures that we can use
1153+
// the `destructure_const` query with an empty `ty::ParamEnv` without
1154+
// introducing ICEs (e.g. via `layout_of`) from missing bounds.
1155+
// E.g. `transmute([0usize; 2]): (u8, *mut T)` needs to know `T: Sized`
1156+
// to be able to destructure the tuple into `(0u8, *mut T)
1157+
//
1158+
// FIXME(eddyb) for `--emit=mir`/`-Z dump-mir`, we should provide the
1159+
// correct `ty::ParamEnv` to allow printing *all* constant values.
1160+
(_, ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) if !ty.has_param_types_or_consts() => {
1161+
let contents = self.tcx().destructure_const(
1162+
ty::ParamEnv::reveal_all()
1163+
.and(self.tcx().mk_const(ty::Const { val: ty::ConstKind::Value(ct), ty })),
1164+
);
1165+
let fields = contents.fields.iter().copied();
1166+
1167+
match ty.kind {
1168+
ty::Array(..) => {
1169+
p!(write("["), comma_sep(fields), write("]"));
1170+
}
1171+
ty::Tuple(..) => {
1172+
p!(write("("), comma_sep(fields));
1173+
if contents.fields.len() == 1 {
1174+
p!(write(","));
1175+
}
1176+
p!(write(")"));
1177+
}
1178+
ty::Adt(def, substs) => {
1179+
let variant_def = &def.variants[contents.variant];
1180+
p!(print_value_path(variant_def.def_id, substs));
1181+
1182+
match variant_def.ctor_kind {
1183+
CtorKind::Const => {}
1184+
CtorKind::Fn => {
1185+
p!(write("("), comma_sep(fields), write(")"));
1186+
}
1187+
CtorKind::Fictive => {
1188+
p!(write(" {{ "));
1189+
let mut first = true;
1190+
for (field_def, field) in variant_def.fields.iter().zip(fields) {
1191+
if !first {
1192+
p!(write(", "));
1193+
}
1194+
p!(write("{}: ", field_def.ident), print(field));
1195+
first = false;
1196+
}
1197+
p!(write(" }}"));
1198+
}
1199+
}
1200+
}
1201+
_ => unreachable!(),
1202+
}
1203+
1204+
Ok(self)
1205+
}
1206+
1207+
(ConstValue::Scalar(scalar), _) => self.pretty_print_const_scalar(scalar, ty, print_ty),
1208+
11621209
// FIXME(oli-obk): also pretty print arrays and other aggregate constants by reading
11631210
// their fields instead of just dumping the memory.
11641211
_ => {

src/test/mir-opt/const_prop/discriminant/32bit/rustc.main.ConstProp.diff

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
StorageLive(_2); // bb0[1]: scope 0 at $DIR/discriminant.rs:6:13: 6:64
1717
StorageLive(_3); // bb0[2]: scope 0 at $DIR/discriminant.rs:6:34: 6:44
1818
- _3 = std::option::Option::<bool>::Some(const true); // bb0[3]: scope 0 at $DIR/discriminant.rs:6:34: 6:44
19-
+ _3 = const {transmute(0x01): std::option::Option<bool>}; // bb0[3]: scope 0 at $DIR/discriminant.rs:6:34: 6:44
19+
+ _3 = const std::option::Option::<bool>::Some(true); // bb0[3]: scope 0 at $DIR/discriminant.rs:6:34: 6:44
2020
// ty::Const
2121
- // + ty: bool
2222
+ // + ty: std::option::Option<bool>

src/test/mir-opt/const_prop/discriminant/64bit/rustc.main.ConstProp.diff

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
StorageLive(_2); // bb0[1]: scope 0 at $DIR/discriminant.rs:6:13: 6:64
1717
StorageLive(_3); // bb0[2]: scope 0 at $DIR/discriminant.rs:6:34: 6:44
1818
- _3 = std::option::Option::<bool>::Some(const true); // bb0[3]: scope 0 at $DIR/discriminant.rs:6:34: 6:44
19-
+ _3 = const {transmute(0x01): std::option::Option<bool>}; // bb0[3]: scope 0 at $DIR/discriminant.rs:6:34: 6:44
19+
+ _3 = const std::option::Option::<bool>::Some(true); // bb0[3]: scope 0 at $DIR/discriminant.rs:6:34: 6:44
2020
// ty::Const
2121
- // + ty: bool
2222
+ // + ty: std::option::Option<bool>

src/test/mir-opt/inline/inline-into-box-place/32bit/rustc.main.Inline.diff

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
_2 = Box(std::vec::Vec<u32>); // bb0[2]: scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43
2020
- (*_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
2121
+ _4 = &mut (*_2); // bb0[3]: scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
22-
+ ((*_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
22+
+ ((*_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
2323
// ty::Const
2424
- // + ty: fn() -> std::vec::Vec<u32> {std::vec::Vec::<u32>::new}
2525
- // + val: Value(Scalar(<ZST>))

src/test/mir-opt/inline/inline-into-box-place/64bit/rustc.main.Inline.diff

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
_2 = Box(std::vec::Vec<u32>); // bb0[2]: scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43
2020
- (*_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
2121
+ _4 = &mut (*_2); // bb0[3]: scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
22-
+ ((*_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
22+
+ ((*_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
2323
// ty::Const
2424
- // + ty: fn() -> std::vec::Vec<u32> {std::vec::Vec::<u32>::new}
2525
- // + val: Value(Scalar(<ZST>))

src/test/mir-opt/simplify-locals-removes-unused-consts/rustc.main.SimplifyLocals.diff

+4-4
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
- StorageLive(_2); // bb0[1]: scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:13:21: 13:23
2525
- _2 = const (); // bb0[2]: scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:13:21: 13:23
2626
+ StorageLive(_1); // bb0[0]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:5: 14:22
27-
+ _1 = const use_zst(const {transmute(()): ((), ())}) -> bb1; // bb0[1]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:5: 14:22
27+
+ _1 = const use_zst(const ((), ())) -> bb1; // bb0[1]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:5: 14:22
2828
// ty::Const
2929
- // + ty: ()
3030
- // + val: Value(Scalar(<ZST>))
@@ -39,7 +39,7 @@
3939
- // mir::Constant
4040
- // + span: $DIR/simplify-locals-removes-unused-consts.rs:13:25: 13:27
4141
- // + literal: Const { ty: (), val: Value(Scalar(<ZST>)) }
42-
- _1 = const {transmute(()): ((), ())}; // bb0[5]: scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:13:20: 13:28
42+
- _1 = const ((), ()); // bb0[5]: scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:13:20: 13:28
4343
- // ty::Const
4444
- // + ty: ((), ())
4545
- // + val: Value(Scalar(<ZST>))
@@ -68,7 +68,7 @@
6868
- // + literal: Const { ty: (), val: Value(Scalar(<ZST>)) }
6969
- StorageDead(_7); // bb0[14]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:20: 14:21
7070
- StorageDead(_6); // bb0[15]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:20: 14:21
71-
- _4 = const use_zst(const {transmute(()): ((), ())}) -> bb1; // bb0[16]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:5: 14:22
71+
- _4 = const use_zst(const ((), ())) -> bb1; // bb0[16]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:5: 14:22
7272
- // ty::Const
7373
// + ty: fn(((), ())) {use_zst}
7474
// + val: Value(Scalar(<ZST>))
@@ -88,7 +88,7 @@
8888
- StorageLive(_8); // bb1[1]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:5: 16:35
8989
- StorageLive(_10); // bb1[2]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:12: 16:30
9090
- StorageLive(_11); // bb1[3]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:12: 16:28
91-
- _11 = const {transmute(0x28): Temp}; // bb1[4]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:12: 16:28
91+
- _11 = const Temp { x: 40u8 }; // bb1[4]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:12: 16:28
9292
+ StorageDead(_1); // bb1[0]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:22: 14:23
9393
+ StorageLive(_2); // bb1[1]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:5: 16:35
9494
+ _2 = const use_u8(const 42u8) -> bb2; // bb1[2]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:5: 16:35

0 commit comments

Comments
 (0)