diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 6de4350c2aa9..e44493dec2cf 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -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> { diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 06db4b9b65bc..87be78857e32 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -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)), } } diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index cf04d6eac3ae..35d0359dbcfd 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -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 { diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 0576bb53d8f4..a3e43d648192 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -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 } => { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 9c3f522d8470..f344c529c59e 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -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();