Skip to content

Commit 10a822b

Browse files
committed
move some MIR const pretty-printing into pretty.rs
1 parent 49f5b17 commit 10a822b

File tree

4 files changed

+176
-177
lines changed

4 files changed

+176
-177
lines changed

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ use rustc_span::Span;
77
use rustc_target::abi::Size;
88

99
use crate::mir::interpret::{ConstValue, ErrorHandled, GlobalAlloc, Scalar};
10-
use crate::mir::{interpret, pretty_print_const, pretty_print_const_value, Promoted};
11-
use crate::ty::{self, List, Ty, TyCtxt};
10+
use crate::mir::{interpret, pretty_print_const_value, Promoted};
11+
use crate::ty::{self, print::pretty_print_const, List, Ty, TyCtxt};
1212
use crate::ty::{GenericArgs, GenericArgsRef};
1313
use crate::ty::{ScalarInt, UserTypeAnnotationIndex};
1414

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

+6-175
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crate::mir::interpret::{AllocRange, ErrorHandled, ConstAllocation, ConstValu
66
use crate::mir::visit::MirVisitable;
77
use crate::ty::codec::{TyDecoder, TyEncoder};
88
use crate::ty::fold::{FallibleTypeFolder, TypeFoldable};
9-
use crate::ty::print::with_no_trimmed_paths;
9+
use crate::ty::print::{pretty_print_const, with_no_trimmed_paths};
1010
use crate::ty::print::{FmtPrinter, Printer};
1111
use crate::ty::visit::TypeVisitableExt;
1212
use crate::ty::{self, List, Ty, TyCtxt};
@@ -20,7 +20,7 @@ use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
2020
use rustc_hir::{self, GeneratorKind, ImplicitSelfKind};
2121
use rustc_hir::{self as hir, HirId};
2222
use rustc_session::Session;
23-
use rustc_target::abi::{FieldIdx, Size, VariantIdx};
23+
use rustc_target::abi::{FieldIdx, VariantIdx};
2424

2525
use polonius_engine::Atom;
2626
pub use rustc_ast::Mutability;
@@ -46,7 +46,6 @@ pub use basic_blocks::BasicBlocks;
4646

4747
mod basic_blocks;
4848
mod consts;
49-
pub use consts::*;
5049
pub mod coverage;
5150
mod generic_graph;
5251
pub mod generic_graphviz;
@@ -58,10 +57,8 @@ pub mod pretty;
5857
mod query;
5958
pub mod spanview;
6059
mod syntax;
61-
pub use syntax::*;
6260
pub mod tcx;
6361
mod terminator;
64-
pub use terminator::*;
6562

6663
pub mod traversal;
6764
mod type_foldable;
@@ -72,6 +69,10 @@ pub use self::graphviz::write_mir_graphviz;
7269
pub use self::pretty::{
7370
create_dump_file, display_allocation, dump_enabled, dump_mir, write_mir_pretty, PassWhere,
7471
};
72+
pub use consts::*;
73+
pub use pretty::pretty_print_const_value;
74+
pub use syntax::*;
75+
pub use terminator::*;
7576

7677
/// Types for locals
7778
pub type LocalDecls<'tcx> = IndexSlice<Local, LocalDecl<'tcx>>;
@@ -2459,176 +2460,6 @@ rustc_index::newtype_index! {
24592460
pub struct Promoted {}
24602461
}
24612462

2462-
fn pretty_print_const<'tcx>(
2463-
c: ty::Const<'tcx>,
2464-
fmt: &mut Formatter<'_>,
2465-
print_types: bool,
2466-
) -> fmt::Result {
2467-
use crate::ty::print::PrettyPrinter;
2468-
ty::tls::with(|tcx| {
2469-
let literal = tcx.lift(c).unwrap();
2470-
let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS);
2471-
cx.print_alloc_ids = true;
2472-
let cx = cx.pretty_print_const(literal, print_types)?;
2473-
fmt.write_str(&cx.into_buffer())?;
2474-
Ok(())
2475-
})
2476-
}
2477-
2478-
fn pretty_print_byte_str(fmt: &mut Formatter<'_>, byte_str: &[u8]) -> fmt::Result {
2479-
write!(fmt, "b\"{}\"", byte_str.escape_ascii())
2480-
}
2481-
2482-
fn comma_sep<'tcx>(
2483-
fmt: &mut Formatter<'_>,
2484-
elems: Vec<(ConstValue<'tcx>, Ty<'tcx>)>,
2485-
) -> fmt::Result {
2486-
let mut first = true;
2487-
for (ct, ty) in elems {
2488-
if !first {
2489-
fmt.write_str(", ")?;
2490-
}
2491-
pretty_print_const_value(ct, ty, fmt)?;
2492-
first = false;
2493-
}
2494-
Ok(())
2495-
}
2496-
2497-
// FIXME: Move that into `mir/pretty.rs`.
2498-
fn pretty_print_const_value<'tcx>(
2499-
ct: ConstValue<'tcx>,
2500-
ty: Ty<'tcx>,
2501-
fmt: &mut Formatter<'_>,
2502-
) -> fmt::Result {
2503-
use crate::ty::print::PrettyPrinter;
2504-
2505-
ty::tls::with(|tcx| {
2506-
let ct = tcx.lift(ct).unwrap();
2507-
let ty = tcx.lift(ty).unwrap();
2508-
2509-
if tcx.sess.verbose() {
2510-
fmt.write_str(&format!("ConstValue({ct:?}: {ty})"))?;
2511-
return Ok(());
2512-
}
2513-
2514-
let u8_type = tcx.types.u8;
2515-
match (ct, ty.kind()) {
2516-
// Byte/string slices, printed as (byte) string literals.
2517-
(_, ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Str) => {
2518-
if let Some(data) = ct.try_get_slice_bytes_for_diagnostics(tcx) {
2519-
fmt.write_str(&format!("{:?}", String::from_utf8_lossy(data)))?;
2520-
return Ok(());
2521-
}
2522-
}
2523-
(_, ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Slice(t) if *t == u8_type) => {
2524-
if let Some(data) = ct.try_get_slice_bytes_for_diagnostics(tcx) {
2525-
pretty_print_byte_str(fmt, data)?;
2526-
return Ok(());
2527-
}
2528-
}
2529-
(ConstValue::Indirect { alloc_id, offset }, ty::Array(t, n)) if *t == u8_type => {
2530-
let n = n.try_to_target_usize(tcx).unwrap();
2531-
let alloc = tcx.global_alloc(alloc_id).unwrap_memory();
2532-
// cast is ok because we already checked for pointer size (32 or 64 bit) above
2533-
let range = AllocRange { start: offset, size: Size::from_bytes(n) };
2534-
let byte_str = alloc.inner().get_bytes_strip_provenance(&tcx, range).unwrap();
2535-
fmt.write_str("*")?;
2536-
pretty_print_byte_str(fmt, byte_str)?;
2537-
return Ok(());
2538-
}
2539-
// Aggregates, printed as array/tuple/struct/variant construction syntax.
2540-
//
2541-
// NB: the `has_non_region_param` check ensures that we can use
2542-
// the `destructure_const` query with an empty `ty::ParamEnv` without
2543-
// introducing ICEs (e.g. via `layout_of`) from missing bounds.
2544-
// E.g. `transmute([0usize; 2]): (u8, *mut T)` needs to know `T: Sized`
2545-
// to be able to destructure the tuple into `(0u8, *mut T)`
2546-
(_, ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) if !ty.has_non_region_param() => {
2547-
let ct = tcx.lift(ct).unwrap();
2548-
let ty = tcx.lift(ty).unwrap();
2549-
if let Some(contents) = tcx.try_destructure_mir_constant_for_diagnostics((ct, ty)) {
2550-
let fields: Vec<(ConstValue<'_>, Ty<'_>)> = contents.fields.to_vec();
2551-
match *ty.kind() {
2552-
ty::Array(..) => {
2553-
fmt.write_str("[")?;
2554-
comma_sep(fmt, fields)?;
2555-
fmt.write_str("]")?;
2556-
}
2557-
ty::Tuple(..) => {
2558-
fmt.write_str("(")?;
2559-
comma_sep(fmt, fields)?;
2560-
if contents.fields.len() == 1 {
2561-
fmt.write_str(",")?;
2562-
}
2563-
fmt.write_str(")")?;
2564-
}
2565-
ty::Adt(def, _) if def.variants().is_empty() => {
2566-
fmt.write_str(&format!("{{unreachable(): {ty}}}"))?;
2567-
}
2568-
ty::Adt(def, args) => {
2569-
let variant_idx = contents
2570-
.variant
2571-
.expect("destructed mir constant of adt without variant idx");
2572-
let variant_def = &def.variant(variant_idx);
2573-
let args = tcx.lift(args).unwrap();
2574-
let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS);
2575-
cx.print_alloc_ids = true;
2576-
let cx = cx.print_value_path(variant_def.def_id, args)?;
2577-
fmt.write_str(&cx.into_buffer())?;
2578-
2579-
match variant_def.ctor_kind() {
2580-
Some(CtorKind::Const) => {}
2581-
Some(CtorKind::Fn) => {
2582-
fmt.write_str("(")?;
2583-
comma_sep(fmt, fields)?;
2584-
fmt.write_str(")")?;
2585-
}
2586-
None => {
2587-
fmt.write_str(" {{ ")?;
2588-
let mut first = true;
2589-
for (field_def, (ct, ty)) in
2590-
iter::zip(&variant_def.fields, fields)
2591-
{
2592-
if !first {
2593-
fmt.write_str(", ")?;
2594-
}
2595-
write!(fmt, "{}: ", field_def.name)?;
2596-
pretty_print_const_value(ct, ty, fmt)?;
2597-
first = false;
2598-
}
2599-
fmt.write_str(" }}")?;
2600-
}
2601-
}
2602-
}
2603-
_ => unreachable!(),
2604-
}
2605-
return Ok(());
2606-
}
2607-
}
2608-
(ConstValue::Scalar(scalar), _) => {
2609-
let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS);
2610-
cx.print_alloc_ids = true;
2611-
let ty = tcx.lift(ty).unwrap();
2612-
cx = cx.pretty_print_const_scalar(scalar, ty)?;
2613-
fmt.write_str(&cx.into_buffer())?;
2614-
return Ok(());
2615-
}
2616-
(ConstValue::ZeroSized, ty::FnDef(d, s)) => {
2617-
let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS);
2618-
cx.print_alloc_ids = true;
2619-
let cx = cx.print_value_path(*d, s)?;
2620-
fmt.write_str(&cx.into_buffer())?;
2621-
return Ok(());
2622-
}
2623-
// FIXME(oli-obk): also pretty print arrays and other aggregate constants by reading
2624-
// their fields instead of just dumping the memory.
2625-
_ => {}
2626-
}
2627-
// Fall back to debug pretty printing for invalid constants.
2628-
write!(fmt, "{ct:?}: {ty}")
2629-
})
2630-
}
2631-
26322463
/// `Location` represents the position of the start of the statement; or, if
26332464
/// `statement_index` equals the number of statements, then the start of the
26342465
/// terminator.

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

