Skip to content

Commit 57444cf

Browse files
committed
use pretty_print_const_value from MIR constant 'extra' printing
1 parent 10a822b commit 57444cf

File tree

6 files changed

+155
-130
lines changed

6 files changed

+155
-130
lines changed

Diff for: compiler/rustc_data_structures/src/lib.rs

+19
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ extern crate cfg_if;
4747
#[macro_use]
4848
extern crate rustc_macros;
4949

50+
use std::fmt;
51+
5052
pub use rustc_index::static_assert_size;
5153

5254
#[inline(never)]
@@ -126,6 +128,23 @@ impl<F: FnOnce()> Drop for OnDrop<F> {
126128
}
127129
}
128130

131+
/// Turns a closure that takes an `&mut Formatter` into something that can be display-formatted.
132+
pub fn make_display(f: impl Fn(&mut fmt::Formatter<'_>) -> fmt::Result) -> impl fmt::Display {
133+
struct Printer<F> {
134+
f: F,
135+
}
136+
impl<F> fmt::Display for Printer<F>
137+
where
138+
F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result,
139+
{
140+
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
141+
(self.f)(fmt)
142+
}
143+
}
144+
145+
Printer { f }
146+
}
147+
129148
// See comments in src/librustc_middle/lib.rs
130149
#[doc(hidden)]
131150
pub fn __noop_fix_for_27438() {}

Diff for: compiler/rustc_middle/src/mir/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ pub use self::pretty::{
7070
create_dump_file, display_allocation, dump_enabled, dump_mir, write_mir_pretty, PassWhere,
7171
};
7272
pub use consts::*;
73-
pub use pretty::pretty_print_const_value;
73+
use pretty::pretty_print_const_value;
7474
pub use syntax::*;
7575
pub use terminator::*;
7676

Diff for: compiler/rustc_middle/src/mir/pretty.rs

+132-126
Original file line numberDiff line numberDiff line change
@@ -455,26 +455,27 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
455455
self.push(&format!("+ user_ty: {user_ty:?}"));
456456
}
457457

458-
// FIXME: this is a poor version of `pretty_print_const_value`.
459-
let fmt_val = |val: &ConstValue<'tcx>| match val {
460-
ConstValue::ZeroSized => "<ZST>".to_string(),
461-
ConstValue::Scalar(s) => format!("Scalar({s:?})"),
462-
ConstValue::Slice { .. } => "Slice(..)".to_string(),
463-
ConstValue::Indirect { .. } => "ByRef(..)".to_string(),
458+
let fmt_val = |val: ConstValue<'tcx>, ty: Ty<'tcx>| {
459+
let tcx = self.tcx;
460+
rustc_data_structures::make_display(move |fmt| {
461+
pretty_print_const_value_tcx(tcx, val, ty, fmt)
462+
})
464463
};
465464

465+
// FIXME: call pretty_print_const_valtree?
466466
let fmt_valtree = |valtree: &ty::ValTree<'tcx>| match valtree {
467-
ty::ValTree::Leaf(leaf) => format!("ValTree::Leaf({leaf:?})"),
468-
ty::ValTree::Branch(_) => "ValTree::Branch(..)".to_string(),
467+
ty::ValTree::Leaf(leaf) => format!("Leaf({leaf:?})"),
468+
ty::ValTree::Branch(_) => "Branch(..)".to_string(),
469469
};
470470

