From 02dbb35b2b6ed869f14a8aecaf9dad5c72d5cb0b Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 23 Dec 2019 17:41:06 +0100 Subject: [PATCH 01/18] Deduplicate and clean up pretty printing logic --- src/librustc/mir/mod.rs | 16 +- src/librustc/ty/print/pretty.rs | 292 +++++++++++++----- .../interpret/intrinsics/type_name.rs | 1 + src/librustc_mir/interpret/operand.rs | 81 +++-- .../mir-opt/const-promotion-extern-static.rs | 4 +- src/test/mir-opt/const_prop/discriminant.rs | 2 +- src/test/mir-opt/const_prop/issue-66971.rs | 2 +- .../const_prop/read_immutable_static.rs | 4 +- .../simplify-locals-removes-unused-consts.rs | 16 +- .../ui/const-generics/raw-ptr-const-param.rs | 3 + .../const-generics/raw-ptr-const-param.stderr | 10 +- src/test/ui/consts/offset_from_ub.stderr | 2 +- 12 files changed, 286 insertions(+), 147 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index b2413f5a2c83f..d9f49b6784e67 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2562,15 +2562,15 @@ impl<'tcx> Debug for Constant<'tcx> { impl<'tcx> Display for Constant<'tcx> { fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { + use crate::ty::print::PrettyPrinter; write!(fmt, "const ")?; - // FIXME make the default pretty printing of raw pointers more detailed. Here we output the - // debug representation of raw pointers, so that the raw pointers in the mir dump output are - // detailed and just not '{pointer}'. - if let ty::RawPtr(_) = self.literal.ty.kind { - write!(fmt, "{:?} : {}", self.literal.val, self.literal.ty) - } else { - write!(fmt, "{}", self.literal) - } + ty::tls::with(|tcx| { + let literal = tcx.lift(&self.literal).unwrap(); + let mut cx = FmtPrinter::new(tcx, fmt, Namespace::ValueNS); + cx.print_alloc_ids = true; + cx.pretty_print_const(literal, true)?; + Ok(()) + }) } } diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 05dcc9e85ac52..2f53b62fdecf8 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -1,7 +1,7 @@ use crate::hir::map::{DefPathData, DisambiguatedDefPathData}; use crate::middle::cstore::{ExternCrate, ExternCrateSource}; use crate::middle::region; -use crate::mir::interpret::{sign_extend, truncate, ConstValue, Scalar}; +use crate::mir::interpret::{sign_extend, truncate, AllocId, ConstValue, Pointer, Scalar}; use crate::ty::layout::{Integer, IntegerExt, Size}; use crate::ty::subst::{GenericArg, GenericArgKind, Subst}; use crate::ty::{self, DefIdTree, ParamConst, Ty, TyCtxt, TypeFoldable}; @@ -457,6 +457,22 @@ pub trait PrettyPrinter<'tcx>: }) } + fn print_type_ascribed( + mut self, + f: impl FnOnce(Self) -> Result, + ty: Ty<'tcx>, + print_ty: bool, + ) -> Result { + self.write_str("{")?; + self = f(self)?; + if print_ty { + self.write_str(": ")?; + self = self.print_type(ty)?; + } + self.write_str("}")?; + Ok(self) + } + fn pretty_print_type(mut self, ty: Ty<'tcx>) -> Result { define_scoped_cx!(self); @@ -893,32 +909,49 @@ pub trait PrettyPrinter<'tcx>: Ok(self) } - fn pretty_print_const_value( + fn pretty_print_const_scalar( mut self, - ct: ConstValue<'tcx>, + scalar: Scalar, ty: Ty<'tcx>, print_ty: bool, ) -> Result { define_scoped_cx!(self); - if self.tcx().sess.verbose() { - p!(write("ConstValue({:?}: {:?})", ct, ty)); - return Ok(self); - } - - let u8 = self.tcx().types.u8; - - match (ct, &ty.kind) { - (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Bool) => { - p!(write("{}", if data == 0 { "false" } else { "true" })) - } - (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Float(ast::FloatTy::F32)) => { + match (scalar, &ty.kind) { + // Single element arrays print their element (they are `#[transparent]`) enclosed in + // square brackets. + (_, ty::Array(t, n)) if n.eval_usize(self.tcx(), ty::ParamEnv::empty()) == 1 => { + p!(write("[")); + self = self.pretty_print_const_scalar(scalar, t, print_ty)?; + p!(write("]")); + } + // Byte strings (&[u8; N]) + (Scalar::Ptr(ptr), ty::Ref(_, ty::TyS { kind: ty::Array(t, n), .. }, _)) + if *t == self.tcx().types.u8 => + { + let n = n.eval_usize(self.tcx(), ty::ParamEnv::empty()); + let byte_str = self + .tcx() + .alloc_map + .lock() + .unwrap_memory(ptr.alloc_id) + .get_bytes(&self.tcx(), ptr, Size::from_bytes(n)) + .unwrap(); + p!(pretty_print_byte_str(byte_str)); + } + // Bool + (Scalar::Raw { data: 0, .. }, ty::Bool) => p!(write("false")), + (Scalar::Raw { data: 1, .. }, ty::Bool) => p!(write("true")), + (Scalar::Raw { data, .. }, ty::Bool) => p!(write("{}_bool", data)), + // Float + (Scalar::Raw { data, .. }, ty::Float(ast::FloatTy::F32)) => { p!(write("{}f32", Single::from_bits(data))) } - (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Float(ast::FloatTy::F64)) => { + (Scalar::Raw { data, .. }, ty::Float(ast::FloatTy::F64)) => { p!(write("{}f64", Double::from_bits(data))) } - (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Uint(ui)) => { + // Int + (Scalar::Raw { data, .. }, ty::Uint(ui)) => { let bit_size = Integer::from_attr(&self.tcx(), UnsignedInt(*ui)).size(); let max = truncate(u128::MAX, bit_size); @@ -929,7 +962,7 @@ pub trait PrettyPrinter<'tcx>: p!(write("{}{}", data, ui_str)) }; } - (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Int(i)) => { + (Scalar::Raw { data, .. }, ty::Int(i)) => { let bit_size = Integer::from_attr(&self.tcx(), SignedInt(*i)).size().bits() as u128; let min = 1u128 << (bit_size - 1); let max = min - 1; @@ -943,76 +976,140 @@ pub trait PrettyPrinter<'tcx>: _ => p!(write("{}{}", sign_extend(data, size) as i128, i_str)), } } - (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Char) => { - p!(write("{:?}", ::std::char::from_u32(data as u32).unwrap())) + // Char + (Scalar::Raw { data, .. }, ty::Char) => match ::std::char::from_u32(data as u32) { + Some(c) => p!(write("{:?}", c)), + None => p!(write("{}_char", data)), + }, + // References and pointers + (Scalar::Raw { data: 0, .. }, ty::RawPtr(_)) => p!(write("{{null pointer}}")), + // This is UB, but we still print it + (Scalar::Raw { data: 0, .. }, ty::Ref(_, ty, _)) => { + p!(write("{{null reference to "), print(ty), write("}}")) } - (ConstValue::Scalar(_), ty::RawPtr(_)) => p!(write("{{pointer}}")), - (ConstValue::Scalar(Scalar::Ptr(ptr)), ty::FnPtr(_)) => { + (Scalar::Raw { data, .. }, ty::Ref(..)) | (Scalar::Raw { data, .. }, ty::RawPtr(_)) => { + let pointer_width = self.tcx().data_layout.pointer_size.bytes(); + p!(write("0x{:01$x}", data, pointer_width as usize * 2)) + } + (Scalar::Ptr(ptr), ty::FnPtr(_)) => { let instance = { let alloc_map = self.tcx().alloc_map.lock(); alloc_map.unwrap_fn(ptr.alloc_id) }; p!(print_value_path(instance.def_id(), instance.substs)); } - _ => { - let printed = if let ty::Ref(_, ref_ty, _) = ty.kind { - let byte_str = match (ct, &ref_ty.kind) { - (ConstValue::Scalar(Scalar::Ptr(ptr)), ty::Array(t, n)) if *t == u8 => { - let n = n.eval_usize(self.tcx(), ty::ParamEnv::empty()); - Some( - self.tcx() - .alloc_map - .lock() - .unwrap_memory(ptr.alloc_id) - .get_bytes(&self.tcx(), ptr, Size::from_bytes(n)) - .unwrap(), - ) - } - (ConstValue::Slice { data, start, end }, ty::Slice(t)) if *t == u8 => { - // The `inspect` here is okay since we checked the bounds, and there are - // no relocations (we have an active slice reference here). We don't use - // this result to affect interpreter execution. - Some(data.inspect_with_undef_and_ptr_outside_interpreter(start..end)) - } - _ => None, - }; + // For zsts just print their type as their value gives no extra information + (Scalar::Raw { size: 0, .. }, _) => p!(print(ty)), + // Nontrivial types with scalar bit representation + (Scalar::Raw { data, size }, _) => { + self = self.print_type_ascribed( + |mut this| { + write!(this, "0x{:01$x}", data, size as usize * 2)?; + Ok(this) + }, + ty, + print_ty, + )? + } + // Any pointer values not covered by a branch above + (Scalar::Ptr(p), _) => { + self = self.pretty_print_const_pointer(p, ty, print_ty)?; + } + } + Ok(self) + } - if let Some(byte_str) = byte_str { - p!(write("b\"")); - for &c in byte_str { - for e in std::ascii::escape_default(c) { - self.write_char(e as char)?; - } - } - p!(write("\"")); - true - } else if let (ConstValue::Slice { data, start, end }, ty::Str) = - (ct, &ref_ty.kind) - { - // The `inspect` here is okay since we checked the bounds, and there are no - // relocations (we have an active `str` reference here). We don't use this - // result to affect interpreter execution. - let slice = data.inspect_with_undef_and_ptr_outside_interpreter(start..end); - let s = ::std::str::from_utf8(slice).expect("non utf8 str from miri"); - p!(write("{:?}", s)); - true - } else { - false - } - } else { - false - }; - if !printed { - // fallback - p!(write("{:?}", ct)); - if print_ty { - p!(write(": "), print(ty)); - } - } + /// This is overridden for MIR printing because we only want to hide alloc ids from users, not + /// from MIR where it is actually useful. + fn pretty_print_const_pointer( + self, + _: Pointer, + ty: Ty<'tcx>, + print_ty: bool, + ) -> Result { + self.print_type_ascribed( + |mut this| { + this.write_str("pointer")?; + Ok(this) + }, + ty, + print_ty, + ) + } + + fn pretty_print_byte_str(mut self, byte_str: &'tcx [u8]) -> Result { + define_scoped_cx!(self); + p!(write("b\"")); + for &c in byte_str { + for e in std::ascii::escape_default(c) { + self.write_char(e as char)?; } - }; + } + p!(write("\"")); Ok(self) } + + fn pretty_print_const_value( + mut self, + ct: ConstValue<'tcx>, + ty: Ty<'tcx>, + print_ty: bool, + ) -> Result { + define_scoped_cx!(self); + + if self.tcx().sess.verbose() { + p!(write("ConstValue({:?}: {:?})", ct, ty)); + return Ok(self); + } + + let u8_type = self.tcx().types.u8; + + match (ct, &ty.kind) { + (ConstValue::Scalar(scalar), _) => self.pretty_print_const_scalar(scalar, ty, print_ty), + ( + ConstValue::Slice { data, start, end }, + ty::Ref(_, ty::TyS { kind: ty::Slice(t), .. }, _), + ) if *t == u8_type => { + // The `inspect` here is okay since we checked the bounds, and there are + // no relocations (we have an active slice reference here). We don't use + // this result to affect interpreter execution. + let byte_str = data.inspect_with_undef_and_ptr_outside_interpreter(start..end); + self.pretty_print_byte_str(byte_str) + } + ( + ConstValue::Slice { data, start, end }, + ty::Ref(_, ty::TyS { kind: ty::Str, .. }, _), + ) => { + // The `inspect` here is okay since we checked the bounds, and there are no + // relocations (we have an active `str` reference here). We don't use this + // result to affect interpreter execution. + let slice = data.inspect_with_undef_and_ptr_outside_interpreter(start..end); + let s = ::std::str::from_utf8(slice).expect("non utf8 str from miri"); + p!(write("{:?}", s)); + Ok(self) + } + (ConstValue::ByRef { alloc, offset }, ty::Array(t, n)) if *t == u8_type => { + let n = n.eval_usize(self.tcx(), ty::ParamEnv::empty()); + let n = Size::from_bytes(n); + let ptr = Pointer::new(AllocId(0), offset); + + let byte_str = alloc.get_bytes(&self.tcx(), ptr, n).unwrap(); + p!(write("*")); + p!(pretty_print_byte_str(byte_str)); + Ok(self) + } + // FIXME(oli-obk): also pretty print arrays and other aggregate constants by reading + // their fields instead of just dumping the memory. + _ => { + // fallback + p!(write("{:?}", ct)); + if print_ty { + p!(write(": "), print(ty)); + } + Ok(self) + } + } + } } // HACK(eddyb) boxed to avoid moving around a large struct by-value. @@ -1024,6 +1121,7 @@ pub struct FmtPrinterData<'a, 'tcx, F> { empty_path: bool, in_value: bool, + pub print_alloc_ids: bool, used_region_names: FxHashSet, region_index: usize, @@ -1054,6 +1152,7 @@ impl FmtPrinter<'a, 'tcx, F> { fmt, empty_path: false, in_value: ns == Namespace::ValueNS, + print_alloc_ids: false, used_region_names: Default::default(), region_index: 0, binder_depth: 0, @@ -1382,6 +1481,45 @@ impl PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx, F> { ty::ReStatic | ty::ReEmpty(_) | ty::ReClosureBound(_) => true, } } + + fn pretty_print_const_pointer( + self, + p: Pointer, + ty: Ty<'tcx>, + print_ty: bool, + ) -> Result { + self.print_type_ascribed( + |mut this| { + define_scoped_cx!(this); + if this.print_alloc_ids { + p!(write("{:?}", p)); + } else { + p!(write("pointer")); + } + Ok(this) + }, + ty, + print_ty, + ) + } + + fn print_type_ascribed( + mut self, + f: impl FnOnce(Self) -> Result, + ty: Ty<'tcx>, + print_ty: bool, + ) -> Result { + self.write_str("{")?; + self = f(self)?; + if print_ty { + self.write_str(": ")?; + let was_in_value = std::mem::replace(&mut self.in_value, false); + self = self.print_type(ty)?; + self.in_value = was_in_value; + } + self.write_str("}")?; + Ok(self) + } } // HACK(eddyb) limited to `FmtPrinter` because of `region_highlight_mode`. diff --git a/src/librustc_mir/interpret/intrinsics/type_name.rs b/src/librustc_mir/interpret/intrinsics/type_name.rs index cd8bf7085d1b1..677dc69773516 100644 --- a/src/librustc_mir/interpret/intrinsics/type_name.rs +++ b/src/librustc_mir/interpret/intrinsics/type_name.rs @@ -157,6 +157,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { } } } + impl PrettyPrinter<'tcx> for AbsolutePathPrinter<'tcx> { fn region_should_not_be_omitted(&self, _region: ty::Region<'_>) -> bool { false diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 22b1a7b7137d9..512eec6b9f14a 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -3,18 +3,20 @@ use std::convert::{TryFrom, TryInto}; -use rustc::ty::layout::{ - self, HasDataLayout, IntegerExt, LayoutOf, PrimitiveExt, Size, TyLayout, VariantIdx, -}; -use rustc::{mir, ty}; - use super::{InterpCx, MPlaceTy, Machine, MemPlace, Place, PlaceTy}; pub use rustc::mir::interpret::ScalarMaybeUndef; use rustc::mir::interpret::{ sign_extend, truncate, AllocId, ConstValue, GlobalId, InterpResult, Pointer, Scalar, }; -use rustc_ast::ast; +use rustc::ty::layout::{ + self, HasDataLayout, IntegerExt, LayoutOf, PrimitiveExt, Size, TyLayout, VariantIdx, +}; +use rustc::ty::print::{FmtPrinter, PrettyPrinter, Printer}; +use rustc::ty::Ty; +use rustc::{mir, ty}; +use rustc_hir::def::Namespace; use rustc_macros::HashStable; +use std::fmt::Write; /// An `Immediate` represents a single immediate self-contained Rust value. /// @@ -92,47 +94,42 @@ pub struct ImmTy<'tcx, Tag = ()> { pub layout: TyLayout<'tcx>, } -// `Tag: Copy` because some methods on `Scalar` consume them by value impl std::fmt::Display for ImmTy<'tcx, Tag> { - fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match &self.imm { - // We cannot use `to_bits_or_ptr` as we do not have a `tcx`. - // So we use `is_bits` and circumvent a bunch of sanity checking -- but - // this is anyway only for printing. - Immediate::Scalar(ScalarMaybeUndef::Scalar(s)) if s.is_ptr() => { - fmt.write_str("{pointer}") + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + /// Helper function for printing a scalar to a FmtPrinter + fn p<'a, 'tcx, F: std::fmt::Write, Tag>( + mut cx: FmtPrinter<'a, 'tcx, F>, + s: ScalarMaybeUndef, + ty: Ty<'tcx>, + ) -> Result, std::fmt::Error> { + match s { + ScalarMaybeUndef::Scalar(s) => { + cx.pretty_print_const_scalar(s.erase_tag(), ty, true) + } + ScalarMaybeUndef::Undef => { + cx.write_str("{undef ")?; + cx = cx.print_type(ty)?; + cx.write_str("}")?; + Ok(cx) + } } - Immediate::Scalar(ScalarMaybeUndef::Scalar(s)) => { - let s = s.assert_bits(self.layout.size); - match self.layout.ty.kind { - ty::Int(_) => { - return write!(fmt, "{}", super::sign_extend(s, self.layout.size) as i128,); - } - ty::Uint(_) => return write!(fmt, "{}", s), - ty::Bool if s == 0 => return fmt.write_str("false"), - ty::Bool if s == 1 => return fmt.write_str("true"), - ty::Char => { - if let Some(c) = u32::try_from(s).ok().and_then(std::char::from_u32) { - return write!(fmt, "{}", c); - } - } - ty::Float(ast::FloatTy::F32) => { - if let Ok(u) = u32::try_from(s) { - return write!(fmt, "{}", f32::from_bits(u)); - } - } - ty::Float(ast::FloatTy::F64) => { - if let Ok(u) = u64::try_from(s) { - return write!(fmt, "{}", f64::from_bits(u)); - } + } + ty::tls::with(|tcx| { + match self.imm { + Immediate::Scalar(s) => { + if let Some(ty) = tcx.lift(&self.layout.ty) { + let cx = FmtPrinter::new(tcx, f, Namespace::ValueNS); + p(cx, s, ty)?; + return Ok(()); } - _ => {} + write!(f, "{:?}: {}", s.erase_tag(), self.layout.ty) + } + Immediate::ScalarPair(a, b) => { + // FIXME(oli-obk): at least print tuples and slices nicely + write!(f, "({:?}, {:?}): {}", a.erase_tag(), b.erase_tag(), self.layout.ty,) } - write!(fmt, "{:x}", s) } - Immediate::Scalar(ScalarMaybeUndef::Undef) => fmt.write_str("{undef}"), - Immediate::ScalarPair(..) => fmt.write_str("{wide pointer or tuple}"), - } + }) } } diff --git a/src/test/mir-opt/const-promotion-extern-static.rs b/src/test/mir-opt/const-promotion-extern-static.rs index f6f7d0910911c..0d4a6d1bafdd2 100644 --- a/src/test/mir-opt/const-promotion-extern-static.rs +++ b/src/test/mir-opt/const-promotion-extern-static.rs @@ -14,7 +14,7 @@ fn main() {} // START rustc.FOO.PromoteTemps.before.mir // bb0: { // ... -// _5 = const Scalar(alloc1+0) : &i32; +// _5 = const {alloc1+0: &i32}; // _4 = &(*_5); // _3 = [move _4]; // _2 = &_3; @@ -31,7 +31,7 @@ fn main() {} // START rustc.BAR.PromoteTemps.before.mir // bb0: { // ... -// _5 = const Scalar(alloc0+0) : &i32; +// _5 = const {alloc0+0: &i32}; // _4 = &(*_5); // _3 = [move _4]; // _2 = &_3; diff --git a/src/test/mir-opt/const_prop/discriminant.rs b/src/test/mir-opt/const_prop/discriminant.rs index 667d21fc14ee4..b308d06999c8a 100644 --- a/src/test/mir-opt/const_prop/discriminant.rs +++ b/src/test/mir-opt/const_prop/discriminant.rs @@ -31,7 +31,7 @@ fn main() { // START rustc.main.ConstProp.after.mir // bb0: { // ... -// _3 = const Scalar(0x01) : std::option::Option; +// _3 = const {0x01: std::option::Option}; // _4 = const 1isize; // switchInt(const 1isize) -> [1isize: bb2, otherwise: bb1]; // } diff --git a/src/test/mir-opt/const_prop/issue-66971.rs b/src/test/mir-opt/const_prop/issue-66971.rs index 30c75303b3e53..f332bb895095b 100644 --- a/src/test/mir-opt/const_prop/issue-66971.rs +++ b/src/test/mir-opt/const_prop/issue-66971.rs @@ -29,7 +29,7 @@ fn main() { // START rustc.main.ConstProp.after.mir // bb0: { // ... -// _3 = const Scalar() : (); +// _3 = const (); // _2 = (move _3, const 0u8, const 0u8); // ... // _1 = const encode(move _2) -> bb1; diff --git a/src/test/mir-opt/const_prop/read_immutable_static.rs b/src/test/mir-opt/const_prop/read_immutable_static.rs index 693ef78398558..d307cebd71539 100644 --- a/src/test/mir-opt/const_prop/read_immutable_static.rs +++ b/src/test/mir-opt/const_prop/read_immutable_static.rs @@ -10,10 +10,10 @@ fn main() { // START rustc.main.ConstProp.before.mir // bb0: { // ... -// _3 = const Scalar(alloc0+0) : &u8; +// _3 = const {alloc0+0: &u8}; // _2 = (*_3); // ... -// _5 = const Scalar(alloc0+0) : &u8; +// _5 = const {alloc0+0: &u8}; // _4 = (*_5); // _1 = Add(move _2, move _4); // ... diff --git a/src/test/mir-opt/simplify-locals-removes-unused-consts.rs b/src/test/mir-opt/simplify-locals-removes-unused-consts.rs index 6f03438ff7234..ca8e60b9e39c8 100644 --- a/src/test/mir-opt/simplify-locals-removes-unused-consts.rs +++ b/src/test/mir-opt/simplify-locals-removes-unused-consts.rs @@ -35,28 +35,28 @@ fn main() { // bb0: { // StorageLive(_1); // StorageLive(_2); -// _2 = const Scalar() : (); +// _2 = const (); // StorageLive(_3); -// _3 = const Scalar() : (); -// _1 = const Scalar() : ((), ()); +// _3 = const (); +// _1 = const ((), ()); // StorageDead(_3); // StorageDead(_2); // StorageDead(_1); // StorageLive(_4); // StorageLive(_6); -// _6 = const Scalar() : (); +// _6 = const (); // StorageLive(_7); -// _7 = const Scalar() : (); +// _7 = const (); // StorageDead(_7); // StorageDead(_6); -// _4 = const use_zst(const Scalar() : ((), ())) -> bb1; +// _4 = const use_zst(const ((), ())) -> bb1; // } // bb1: { // StorageDead(_4); // StorageLive(_8); // StorageLive(_10); // StorageLive(_11); -// _11 = const Scalar(0x28) : Temp; +// _11 = const {0x28 : Temp}; // _10 = const 40u8; // StorageDead(_10); // _8 = const use_u8(const 42u8) -> bb2; @@ -75,7 +75,7 @@ fn main() { // } // bb0: { // StorageLive(_1); -// _1 = const use_zst(const Scalar() : ((), ())) -> bb1; +// _1 = const use_zst(const ((), ())) -> bb1; // } // bb1: { // StorageDead(_1); diff --git a/src/test/ui/const-generics/raw-ptr-const-param.rs b/src/test/ui/const-generics/raw-ptr-const-param.rs index f69c37fbb8f3d..f8ae1b3fdc948 100644 --- a/src/test/ui/const-generics/raw-ptr-const-param.rs +++ b/src/test/ui/const-generics/raw-ptr-const-param.rs @@ -1,3 +1,6 @@ +// normalize-stderr-64bit "0x00000000" -> "0x[PREFIX]" +// normalize-stderr-32bit "0x" -> "0x[PREFIX]" + #![feature(const_generics, const_compare_raw_pointers)] //~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash diff --git a/src/test/ui/const-generics/raw-ptr-const-param.stderr b/src/test/ui/const-generics/raw-ptr-const-param.stderr index 9cd39b61dc936..850bb89e95653 100644 --- a/src/test/ui/const-generics/raw-ptr-const-param.stderr +++ b/src/test/ui/const-generics/raw-ptr-const-param.stderr @@ -1,5 +1,5 @@ warning: the feature `const_generics` is incomplete and may cause the compiler to crash - --> $DIR/raw-ptr-const-param.rs:1:12 + --> $DIR/raw-ptr-const-param.rs:4:12 | LL | #![feature(const_generics, const_compare_raw_pointers)] | ^^^^^^^^^^^^^^ @@ -7,15 +7,15 @@ LL | #![feature(const_generics, const_compare_raw_pointers)] = note: `#[warn(incomplete_features)]` on by default error[E0308]: mismatched types - --> $DIR/raw-ptr-const-param.rs:7:38 + --> $DIR/raw-ptr-const-param.rs:10:38 | LL | let _: Const<{15 as *const _}> = Const::<{10 as *const _}>; - | ----------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{pointer}`, found `{pointer}` + | ----------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `0x[PREFIX]0000000f`, found `0x[PREFIX]0000000a` | | | expected due to this | - = note: expected struct `Const<{pointer}>` - found struct `Const<{pointer}>` + = note: expected struct `Const<0x[PREFIX]0000000f>` + found struct `Const<0x[PREFIX]0000000a>` error: aborting due to previous error diff --git a/src/test/ui/consts/offset_from_ub.stderr b/src/test/ui/consts/offset_from_ub.stderr index 24da983cf0868..bbe3344b412b3 100644 --- a/src/test/ui/consts/offset_from_ub.stderr +++ b/src/test/ui/consts/offset_from_ub.stderr @@ -43,7 +43,7 @@ error: any use of this value will cause an error LL | intrinsics::ptr_offset_from(self, origin) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | - | exact_div: 1 cannot be divided by 2 without remainder + | exact_div: 1isize cannot be divided by 2isize without remainder | inside call to `std::ptr::const_ptr::::offset_from` at $DIR/offset_from_ub.rs:36:14 | ::: $DIR/offset_from_ub.rs:31:1 From 02f4eeb7cb78f1cf7bcfe18db3b700b02576ca55 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 27 Jan 2020 18:49:05 +0100 Subject: [PATCH 02/18] Address review comments around `type_ascribed_value` --- src/librustc/ty/print/pretty.rs | 81 +++++++++++++++++---------------- 1 file changed, 41 insertions(+), 40 deletions(-) diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 2f53b62fdecf8..6e960f66c7c99 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -210,6 +210,23 @@ pub trait PrettyPrinter<'tcx>: Ok(self) } + /// Prints `{...}` around what `f` and optionally `t` print + fn type_ascribed_value( + mut self, + f: impl FnOnce(Self) -> Result, + t: impl FnOnce(Self) -> Result, + print_ty: bool, + ) -> Result { + self.write_str("{")?; + self = f(self)?; + if print_ty { + self.write_str(": ")?; + self = t(self)?; + } + self.write_str("}")?; + Ok(self) + } + /// Prints `<...>` around what `f` prints. fn generic_delimiters( self, @@ -457,22 +474,6 @@ pub trait PrettyPrinter<'tcx>: }) } - fn print_type_ascribed( - mut self, - f: impl FnOnce(Self) -> Result, - ty: Ty<'tcx>, - print_ty: bool, - ) -> Result { - self.write_str("{")?; - self = f(self)?; - if print_ty { - self.write_str(": ")?; - self = self.print_type(ty)?; - } - self.write_str("}")?; - Ok(self) - } - fn pretty_print_type(mut self, ty: Ty<'tcx>) -> Result { define_scoped_cx!(self); @@ -1002,12 +1003,12 @@ pub trait PrettyPrinter<'tcx>: (Scalar::Raw { size: 0, .. }, _) => p!(print(ty)), // Nontrivial types with scalar bit representation (Scalar::Raw { data, size }, _) => { - self = self.print_type_ascribed( + self = self.type_ascribed_value( |mut this| { write!(this, "0x{:01$x}", data, size as usize * 2)?; Ok(this) }, - ty, + |this| this.print_type(ty), print_ty, )? } @@ -1027,12 +1028,12 @@ pub trait PrettyPrinter<'tcx>: ty: Ty<'tcx>, print_ty: bool, ) -> Result { - self.print_type_ascribed( + self.type_ascribed_value( |mut this| { this.write_str("pointer")?; Ok(this) }, - ty, + |this| this.print_type(ty), print_ty, ) } @@ -1425,6 +1426,24 @@ impl PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx, F> { self.pretty_in_binder(value) } + fn type_ascribed_value( + mut self, + f: impl FnOnce(Self) -> Result, + t: impl FnOnce(Self) -> Result, + print_ty: bool, + ) -> Result { + self.write_str("{")?; + self = f(self)?; + if print_ty { + self.write_str(": ")?; + let was_in_value = std::mem::replace(&mut self.in_value, false); + self = t(self)?; + self.in_value = was_in_value; + } + self.write_str("}")?; + Ok(self) + } + fn generic_delimiters( mut self, f: impl FnOnce(Self) -> Result, @@ -1488,7 +1507,7 @@ impl PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx, F> { ty: Ty<'tcx>, print_ty: bool, ) -> Result { - self.print_type_ascribed( + self.type_ascribed_value( |mut this| { define_scoped_cx!(this); if this.print_alloc_ids { @@ -1498,28 +1517,10 @@ impl PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx, F> { } Ok(this) }, - ty, + |this| this.print_type(ty), print_ty, ) } - - fn print_type_ascribed( - mut self, - f: impl FnOnce(Self) -> Result, - ty: Ty<'tcx>, - print_ty: bool, - ) -> Result { - self.write_str("{")?; - self = f(self)?; - if print_ty { - self.write_str(": ")?; - let was_in_value = std::mem::replace(&mut self.in_value, false); - self = self.print_type(ty)?; - self.in_value = was_in_value; - } - self.write_str("}")?; - Ok(self) - } } // HACK(eddyb) limited to `FmtPrinter` because of `region_highlight_mode`. From 3b82edd279e2055a65135a2469b3ad539c5665e3 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 5 Feb 2020 11:00:52 +0100 Subject: [PATCH 03/18] Print braces only in print_ty mode --- src/librustc/ty/print/pretty.rs | 86 ++++++++++++++++----------------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 6e960f66c7c99..b992e13daf0b9 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -210,19 +210,16 @@ pub trait PrettyPrinter<'tcx>: Ok(self) } - /// Prints `{...}` around what `f` and optionally `t` print + /// Prints `{...}` around what `f` (and optionally `t`) print fn type_ascribed_value( mut self, f: impl FnOnce(Self) -> Result, t: impl FnOnce(Self) -> Result, - print_ty: bool, ) -> Result { self.write_str("{")?; self = f(self)?; - if print_ty { - self.write_str(": ")?; - self = t(self)?; - } + self.write_str(": ")?; + self = t(self)?; self.write_str("}")?; Ok(self) } @@ -1003,14 +1000,15 @@ pub trait PrettyPrinter<'tcx>: (Scalar::Raw { size: 0, .. }, _) => p!(print(ty)), // Nontrivial types with scalar bit representation (Scalar::Raw { data, size }, _) => { - self = self.type_ascribed_value( - |mut this| { - write!(this, "0x{:01$x}", data, size as usize * 2)?; - Ok(this) - }, - |this| this.print_type(ty), - print_ty, - )? + let print = |mut this: Self| { + write!(this, "0x{:01$x}", data, size as usize * 2)?; + Ok(this) + }; + self = if print_ty { + self.type_ascribed_value(print, |this| this.print_type(ty))? + } else { + print(self)? + }; } // Any pointer values not covered by a branch above (Scalar::Ptr(p), _) => { @@ -1023,19 +1021,23 @@ pub trait PrettyPrinter<'tcx>: /// This is overridden for MIR printing because we only want to hide alloc ids from users, not /// from MIR where it is actually useful. fn pretty_print_const_pointer( - self, + mut self, _: Pointer, ty: Ty<'tcx>, print_ty: bool, ) -> Result { - self.type_ascribed_value( - |mut this| { - this.write_str("pointer")?; - Ok(this) - }, - |this| this.print_type(ty), - print_ty, - ) + if print_ty { + self.type_ascribed_value( + |mut this| { + this.write_str("&_")?; + Ok(this) + }, + |this| this.print_type(ty), + ) + } else { + self.write_str("&_")?; + Ok(self) + } } fn pretty_print_byte_str(mut self, byte_str: &'tcx [u8]) -> Result { @@ -1430,16 +1432,13 @@ impl PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx, F> { mut self, f: impl FnOnce(Self) -> Result, t: impl FnOnce(Self) -> Result, - print_ty: bool, ) -> Result { self.write_str("{")?; self = f(self)?; - if print_ty { - self.write_str(": ")?; - let was_in_value = std::mem::replace(&mut self.in_value, false); - self = t(self)?; - self.in_value = was_in_value; - } + self.write_str(": ")?; + let was_in_value = std::mem::replace(&mut self.in_value, false); + self = t(self)?; + self.in_value = was_in_value; self.write_str("}")?; Ok(self) } @@ -1507,19 +1506,20 @@ impl PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx, F> { ty: Ty<'tcx>, print_ty: bool, ) -> Result { - self.type_ascribed_value( - |mut this| { - define_scoped_cx!(this); - if this.print_alloc_ids { - p!(write("{:?}", p)); - } else { - p!(write("pointer")); - } - Ok(this) - }, - |this| this.print_type(ty), - print_ty, - ) + let print = |mut this: Self| { + define_scoped_cx!(this); + if this.print_alloc_ids { + p!(write("{:?}", p)); + } else { + p!(write("&_")); + } + Ok(this) + }; + if print_ty { + self.type_ascribed_value(print, |this| this.print_type(ty)) + } else { + print(self) + } } } From 4ddb4bdaad8c0359e18ffcfe769020d0b20b1937 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 5 Feb 2020 11:58:47 +0100 Subject: [PATCH 04/18] Eliminate all ParamEnv::empty uses in pretty printing --- src/librustc/ty/print/pretty.rs | 41 +++++++++++++++------------------ 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index b992e13daf0b9..d750fcdef89fd 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -703,7 +703,7 @@ pub trait PrettyPrinter<'tcx>: // array length anon const, rustc will (with debug assertions) print the // constant's path. Which will end up here again. p!(write("_")); - } else if let Some(n) = sz.try_eval_usize(self.tcx(), ty::ParamEnv::empty()) { + } else if let Some(n) = sz.val.try_to_bits(self.tcx().data_layout.pointer_size) { p!(write("{}", n)); } else { p!(write("_")); @@ -916,26 +916,23 @@ pub trait PrettyPrinter<'tcx>: define_scoped_cx!(self); match (scalar, &ty.kind) { - // Single element arrays print their element (they are `#[transparent]`) enclosed in - // square brackets. - (_, ty::Array(t, n)) if n.eval_usize(self.tcx(), ty::ParamEnv::empty()) == 1 => { - p!(write("[")); - self = self.pretty_print_const_scalar(scalar, t, print_ty)?; - p!(write("]")); - } // Byte strings (&[u8; N]) (Scalar::Ptr(ptr), ty::Ref(_, ty::TyS { kind: ty::Array(t, n), .. }, _)) if *t == self.tcx().types.u8 => { - let n = n.eval_usize(self.tcx(), ty::ParamEnv::empty()); - let byte_str = self - .tcx() - .alloc_map - .lock() - .unwrap_memory(ptr.alloc_id) - .get_bytes(&self.tcx(), ptr, Size::from_bytes(n)) - .unwrap(); - p!(pretty_print_byte_str(byte_str)); + match n.val.try_to_bits(self.tcx().data_layout.pointer_size) { + Some(n) => { + let byte_str = self + .tcx() + .alloc_map + .lock() + .unwrap_memory(ptr.alloc_id) + .get_bytes(&self.tcx(), ptr, Size::from_bytes(n as u64)) + .unwrap(); + p!(pretty_print_byte_str(byte_str)); + } + None => self.write_str("_")?, + } } // Bool (Scalar::Raw { data: 0, .. }, ty::Bool) => p!(write("false")), @@ -961,12 +958,11 @@ pub trait PrettyPrinter<'tcx>: }; } (Scalar::Raw { data, .. }, ty::Int(i)) => { - let bit_size = Integer::from_attr(&self.tcx(), SignedInt(*i)).size().bits() as u128; + let size = Integer::from_attr(&self.tcx(), SignedInt(*i)).size(); + let bit_size = size.bits() as u128; let min = 1u128 << (bit_size - 1); let max = min - 1; - let ty = self.tcx().lift(&ty).unwrap(); - let size = self.tcx().layout_of(ty::ParamEnv::empty().and(ty)).unwrap().size; let i_str = i.name_str(); match data { d if d == min => p!(write("std::{}::MIN", i_str)), @@ -1092,8 +1088,9 @@ pub trait PrettyPrinter<'tcx>: Ok(self) } (ConstValue::ByRef { alloc, offset }, ty::Array(t, n)) if *t == u8_type => { - let n = n.eval_usize(self.tcx(), ty::ParamEnv::empty()); - let n = Size::from_bytes(n); + let n = n.val.try_to_bits(self.tcx().data_layout.pointer_size).unwrap(); + // cast is ok because we already checked for pointer size (32 or 64 bit) above + let n = Size::from_bytes(n as u64); let ptr = Pointer::new(AllocId(0), offset); let byte_str = alloc.get_bytes(&self.tcx(), ptr, n).unwrap(); From e22ddfd80d840f310d00fc756ab298caa181a326 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 5 Feb 2020 12:17:41 +0100 Subject: [PATCH 05/18] Don't print leading zeros on hex dumps constants --- src/librustc/ty/print/pretty.rs | 7 +++---- src/test/mir-opt/const_prop/discriminant.rs | 2 +- .../mir-opt/simplify-locals-removes-unused-consts.rs | 10 +++++----- src/test/ui/const-generics/raw-ptr-const-param.rs | 7 ++----- .../ui/const-generics/raw-ptr-const-param.stderr | 12 ++++++------ 5 files changed, 17 insertions(+), 21 deletions(-) diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index d750fcdef89fd..86791ece5fcf1 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -982,8 +982,7 @@ pub trait PrettyPrinter<'tcx>: p!(write("{{null reference to "), print(ty), write("}}")) } (Scalar::Raw { data, .. }, ty::Ref(..)) | (Scalar::Raw { data, .. }, ty::RawPtr(_)) => { - let pointer_width = self.tcx().data_layout.pointer_size.bytes(); - p!(write("0x{:01$x}", data, pointer_width as usize * 2)) + p!(write("0x{:x}", data)) } (Scalar::Ptr(ptr), ty::FnPtr(_)) => { let instance = { @@ -995,9 +994,9 @@ pub trait PrettyPrinter<'tcx>: // For zsts just print their type as their value gives no extra information (Scalar::Raw { size: 0, .. }, _) => p!(print(ty)), // Nontrivial types with scalar bit representation - (Scalar::Raw { data, size }, _) => { + (Scalar::Raw { data, .. }, _) => { let print = |mut this: Self| { - write!(this, "0x{:01$x}", data, size as usize * 2)?; + write!(this, "transmute(0x{:x})", data)?; Ok(this) }; self = if print_ty { diff --git a/src/test/mir-opt/const_prop/discriminant.rs b/src/test/mir-opt/const_prop/discriminant.rs index b308d06999c8a..587f81f7f879e 100644 --- a/src/test/mir-opt/const_prop/discriminant.rs +++ b/src/test/mir-opt/const_prop/discriminant.rs @@ -31,7 +31,7 @@ fn main() { // START rustc.main.ConstProp.after.mir // bb0: { // ... -// _3 = const {0x01: std::option::Option}; +// _3 = const {transmute(0x1): std::option::Option}; // _4 = const 1isize; // switchInt(const 1isize) -> [1isize: bb2, otherwise: bb1]; // } diff --git a/src/test/mir-opt/simplify-locals-removes-unused-consts.rs b/src/test/mir-opt/simplify-locals-removes-unused-consts.rs index ca8e60b9e39c8..730314a788820 100644 --- a/src/test/mir-opt/simplify-locals-removes-unused-consts.rs +++ b/src/test/mir-opt/simplify-locals-removes-unused-consts.rs @@ -1,18 +1,18 @@ // compile-flags: -C overflow-checks=no -fn use_zst(_: ((), ())) { } +fn use_zst(_: ((), ())) {} struct Temp { - x: u8 + x: u8, } -fn use_u8(_: u8) { } +fn use_u8(_: u8) {} fn main() { let ((), ()) = ((), ()); use_zst(((), ())); - use_u8((Temp { x : 40 }).x + 2); + use_u8((Temp { x: 40 }).x + 2); } // END RUST SOURCE @@ -56,7 +56,7 @@ fn main() { // StorageLive(_8); // StorageLive(_10); // StorageLive(_11); -// _11 = const {0x28 : Temp}; +// _11 = const {transmute(0x28) : Temp}; // _10 = const 40u8; // StorageDead(_10); // _8 = const use_u8(const 42u8) -> bb2; diff --git a/src/test/ui/const-generics/raw-ptr-const-param.rs b/src/test/ui/const-generics/raw-ptr-const-param.rs index f8ae1b3fdc948..f0349f469626f 100644 --- a/src/test/ui/const-generics/raw-ptr-const-param.rs +++ b/src/test/ui/const-generics/raw-ptr-const-param.rs @@ -1,12 +1,9 @@ -// normalize-stderr-64bit "0x00000000" -> "0x[PREFIX]" -// normalize-stderr-32bit "0x" -> "0x[PREFIX]" - #![feature(const_generics, const_compare_raw_pointers)] //~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash struct Const; fn main() { - let _: Const<{15 as *const _}> = Const::<{10 as *const _}>; //~ mismatched types - let _: Const<{10 as *const _}> = Const::<{10 as *const _}>; + let _: Const<{ 15 as *const _ }> = Const::<{ 10 as *const _ }>; //~ mismatched types + let _: Const<{ 10 as *const _ }> = Const::<{ 10 as *const _ }>; } diff --git a/src/test/ui/const-generics/raw-ptr-const-param.stderr b/src/test/ui/const-generics/raw-ptr-const-param.stderr index 850bb89e95653..7bf2616fea29a 100644 --- a/src/test/ui/const-generics/raw-ptr-const-param.stderr +++ b/src/test/ui/const-generics/raw-ptr-const-param.stderr @@ -1,5 +1,5 @@ warning: the feature `const_generics` is incomplete and may cause the compiler to crash - --> $DIR/raw-ptr-const-param.rs:4:12 + --> $DIR/raw-ptr-const-param.rs:1:12 | LL | #![feature(const_generics, const_compare_raw_pointers)] | ^^^^^^^^^^^^^^ @@ -7,15 +7,15 @@ LL | #![feature(const_generics, const_compare_raw_pointers)] = note: `#[warn(incomplete_features)]` on by default error[E0308]: mismatched types - --> $DIR/raw-ptr-const-param.rs:10:38 + --> $DIR/raw-ptr-const-param.rs:7:40 | -LL | let _: Const<{15 as *const _}> = Const::<{10 as *const _}>; - | ----------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `0x[PREFIX]0000000f`, found `0x[PREFIX]0000000a` +LL | let _: Const<{ 15 as *const _ }> = Const::<{ 10 as *const _ }>; + | ------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `0xf`, found `0xa` | | | expected due to this | - = note: expected struct `Const<0x[PREFIX]0000000f>` - found struct `Const<0x[PREFIX]0000000a>` + = note: expected struct `Const<0xf>` + found struct `Const<0xa>` error: aborting due to previous error From b837e7173236b27ba76660864cd160aacbe66c57 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 10 Feb 2020 15:36:14 +0100 Subject: [PATCH 06/18] Reduce special casing in the const pretty printer --- src/librustc/ty/print/pretty.rs | 12 +++--------- .../ui/const-generics/raw-ptr-const-param.stderr | 6 +++--- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 86791ece5fcf1..446bb3db00464 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -937,7 +937,6 @@ pub trait PrettyPrinter<'tcx>: // Bool (Scalar::Raw { data: 0, .. }, ty::Bool) => p!(write("false")), (Scalar::Raw { data: 1, .. }, ty::Bool) => p!(write("true")), - (Scalar::Raw { data, .. }, ty::Bool) => p!(write("{}_bool", data)), // Float (Scalar::Raw { data, .. }, ty::Float(ast::FloatTy::F32)) => { p!(write("{}f32", Single::from_bits(data))) @@ -975,14 +974,9 @@ pub trait PrettyPrinter<'tcx>: Some(c) => p!(write("{:?}", c)), None => p!(write("{}_char", data)), }, - // References and pointers - (Scalar::Raw { data: 0, .. }, ty::RawPtr(_)) => p!(write("{{null pointer}}")), - // This is UB, but we still print it - (Scalar::Raw { data: 0, .. }, ty::Ref(_, ty, _)) => { - p!(write("{{null reference to "), print(ty), write("}}")) - } - (Scalar::Raw { data, .. }, ty::Ref(..)) | (Scalar::Raw { data, .. }, ty::RawPtr(_)) => { - p!(write("0x{:x}", data)) + // Raw pointers + (Scalar::Raw { data, .. }, ty::RawPtr(_)) => { + p!(write("{{0x{:x} as ", data), print(ty), write("}}")) } (Scalar::Ptr(ptr), ty::FnPtr(_)) => { let instance = { diff --git a/src/test/ui/const-generics/raw-ptr-const-param.stderr b/src/test/ui/const-generics/raw-ptr-const-param.stderr index 7bf2616fea29a..d9794f60a19ce 100644 --- a/src/test/ui/const-generics/raw-ptr-const-param.stderr +++ b/src/test/ui/const-generics/raw-ptr-const-param.stderr @@ -10,12 +10,12 @@ error[E0308]: mismatched types --> $DIR/raw-ptr-const-param.rs:7:40 | LL | let _: Const<{ 15 as *const _ }> = Const::<{ 10 as *const _ }>; - | ------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `0xf`, found `0xa` + | ------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{0xf as *const u32}`, found `{0xa as *const u32}` | | | expected due to this | - = note: expected struct `Const<0xf>` - found struct `Const<0xa>` + = note: expected struct `Const<{0xf as *const u32}>` + found struct `Const<{0xa as *const u32}>` error: aborting due to previous error From b2e93a41a653ea96954ae3780ea7d4c0368ed9c3 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 10 Feb 2020 17:05:18 +0100 Subject: [PATCH 07/18] Print leading zeros for non pointers --- src/librustc/ty/print/pretty.rs | 4 ++-- src/test/mir-opt/const_prop/discriminant.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 446bb3db00464..76503eb10fcf3 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -988,9 +988,9 @@ pub trait PrettyPrinter<'tcx>: // For zsts just print their type as their value gives no extra information (Scalar::Raw { size: 0, .. }, _) => p!(print(ty)), // Nontrivial types with scalar bit representation - (Scalar::Raw { data, .. }, _) => { + (Scalar::Raw { data, size }, _) => { let print = |mut this: Self| { - write!(this, "transmute(0x{:x})", data)?; + write!(this, "transmute(0x{:01$x})", data, size as usize * 2)?; Ok(this) }; self = if print_ty { diff --git a/src/test/mir-opt/const_prop/discriminant.rs b/src/test/mir-opt/const_prop/discriminant.rs index 587f81f7f879e..636aa1af65333 100644 --- a/src/test/mir-opt/const_prop/discriminant.rs +++ b/src/test/mir-opt/const_prop/discriminant.rs @@ -31,7 +31,7 @@ fn main() { // START rustc.main.ConstProp.after.mir // bb0: { // ... -// _3 = const {transmute(0x1): std::option::Option}; +// _3 = const {transmute(0x01): std::option::Option}; // _4 = const 1isize; // switchInt(const 1isize) -> [1isize: bb2, otherwise: bb1]; // } From 1191eb45859041b467d4e0bd8accca3e164b1dad Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 12 Feb 2020 13:30:31 +0100 Subject: [PATCH 08/18] Prefer fall through to code repetition --- src/librustc/ty/print/pretty.rs | 54 +++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 20 deletions(-) diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 76503eb10fcf3..6edab2708386d 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -17,6 +17,7 @@ use rustc_span::symbol::{kw, Symbol}; use rustc_target::spec::abi::Abi; use std::cell::Cell; +use std::char; use std::collections::BTreeMap; use std::fmt::{self, Write as _}; use std::ops::{Deref, DerefMut}; @@ -917,22 +918,36 @@ pub trait PrettyPrinter<'tcx>: match (scalar, &ty.kind) { // Byte strings (&[u8; N]) - (Scalar::Ptr(ptr), ty::Ref(_, ty::TyS { kind: ty::Array(t, n), .. }, _)) - if *t == self.tcx().types.u8 => - { - match n.val.try_to_bits(self.tcx().data_layout.pointer_size) { - Some(n) => { - let byte_str = self - .tcx() - .alloc_map - .lock() - .unwrap_memory(ptr.alloc_id) - .get_bytes(&self.tcx(), ptr, Size::from_bytes(n as u64)) - .unwrap(); - p!(pretty_print_byte_str(byte_str)); - } - None => self.write_str("_")?, - } + ( + Scalar::Ptr(ptr), + ty::Ref( + _, + ty::TyS { + kind: + ty::Array( + ty::TyS { kind: ty::Uint(ast::UintTy::U8), .. }, + ty::Const { + val: + ty::ConstKind::Value(ConstValue::Scalar(Scalar::Raw { + data, + .. + })), + .. + }, + ), + .. + }, + _, + ), + ) => { + let byte_str = self + .tcx() + .alloc_map + .lock() + .unwrap_memory(ptr.alloc_id) + .get_bytes(&self.tcx(), ptr, Size::from_bytes(*data as u64)) + .unwrap(); + p!(pretty_print_byte_str(byte_str)); } // Bool (Scalar::Raw { data: 0, .. }, ty::Bool) => p!(write("false")), @@ -970,10 +985,9 @@ pub trait PrettyPrinter<'tcx>: } } // Char - (Scalar::Raw { data, .. }, ty::Char) => match ::std::char::from_u32(data as u32) { - Some(c) => p!(write("{:?}", c)), - None => p!(write("{}_char", data)), - }, + (Scalar::Raw { data, .. }, ty::Char) if char::from_u32(data as u32).is_some() => { + p!(write("{:?}", char::from_u32(data as u32).unwrap())) + } // Raw pointers (Scalar::Raw { data, .. }, ty::RawPtr(_)) => { p!(write("{{0x{:x} as ", data), print(ty), write("}}")) From 154f3f19ab10723ef3afd7b6166384356df631dc Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 12 Feb 2020 13:47:00 +0100 Subject: [PATCH 09/18] Don't print all zsts as their type as it makes no sense for more complex examples (e.g. structs) --- src/librustc/ty/print/pretty.rs | 23 ++++++++++++++++--- .../simplify-locals-removes-unused-consts.rs | 6 ++--- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 6edab2708386d..d1aee1290c9b3 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -999,12 +999,29 @@ pub trait PrettyPrinter<'tcx>: }; p!(print_value_path(instance.def_id(), instance.substs)); } - // For zsts just print their type as their value gives no extra information - (Scalar::Raw { size: 0, .. }, _) => p!(print(ty)), + // For function type zsts just printing the type is enough + (Scalar::Raw { size: 0, .. }, ty::FnDef(..)) => p!(print(ty)), + // Empty tuples are frequently occurring, so don't print the fallback. + (Scalar::Raw { size: 0, .. }, ty::Tuple(ts)) if ts.is_empty() => p!(write("()")), + // Zero element arrays have a trivial representation. + ( + Scalar::Raw { size: 0, .. }, + ty::Array( + _, + ty::Const { + val: ty::ConstKind::Value(ConstValue::Scalar(Scalar::Raw { data: 0, .. })), + .. + }, + ), + ) => p!(write("[]")), // Nontrivial types with scalar bit representation (Scalar::Raw { data, size }, _) => { let print = |mut this: Self| { - write!(this, "transmute(0x{:01$x})", data, size as usize * 2)?; + if size == 0 { + write!(this, "transmute(())")?; + } else { + write!(this, "transmute(0x{:01$x})", data, size as usize * 2)?; + } Ok(this) }; self = if print_ty { diff --git a/src/test/mir-opt/simplify-locals-removes-unused-consts.rs b/src/test/mir-opt/simplify-locals-removes-unused-consts.rs index 730314a788820..e427fd55ad680 100644 --- a/src/test/mir-opt/simplify-locals-removes-unused-consts.rs +++ b/src/test/mir-opt/simplify-locals-removes-unused-consts.rs @@ -38,7 +38,7 @@ fn main() { // _2 = const (); // StorageLive(_3); // _3 = const (); -// _1 = const ((), ()); +// _1 = const {transmute(()): ((), ())}; // StorageDead(_3); // StorageDead(_2); // StorageDead(_1); @@ -49,7 +49,7 @@ fn main() { // _7 = const (); // StorageDead(_7); // StorageDead(_6); -// _4 = const use_zst(const ((), ())) -> bb1; +// _4 = const use_zst(const {transmute(()): ((), ())}) -> bb1; // } // bb1: { // StorageDead(_4); @@ -75,7 +75,7 @@ fn main() { // } // bb0: { // StorageLive(_1); -// _1 = const use_zst(const ((), ())) -> bb1; +// _1 = const use_zst(const {transmute(()): ((), ())}) -> bb1; // } // bb1: { // StorageDead(_1); From b78dbf43f4b88e94b7b7f90f0cbe100e52afeae6 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Thu, 13 Feb 2020 19:02:58 +0100 Subject: [PATCH 10/18] Reuse type ascripted printing for type cast printing --- src/librustc/ty/print/pretty.rs | 36 ++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index d1aee1290c9b3..230ddb2e72317 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -211,15 +211,20 @@ pub trait PrettyPrinter<'tcx>: Ok(self) } - /// Prints `{...}` around what `f` (and optionally `t`) print - fn type_ascribed_value( + /// Prints `{f: t}` or `{f as t}` depending on the `cast` argument + fn typed_value( mut self, f: impl FnOnce(Self) -> Result, t: impl FnOnce(Self) -> Result, + cast: bool, ) -> Result { self.write_str("{")?; self = f(self)?; - self.write_str(": ")?; + if cast { + self.write_str(" as ")?; + } else { + self.write_str(": ")?; + } self = t(self)?; self.write_str("}")?; Ok(self) @@ -990,7 +995,14 @@ pub trait PrettyPrinter<'tcx>: } // Raw pointers (Scalar::Raw { data, .. }, ty::RawPtr(_)) => { - p!(write("{{0x{:x} as ", data), print(ty), write("}}")) + self = self.typed_value( + |mut this| { + write!(this, "0x{:x}", data)?; + Ok(this) + }, + |this| this.print_type(ty), + true, + )?; } (Scalar::Ptr(ptr), ty::FnPtr(_)) => { let instance = { @@ -1025,7 +1037,7 @@ pub trait PrettyPrinter<'tcx>: Ok(this) }; self = if print_ty { - self.type_ascribed_value(print, |this| this.print_type(ty))? + self.typed_value(print, |this| this.print_type(ty), false)? } else { print(self)? }; @@ -1047,12 +1059,13 @@ pub trait PrettyPrinter<'tcx>: print_ty: bool, ) -> Result { if print_ty { - self.type_ascribed_value( + self.typed_value( |mut this| { this.write_str("&_")?; Ok(this) }, |this| this.print_type(ty), + false, ) } else { self.write_str("&_")?; @@ -1449,14 +1462,19 @@ impl PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx, F> { self.pretty_in_binder(value) } - fn type_ascribed_value( + fn typed_value( mut self, f: impl FnOnce(Self) -> Result, t: impl FnOnce(Self) -> Result, + cast: bool, ) -> Result { self.write_str("{")?; self = f(self)?; - self.write_str(": ")?; + if cast { + self.write_str(" as ")?; + } else { + self.write_str(": ")?; + } let was_in_value = std::mem::replace(&mut self.in_value, false); self = t(self)?; self.in_value = was_in_value; @@ -1537,7 +1555,7 @@ impl PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx, F> { Ok(this) }; if print_ty { - self.type_ascribed_value(print, |this| this.print_type(ty)) + self.typed_value(print, |this| this.print_type(ty), false) } else { print(self) } From fff2e0f8060c27a17abf1af79b73326e59a8661b Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 26 Feb 2020 19:19:56 +0100 Subject: [PATCH 11/18] Print function pointer type for function pointer const generics --- src/librustc/ty/print/pretty.rs | 6 +++++- .../ui/const-generics/fn-const-param-infer.stderr | 12 ++++++------ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 230ddb2e72317..32630737cd57f 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -1009,7 +1009,11 @@ pub trait PrettyPrinter<'tcx>: let alloc_map = self.tcx().alloc_map.lock(); alloc_map.unwrap_fn(ptr.alloc_id) }; - p!(print_value_path(instance.def_id(), instance.substs)); + self = self.typed_value( + |this| this.print_value_path(instance.def_id(), instance.substs), + |this| this.print_type(ty), + true, + )?; } // For function type zsts just printing the type is enough (Scalar::Raw { size: 0, .. }, ty::FnDef(..)) => p!(print(ty)), diff --git a/src/test/ui/const-generics/fn-const-param-infer.stderr b/src/test/ui/const-generics/fn-const-param-infer.stderr index 44eab8baa40a6..05d2dff8e9868 100644 --- a/src/test/ui/const-generics/fn-const-param-infer.stderr +++ b/src/test/ui/const-generics/fn-const-param-infer.stderr @@ -10,12 +10,12 @@ error[E0308]: mismatched types --> $DIR/fn-const-param-infer.rs:16:31 | LL | let _: Checked = Checked::; - | ---------------- ^^^^^^^^^^^^^^^^^^ expected `not_one`, found `not_two` + | ---------------- ^^^^^^^^^^^^^^^^^^ expected `{not_one as fn(usize) -> bool}`, found `{not_two as fn(usize) -> bool}` | | | expected due to this | - = note: expected struct `Checked` - found struct `Checked` + = note: expected struct `Checked<{not_one as fn(usize) -> bool}>` + found struct `Checked<{not_two as fn(usize) -> bool}>` error[E0308]: mismatched types --> $DIR/fn-const-param-infer.rs:20:24 @@ -36,12 +36,12 @@ error[E0308]: mismatched types --> $DIR/fn-const-param-infer.rs:25:40 | LL | let _: Checked<{generic::}> = Checked::<{generic::}>; - | ------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `generic::`, found `generic::` + | ------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{generic:: as fn(usize) -> bool}`, found `{generic:: as fn(usize) -> bool}` | | | expected due to this | - = note: expected struct `Checked>` - found struct `Checked>` + = note: expected struct `Checked<{generic:: as fn(usize) -> bool}>` + found struct `Checked<{generic:: as fn(usize) -> bool}>` error: aborting due to 4 previous errors From cc9ca640c2a402f620a6b664a25b4417e8d3615a Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 26 Feb 2020 19:20:14 +0100 Subject: [PATCH 12/18] Don't print literal type suffixes if `print_ty` is false --- src/librustc/ty/print/pretty.rs | 11 +++++++++-- src/test/ui/const-generics/const-generic-type_name.rs | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 32630737cd57f..819895e6d1c0a 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -973,7 +973,7 @@ pub trait PrettyPrinter<'tcx>: if data == max { p!(write("std::{}::MAX", ui_str)) } else { - p!(write("{}{}", data, ui_str)) + if print_ty { p!(write("{}{}", data, ui_str)) } else { p!(write("{}", data)) } }; } (Scalar::Raw { data, .. }, ty::Int(i)) => { @@ -986,7 +986,14 @@ pub trait PrettyPrinter<'tcx>: match data { d if d == min => p!(write("std::{}::MIN", i_str)), d if d == max => p!(write("std::{}::MAX", i_str)), - _ => p!(write("{}{}", sign_extend(data, size) as i128, i_str)), + _ => { + let data = sign_extend(data, size) as i128; + if print_ty { + p!(write("{}{}", data, i_str)) + } else { + p!(write("{}", data)) + } + } } } // Char diff --git a/src/test/ui/const-generics/const-generic-type_name.rs b/src/test/ui/const-generics/const-generic-type_name.rs index 28586426b44e9..469843d6aae1e 100644 --- a/src/test/ui/const-generics/const-generic-type_name.rs +++ b/src/test/ui/const-generics/const-generic-type_name.rs @@ -7,5 +7,5 @@ struct S; fn main() { - assert_eq!(std::any::type_name::>(), "const_generic_type_name::S<3usize>"); + assert_eq!(std::any::type_name::>(), "const_generic_type_name::S<3>"); } From 2e91065a6f4f3d27eab5fe66dc34c33c016c244d Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 26 Feb 2020 19:36:10 +0100 Subject: [PATCH 13/18] Generalize typed value printing and use for undef printing --- src/librustc/ty/print/pretty.rs | 26 +++++++++----------------- src/librustc_mir/interpret/operand.rs | 16 +++++++++------- 2 files changed, 18 insertions(+), 24 deletions(-) diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 819895e6d1c0a..f1d17c872489e 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -216,15 +216,11 @@ pub trait PrettyPrinter<'tcx>: mut self, f: impl FnOnce(Self) -> Result, t: impl FnOnce(Self) -> Result, - cast: bool, + conversion: &str, ) -> Result { self.write_str("{")?; self = f(self)?; - if cast { - self.write_str(" as ")?; - } else { - self.write_str(": ")?; - } + self.write_str(conversion)?; self = t(self)?; self.write_str("}")?; Ok(self) @@ -1008,7 +1004,7 @@ pub trait PrettyPrinter<'tcx>: Ok(this) }, |this| this.print_type(ty), - true, + " as ", )?; } (Scalar::Ptr(ptr), ty::FnPtr(_)) => { @@ -1019,7 +1015,7 @@ pub trait PrettyPrinter<'tcx>: self = self.typed_value( |this| this.print_value_path(instance.def_id(), instance.substs), |this| this.print_type(ty), - true, + " as ", )?; } // For function type zsts just printing the type is enough @@ -1048,7 +1044,7 @@ pub trait PrettyPrinter<'tcx>: Ok(this) }; self = if print_ty { - self.typed_value(print, |this| this.print_type(ty), false)? + self.typed_value(print, |this| this.print_type(ty), ": ")? } else { print(self)? }; @@ -1076,7 +1072,7 @@ pub trait PrettyPrinter<'tcx>: Ok(this) }, |this| this.print_type(ty), - false, + ": ", ) } else { self.write_str("&_")?; @@ -1477,15 +1473,11 @@ impl PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx, F> { mut self, f: impl FnOnce(Self) -> Result, t: impl FnOnce(Self) -> Result, - cast: bool, + conversion: &str, ) -> Result { self.write_str("{")?; self = f(self)?; - if cast { - self.write_str(" as ")?; - } else { - self.write_str(": ")?; - } + self.write_str(conversion)?; let was_in_value = std::mem::replace(&mut self.in_value, false); self = t(self)?; self.in_value = was_in_value; @@ -1566,7 +1558,7 @@ impl PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx, F> { Ok(this) }; if print_ty { - self.typed_value(print, |this| this.print_type(ty), false) + self.typed_value(print, |this| this.print_type(ty), ": ") } else { print(self) } diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 512eec6b9f14a..75452b9395b50 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -98,7 +98,7 @@ impl std::fmt::Display for ImmTy<'tcx, Tag> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { /// Helper function for printing a scalar to a FmtPrinter fn p<'a, 'tcx, F: std::fmt::Write, Tag>( - mut cx: FmtPrinter<'a, 'tcx, F>, + cx: FmtPrinter<'a, 'tcx, F>, s: ScalarMaybeUndef, ty: Ty<'tcx>, ) -> Result, std::fmt::Error> { @@ -106,12 +106,14 @@ impl std::fmt::Display for ImmTy<'tcx, Tag> { ScalarMaybeUndef::Scalar(s) => { cx.pretty_print_const_scalar(s.erase_tag(), ty, true) } - ScalarMaybeUndef::Undef => { - cx.write_str("{undef ")?; - cx = cx.print_type(ty)?; - cx.write_str("}")?; - Ok(cx) - } + ScalarMaybeUndef::Undef => cx.typed_value( + |mut this| { + this.write_str("{undef ")?; + Ok(this) + }, + |this| this.print_type(ty), + " ", + ), } } ty::tls::with(|tcx| { From db9ddf1cf1a0977065fcaa7fe874f6509037dbcc Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 11 Mar 2020 09:39:58 +0100 Subject: [PATCH 14/18] Address review comments --- src/librustc/ty/print/pretty.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index f1d17c872489e..d6efb28bcc36b 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -1019,7 +1019,7 @@ pub trait PrettyPrinter<'tcx>: )?; } // For function type zsts just printing the type is enough - (Scalar::Raw { size: 0, .. }, ty::FnDef(..)) => p!(print(ty)), + (Scalar::Raw { size: 0, .. }, ty::FnDef(d, s)) => p!(print_value_path(*d, s)), // Empty tuples are frequently occurring, so don't print the fallback. (Scalar::Raw { size: 0, .. }, ty::Tuple(ts)) if ts.is_empty() => p!(write("()")), // Zero element arrays have a trivial representation. From d0b12117c5b82942769dc4daf4887a31f96c8183 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Thu, 12 Mar 2020 11:06:14 +0100 Subject: [PATCH 15/18] Comment nit --- src/librustc/ty/print/pretty.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index d6efb28bcc36b..0eb9c102b5885 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -1018,7 +1018,7 @@ pub trait PrettyPrinter<'tcx>: " as ", )?; } - // For function type zsts just printing the type is enough + // For function type zsts just printing the path is enough (Scalar::Raw { size: 0, .. }, ty::FnDef(d, s)) => p!(print_value_path(*d, s)), // Empty tuples are frequently occurring, so don't print the fallback. (Scalar::Raw { size: 0, .. }, ty::Tuple(ts)) if ts.is_empty() => p!(write("()")), From 6e73a14234cf1c1e7bf7a1597f1db4a518e1c6bb Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Thu, 12 Mar 2020 13:35:44 +0100 Subject: [PATCH 16/18] Remove fn special casing in const printing --- src/librustc/ty/print/pretty.rs | 37 +++++++++++++------ .../cannot-infer-const-args.stderr | 2 +- 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 0eb9c102b5885..fdd1533e1302f 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -858,16 +858,23 @@ pub trait PrettyPrinter<'tcx>: macro_rules! print_underscore { () => {{ - p!(write("_")); if print_ty { - p!(write(": "), print(ct.ty)); + self = self.typed_value( + |mut this| { + write!(this, "_")?; + Ok(this) + }, + |this| this.print_type(ct.ty), + ": ", + )?; + } else { + write!(self, "_")?; } }}; } - match (ct.val, &ct.ty.kind) { - (_, ty::FnDef(did, substs)) => p!(print_value_path(*did, substs)), - (ty::ConstKind::Unevaluated(did, substs, promoted), _) => { + match ct.val { + ty::ConstKind::Unevaluated(did, substs, promoted) => { if let Some(promoted) = promoted { p!(print_value_path(did, substs)); p!(write("::{:?}", promoted)); @@ -892,17 +899,25 @@ pub trait PrettyPrinter<'tcx>: } } } - (ty::ConstKind::Infer(..), _) => print_underscore!(), - (ty::ConstKind::Param(ParamConst { name, .. }), _) => p!(write("{}", name)), - (ty::ConstKind::Value(value), _) => { + ty::ConstKind::Infer(..) => print_underscore!(), + ty::ConstKind::Param(ParamConst { name, .. }) => p!(write("{}", name)), + ty::ConstKind::Value(value) => { return self.pretty_print_const_value(value, ct.ty, print_ty); } - _ => { + ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(_) => { // fallback - p!(write("{:?}", ct.val)); if print_ty { - p!(write(": "), print(ct.ty)); + self = self.typed_value( + |mut this| { + write!(this, "{:?}", ct.val)?; + Ok(this) + }, + |this| this.print_type(ct.ty), + ": ", + )?; + } else { + p!(write("{:?}", ct.val)); } } }; diff --git a/src/test/ui/const-generics/cannot-infer-const-args.stderr b/src/test/ui/const-generics/cannot-infer-const-args.stderr index 8379cbd4908e9..c1d7022d56b5f 100644 --- a/src/test/ui/const-generics/cannot-infer-const-args.stderr +++ b/src/test/ui/const-generics/cannot-infer-const-args.stderr @@ -10,7 +10,7 @@ error[E0282]: type annotations needed --> $DIR/cannot-infer-const-args.rs:9:5 | LL | foo(); - | ^^^ cannot infer type for fn item `fn() -> usize {foo::<_: usize>}` + | ^^^ cannot infer type for fn item `fn() -> usize {foo::<{_: usize}>}` error: aborting due to previous error From 306df94ed34521d3d3536e2393b466519f6dfc96 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 13 Mar 2020 10:48:41 +0100 Subject: [PATCH 17/18] Print ConstKind::Bound the same as TyKind::Bound --- src/librustc/ty/print/pretty.rs | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index fdd1533e1302f..1dade8c0e0887 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -533,14 +533,7 @@ pub trait PrettyPrinter<'tcx>: ty::Error => p!(write("[type error]")), ty::Param(ref param_ty) => p!(write("{}", param_ty)), ty::Bound(debruijn, bound_ty) => match bound_ty.kind { - ty::BoundTyKind::Anon => { - if debruijn == ty::INNERMOST { - p!(write("^{}", bound_ty.var.index())) - } else { - p!(write("^{}_{}", debruijn.index(), bound_ty.var.index())) - } - } - + ty::BoundTyKind::Anon => self.pretty_print_bound_var(debruijn, bound_ty.var)?, ty::BoundTyKind::Param(p) => p!(write("{}", p)), }, ty::Adt(def, substs) => { @@ -718,6 +711,18 @@ pub trait PrettyPrinter<'tcx>: Ok(self) } + fn pretty_print_bound_var( + &mut self, + debruijn: ty::DebruijnIndex, + var: ty::BoundVar, + ) -> Result<(), Self::Error> { + if debruijn == ty::INNERMOST { + write!(self, "^{}", var.index()) + } else { + write!(self, "^{}_{}", debruijn.index(), var.index()) + } + } + fn infer_ty_name(&self, _: ty::TyVid) -> Option { None } @@ -905,7 +910,10 @@ pub trait PrettyPrinter<'tcx>: return self.pretty_print_const_value(value, ct.ty, print_ty); } - ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(_) => { + ty::ConstKind::Bound(debruijn, bound_var) => { + self.pretty_print_bound_var(debruijn, bound_var)? + } + ty::ConstKind::Placeholder(_) => { // fallback if print_ty { self = self.typed_value( From 6ca65bdd752a32b376a7f5cb1dba4953e91f46bb Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 13 Mar 2020 10:55:57 +0100 Subject: [PATCH 18/18] Print ConstKind::Placeholder just like TyKind::Placeholder --- src/librustc/ty/print/pretty.rs | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 1dade8c0e0887..cb01d821c1871 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -913,21 +913,7 @@ pub trait PrettyPrinter<'tcx>: ty::ConstKind::Bound(debruijn, bound_var) => { self.pretty_print_bound_var(debruijn, bound_var)? } - ty::ConstKind::Placeholder(_) => { - // fallback - if print_ty { - self = self.typed_value( - |mut this| { - write!(this, "{:?}", ct.val)?; - Ok(this) - }, - |this| this.print_type(ct.ty), - ": ", - )?; - } else { - p!(write("{:?}", ct.val)); - } - } + ty::ConstKind::Placeholder(placeholder) => p!(write("Placeholder({:?})", placeholder)), }; Ok(self) }