+153
Original file line numberDiff line numberDiff line change
@@ -1085,6 +1085,159 @@ pub fn dump_mir_def_ids(tcx: TyCtxt<'_>, single: Option<DefId>) -> Vec<DefId> {
10851085
}
10861086
}
10871087

1088+
fn pretty_print_byte_str(fmt: &mut Formatter<'_>, byte_str: &[u8]) -> fmt::Result {
1089+
write!(fmt, "b\"{}\"", byte_str.escape_ascii())
1090+
}
1091+
1092+
fn comma_sep<'tcx>(
1093+
fmt: &mut Formatter<'_>,
1094+
elems: Vec<(ConstValue<'tcx>, Ty<'tcx>)>,
1095+
) -> fmt::Result {
1096+
let mut first = true;
1097+
for (ct, ty) in elems {
1098+
if !first {
1099+
fmt.write_str(", ")?;
1100+
}
1101+
pretty_print_const_value(ct, ty, fmt)?;
1102+
first = false;
1103+
}
1104+
Ok(())
1105+
}
1106+
1107+
pub fn pretty_print_const_value<'tcx>(
1108+
ct: ConstValue<'tcx>,
1109+
ty: Ty<'tcx>,
1110+
fmt: &mut Formatter<'_>,
1111+
) -> fmt::Result {
1112+
use crate::ty::print::PrettyPrinter;
1113+
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+
}
1122+
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+
}
1137+
}
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)?;
1146+
return Ok(());
1147+
}
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("]")?;
1165+
}
1166+
ty::Tuple(..) => {
1167+
fmt.write_str("(")?;
1168+
comma_sep(fmt, fields)?;
1169+
if contents.fields.len() == 1 {
1170+
fmt.write_str(",")?;
1171+
}
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;
1207+
}
1208+
fmt.write_str(" }}")?;
1209+
}
1210+
}
1211+
}
1212+
_ => unreachable!(),
1213+
}
1214+
return Ok(());
1215+
}
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())?;
1230+
return Ok(());
1231+
}
1232+
// FIXME(oli-obk): also pretty print arrays and other aggregate constants by reading
1233+
// their fields instead of just dumping the memory.
1234+
_ => {}
1235+
}
1236+
// Fall back to debug pretty printing for invalid constants.
1237+
write!(fmt, "{ct:?}: {ty}")
1238+
})
1239+
}
1240+
10881241
/// Calc converted u64 decimal into hex and return it's length in chars
10891242
///
10901243
/// ```ignore (cannot-test-private-function)

0 commit comments

Comments
 (0)