471471
let val = match literal {
472472
ConstantKind::Ty(ct) => match ct.kind() {
473-
ty::ConstKind::Param(p) => format!("Param({p})"),
473+
ty::ConstKind::Param(p) => format!("ty::Param({p})"),
474474
ty::ConstKind::Unevaluated(uv) => {
475-
format!("Unevaluated({}, {:?})", self.tcx.def_path_str(uv.def), uv.args,)
475+
format!("ty::Unevaluated({}, {:?})", self.tcx.def_path_str(uv.def), uv.args,)
476476
}
477-
ty::ConstKind::Value(val) => format!("Value({})", fmt_valtree(&val)),
477+
ty::ConstKind::Value(val) => format!("ty::Valtree({})", fmt_valtree(&val)),
478+
// No `ty::` prefix since we also use this to represent errors from `mir::Unevaluated`.
478479
ty::ConstKind::Error(_) => "Error".to_string(),
479480
// These variants shouldn't exist in the MIR.
480481
ty::ConstKind::Placeholder(_)
@@ -490,10 +491,7 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
490491
uv.promoted,
491492
)
492493
}
493-
// To keep the diffs small, we render this like we render `ty::Const::Value`.
494-
//
495-
// This changes once `ty::Const::Value` is represented using valtrees.
496-
ConstantKind::Val(val, _) => format!("Value({})", fmt_val(&val)),
494+
ConstantKind::Val(val, ty) => format!("Value({})", fmt_val(*val, *ty)),
497495
};
498496

499497
// This reflects what `Const` looked liked before `val` was renamed
@@ -1090,6 +1088,7 @@ fn pretty_print_byte_str(fmt: &mut Formatter<'_>, byte_str: &[u8]) -> fmt::Resul
10901088
}
10911089

10921090
fn comma_sep<'tcx>(
1091+
tcx: TyCtxt<'tcx>,
10931092
fmt: &mut Formatter<'_>,
10941093
elems: Vec<(ConstValue<'tcx>, Ty<'tcx>)>,
10951094
) -> fmt::Result {
@@ -1098,143 +1097,150 @@ fn comma_sep<'tcx>(
10981097
if !first {
10991098
fmt.write_str(", ")?;
11001099
}
1101-
pretty_print_const_value(ct, ty, fmt)?;
1100+
pretty_print_const_value_tcx(tcx, ct, ty, fmt)?;
11021101
first = false;
11031102
}
11041103
Ok(())
11051104
}
11061105

