Reuse the pretty printing architecture for printing of constants
This commit is contained in:
parent
d85e866c0d
commit
8d4f4cdada
5 changed files with 100 additions and 80 deletions
|
|
@ -9,8 +9,6 @@ use crate::hir::def_id::DefId;
|
|||
use crate::hir::{self, InlineAsm as HirInlineAsm};
|
||||
use crate::mir::interpret::{ConstValue, InterpError, Scalar};
|
||||
use crate::mir::visit::MirVisitable;
|
||||
use rustc_apfloat::ieee::{Double, Single};
|
||||
use rustc_apfloat::Float;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_data_structures::graph::dominators::{dominators, Dominators};
|
||||
use rustc_data_structures::graph::{self, GraphPredecessors, GraphSuccessors};
|
||||
|
|
@ -21,13 +19,13 @@ use rustc_macros::HashStable;
|
|||
use crate::rustc_serialize::{self as serialize};
|
||||
use smallvec::SmallVec;
|
||||
use std::borrow::Cow;
|
||||
use std::fmt::{self, Debug, Formatter, Write};
|
||||
use std::fmt::{self, Debug, Formatter, Write, Display};
|
||||
use std::iter::FusedIterator;
|
||||
use std::ops::{Index, IndexMut};
|
||||
use std::slice;
|
||||
use std::vec::IntoIter;
|
||||
use std::{iter, mem, option, u32};
|
||||
use syntax::ast::{self, Name};
|
||||
use syntax::ast::Name;
|
||||
use syntax::symbol::{InternedString, Symbol};
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
|
||||
|
|
@ -1670,8 +1668,7 @@ impl<'tcx> TerminatorKind<'tcx> {
|
|||
values
|
||||
.iter()
|
||||
.map(|&u| {
|
||||
let mut s = String::new();
|
||||
let c = ty::Const {
|
||||
(&ty::Const {
|
||||
val: ConstValue::Scalar(
|
||||
Scalar::Bits {
|
||||
bits: u,
|
||||
|
|
@ -1679,9 +1676,7 @@ impl<'tcx> TerminatorKind<'tcx> {
|
|||
}.into(),
|
||||
),
|
||||
ty: switch_ty,
|
||||
};
|
||||
fmt_const_val(&mut s, c).unwrap();
|
||||
s.into()
|
||||
}).to_string().into()
|
||||
}).chain(iter::once("otherwise".into()))
|
||||
.collect()
|
||||
}
|
||||
|
|
@ -2827,67 +2822,15 @@ newtype_index! {
|
|||
|
||||
impl<'tcx> Debug for Constant<'tcx> {
|
||||
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
|
||||
write!(fmt, "const ")?;
|
||||
fmt_const_val(fmt, *self.literal)
|
||||
write!(fmt, "{}", self)
|
||||
}
|
||||
}
|
||||
/// Write a `ConstValue` in a way closer to the original source code than the `Debug` output.
|
||||
pub fn fmt_const_val(f: &mut impl Write, const_val: ty::Const<'_>) -> fmt::Result {
|
||||
use crate::ty::TyKind::*;
|
||||
let value = const_val.val;
|
||||
let ty = const_val.ty;
|
||||
// print some primitives
|
||||
if let ConstValue::Scalar(Scalar::Bits { bits, .. }) = value {
|
||||
match ty.sty {
|
||||
Bool if bits == 0 => return write!(f, "false"),
|
||||
Bool if bits == 1 => return write!(f, "true"),
|
||||
Float(ast::FloatTy::F32) => return write!(f, "{}f32", Single::from_bits(bits)),
|
||||
Float(ast::FloatTy::F64) => return write!(f, "{}f64", Double::from_bits(bits)),
|
||||
Uint(ui) => return write!(f, "{:?}{}", bits, ui),
|
||||
Int(i) => {
|
||||
let bit_width = ty::tls::with(|tcx| {
|
||||
let ty = tcx.lift_to_global(&ty).unwrap();
|
||||
tcx.layout_of(ty::ParamEnv::empty().and(ty))
|
||||
.unwrap()
|
||||
.size
|
||||
.bits()
|
||||
});
|
||||
let shift = 128 - bit_width;
|
||||
return write!(f, "{:?}{}", ((bits as i128) << shift) >> shift, i);
|
||||
}
|
||||
Char => return write!(f, "{:?}", ::std::char::from_u32(bits as u32).unwrap()),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
// print function definitions
|
||||
if let FnDef(did, _) = ty.sty {
|
||||
return write!(f, "{}", def_path_str(did));
|
||||
}
|
||||
// print string literals
|
||||
if let ConstValue::Slice(ptr, len) = value {
|
||||
if let Scalar::Ptr(ptr) = ptr {
|
||||
if let Ref(_, &ty::TyS { sty: Str, .. }, _) = ty.sty {
|
||||
return ty::tls::with(|tcx| {
|
||||
let alloc = tcx.alloc_map.lock().get(ptr.alloc_id);
|
||||
if let Some(interpret::AllocKind::Memory(alloc)) = alloc {
|
||||
assert_eq!(len as usize as u64, len);
|
||||
let slice =
|
||||
&alloc.bytes[(ptr.offset.bytes() as usize)..][..(len as usize)];
|
||||
let s = ::std::str::from_utf8(slice).expect("non utf8 str from miri");
|
||||
write!(f, "{:?}", s)
|
||||
} else {
|
||||
write!(f, "pointer to erroneous constant {:?}, {:?}", ptr, len)
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
// just raw dump everything else
|
||||
write!(f, "{:?} : {}", value, ty)
|
||||
}
|
||||
|
||||
fn def_path_str(def_id: DefId) -> String {
|
||||
ty::tls::with(|tcx| tcx.def_path_str(def_id))
|
||||
impl<'tcx> Display for Constant<'tcx> {
|
||||
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
|
||||
write!(fmt, "const ")?;
|
||||
write!(fmt, "{}", self.literal)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> graph::DirectedGraph for Mir<'tcx> {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,10 @@ use crate::middle::cstore::{ExternCrate, ExternCrateSource};
|
|||
use crate::middle::region;
|
||||
use crate::ty::{self, DefIdTree, ParamConst, Ty, TyCtxt, TypeFoldable};
|
||||
use crate::ty::subst::{Kind, Subst, UnpackedKind};
|
||||
use crate::mir::interpret::ConstValue;
|
||||
use crate::mir::interpret::{ConstValue, sign_extend, Scalar};
|
||||
use syntax::ast;
|
||||
use rustc_apfloat::ieee::{Double, Single};
|
||||
use rustc_apfloat::Float;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use syntax::symbol::{kw, InternedString};
|
||||
|
||||
|
|
@ -1533,12 +1536,54 @@ define_print_and_forward_display! {
|
|||
p!(print_def_path(self.def_id, self.substs));
|
||||
}
|
||||
|
||||
&'tcx ty::Const<'tcx> {
|
||||
match self.val {
|
||||
ConstValue::Unevaluated(..) |
|
||||
ConstValue::Infer(..) => p!(write("_")),
|
||||
ConstValue::Param(ParamConst { name, .. }) => p!(write("{}", name)),
|
||||
_ => p!(write("{:?}", self)),
|
||||
ty::Const<'tcx> {
|
||||
match (self.val, &self.ty.sty) {
|
||||
| (ConstValue::Unevaluated(..), _)
|
||||
| (ConstValue::Infer(..), _)
|
||||
=> p!(write("_: "), print(self.ty)),
|
||||
(ConstValue::Param(ParamConst { name, .. }), _) => p!(write("{}", name)),
|
||||
(ConstValue::Scalar(Scalar::Bits { bits: 0, .. }), ty::Bool) => p!(write("false")),
|
||||
(ConstValue::Scalar(Scalar::Bits { bits: 1, .. }), ty::Bool) => p!(write("true")),
|
||||
(ConstValue::Scalar(Scalar::Bits { bits, .. }), ty::Float(ast::FloatTy::F32)) =>
|
||||
p!(write(
|
||||
"{}f32",
|
||||
Single::from_bits(bits)
|
||||
)),
|
||||
(ConstValue::Scalar(Scalar::Bits { bits, .. }), ty::Float(ast::FloatTy::F64)) =>
|
||||
p!(write(
|
||||
"{}f64",
|
||||
Double::from_bits(bits)
|
||||
)),
|
||||
(ConstValue::Scalar(Scalar::Bits { bits, ..}), ty::Uint(ui)) =>
|
||||
p!(write("{}{}", bits, ui)),
|
||||
(ConstValue::Scalar(Scalar::Bits { bits, ..}), ty::Int(i)) => {
|
||||
let size = ty::tls::with(|tcx| {
|
||||
let ty = tcx.lift_to_global(&self.ty).unwrap();
|
||||
tcx.layout_of(ty::ParamEnv::empty().and(ty))
|
||||
.unwrap()
|
||||
.size
|
||||
});
|
||||
p!(write("{}{}", sign_extend(bits, size) as i128, i))
|
||||
},
|
||||
(ConstValue::Scalar(Scalar::Bits { bits, ..}), ty::Char)
|
||||
=> p!(write("{}", ::std::char::from_u32(bits as u32).unwrap())),
|
||||
(_, ty::FnDef(did, _)) => p!(write("{}", ty::tls::with(|tcx| tcx.def_path_str(*did)))),
|
||||
(ConstValue::Slice(_, 0), ty::Ref(_, &ty::TyS { sty: ty::Str, .. }, _)) =>
|
||||
p!(write("\"\"")),
|
||||
(
|
||||
ConstValue::Slice(Scalar::Ptr(ptr), len),
|
||||
ty::Ref(_, &ty::TyS { sty: ty::Str, .. }, _),
|
||||
) => {
|
||||
ty::tls::with(|tcx| {
|
||||
let alloc = tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id);
|
||||
assert_eq!(len as usize as u64, len);
|
||||
let slice =
|
||||
&alloc.bytes[(ptr.offset.bytes() as usize)..][..(len as usize)];
|
||||
let s = ::std::str::from_utf8(slice).expect("non utf8 str from miri");
|
||||
Ok(p!(write("{:?}", s)))
|
||||
})?;
|
||||
},
|
||||
_ => p!(write("{:?} : ", self.val), print(self.ty)),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -295,6 +295,9 @@ CloneTypeFoldableAndLiftImpls! {
|
|||
(),
|
||||
bool,
|
||||
usize,
|
||||
u32,
|
||||
crate::ty::BoundVar,
|
||||
crate::ty::DebruijnIndex,
|
||||
crate::ty::layout::VariantIdx,
|
||||
u64,
|
||||
String,
|
||||
|
|
@ -311,6 +314,8 @@ CloneTypeFoldableAndLiftImpls! {
|
|||
::rustc_target::spec::abi::Abi,
|
||||
crate::mir::Local,
|
||||
crate::mir::Promoted,
|
||||
crate::mir::interpret::Scalar,
|
||||
crate::mir::interpret::Pointer,
|
||||
crate::traits::Reveal,
|
||||
crate::ty::adjustment::AutoBorrowMutability,
|
||||
crate::ty::AdtKind,
|
||||
|
|
@ -788,6 +793,34 @@ BraceStructLiftImpl! {
|
|||
}
|
||||
}
|
||||
|
||||
BraceStructLiftImpl! {
|
||||
impl<'a, 'tcx> Lift<'tcx> for ty::Const<'a> {
|
||||
type Lifted = ty::Const<'tcx>;
|
||||
val, ty
|
||||
}
|
||||
}
|
||||
|
||||
EnumLiftImpl! {
|
||||
impl<'a, 'tcx> Lift<'tcx> for interpret::ConstValue<'a> {
|
||||
type Lifted = interpret::ConstValue<'tcx>;
|
||||
(interpret::ConstValue::Unevaluated)(a, b),
|
||||
(interpret::ConstValue::Param)(a),
|
||||
(interpret::ConstValue::Infer)(a),
|
||||
(interpret::ConstValue::Scalar)(a),
|
||||
(interpret::ConstValue::Slice)(a, b),
|
||||
(interpret::ConstValue::ByRef)(a, b),
|
||||
}
|
||||
}
|
||||
|
||||
EnumLiftImpl! {
|
||||
impl<'a, 'tcx> Lift<'tcx> for ty::InferConst<'a> {
|
||||
type Lifted = ty::InferConst<'tcx>;
|
||||
(ty::InferConst::Var)(a),
|
||||
(ty::InferConst::Fresh)(a),
|
||||
(ty::InferConst::Canonical)(a, b),
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Lift<'tcx> for ConstVid<'a> {
|
||||
type Lifted = ConstVid<'tcx>;
|
||||
fn lift_to_tcx<'b, 'gcx>(&self, _: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ use crate::const_eval::{const_field, const_variant_index};
|
|||
use crate::hair::util::UserAnnotatedTyHelpers;
|
||||
use crate::hair::constant::*;
|
||||
|
||||
use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability};
|
||||
use rustc::mir::{Field, BorrowKind, Mutability};
|
||||
use rustc::mir::{UserTypeProjection};
|
||||
use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, sign_extend};
|
||||
use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty, UserType, DefIdTree};
|
||||
|
|
@ -291,15 +291,15 @@ impl<'tcx> fmt::Display for Pattern<'tcx> {
|
|||
write!(f, "{}", subpattern)
|
||||
}
|
||||
PatternKind::Constant { value } => {
|
||||
fmt_const_val(f, value)
|
||||
write!(f, "{}", &value)
|
||||
}
|
||||
PatternKind::Range(PatternRange { lo, hi, ty: _, end }) => {
|
||||
fmt_const_val(f, lo)?;
|
||||
write!(f, "{}", &lo)?;
|
||||
match end {
|
||||
RangeEnd::Included => write!(f, "..=")?,
|
||||
RangeEnd::Excluded => write!(f, "..")?,
|
||||
}
|
||||
fmt_const_val(f, hi)
|
||||
write!(f, "{}", &hi)
|
||||
}
|
||||
PatternKind::Slice { ref prefix, ref slice, ref suffix } |
|
||||
PatternKind::Array { ref prefix, ref slice, ref suffix } => {
|
||||
|
|
|
|||
|
|
@ -4136,8 +4136,7 @@ fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String {
|
|||
}
|
||||
},
|
||||
_ => {
|
||||
let mut s = String::new();
|
||||
::rustc::mir::fmt_const_val(&mut s, n).expect("fmt_const_val failed");
|
||||
let mut s = n.to_string();
|
||||
// array lengths are obviously usize
|
||||
if s.ends_with("usize") {
|
||||
let n = s.len() - "usize".len();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue