Skip to content

Commit b90e7e0

Browse files
committed
move some MIR const pretty-printing into pretty.rs
1 parent 7a08272 commit b90e7e0

File tree

4 files changed

+176
-177
lines changed

4 files changed

+176
-177
lines changed

compiler/rustc_middle/src/mir/consts.rs

Lines changed: 2 additions & 2 deletions
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

compiler/rustc_middle/src/mir/mod.rs

Lines changed: 6 additions & 175 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crate::mir::interpret::{AllocRange, ConstAllocation, ConstValue, Scalar};
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>>;
@@ -2431,176 +2432,6 @@ rustc_index::newtype_index! {
24312432
pub struct Promoted {}
24322433
}
24332434

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

compiler/rustc_middle/src/mir/pretty.rs

Lines changed: 153 additions & 0 deletions
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)