1107-
pub fn pretty_print_const_value<'tcx>(
1106+
fn pretty_print_const_value_tcx<'tcx>(
1107+
tcx: TyCtxt<'tcx>,
11081108
ct: ConstValue<'tcx>,
11091109
ty: Ty<'tcx>,
11101110
fmt: &mut Formatter<'_>,
11111111
) -> fmt::Result {
11121112
use crate::ty::print::PrettyPrinter;
11131113

1114-
ty::tls::with(|tcx| {
1115-
let ct = tcx.lift(ct).unwrap();
1116-
let ty = tcx.lift(ty).unwrap();
1117-
1118-
if tcx.sess.verbose() {
1119-
fmt.write_str(&format!("ConstValue({ct:?}: {ty})"))?;
1120-
return Ok(());
1121-
}
1114+
if tcx.sess.verbose() {
1115+
fmt.write_str(&format!("ConstValue({ct:?}: {ty})"))?;
1116+
return Ok(());
1117+
}
11221118

1123-
let u8_type = tcx.types.u8;
1124-
match (ct, ty.kind()) {
1125-
// Byte/string slices, printed as (byte) string literals.
1126-
(_, ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Str) => {
1127-
if let Some(data) = ct.try_get_slice_bytes_for_diagnostics(tcx) {
1128-
fmt.write_str(&format!("{:?}", String::from_utf8_lossy(data)))?;
1129-
return Ok(());
1130-
}
1131-
}
1132-
(_, ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Slice(t) if *t == u8_type) => {
1133-
if let Some(data) = ct.try_get_slice_bytes_for_diagnostics(tcx) {
1134-
pretty_print_byte_str(fmt, data)?;
1135-
return Ok(());
1136-
}
1119+
let u8_type = tcx.types.u8;
1120+
match (ct, ty.kind()) {
1121+
// Byte/string slices, printed as (byte) string literals.
1122+
(_, ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Str) => {
1123+
if let Some(data) = ct.try_get_slice_bytes_for_diagnostics(tcx) {
1124+
fmt.write_str(&format!("{:?}", String::from_utf8_lossy(data)))?;
1125+
return Ok(());
11371126
}
1138-
(ConstValue::Indirect { alloc_id, offset }, ty::Array(t, n)) if *t == u8_type => {
1139-
let n = n.try_to_target_usize(tcx).unwrap();
1140-
let alloc = tcx.global_alloc(alloc_id).unwrap_memory();
1141-
// cast is ok because we already checked for pointer size (32 or 64 bit) above
1142-
let range = AllocRange { start: offset, size: Size::from_bytes(n) };
1143-
let byte_str = alloc.inner().get_bytes_strip_provenance(&tcx, range).unwrap();
1144-
fmt.write_str("*")?;
1145-
pretty_print_byte_str(fmt, byte_str)?;
1127+
}
1128+
(_, ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Slice(t) if *t == u8_type) => {
1129+
if let Some(data) = ct.try_get_slice_bytes_for_diagnostics(tcx) {
1130+
pretty_print_byte_str(fmt, data)?;
11461131
return Ok(());
11471132
}
1148-
// Aggregates, printed as array/tuple/struct/variant construction syntax.
1149-
//
1150-
// NB: the `has_non_region_param` check ensures that we can use
1151-
// the `destructure_const` query with an empty `ty::ParamEnv` without
1152-
// introducing ICEs (e.g. via `layout_of`) from missing bounds.
1153-
// E.g. `transmute([0usize; 2]): (u8, *mut T)` needs to know `T: Sized`
1154-
// to be able to destructure the tuple into `(0u8, *mut T)`
1155-
(_, ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) if !ty.has_non_region_param() => {
1156-
let ct = tcx.lift(ct).unwrap();
1157-
let ty = tcx.lift(ty).unwrap();
1158-
if let Some(contents) = tcx.try_destructure_mir_constant_for_diagnostics((ct, ty)) {
1159-
let fields: Vec<(ConstValue<'_>, Ty<'_>)> = contents.fields.to_vec();
1160-
match *ty.kind() {
1161-
ty::Array(..) => {
1162-
fmt.write_str("[")?;
1163-
comma_sep(fmt, fields)?;
1164-
fmt.write_str("]")?;
1133+
}
1134+
(ConstValue::Indirect { alloc_id, offset }, ty::Array(t, n)) if *t == u8_type => {
1135+
let n = n.try_to_target_usize(tcx).unwrap();
1136+
let alloc = tcx.global_alloc(alloc_id).unwrap_memory();
1137+
// cast is ok because we already checked for pointer size (32 or 64 bit) above
1138+
let range = AllocRange { start: offset, size: Size::from_bytes(n) };
1139+
let byte_str = alloc.inner().get_bytes_strip_provenance(&tcx, range).unwrap();
1140+
fmt.write_str("*")?;
1141+
pretty_print_byte_str(fmt, byte_str)?;
1142+
return Ok(());
1143+
}
1144+
// Aggregates, printed as array/tuple/struct/variant construction syntax.
1145+
//
1146+
// NB: the `has_non_region_param` check ensures that we can use
1147+
// the `destructure_const` query with an empty `ty::ParamEnv` without
1148+
// introducing ICEs (e.g. via `layout_of`) from missing bounds.
1149+
// E.g. `transmute([0usize; 2]): (u8, *mut T)` needs to know `T: Sized`
1150+
// to be able to destructure the tuple into `(0u8, *mut T)`
1151+
(_, ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) if !ty.has_non_region_param() => {
1152+
let ct = tcx.lift(ct).unwrap();
1153+
let ty = tcx.lift(ty).unwrap();
1154+
if let Some(contents) = tcx.try_destructure_mir_constant_for_diagnostics((ct, ty)) {
1155+
let fields: Vec<(ConstValue<'_>, Ty<'_>)> = contents.fields.to_vec();
1156+
match *ty.kind() {
1157+
ty::Array(..) => {
1158+
fmt.write_str("[")?;
1159+
comma_sep(tcx, fmt, fields)?;
1160+
fmt.write_str("]")?;
1161+
}
1162+
ty::Tuple(..) => {
1163+
fmt.write_str("(")?;
1164+
comma_sep(tcx, fmt, fields)?;
1165+
if contents.fields.len() == 1 {
1166+
fmt.write_str(",")?;
11651167
}
1166-
ty::Tuple(..) => {
1167-
fmt.write_str("(")?;
1168-
comma_sep(fmt, fields)?;
1169-
if contents.fields.len() == 1 {
1170-
fmt.write_str(",")?;
1168+
fmt.write_str(")")?;
1169+
}
1170+
ty::Adt(def, _) if def.variants().is_empty() => {
1171+
fmt.write_str(&format!("{{unreachable(): {ty}}}"))?;
1172+
}
1173+
ty::Adt(def, args) => {
1174+
let variant_idx = contents
1175+
.variant
1176+
.expect("destructed mir constant of adt without variant idx");
1177+
let variant_def = &def.variant(variant_idx);
1178+
let args = tcx.lift(args).unwrap();
1179+
let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS);
1180+
cx.print_alloc_ids = true;
1181+
let cx = cx.print_value_path(variant_def.def_id, args)?;
1182+
fmt.write_str(&cx.into_buffer())?;
1183+
1184+
match variant_def.ctor_kind() {
1185+
Some(CtorKind::Const) => {}
1186+
Some(CtorKind::Fn) => {
1187+
fmt.write_str("(")?;
1188+
comma_sep(tcx, fmt, fields)?;
1189+
fmt.write_str(")")?;
11711190
}
1172-
fmt.write_str(")")?;
1173-
}
1174-
ty::Adt(def, _) if def.variants().is_empty() => {
1175-
fmt.write_str(&format!("{{unreachable(): {ty}}}"))?;
1176-
}
1177-
ty::Adt(def, args) => {
1178-
let variant_idx = contents
1179-
.variant
1180-
.expect("destructed mir constant of adt without variant idx");
1181-
let variant_def = &def.variant(variant_idx);
1182-
let args = tcx.lift(args).unwrap();
1183-
let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS);
1184-
cx.print_alloc_ids = true;
1185-
let cx = cx.print_value_path(variant_def.def_id, args)?;
1186-
fmt.write_str(&cx.into_buffer())?;
1187-
1188-
match variant_def.ctor_kind() {
1189-
Some(CtorKind::Const) => {}
1190-
Some(CtorKind::Fn) => {
1191-
fmt.write_str("(")?;
1192-
comma_sep(fmt, fields)?;
1193-
fmt.write_str(")")?;
1194-
}
1195-
None => {
1196-
fmt.write_str(" {{ ")?;
1197-
let mut first = true;
1198-
for (field_def, (ct, ty)) in
1199-
iter::zip(&variant_def.fields, fields)
1200-
{
1201-
if !first {
1202-
fmt.write_str(", ")?;
1203-
}
1204-
write!(fmt, "{}: ", field_def.name)?;
1205-
pretty_print_const_value(ct, ty, fmt)?;
1206-
first = false;
1191+
None => {
1192+
fmt.write_str(" {{ ")?;
1193+
let mut first = true;
1194+
for (field_def, (ct, ty)) in iter::zip(&variant_def.fields, fields)
1195+
{
1196+
if !first {
1197+
fmt.write_str(", ")?;
12071198
}
1208-
fmt.write_str(" }}")?;
1199+
write!(fmt, "{}: ", field_def.name)?;
1200+
pretty_print_const_value_tcx(tcx, ct, ty, fmt)?;
1201+
first = false;
12091202
}
1203+
fmt.write_str(" }}")?;
12101204
}
12111205
}
1212-
_ => unreachable!(),
12131206
}
1214-
return Ok(());
1207+
_ => unreachable!(),
12151208
}
1216-
}
1217-
(ConstValue::Scalar(scalar), _) => {
1218-
let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS);
1219-
cx.print_alloc_ids = true;
1220-
let ty = tcx.lift(ty).unwrap();
1221-
cx = cx.pretty_print_const_scalar(scalar, ty)?;
1222-
fmt.write_str(&cx.into_buffer())?;
1223-
return Ok(());
1224-
}
1225-
(ConstValue::ZeroSized, ty::FnDef(d, s)) => {
1226-
let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS);
1227-
cx.print_alloc_ids = true;
1228-
let cx = cx.print_value_path(*d, s)?;
1229-
fmt.write_str(&cx.into_buffer())?;
12301209
return Ok(());
12311210
}
1232-
// FIXME(oli-obk): also pretty print arrays and other aggregate constants by reading
1233-
// their fields instead of just dumping the memory.
1234-
_ => {}
12351211
}
1236-
// Fall back to debug pretty printing for invalid constants.
1237-
write!(fmt, "{ct:?}: {ty}")
1212+
(ConstValue::Scalar(scalar), _) => {
1213+
let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS);
1214+
cx.print_alloc_ids = true;
1215+
let ty = tcx.lift(ty).unwrap();
1216+
cx = cx.pretty_print_const_scalar(scalar, ty)?;
1217+
fmt.write_str(&cx.into_buffer())?;
1218+
return Ok(());
1219+
}
1220+
(ConstValue::ZeroSized, ty::FnDef(d, s)) => {
1221+
let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS);
1222+
cx.print_alloc_ids = true;
1223+
let cx = cx.print_value_path(*d, s)?;
1224+
fmt.write_str(&cx.into_buffer())?;
1225+
return Ok(());
1226+
}
1227+
// FIXME(oli-obk): also pretty print arrays and other aggregate constants by reading
1228+
// their fields instead of just dumping the memory.
1229+
_ => {}
1230+
}
1231+
// Fall back to debug pretty printing for invalid constants.
1232+
write!(fmt, "{ct:?}: {ty}")
1233+
}
1234+
1235+
pub(crate) fn pretty_print_const_value<'tcx>(
1236+
ct: ConstValue<'tcx>,
1237+
ty: Ty<'tcx>,
1238+
fmt: &mut Formatter<'_>,
1239+
) -> fmt::Result {
1240+
ty::tls::with(|tcx| {
1241+
let ct = tcx.lift(ct).unwrap();
1242+
let ty = tcx.lift(ty).unwrap();
1243+
pretty_print_const_value_tcx(tcx, ct, ty, fmt)
12381244
})
12391245
}
12401246

Diff for: compiler/rustc_middle/src/ty/print/pretty.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1713,7 +1713,7 @@ pub trait PrettyPrinter<'tcx>:
17131713
}
17141714
}
17151715

1716-
pub fn pretty_print_const<'tcx>(
1716+
pub(crate) fn pretty_print_const<'tcx>(
17171717
c: ty::Const<'tcx>,
17181718
fmt: &mut fmt::Formatter<'_>,
17191719
print_types: bool,

Diff for: tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-abort.mir

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ fn outer(_1: u8) -> u8 {
1111
_0 = inner(move _2) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/spans.rs:10:5: 10:14
1212
// mir::Constant
1313
// + span: $DIR/spans.rs:10:5: 10:10
14-
// + literal: Const { ty: for<'a> fn(&'a u8) -> u8 {inner}, val: Value(<ZST>) }
14+
// + literal: Const { ty: for<'a> fn(&'a u8) -> u8 {inner}, val: Value(inner) }
1515
}
1616

1717
bb1: {

Diff for: tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-unwind.mir

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ fn outer(_1: u8) -> u8 {
1111
_0 = inner(move _2) -> [return: bb1, unwind continue]; // scope 0 at $DIR/spans.rs:10:5: 10:14
1212
// mir::Constant
1313
// + span: $DIR/spans.rs:10:5: 10:10
14-
// + literal: Const { ty: for<'a> fn(&'a u8) -> u8 {inner}, val: Value(<ZST>) }
14+
// + literal: Const { ty: for<'a> fn(&'a u8) -> u8 {inner}, val: Value(inner) }
1515
}
1616

1717
bb1: {

0 commit comments

Comments
 (0)