From 86d65d8ec8bb815de70a975ba3feb788e07dd491 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 18 Mar 2019 14:21:41 +0100 Subject: [PATCH 01/27] Remove unnecessary secondary recursion --- src/librustc/ty/fold.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index dbf9047f775bf..dae28d51efc2e 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -939,7 +939,7 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor { fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool { let flags = FlagComputation::for_const(c); debug!("HasTypeFlagsVisitor: c={:?} c.flags={:?} self.flags={:?}", c, flags, self.flags); - flags.intersects(self.flags) || c.super_visit_with(self) + flags.intersects(self.flags) } } From d85e866c0d28fce32856d200fd534ac1c2c721c8 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 26 Mar 2019 17:57:13 +0100 Subject: [PATCH 02/27] Ignore .vscode even if it is a symlink --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 67e0dd8e795bb..d34ed114972c5 100644 --- a/.gitignore +++ b/.gitignore @@ -12,7 +12,7 @@ __pycache__/ .project .settings/ .valgrindrc -.vscode/ +.vscode .favorites.json /*-*-*-*/ /*-*-*/ From 8d4f4cdadafe7c7deca5bc3a2725a380cfe9d01b Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 29 Mar 2019 10:52:09 +0100 Subject: [PATCH 03/27] Reuse the pretty printing architecture for printing of constants --- src/librustc/mir/mod.rs | 77 ++++------------------------ src/librustc/ty/print/pretty.rs | 59 ++++++++++++++++++--- src/librustc/ty/structural_impls.rs | 33 ++++++++++++ src/librustc_mir/hair/pattern/mod.rs | 8 +-- src/librustdoc/clean/mod.rs | 3 +- 5 files changed, 100 insertions(+), 80 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 6de4350c2aa98..e44493dec2cf4 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 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()), - _ => {} - } + write!(fmt, "{}", self) } - // 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 06db4b9b65bca..87be78857e325 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 cf04d6eac3ae0..35d0359dbcfd2 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 0576bb53d8f42..a3e43d6481926 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 9c3f522d8470f..f344c529c59e4 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(); From a92d97ee70e84e3568eb28cf8e01d2ac6a67e12c Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 2 Apr 2019 14:23:23 +0200 Subject: [PATCH 04/27] There's a tcx in scope, don't use the tls one --- src/librustc/ty/print/pretty.rs | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 87be78857e325..81f5c87184e3c 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -1557,31 +1557,27 @@ define_print_and_forward_display! { (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 - }); + let ty = cx.tcx().lift_to_global(&self.ty).unwrap(); + let size = cx.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)))), + (_, ty::FnDef(did, _)) => p!(write("{}", cx.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))) - })?; + let alloc = cx.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"); + p!(write("{:?}", s)) }, _ => p!(write("{:?} : ", self.val), print(self.ty)), } From 5713677862b716ed65f653ed065128c98e6fcbb6 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 2 Apr 2019 14:26:28 +0200 Subject: [PATCH 05/27] Merge the string printing paths of ty::Const --- src/librustc/ty/print/pretty.rs | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 81f5c87184e3c..085a0edc9861d 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -1566,17 +1566,21 @@ define_print_and_forward_display! { (ConstValue::Scalar(Scalar::Bits { bits, ..}), ty::Char) => p!(write("{}", ::std::char::from_u32(bits as u32).unwrap())), (_, ty::FnDef(did, _)) => p!(write("{}", cx.tcx().def_path_str(*did))), - (ConstValue::Slice(_, 0), ty::Ref(_, &ty::TyS { sty: ty::Str, .. }, _)) => - p!(write("\"\"")), ( - ConstValue::Slice(Scalar::Ptr(ptr), len), + ConstValue::Slice(place, len), ty::Ref(_, &ty::TyS { sty: ty::Str, .. }, _), ) => { - let alloc = cx.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"); + let s = match (place, len) { + (_, 0) => "", + (Scalar::Ptr(ptr), len) => { + let alloc = cx.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)]; + ::std::str::from_utf8(slice).expect("non utf8 str from miri") + }, + _ => bug!("invalid slice: {:#?}", self), + }; p!(write("{:?}", s)) }, _ => p!(write("{:?} : ", self.val), print(self.ty)), From 9d82107f16185987048fdf06dae59efe3cf60924 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 2 Apr 2019 14:26:56 +0200 Subject: [PATCH 06/27] Print const chars escaped with surrounding quotes --- 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 085a0edc9861d..ca89346b4b4d2 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -1564,7 +1564,7 @@ define_print_and_forward_display! { 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())), + => p!(write("{:?}", ::std::char::from_u32(bits as u32).unwrap())), (_, ty::FnDef(did, _)) => p!(write("{}", cx.tcx().def_path_str(*did))), ( ConstValue::Slice(place, len), From e694b63cd147512ad5e73ff4f9bee057e0c27c19 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 3 Apr 2019 15:29:31 +0200 Subject: [PATCH 07/27] Don't use `ty::Const` without immediately interning --- src/librustc/mir/interpret/error.rs | 2 +- src/librustc/mir/mod.rs | 38 ++++++++------- src/librustc/traits/project.rs | 3 +- src/librustc/traits/query/normalize.rs | 3 +- src/librustc/ty/context.rs | 19 +++----- src/librustc/ty/print/pretty.rs | 2 +- src/librustc/ty/structural_impls.rs | 46 +------------------ src/librustc/ty/sty.rs | 19 ++++---- src/librustc_codegen_ssa/mir/constant.rs | 6 +-- src/librustc_codegen_ssa/mir/operand.rs | 2 +- src/librustc_mir/build/matches/mod.rs | 4 +- src/librustc_mir/build/matches/test.rs | 11 ++--- src/librustc_mir/build/misc.rs | 4 +- src/librustc_mir/const_eval.rs | 14 +++--- src/librustc_mir/hair/constant.rs | 8 ++-- src/librustc_mir/hair/cx/expr.rs | 23 ++++------ src/librustc_mir/hair/cx/mod.rs | 12 ++--- src/librustc_mir/hair/pattern/_match.rs | 12 ++--- src/librustc_mir/hair/pattern/mod.rs | 24 +++++----- src/librustc_mir/interpret/operand.rs | 4 +- src/librustc_mir/monomorphize/collector.rs | 4 +- src/librustc_mir/shim.rs | 12 ++--- src/librustc_mir/transform/const_prop.rs | 2 +- src/librustc_mir/transform/elaborate_drops.rs | 4 +- src/librustc_mir/transform/generator.rs | 4 +- src/librustc_mir/util/elaborate_drops.rs | 4 +- src/librustc_typeck/check/mod.rs | 2 +- src/librustdoc/clean/mod.rs | 8 +++- 28 files changed, 114 insertions(+), 182 deletions(-) diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index 5c6fc6f49f0f0..9c2fd399ee029 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -38,7 +38,7 @@ impl ErrorHandled { } pub type ConstEvalRawResult<'tcx> = Result, ErrorHandled>; -pub type ConstEvalResult<'tcx> = Result, ErrorHandled>; +pub type ConstEvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, ErrorHandled>; #[derive(Clone, Debug, RustcEncodable, RustcDecodable)] pub struct ConstEvalErr<'tcx> { diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index e44493dec2cf4..84aff8101a09d 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1660,25 +1660,25 @@ impl<'tcx> TerminatorKind<'tcx> { switch_ty, .. } => { - let size = ty::tls::with(|tcx| { + ty::tls::with(|tcx| { let param_env = ty::ParamEnv::empty(); let switch_ty = tcx.lift_to_global(&switch_ty).unwrap(); - tcx.layout_of(param_env.and(switch_ty)).unwrap().size - }); - values - .iter() - .map(|&u| { - (&ty::Const { - val: ConstValue::Scalar( - Scalar::Bits { - bits: u, - size: size.bytes() as u8, - }.into(), - ), - ty: switch_ty, - }).to_string().into() - }).chain(iter::once("otherwise".into())) - .collect() + let size = tcx.layout_of(param_env.and(switch_ty)).unwrap().size; + values + .iter() + .map(|&u| { + tcx.mk_const(ty::Const { + val: ConstValue::Scalar( + Scalar::Bits { + bits: u, + size: size.bytes() as u8, + }.into(), + ), + ty: switch_ty, + }).to_string().into() + }).chain(iter::once("otherwise".into())) + .collect() + }) } Call { destination: Some(_), @@ -2326,9 +2326,7 @@ impl<'tcx> Operand<'tcx> { span, ty, user_ty: None, - literal: tcx.mk_const( - ty::Const::zero_sized(ty), - ), + literal: ty::Const::zero_sized(tcx, ty), }) } diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index 67e76f7625cee..b1c4e40911280 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -412,7 +412,6 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a, }; if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) { let substs = tcx.lift_to_global(&substs).unwrap(); - let evaluated = tcx.mk_const(evaluated); let evaluated = evaluated.subst(tcx, substs); return evaluated; } @@ -426,7 +425,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a, promoted: None }; if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) { - return tcx.mk_const(evaluated); + return evaluated; } } } diff --git a/src/librustc/traits/query/normalize.rs b/src/librustc/traits/query/normalize.rs index 9940249da8ba9..d09a9c107869b 100644 --- a/src/librustc/traits/query/normalize.rs +++ b/src/librustc/traits/query/normalize.rs @@ -202,7 +202,6 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx }; if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) { let substs = tcx.lift_to_global(&substs).unwrap(); - let evaluated = tcx.mk_const(evaluated); let evaluated = evaluated.subst(tcx, substs); return evaluated; } @@ -216,7 +215,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx promoted: None, }; if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) { - return tcx.mk_const(evaluated); + return evaluated; } } } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index d83b2ce842a88..a56fe7d7003a1 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -24,7 +24,7 @@ use crate::middle::lang_items; use crate::middle::resolve_lifetime::{self, ObjectLifetimeDefault}; use crate::middle::stability; use crate::mir::{self, Mir, interpret, ProjectionKind}; -use crate::mir::interpret::{ConstValue, Allocation}; +use crate::mir::interpret::{ConstValue, Allocation, Scalar}; use crate::ty::subst::{Kind, InternalSubsts, SubstsRef, Subst}; use crate::ty::ReprOptions; use crate::traits; @@ -1000,7 +1000,10 @@ impl<'tcx> CommonConsts<'tcx> { }; CommonConsts { - err: mk_const(ty::Const::zero_sized(types.err)), + err: mk_const(ty::Const { + val: ConstValue::Scalar(Scalar::Bits { bits: 0, size: 0 }), + ty: types.err, + }), } } } @@ -1822,14 +1825,6 @@ nop_list_lift!{ProjectionKind => ProjectionKind} // this is the impl for `&'a InternalSubsts<'a>` nop_list_lift!{Kind<'a> => Kind<'tcx>} -impl<'a, 'tcx> Lift<'tcx> for &'a mir::interpret::Allocation { - type Lifted = &'tcx mir::interpret::Allocation; - fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option { - assert!(tcx.global_arenas.const_allocs.in_arena(*self as *const _)); - Some(unsafe { mem::transmute(*self) }) - } -} - pub mod tls { use super::{GlobalCtxt, TyCtxt, ptr_eq}; @@ -2594,9 +2589,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { #[inline] pub fn mk_array(self, ty: Ty<'tcx>, n: u64) -> Ty<'tcx> { - self.mk_ty(Array(ty, self.mk_const( - ty::Const::from_usize(self.global_tcx(), n) - ))) + self.mk_ty(Array(ty, ty::Const::from_usize(self.global_tcx(), n))) } #[inline] diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index ca89346b4b4d2..7b363ad6ac490 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -1536,7 +1536,7 @@ define_print_and_forward_display! { p!(print_def_path(self.def_id, self.substs)); } - ty::Const<'tcx> { + &'tcx ty::Const<'tcx> { match (self.val, &self.ty.sty) { | (ConstValue::Unevaluated(..), _) | (ConstValue::Infer(..), _) diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 35d0359dbcfd2..86883a14f687c 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -6,7 +6,7 @@ use crate::hir::def::Namespace; use crate::mir::ProjectionKind; use crate::mir::interpret::ConstValue; -use crate::ty::{self, Lift, Ty, TyCtxt, ConstVid, InferConst}; +use crate::ty::{self, Lift, Ty, TyCtxt, InferConst}; use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; use crate::ty::print::{FmtPrinter, Printer}; use rustc_data_structures::indexed_vec::{IndexVec, Idx}; @@ -14,7 +14,6 @@ use smallvec::SmallVec; use crate::mir::interpret; use std::fmt; -use std::marker::PhantomData; use std::rc::Rc; impl fmt::Debug for ty::GenericParamDef { @@ -295,9 +294,6 @@ CloneTypeFoldableAndLiftImpls! { (), bool, usize, - u32, - crate::ty::BoundVar, - crate::ty::DebruijnIndex, crate::ty::layout::VariantIdx, u64, String, @@ -314,8 +310,6 @@ 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, @@ -793,44 +787,6 @@ 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 { - Some(ConstVid { - index: self.index, - phantom: PhantomData, - }) - } -} - /////////////////////////////////////////////////////////////////////////// // TypeFoldable implementations. // diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 0b5a6fce5cb87..b2ac40f845a75 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -2212,13 +2212,14 @@ static_assert_size!(Const<'_>, 48); impl<'tcx> Const<'tcx> { #[inline] pub fn from_scalar( + tcx: TyCtxt<'_, '_, 'tcx>, val: Scalar, ty: Ty<'tcx>, - ) -> Self { - Self { + ) -> &'tcx Self { + tcx.mk_const(Self { val: ConstValue::Scalar(val), ty, - } + }) } #[inline] @@ -2226,28 +2227,28 @@ impl<'tcx> Const<'tcx> { tcx: TyCtxt<'_, '_, 'tcx>, bits: u128, ty: ParamEnvAnd<'tcx, Ty<'tcx>>, - ) -> Self { + ) -> &'tcx Self { let ty = tcx.lift_to_global(&ty).unwrap(); let size = tcx.layout_of(ty).unwrap_or_else(|e| { panic!("could not compute layout for {:?}: {:?}", ty, e) }).size; let truncated = truncate(bits, size); assert_eq!(truncated, bits, "from_bits called with untruncated value"); - Self::from_scalar(Scalar::Bits { bits, size: size.bytes() as u8 }, ty.value) + Self::from_scalar(tcx, Scalar::Bits { bits, size: size.bytes() as u8 }, ty.value) } #[inline] - pub fn zero_sized(ty: Ty<'tcx>) -> Self { - Self::from_scalar(Scalar::Bits { bits: 0, size: 0 }, ty) + pub fn zero_sized(tcx: TyCtxt<'_, '_, 'tcx>, ty: Ty<'tcx>) -> &'tcx Self { + Self::from_scalar(tcx, Scalar::Bits { bits: 0, size: 0 }, ty) } #[inline] - pub fn from_bool(tcx: TyCtxt<'_, '_, 'tcx>, v: bool) -> Self { + pub fn from_bool(tcx: TyCtxt<'_, '_, 'tcx>, v: bool) -> &'tcx Self { Self::from_bits(tcx, v as u128, ParamEnv::empty().and(tcx.types.bool)) } #[inline] - pub fn from_usize(tcx: TyCtxt<'_, '_, 'tcx>, n: u64) -> Self { + pub fn from_usize(tcx: TyCtxt<'_, '_, 'tcx>, n: u64) -> &'tcx Self { Self::from_bits(tcx, n as u128, ParamEnv::empty().and(tcx.types.usize)) } diff --git a/src/librustc_codegen_ssa/mir/constant.rs b/src/librustc_codegen_ssa/mir/constant.rs index 3f8dc420cf402..eaa1dd186a536 100644 --- a/src/librustc_codegen_ssa/mir/constant.rs +++ b/src/librustc_codegen_ssa/mir/constant.rs @@ -13,7 +13,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { pub fn eval_mir_constant( &mut self, constant: &mir::Constant<'tcx>, - ) -> Result, ErrorHandled> { + ) -> Result<&'tcx ty::Const<'tcx>, ErrorHandled> { match constant.literal.val { mir::interpret::ConstValue::Unevaluated(def_id, ref substs) => { let substs = self.monomorphize(substs); @@ -26,7 +26,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }; self.cx.tcx().const_eval(ty::ParamEnv::reveal_all().and(cid)) }, - _ => Ok(*self.monomorphize(&constant.literal)), + _ => Ok(self.monomorphize(&constant.literal)), } } @@ -36,7 +36,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx: &Bx, span: Span, ty: Ty<'tcx>, - constant: Result, ErrorHandled>, + constant: Result<&'tcx ty::Const<'tcx>, ErrorHandled>, ) -> (Bx::Value, Ty<'tcx>) { constant .map(|c| { diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs index 3db05b7214d65..75f0c6a6c53bf 100644 --- a/src/librustc_codegen_ssa/mir/operand.rs +++ b/src/librustc_codegen_ssa/mir/operand.rs @@ -67,7 +67,7 @@ impl<'a, 'tcx: 'a, V: CodegenObject> OperandRef<'tcx, V> { pub fn from_const>( bx: &mut Bx, - val: ty::Const<'tcx> + val: &'tcx ty::Const<'tcx> ) -> Result { let layout = bx.layout_of(val.ty); diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index 58ca35abcb123..8c2ef082c339f 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -737,12 +737,12 @@ enum TestKind<'tcx> { SwitchInt { switch_ty: Ty<'tcx>, options: Vec, - indices: FxHashMap, usize>, + indices: FxHashMap<&'tcx ty::Const<'tcx>, usize>, }, // test for equality Eq { - value: ty::Const<'tcx>, + value: &'tcx ty::Const<'tcx>, ty: Ty<'tcx>, }, diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs index a5834b02ffc82..0995a2f7fdf49 100644 --- a/src/librustc_mir/build/matches/test.rs +++ b/src/librustc_mir/build/matches/test.rs @@ -98,7 +98,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { candidate: &Candidate<'pat, 'tcx>, switch_ty: Ty<'tcx>, options: &mut Vec, - indices: &mut FxHashMap, usize>) + indices: &mut FxHashMap<&'tcx ty::Const<'tcx>, usize>) -> bool { let match_pair = match candidate.match_pairs.iter().find(|mp| mp.place == *test_place) { @@ -305,7 +305,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } let eq_def_id = self.hir.tcx().lang_items().eq_trait().unwrap(); let (mty, method) = self.hir.trait_method(eq_def_id, "eq", ty, &[ty.into()]); - let method = self.hir.tcx().mk_const(method); let re_erased = self.hir.tcx().lifetimes.re_erased; // take the argument by reference @@ -371,8 +370,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { TestKind::Range(PatternRange { ref lo, ref hi, ty, ref end }) => { // Test `val` by computing `lo <= val && val <= hi`, using primitive comparisons. - let lo = self.literal_operand(test.span, ty.clone(), lo.clone()); - let hi = self.literal_operand(test.span, ty.clone(), hi.clone()); + let lo = self.literal_operand(test.span, ty, lo); + let hi = self.literal_operand(test.span, ty, hi); let val = Operand::Copy(place.clone()); let fail = self.cfg.start_new_block(); @@ -724,7 +723,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { fn const_range_contains( &self, range: PatternRange<'tcx>, - value: ty::Const<'tcx>, + value: &'tcx ty::Const<'tcx>, ) -> Option { use std::cmp::Ordering::*; @@ -744,7 +743,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { fn values_not_contained_in_range( &self, range: PatternRange<'tcx>, - indices: &FxHashMap, usize>, + indices: &FxHashMap<&'tcx ty::Const<'tcx>, usize>, ) -> Option { for &val in indices.keys() { if self.const_range_contains(range, val)? { diff --git a/src/librustc_mir/build/misc.rs b/src/librustc_mir/build/misc.rs index d71a13dec5a2f..daf59d7a1353c 100644 --- a/src/librustc_mir/build/misc.rs +++ b/src/librustc_mir/build/misc.rs @@ -27,13 +27,13 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { pub fn literal_operand(&mut self, span: Span, ty: Ty<'tcx>, - literal: ty::Const<'tcx>) + literal: &'tcx ty::Const<'tcx>) -> Operand<'tcx> { let constant = box Constant { span, ty, user_ty: None, - literal: self.hir.tcx().mk_const(literal), + literal, }; Operand::Constant(constant) } diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 866b6492d10bc..2bfc10f8e8c4e 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -65,7 +65,7 @@ pub(crate) fn eval_promoted<'a, 'mir, 'tcx>( fn mplace_to_const<'tcx>( ecx: &CompileTimeEvalContext<'_, '_, 'tcx>, mplace: MPlaceTy<'tcx>, -) -> ty::Const<'tcx> { +) -> &'tcx ty::Const<'tcx> { let MemPlace { ptr, align, meta } = *mplace; // extract alloc-offset pair assert!(meta.is_none()); @@ -79,13 +79,13 @@ fn mplace_to_const<'tcx>( // interned this? I thought that is the entire point of that `FinishStatic` stuff? let alloc = ecx.tcx.intern_const_alloc(alloc); let val = ConstValue::ByRef(ptr, alloc); - ty::Const { val, ty: mplace.layout.ty } + ecx.tcx.mk_const(ty::Const { val, ty: mplace.layout.ty }) } fn op_to_const<'tcx>( ecx: &CompileTimeEvalContext<'_, '_, 'tcx>, op: OpTy<'tcx>, -) -> ty::Const<'tcx> { +) -> &'tcx ty::Const<'tcx> { // We do not normalize just any data. Only non-union scalars and slices. let normalize = match op.layout.abi { layout::Abi::Scalar(..) => op.layout.ty.ty_adt_def().map_or(true, |adt| !adt.is_union()), @@ -104,7 +104,7 @@ fn op_to_const<'tcx>( Err(Immediate::ScalarPair(a, b)) => ConstValue::Slice(a.not_undef().unwrap(), b.to_usize(ecx).unwrap()), }; - ty::Const { val, ty: op.layout.ty } + ecx.tcx.mk_const(ty::Const { val, ty: op.layout.ty }) } // Returns a pointer to where the result lives @@ -450,8 +450,8 @@ pub fn const_field<'a, 'tcx>( param_env: ty::ParamEnv<'tcx>, variant: Option, field: mir::Field, - value: ty::Const<'tcx>, -) -> ty::Const<'tcx> { + value: &'tcx ty::Const<'tcx>, +) -> &'tcx ty::Const<'tcx> { trace!("const_field: {:?}, {:?}", field, value); let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env); // get the operand again @@ -473,7 +473,7 @@ pub fn const_field<'a, 'tcx>( pub fn const_variant_index<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, param_env: ty::ParamEnv<'tcx>, - val: ty::Const<'tcx>, + val: &'tcx ty::Const<'tcx>, ) -> VariantIdx { trace!("const_variant_index: {:?}", val); let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env); diff --git a/src/librustc_mir/hair/constant.rs b/src/librustc_mir/hair/constant.rs index caadc6055b5c6..5ed16abb9a672 100644 --- a/src/librustc_mir/hair/constant.rs +++ b/src/librustc_mir/hair/constant.rs @@ -14,7 +14,7 @@ crate fn lit_to_const<'a, 'gcx, 'tcx>( tcx: TyCtxt<'a, 'gcx, 'tcx>, ty: Ty<'tcx>, neg: bool, -) -> Result, LitToConstError> { +) -> Result<&'tcx ty::Const<'tcx>, LitToConstError> { use syntax::ast::*; let trunc = |n| { @@ -39,10 +39,10 @@ crate fn lit_to_const<'a, 'gcx, 'tcx>( LitKind::Err(ref s) => { let s = s.as_str(); let id = tcx.allocate_bytes(s.as_bytes()); - return Ok(ty::Const { + return Ok(tcx.mk_const(ty::Const { val: ConstValue::new_slice(Scalar::Ptr(id.into()), s.len() as u64), ty: tcx.types.err, - }); + })); }, LitKind::ByteStr(ref data) => { let id = tcx.allocate_bytes(data); @@ -71,7 +71,7 @@ crate fn lit_to_const<'a, 'gcx, 'tcx>( LitKind::Bool(b) => ConstValue::Scalar(Scalar::from_bool(b)), LitKind::Char(c) => ConstValue::Scalar(Scalar::from_char(c)), }; - Ok(ty::Const { val: lit, ty }) + Ok(tcx.mk_const(ty::Const { val: lit, ty })) } fn parse_float<'tcx>( diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index d623f149988c7..ca457b0ac7c72 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -329,9 +329,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } hir::ExprKind::Lit(ref lit) => ExprKind::Literal { - literal: cx.tcx.mk_const( - cx.const_eval_literal(&lit.node, expr_ty, lit.span, false) - ), + literal: cx.const_eval_literal(&lit.node, expr_ty, lit.span, false), user_ty: None, }, @@ -429,9 +427,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } else { if let hir::ExprKind::Lit(ref lit) = arg.node { ExprKind::Literal { - literal: cx.tcx.mk_const( - cx.const_eval_literal(&lit.node, expr_ty, lit.span, true) - ), + literal: cx.const_eval_literal(&lit.node, expr_ty, lit.span, true), user_ty: None, } } else { @@ -680,7 +676,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, ty: var_ty, span: expr.span, kind: ExprKind::Literal { - literal: cx.tcx.mk_const(literal), + literal, user_ty: None }, }.to_ref(); @@ -694,10 +690,10 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, // in case we are offsetting from a computed discriminant // and not the beginning of discriminants (which is always `0`) let substs = InternalSubsts::identity_for_item(cx.tcx(), did); - let lhs = mk_const(ty::Const { + let lhs = mk_const(cx.tcx().mk_const(ty::Const { val: ConstValue::Unevaluated(did, substs), ty: var_ty, - }); + })); let bin = ExprKind::Binary { op: BinOp::Add, lhs, @@ -837,9 +833,7 @@ fn method_callee<'a, 'gcx, 'tcx>( ty, span, kind: ExprKind::Literal { - literal: cx.tcx().mk_const( - ty::Const::zero_sized(ty) - ), + literal: ty::Const::zero_sized(cx.tcx(), ty), user_ty, }, } @@ -902,9 +896,10 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, let user_ty = user_substs_applied_to_res(cx, expr.hir_id, res); debug!("convert_path_expr: user_ty={:?}", user_ty); ExprKind::Literal { - literal: cx.tcx.mk_const(ty::Const::zero_sized( + literal: ty::Const::zero_sized( + cx.tcx, cx.tables().node_type(expr.hir_id), - )), + ), user_ty, } } diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index e8070b21bb8c7..c993a02a6decc 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -106,7 +106,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { } pub fn usize_literal(&mut self, value: u64) -> &'tcx ty::Const<'tcx> { - self.tcx.mk_const(ty::Const::from_usize(self.tcx, value)) + ty::Const::from_usize(self.tcx, value) } pub fn bool_ty(&mut self) -> Ty<'tcx> { @@ -118,11 +118,11 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { } pub fn true_literal(&mut self) -> &'tcx ty::Const<'tcx> { - self.tcx.mk_const(ty::Const::from_bool(self.tcx, true)) + ty::Const::from_bool(self.tcx, true) } pub fn false_literal(&mut self) -> &'tcx ty::Const<'tcx> { - self.tcx.mk_const(ty::Const::from_bool(self.tcx, false)) + ty::Const::from_bool(self.tcx, false) } pub fn const_eval_literal( @@ -131,7 +131,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { ty: Ty<'tcx>, sp: Span, neg: bool, - ) -> ty::Const<'tcx> { + ) -> &'tcx ty::Const<'tcx> { trace!("const_eval_literal: {:#?}, {:?}, {:?}, {:?}", lit, ty, sp, neg); match lit_to_const(lit, self.tcx, ty, neg) { @@ -166,14 +166,14 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { method_name: &str, self_ty: Ty<'tcx>, params: &[Kind<'tcx>]) - -> (Ty<'tcx>, ty::Const<'tcx>) { + -> (Ty<'tcx>, &'tcx ty::Const<'tcx>) { let method_name = Symbol::intern(method_name); let substs = self.tcx.mk_substs_trait(self_ty, params); for item in self.tcx.associated_items(trait_def_id) { if item.kind == ty::AssociatedKind::Method && item.ident.name == method_name { let method_ty = self.tcx.type_of(item.def_id); let method_ty = method_ty.subst(self.tcx, substs); - return (method_ty, ty::Const::zero_sized(method_ty)); + return (method_ty, ty::Const::zero_sized(self.tcx, method_ty)); } } diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index fd4416fc2b763..83e17514c08f8 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -255,10 +255,10 @@ impl<'a, 'tcx> PatternFolder<'tcx> for LiteralExpander<'a, 'tcx> { subpattern: Pattern { ty: rty, span: pat.span, - kind: box PatternKind::Constant { value: Const { - val: self.fold_const_value_deref(val, rty, crty), + kind: box PatternKind::Constant { value: self.tcx.mk_const(Const { + val: self.fold_const_value_deref(*val, rty, crty), ty: rty, - } }, + }) }, } } } @@ -423,7 +423,7 @@ enum Constructor<'tcx> { /// Enum variants. Variant(DefId), /// Literal values. - ConstantValue(ty::Const<'tcx>), + ConstantValue(&'tcx ty::Const<'tcx>), /// Ranges of literal values (`2...5` and `2..5`). ConstantRange(u128, u128, Ty<'tcx>, RangeEnd), /// Array patterns of length n. @@ -1424,7 +1424,7 @@ fn constructor_sub_pattern_tys<'a, 'tcx: 'a>(cx: &MatchCheckCtxt<'a, 'tcx>, fn slice_pat_covered_by_const<'tcx>( tcx: TyCtxt<'_, 'tcx, '_>, _span: Span, - const_val: ty::Const<'tcx>, + const_val: &'tcx ty::Const<'tcx>, prefix: &[Pattern<'tcx>], slice: &Option>, suffix: &[Pattern<'tcx>] @@ -1824,7 +1824,7 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>( &cx.tcx, ptr, layout.size, ).ok()?; let scalar = scalar.not_undef().ok()?; - let value = ty::Const::from_scalar(scalar, ty); + let value = ty::Const::from_scalar(cx.tcx, scalar, ty); let pattern = Pattern { ty, span: pat.span, diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index a3e43d6481926..4cc42e3ee0e62 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -152,7 +152,7 @@ pub enum PatternKind<'tcx> { }, Constant { - value: ty::Const<'tcx>, + value: &'tcx ty::Const<'tcx>, }, Range(PatternRange<'tcx>), @@ -176,8 +176,8 @@ pub enum PatternKind<'tcx> { #[derive(Copy, Clone, Debug, PartialEq)] pub struct PatternRange<'tcx> { - pub lo: ty::Const<'tcx>, - pub hi: ty::Const<'tcx>, + pub lo: &'tcx ty::Const<'tcx>, + pub hi: &'tcx ty::Const<'tcx>, pub ty: Ty<'tcx>, pub end: RangeEnd, } @@ -291,15 +291,15 @@ impl<'tcx> fmt::Display for Pattern<'tcx> { write!(f, "{}", subpattern) } PatternKind::Constant { value } => { - write!(f, "{}", &value) + write!(f, "{}", value) } PatternKind::Range(PatternRange { lo, hi, ty: _, end }) => { - write!(f, "{}", &lo)?; + write!(f, "{}", lo)?; match end { RangeEnd::Included => write!(f, "..=")?, RangeEnd::Excluded => write!(f, "..")?, } - write!(f, "{}", &hi) + write!(f, "{}", hi) } PatternKind::Slice { ref prefix, ref slice, ref suffix } | PatternKind::Array { ref prefix, ref slice, ref suffix } => { @@ -942,7 +942,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { fn const_to_pat( &self, instance: ty::Instance<'tcx>, - cv: ty::Const<'tcx>, + cv: &'tcx ty::Const<'tcx>, id: hir::HirId, span: Span, ) -> Pattern<'tcx> { @@ -1205,7 +1205,7 @@ impl<'tcx> PatternFoldable<'tcx> for PatternKind<'tcx> { PatternKind::Constant { value } => PatternKind::Constant { - value: value.fold_with(folder) + value, }, PatternKind::Range(PatternRange { lo, @@ -1213,8 +1213,8 @@ impl<'tcx> PatternFoldable<'tcx> for PatternKind<'tcx> { ty, end, }) => PatternKind::Range(PatternRange { - lo: lo.fold_with(folder), - hi: hi.fold_with(folder), + lo, + hi, ty: ty.fold_with(folder), end, }), @@ -1242,8 +1242,8 @@ impl<'tcx> PatternFoldable<'tcx> for PatternKind<'tcx> { pub fn compare_const_vals<'a, 'gcx, 'tcx>( tcx: TyCtxt<'a, 'gcx, 'tcx>, - a: ty::Const<'tcx>, - b: ty::Const<'tcx>, + a: &'tcx ty::Const<'tcx>, + b: &'tcx ty::Const<'tcx>, ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, ) -> Option { trace!("compare_const_vals: {:?}, {:?}", a, b); diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 9c2b491925f47..9481dd3cb8f8f 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -500,7 +500,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> Move(ref place) => self.eval_place_to_op(place, layout)?, - Constant(ref constant) => self.eval_const_to_op(*constant.literal, layout)?, + Constant(ref constant) => self.eval_const_to_op(constant.literal, layout)?, }; trace!("{:?}: {:?}", mir_op, *op); Ok(op) @@ -520,7 +520,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> // in patterns via the `const_eval` module crate fn eval_const_to_op( &self, - val: ty::Const<'tcx>, + val: &'tcx ty::Const<'tcx>, layout: Option>, ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> { let op = match val.val { diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 91cf0fbb9b44f..e0d6784789e2d 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -609,7 +609,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { fn visit_const(&mut self, constant: &&'tcx ty::Const<'tcx>, location: Location) { debug!("visiting const {:?} @ {:?}", *constant, location); - collect_const(self.tcx, **constant, self.param_substs, self.output); + collect_const(self.tcx, *constant, self.param_substs, self.output); self.super_const(constant); } @@ -1248,7 +1248,7 @@ fn def_id_to_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn collect_const<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, - constant: ty::Const<'tcx>, + constant: &'tcx ty::Const<'tcx>, param_substs: SubstsRef<'tcx>, output: &mut Vec>, ) { diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index b9224d973fe7b..8be660ae17ae9 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -458,9 +458,7 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> { span: self.span, ty: func_ty, user_ty: None, - literal: tcx.mk_const( - ty::Const::zero_sized(func_ty), - ), + literal: ty::Const::zero_sized(tcx, func_ty), }); let ref_loc = self.make_place( @@ -520,9 +518,7 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> { span: self.span, ty: self.tcx.types.usize, user_ty: None, - literal: self.tcx.mk_const( - ty::Const::from_usize(self.tcx, value), - ), + literal: ty::Const::from_usize(self.tcx, value), } } @@ -762,9 +758,7 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, span, ty, user_ty: None, - literal: tcx.mk_const( - ty::Const::zero_sized(ty) - ), + literal: ty::Const::zero_sized(tcx, ty), }), vec![rcvr]) } diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 8f3dd72c4f245..05518ca48d30e 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -282,7 +282,7 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> { c: &Constant<'tcx>, ) -> Option> { self.ecx.tcx.span = c.span; - match self.ecx.eval_const_to_op(*c.literal, None) { + match self.ecx.eval_const_to_op(c.literal, None) { Ok(op) => { Some(op) }, diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs index 023a61588c42e..6320cb4424814 100644 --- a/src/librustc_mir/transform/elaborate_drops.rs +++ b/src/librustc_mir/transform/elaborate_drops.rs @@ -533,9 +533,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { span, ty: self.tcx.types.bool, user_ty: None, - literal: self.tcx.mk_const( - ty::Const::from_bool(self.tcx, val), - ), + literal: ty::Const::from_bool(self.tcx, val), }))) } diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 780b3c9686b6a..ab2f2933a969e 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -757,9 +757,7 @@ fn insert_panic_block<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, span: mir.span, ty: tcx.types.bool, user_ty: None, - literal: tcx.mk_const( - ty::Const::from_bool(tcx, false), - ), + literal: ty::Const::from_bool(tcx, false), }), expected: true, msg: message, diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index 98ca7c32675c8..ac5ebc5e2512a 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -975,9 +975,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> span: self.source_info.span, ty: self.tcx().types.usize, user_ty: None, - literal: self.tcx().mk_const( - ty::Const::from_usize(self.tcx(), val.into()) - ), + literal: ty::Const::from_usize(self.tcx(), val.into()), }) } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 655bf5722ae5a..b5bb62a0f460c 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4441,7 +4441,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if element_ty.references_error() { tcx.types.err } else if let Ok(count) = count { - tcx.mk_ty(ty::Array(t, tcx.mk_const(count))) + tcx.mk_ty(ty::Array(t, count)) } else { tcx.types.err } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index f344c529c59e4..fb0caa55ffbb4 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2956,7 +2956,7 @@ impl<'tcx> Clean for Ty<'tcx> { ty::Str => Primitive(PrimitiveType::Str), ty::Slice(ty) => Slice(box ty.clean(cx)), ty::Array(ty, n) => { - let mut n = *cx.tcx.lift(&n).expect("array lift failed"); + let mut n = cx.tcx.lift(&n).expect("array lift failed"); if let ConstValue::Unevaluated(def_id, substs) = n.val { let param_env = cx.tcx.param_env(def_id); let cid = GlobalId { @@ -4126,7 +4126,7 @@ fn name_from_pat(p: &hir::Pat) -> String { } } -fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String { +fn print_const(cx: &DocContext<'_>, n: &ty::Const<'_>) -> String { match n.val { ConstValue::Unevaluated(def_id, _) => { if let Some(hir_id) = cx.tcx.hir().as_local_hir_id(def_id) { @@ -4141,6 +4141,10 @@ fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String { if s.ends_with("usize") { let n = s.len() - "usize".len(); s.truncate(n); + if s.ends_with(": ") { + let n = s.len() - ": ".len(); + s.truncate(n); + } } s }, From 264c149c8945b714a2922d412dde07b7651a5ea1 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Thu, 11 Apr 2019 11:11:11 +0200 Subject: [PATCH 08/27] Add test showing how byte slices are printed in MIR --- src/test/mir-opt/byte_slice.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 src/test/mir-opt/byte_slice.rs diff --git a/src/test/mir-opt/byte_slice.rs b/src/test/mir-opt/byte_slice.rs new file mode 100644 index 0000000000000..ae5d7c4895f72 --- /dev/null +++ b/src/test/mir-opt/byte_slice.rs @@ -0,0 +1,15 @@ +// compile-flags: -Z mir-opt-level=0 + +fn main() { + let x = b"foo"; + let y = [5u8, b'x']; +} + +// END RUST SOURCE +// START rustc.main.EraseRegions.after.mir +// ... +// _1 = const Scalar(Ptr(Pointer { alloc_id: AllocId(0), offset: Size { raw: 0 }, tag: () })) : &[u8; 3]; +// ... +// _2 = [const 5u8, const 120u8]; +// ... +// END rustc.main.EraseRegions.after.mir From af6ac1fa14b8a753261c19f2afbc62cabdd894d2 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Thu, 11 Apr 2019 11:12:47 +0200 Subject: [PATCH 09/27] Refactor string constant printing to prep for byte string printing --- src/librustc/ty/print/pretty.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 7b363ad6ac490..817205af1b341 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -1570,18 +1570,18 @@ define_print_and_forward_display! { ConstValue::Slice(place, len), ty::Ref(_, &ty::TyS { sty: ty::Str, .. }, _), ) => { - let s = match (place, len) { + match (place, len) { (_, 0) => "", (Scalar::Ptr(ptr), len) => { let alloc = cx.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)]; - ::std::str::from_utf8(slice).expect("non utf8 str from miri") + let s = ::std::str::from_utf8(slice).expect("non utf8 str from miri"); + p!(write("{:?}", s)) }, _ => bug!("invalid slice: {:#?}", self), }; - p!(write("{:?}", s)) }, _ => p!(write("{:?} : ", self.val), print(self.ty)), } From fa17654f7966109d87a5d1741acb7a60732de030 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Thu, 11 Apr 2019 15:06:42 +0200 Subject: [PATCH 10/27] Make `ConstValue::Slice` solely take `[u8]` and `str` --- src/librustc/infer/freshen.rs | 2 +- src/librustc/mir/interpret/value.rs | 26 ++-- src/librustc/ty/print/pretty.rs | 28 ++-- src/librustc/ty/structural_impls.rs | 4 +- src/librustc/ty/sty.rs | 2 +- src/librustc_codegen_ssa/mir/operand.rs | 12 +- src/librustc_mir/const_eval.rs | 32 ++++- src/librustc_mir/hair/constant.rs | 10 +- src/librustc_mir/hair/pattern/_match.rs | 123 +++++++----------- src/librustc_mir/hair/pattern/mod.rs | 39 +++--- src/librustc_mir/interpret/operand.rs | 13 +- src/librustc_mir/monomorphize/collector.rs | 4 +- src/test/ui/pattern/slice-pattern-const-2.rs | 4 +- .../ui/pattern/slice-pattern-const-2.stderr | 20 +-- 14 files changed, 157 insertions(+), 162 deletions(-) diff --git a/src/librustc/infer/freshen.rs b/src/librustc/infer/freshen.rs index 679635bef13e5..8f52ef7a3f3a4 100644 --- a/src/librustc/infer/freshen.rs +++ b/src/librustc/infer/freshen.rs @@ -260,7 +260,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> { ConstValue::Param(_) | ConstValue::Scalar(_) | - ConstValue::Slice(..) | + ConstValue::Slice { .. } | ConstValue::ByRef(..) | ConstValue::Unevaluated(..) => {} } diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs index 6b6f7f7a30740..72545f23f8e2b 100644 --- a/src/librustc/mir/interpret/value.rs +++ b/src/librustc/mir/interpret/value.rs @@ -35,14 +35,12 @@ pub enum ConstValue<'tcx> { /// Not using the enum `Value` to encode that this must not be `Undef`. Scalar(Scalar), - /// Used only for slices and strings (`&[T]`, `&str`, `*const [T]`, `*mut str`, `Box`, - /// etc.). - /// - /// Empty slices don't necessarily have an address backed by an `AllocId`, thus we also need to - /// enable integer pointers. The `Scalar` type covers exactly those two cases. While we could - /// create dummy-`AllocId`s, the additional code effort for the conversions doesn't seem worth - /// it. - Slice(Scalar, u64), + /// Used only for `&[u8]` and `&str` + Slice { + data: &'tcx Allocation, + start: usize, + end: usize, + }, /// An allocation together with a pointer into the allocation. /// Invariant: the pointer's `AllocId` resolves to the allocation. @@ -54,7 +52,7 @@ pub enum ConstValue<'tcx> { } #[cfg(target_arch = "x86_64")] -static_assert_size!(ConstValue<'_>, 40); +static_assert_size!(ConstValue<'_>, 32); impl<'tcx> ConstValue<'tcx> { #[inline] @@ -65,7 +63,7 @@ impl<'tcx> ConstValue<'tcx> { ConstValue::Placeholder(_) | ConstValue::ByRef(..) | ConstValue::Unevaluated(..) | - ConstValue::Slice(..) => None, + ConstValue::Slice { .. } => None, ConstValue::Scalar(val) => Some(val), } } @@ -79,14 +77,6 @@ impl<'tcx> ConstValue<'tcx> { pub fn try_to_ptr(&self) -> Option { self.try_to_scalar()?.to_ptr().ok() } - - #[inline] - pub fn new_slice( - val: Scalar, - len: u64, - ) -> Self { - ConstValue::Slice(val, len) - } } /// A `Scalar` represents an immediate, primitive value existing outside of a diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 817205af1b341..793d3d8ec6df3 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -1567,21 +1567,27 @@ define_print_and_forward_display! { => p!(write("{:?}", ::std::char::from_u32(bits as u32).unwrap())), (_, ty::FnDef(did, _)) => p!(write("{}", cx.tcx().def_path_str(*did))), ( - ConstValue::Slice(place, len), - ty::Ref(_, &ty::TyS { sty: ty::Str, .. }, _), + ConstValue::Slice { data, start, end }, + ty::Ref(_, slice_ty, _), ) => { - match (place, len) { - (_, 0) => "", - (Scalar::Ptr(ptr), len) => { - let alloc = cx.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"); + let slice = &data.bytes[start..end]; + match slice_ty.sty { + ty::Str => { + let s = ::std::str::from_utf8(slice) + .expect("non utf8 str from miri"); p!(write("{:?}", s)) }, + ty::Slice(elem) if elem == cx.tcx().types.u8 => { + p!(write("b\"")); + for &c in slice { + for e in std::ascii::escape_default(c) { + p!(write("{}", e)); + } + } + p!(write("\"")); + }, _ => bug!("invalid slice: {:#?}", self), - }; + } }, _ => p!(write("{:?} : ", self.val), print(self.ty)), } diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 86883a14f687c..0daa567052d56 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -1345,7 +1345,7 @@ impl<'tcx> TypeFoldable<'tcx> for ConstValue<'tcx> { ConstValue::Param(p) => ConstValue::Param(p.fold_with(folder)), ConstValue::Placeholder(p) => ConstValue::Placeholder(p), ConstValue::Scalar(a) => ConstValue::Scalar(a), - ConstValue::Slice(a, b) => ConstValue::Slice(a, b), + ConstValue::Slice { data, start, end } => ConstValue::Slice { data, start, end }, ConstValue::Unevaluated(did, substs) => ConstValue::Unevaluated(did, substs.fold_with(folder)), } @@ -1358,7 +1358,7 @@ impl<'tcx> TypeFoldable<'tcx> for ConstValue<'tcx> { ConstValue::Param(p) => p.visit_with(visitor), ConstValue::Placeholder(_) => false, ConstValue::Scalar(_) => false, - ConstValue::Slice(..) => false, + ConstValue::Slice { .. } => false, ConstValue::Unevaluated(_, substs) => substs.visit_with(visitor), } } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index b2ac40f845a75..a2b2fc7a4451a 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -2207,7 +2207,7 @@ pub struct Const<'tcx> { } #[cfg(target_arch = "x86_64")] -static_assert_size!(Const<'_>, 48); +static_assert_size!(Const<'_>, 40); impl<'tcx> Const<'tcx> { #[inline] diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs index 75f0c6a6c53bf..ec471a1323eab 100644 --- a/src/librustc_codegen_ssa/mir/operand.rs +++ b/src/librustc_codegen_ssa/mir/operand.rs @@ -1,7 +1,7 @@ -use rustc::mir::interpret::{ConstValue, ErrorHandled}; +use rustc::mir::interpret::{ConstValue, ErrorHandled, Pointer, Scalar}; use rustc::mir; use rustc::ty; -use rustc::ty::layout::{self, Align, LayoutOf, TyLayout}; +use rustc::ty::layout::{self, Align, LayoutOf, TyLayout, Size}; use crate::base; use crate::MemFlags; @@ -92,17 +92,21 @@ impl<'a, 'tcx: 'a, V: CodegenObject> OperandRef<'tcx, V> { ); OperandValue::Immediate(llval) }, - ConstValue::Slice(a, b) => { + ConstValue::Slice { data, start, end } => { let a_scalar = match layout.abi { layout::Abi::ScalarPair(ref a, _) => a, _ => bug!("from_const: invalid ScalarPair layout: {:#?}", layout) }; + let a = Scalar::from(Pointer::new( + bx.tcx().alloc_map.lock().allocate(data), + Size::from_bytes(start as u64), + )).into(); let a_llval = bx.scalar_to_backend( a, a_scalar, bx.scalar_pair_element_backend_type(layout, 0, true), ); - let b_llval = bx.const_usize(b); + let b_llval = bx.const_usize((end - start) as u64); OperandValue::Pair(a_llval, b_llval) }, ConstValue::ByRef(ptr, alloc) => { diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 2bfc10f8e8c4e..776d4c242415a 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -5,6 +5,7 @@ use std::error::Error; use std::borrow::{Borrow, Cow}; use std::hash::Hash; use std::collections::hash_map::Entry; +use std::convert::TryInto; use rustc::hir::def::DefKind; use rustc::hir::def_id::DefId; @@ -89,7 +90,14 @@ fn op_to_const<'tcx>( // We do not normalize just any data. Only non-union scalars and slices. let normalize = match op.layout.abi { layout::Abi::Scalar(..) => op.layout.ty.ty_adt_def().map_or(true, |adt| !adt.is_union()), - layout::Abi::ScalarPair(..) => op.layout.ty.is_slice(), + layout::Abi::ScalarPair(..) => match op.layout.ty.sty { + ty::Ref(_, inner, _) => match inner.sty { + ty::Slice(elem) => elem == ecx.tcx.types.u8, + ty::Str => true, + _ => false, + }, + _ => false, + }, _ => false, }; let normalized_op = if normalize { @@ -101,8 +109,26 @@ fn op_to_const<'tcx>( Ok(mplace) => return mplace_to_const(ecx, mplace), Err(Immediate::Scalar(x)) => ConstValue::Scalar(x.not_undef().unwrap()), - Err(Immediate::ScalarPair(a, b)) => - ConstValue::Slice(a.not_undef().unwrap(), b.to_usize(ecx).unwrap()), + Err(Immediate::ScalarPair(a, b)) => { + let (data, start) = match a.not_undef().unwrap() { + Scalar::Ptr(ptr) => ( + ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id), + ptr.offset.bytes(), + ), + Scalar::Bits { .. } => ( + ecx.tcx.intern_const_alloc(Allocation::from_byte_aligned_bytes(b"", ())), + 0, + ), + }; + let len = b.to_usize(&ecx.tcx.tcx).unwrap(); + let start = start.try_into().unwrap(); + let len: usize = len.try_into().unwrap(); + ConstValue::Slice { + data, + start, + end: start + len, + } + }, }; ecx.tcx.mk_const(ty::Const { val, ty: op.layout.ty }) } diff --git a/src/librustc_mir/hair/constant.rs b/src/librustc_mir/hair/constant.rs index 5ed16abb9a672..d2c86d36238e1 100644 --- a/src/librustc_mir/hair/constant.rs +++ b/src/librustc_mir/hair/constant.rs @@ -33,14 +33,16 @@ crate fn lit_to_const<'a, 'gcx, 'tcx>( let lit = match *lit { LitKind::Str(ref s, _) => { let s = s.as_str(); - let id = tcx.allocate_bytes(s.as_bytes()); - ConstValue::new_slice(Scalar::Ptr(id.into()), s.len() as u64) + let allocation = Allocation::from_byte_aligned_bytes(s.as_bytes(), ()); + let allocation = tcx.intern_const_alloc(allocation); + ConstValue::Slice { data: allocation, start: 0, end: s.len() } }, LitKind::Err(ref s) => { let s = s.as_str(); - let id = tcx.allocate_bytes(s.as_bytes()); + let allocation = Allocation::from_byte_aligned_bytes(s.as_bytes(), ()); + let allocation = tcx.intern_const_alloc(allocation); return Ok(tcx.mk_const(ty::Const { - val: ConstValue::new_slice(Scalar::Ptr(id.into()), s.len() as u64), + val: ConstValue::Slice{ data: allocation, start: 0, end: s.len() }, ty: tcx.types.err, })); }, diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index 83e17514c08f8..29e9c425685e8 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -172,7 +172,7 @@ use rustc::ty::{self, Ty, TyCtxt, TypeFoldable, Const}; use rustc::ty::layout::{Integer, IntegerExt, VariantIdx, Size}; use rustc::mir::Field; -use rustc::mir::interpret::{ConstValue, Scalar, truncate}; +use rustc::mir::interpret::{ConstValue, Scalar, truncate, AllocId, Pointer}; use rustc::util::common::ErrorReported; use syntax::attr::{SignedInt, UnsignedInt}; @@ -186,6 +186,7 @@ use std::fmt; use std::iter::{FromIterator, IntoIterator}; use std::ops::RangeInclusive; use std::u128; +use std::convert::TryInto; pub fn expand_pattern<'a, 'tcx>(cx: &MatchCheckCtxt<'a, 'tcx>, pat: Pattern<'tcx>) -> &'a Pattern<'tcx> @@ -221,16 +222,17 @@ impl<'a, 'tcx> LiteralExpander<'a, 'tcx> { // unsize array to slice if pattern is array but match value or other patterns are slice (ConstValue::Scalar(Scalar::Ptr(p)), ty::Array(t, n), ty::Slice(u)) => { assert_eq!(t, u); - ConstValue::Slice( - Scalar::Ptr(p), - n.val.try_to_scalar() - .unwrap() - .to_usize(&self.tcx) - .unwrap(), - ) + ConstValue::Slice { + data: self.tcx.alloc_map.lock().unwrap_memory(p.alloc_id), + start: p.offset.bytes().try_into().unwrap(), + end: n.unwrap_usize(self.tcx).try_into().unwrap(), + } }, // fat pointers stay the same - (ConstValue::Slice(..), _, _) => val, + | (ConstValue::Slice { .. }, _, _) + | (_, ty::Slice(_), ty::Slice(_)) + | (_, ty::Str, ty::Str) + => val, // FIXME(oli-obk): this is reachable for `const FOO: &&&u32 = &&&42;` being used _ => bug!("cannot deref {:#?}, {} -> {}", val, crty, rty), } @@ -786,9 +788,9 @@ fn max_slice_length<'p, 'a: 'p, 'tcx: 'a, I>( max_fixed_len, n.unwrap_usize(cx.tcx), ), - (ConstValue::Slice(_, n), ty::Slice(_)) => max_fixed_len = cmp::max( + (ConstValue::Slice{ start, end, .. }, ty::Slice(_)) => max_fixed_len = cmp::max( max_fixed_len, - n, + (end - start) as u64, ), _ => {}, } @@ -1431,42 +1433,17 @@ fn slice_pat_covered_by_const<'tcx>( ) -> Result { let data: &[u8] = match (const_val.val, &const_val.ty.sty) { (ConstValue::ByRef(ptr, alloc), ty::Array(t, n)) => { - if *t != tcx.types.u8 { - // FIXME(oli-obk): can't mix const patterns with slice patterns and get - // any sort of exhaustiveness/unreachable check yet - // This solely means that we don't lint about unreachable patterns, even if some - // are definitely unreachable. - return Ok(false); - } + assert_eq!(*t, tcx.types.u8); let n = n.assert_usize(tcx).unwrap(); alloc.get_bytes(&tcx, ptr, Size::from_bytes(n)).unwrap() }, - // a slice fat pointer to a zero length slice - (ConstValue::Slice(Scalar::Bits { .. }, 0), ty::Slice(t)) => { - if *t != tcx.types.u8 { - // FIXME(oli-obk): can't mix const patterns with slice patterns and get - // any sort of exhaustiveness/unreachable check yet - // This solely means that we don't lint about unreachable patterns, even if some - // are definitely unreachable. - return Ok(false); - } - &[] - }, - // - (ConstValue::Slice(Scalar::Ptr(ptr), n), ty::Slice(t)) => { - if *t != tcx.types.u8 { - // FIXME(oli-obk): can't mix const patterns with slice patterns and get - // any sort of exhaustiveness/unreachable check yet - // This solely means that we don't lint about unreachable patterns, even if some - // are definitely unreachable. - return Ok(false); - } - tcx.alloc_map - .lock() - .unwrap_memory(ptr.alloc_id) - .get_bytes(&tcx, ptr, Size::from_bytes(n)) - .unwrap() + (ConstValue::Slice { data, start, end }, ty::Slice(t)) => { + assert_eq!(*t, tcx.types.u8); + let ptr = Pointer::new(AllocId(0), Size::from_bytes(start as u64)); + data.get_bytes(&tcx, ptr, Size::from_bytes((end - start) as u64)).unwrap() }, + // FIXME(oli-obk): create a way to extract fat pointers from ByRef + (_, ty::Slice(_)) => return Ok(false), _ => bug!( "slice_pat_covered_by_const: {:#?}, {:#?}, {:#?}, {:#?}", const_val, prefix, slice, suffix, @@ -1774,11 +1751,12 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>( // necessarily point to memory, they are usually just integers. The only time // they should be pointing to memory is when they are subslices of nonzero // slices - let (opt_ptr, n, ty) = match value.ty.sty { + let (alloc, offset, n, ty) = match value.ty.sty { ty::Array(t, n) => { match value.val { ConstValue::ByRef(ptr, alloc) => ( - Some((ptr, alloc)), + alloc, + ptr.offset, n.unwrap_usize(cx.tcx), t, ), @@ -1790,14 +1768,16 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>( }, ty::Slice(t) => { match value.val { - ConstValue::Slice(ptr, n) => ( - ptr.to_ptr().ok().map(|ptr| ( - ptr, - cx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id), - )), - n, + ConstValue::Slice { data, start, end } => ( + data, + Size::from_bytes(start as u64), + (end - start) as u64, t, ), + ConstValue::ByRef(..) => { + // FIXME(oli-obk): implement `deref` for `ConstValue` + return None; + }, _ => span_bug!( pat.span, "slice pattern constant must be scalar pair but is {:?}", @@ -1814,31 +1794,22 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>( }; if wild_patterns.len() as u64 == n { // convert a constant slice/array pattern to a list of patterns. - match (n, opt_ptr) { - (0, _) => Some(SmallVec::new()), - (_, Some((ptr, alloc))) => { - let layout = cx.tcx.layout_of(cx.param_env.and(ty)).ok()?; - (0..n).map(|i| { - let ptr = ptr.offset(layout.size * i, &cx.tcx).ok()?; - let scalar = alloc.read_scalar( - &cx.tcx, ptr, layout.size, - ).ok()?; - let scalar = scalar.not_undef().ok()?; - let value = ty::Const::from_scalar(cx.tcx, scalar, ty); - let pattern = Pattern { - ty, - span: pat.span, - kind: box PatternKind::Constant { value }, - }; - Some(&*cx.pattern_arena.alloc(pattern)) - }).collect() - }, - (_, None) => span_bug!( - pat.span, - "non zero length slice with const-val {:?}", - value, - ), - } + let layout = cx.tcx.layout_of(cx.param_env.and(ty)).ok()?; + let ptr = Pointer::new(AllocId(0), offset); + (0..n).map(|i| { + let ptr = ptr.offset(layout.size * i, &cx.tcx).ok()?; + let scalar = alloc.read_scalar( + &cx.tcx, ptr, layout.size, + ).ok()?; + let scalar = scalar.not_undef().ok()?; + let value = ty::Const::from_scalar(cx.tcx, scalar, ty); + let pattern = Pattern { + ty, + span: pat.span, + kind: box PatternKind::Constant { value }, + }; + Some(&*cx.pattern_arena.alloc(pattern)) + }).collect() } else { None } diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 4cc42e3ee0e62..1c47f850ddb75 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -12,11 +12,11 @@ use crate::hair::constant::*; use rustc::mir::{Field, BorrowKind, Mutability}; use rustc::mir::{UserTypeProjection}; -use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, sign_extend}; +use rustc::mir::interpret::{GlobalId, ConstValue, sign_extend, AllocId, Pointer}; use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty, UserType, DefIdTree}; use rustc::ty::{CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations}; use rustc::ty::subst::{SubstsRef, Kind}; -use rustc::ty::layout::VariantIdx; +use rustc::ty::layout::{VariantIdx, Size}; use rustc::hir::{self, PatKind, RangeEnd}; use rustc::hir::def::{CtorOf, Res, DefKind, CtorKind}; use rustc::hir::pat_util::EnumerateAndAdjustIterator; @@ -1293,22 +1293,25 @@ pub fn compare_const_vals<'a, 'gcx, 'tcx>( if let ty::Str = ty.value.sty { match (a.val, b.val) { ( - ConstValue::Slice( - Scalar::Ptr(ptr_a), - len_a, - ), - ConstValue::Slice( - Scalar::Ptr(ptr_b), - len_b, - ), - ) if ptr_a.offset.bytes() == 0 && ptr_b.offset.bytes() == 0 => { - if len_a == len_b { - let map = tcx.alloc_map.lock(); - let alloc_a = map.unwrap_memory(ptr_a.alloc_id); - let alloc_b = map.unwrap_memory(ptr_b.alloc_id); - if alloc_a.bytes.len() as u64 == len_a { - return from_bool(alloc_a == alloc_b); - } + ConstValue::Slice { data: alloc_a, start: offset_a, end: end_a }, + ConstValue::Slice { data: alloc_b, start: offset_b, end: end_b }, + ) => { + let len_a = end_a - offset_a; + let len_b = end_b - offset_b; + let a = alloc_a.get_bytes( + &tcx, + // invent a pointer, only the offset is relevant anyway + Pointer::new(AllocId(0), Size::from_bytes(offset_a as u64)), + Size::from_bytes(len_a as u64), + ); + let b = alloc_b.get_bytes( + &tcx, + // invent a pointer, only the offset is relevant anyway + Pointer::new(AllocId(0), Size::from_bytes(offset_b as u64)), + Size::from_bytes(len_b as u64), + ); + if let (Ok(a), Ok(b)) = (a, b) { + return from_bool(a == b); } } _ => (), diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 9481dd3cb8f8f..407622dc2599b 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -533,11 +533,16 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> MemPlace::from_ptr(ptr.with_default_tag(), alloc.align) ) }, - ConstValue::Slice(a, b) => + ConstValue::Slice { data, start, end } => Operand::Immediate(Immediate::ScalarPair( - a.with_default_tag().into(), - Scalar::from_uint(b, self.tcx.data_layout.pointer_size) - .with_default_tag().into(), + Scalar::from(Pointer::new( + self.tcx.alloc_map.lock().allocate(data), + Size::from_bytes(start as u64), + )).with_default_tag().into(), + Scalar::from_uint( + (end - start) as u64, + self.tcx.data_layout.pointer_size, + ).with_default_tag().into(), )), ConstValue::Scalar(x) => Operand::Immediate(Immediate::Scalar(x.with_default_tag().into())), diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index e0d6784789e2d..b90db7646d492 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -1255,10 +1255,10 @@ fn collect_const<'a, 'tcx>( debug!("visiting const {:?}", constant); match constant.val { - ConstValue::Slice(Scalar::Ptr(ptr), _) | ConstValue::Scalar(Scalar::Ptr(ptr)) => collect_miri(tcx, ptr.alloc_id, output), - ConstValue::ByRef(_ptr, alloc) => { + ConstValue::Slice { data: alloc, start: _, end: _ } | + ConstValue::ByRef(_, alloc) => { for &((), id) in alloc.relocations.values() { collect_miri(tcx, id, output); } diff --git a/src/test/ui/pattern/slice-pattern-const-2.rs b/src/test/ui/pattern/slice-pattern-const-2.rs index 6cfef115d08dc..a36c550f530a9 100644 --- a/src/test/ui/pattern/slice-pattern-const-2.rs +++ b/src/test/ui/pattern/slice-pattern-const-2.rs @@ -6,13 +6,13 @@ fn main() { match s { MAGIC_TEST => (), [0x00, 0x00, 0x00, 0x00] => (), - [4, 5, 6, 7] => (), //~ ERROR unreachable pattern + [4, 5, 6, 7] => (), // FIXME(oli-obk): this should warn, but currently does not _ => (), } match s { [0x00, 0x00, 0x00, 0x00] => (), MAGIC_TEST => (), - [4, 5, 6, 7] => (), //~ ERROR unreachable pattern + [4, 5, 6, 7] => (), // FIXME(oli-obk): this should warn, but currently does not _ => (), } match s { diff --git a/src/test/ui/pattern/slice-pattern-const-2.stderr b/src/test/ui/pattern/slice-pattern-const-2.stderr index e2c408a90e4e1..0c7401269dfc7 100644 --- a/src/test/ui/pattern/slice-pattern-const-2.stderr +++ b/src/test/ui/pattern/slice-pattern-const-2.stderr @@ -1,8 +1,8 @@ error: unreachable pattern - --> $DIR/slice-pattern-const-2.rs:9:9 + --> $DIR/slice-pattern-const-2.rs:28:9 | -LL | [4, 5, 6, 7] => (), - | ^^^^^^^^^^^^ +LL | FOO => (), + | ^^^ | note: lint level defined here --> $DIR/slice-pattern-const-2.rs:1:9 @@ -10,17 +10,5 @@ note: lint level defined here LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ -error: unreachable pattern - --> $DIR/slice-pattern-const-2.rs:15:9 - | -LL | [4, 5, 6, 7] => (), - | ^^^^^^^^^^^^ - -error: unreachable pattern - --> $DIR/slice-pattern-const-2.rs:28:9 - | -LL | FOO => (), - | ^^^ - -error: aborting due to 3 previous errors +error: aborting due to previous error From 9b5896ade3ae279a2d91773b3ae0b097657b8b6e Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Thu, 11 Apr 2019 22:04:04 +0200 Subject: [PATCH 11/27] Render const byte slices in MIR --- src/librustc/ty/print/pretty.rs | 54 ++++++++++++++++++++------------- src/test/mir-opt/byte_slice.rs | 2 +- 2 files changed, 34 insertions(+), 22 deletions(-) diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 793d3d8ec6df3..10038603f3013 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -6,6 +6,7 @@ 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::ty::layout::Size; use crate::mir::interpret::{ConstValue, sign_extend, Scalar}; use syntax::ast; use rustc_apfloat::ieee::{Double, Single}; @@ -1537,6 +1538,7 @@ define_print_and_forward_display! { } &'tcx ty::Const<'tcx> { + let u8 = cx.tcx().types.u8; match (self.val, &self.ty.sty) { | (ConstValue::Unevaluated(..), _) | (ConstValue::Infer(..), _) @@ -1566,28 +1568,38 @@ define_print_and_forward_display! { (ConstValue::Scalar(Scalar::Bits { bits, ..}), ty::Char) => p!(write("{:?}", ::std::char::from_u32(bits as u32).unwrap())), (_, ty::FnDef(did, _)) => p!(write("{}", cx.tcx().def_path_str(*did))), - ( - ConstValue::Slice { data, start, end }, - ty::Ref(_, slice_ty, _), - ) => { - let slice = &data.bytes[start..end]; - match slice_ty.sty { - ty::Str => { - let s = ::std::str::from_utf8(slice) - .expect("non utf8 str from miri"); - p!(write("{:?}", s)) - }, - ty::Slice(elem) if elem == cx.tcx().types.u8 => { - p!(write("b\"")); - for &c in slice { - for e in std::ascii::escape_default(c) { - p!(write("{}", e)); - } + (_, ty::Ref(_, ref_ty, _)) => match (self.val, &ref_ty.sty) { + (ConstValue::Scalar(Scalar::Ptr(ptr)), ty::Array(t, n)) if *t == u8 => { + let n = n.unwrap_usize(cx.tcx()); + let slice = cx.tcx() + .alloc_map.lock() + .unwrap_memory(ptr.alloc_id) + .get_bytes(&cx.tcx(), ptr, Size::from_bytes(n)).unwrap(); + p!(write("b\"")); + for &c in slice { + for e in std::ascii::escape_default(c) { + p!(write("{}", e)); } - p!(write("\"")); - }, - _ => bug!("invalid slice: {:#?}", self), - } + } + p!(write("\"")); + }, + (ConstValue::Slice { data, start, end }, ty::Str) => { + let slice = &data.bytes[start..end]; + let s = ::std::str::from_utf8(slice) + .expect("non utf8 str from miri"); + p!(write("{:?}", s)) + }, + (ConstValue::Slice { data, start, end }, ty::Slice(t)) if *t == u8 => { + let slice = &data.bytes[start..end]; + p!(write("b\"")); + for &c in slice { + for e in std::ascii::escape_default(c) { + p!(write("{}", e)); + } + } + p!(write("\"")); + }, + _ => p!(write("{:?} : ", self.val), print(self.ty)), }, _ => p!(write("{:?} : ", self.val), print(self.ty)), } diff --git a/src/test/mir-opt/byte_slice.rs b/src/test/mir-opt/byte_slice.rs index ae5d7c4895f72..23faf7e16a7ed 100644 --- a/src/test/mir-opt/byte_slice.rs +++ b/src/test/mir-opt/byte_slice.rs @@ -8,7 +8,7 @@ fn main() { // END RUST SOURCE // START rustc.main.EraseRegions.after.mir // ... -// _1 = const Scalar(Ptr(Pointer { alloc_id: AllocId(0), offset: Size { raw: 0 }, tag: () })) : &[u8; 3]; +// _1 = const b"102111111"; // ... // _2 = [const 5u8, const 120u8]; // ... From 669bc7788667db2fc113e4ba2ab3bdc2119665f6 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 15 Apr 2019 11:00:55 +0200 Subject: [PATCH 12/27] `u8` is printed as a number, not a character --- src/librustc/ty/print/pretty.rs | 4 ++-- src/test/mir-opt/byte_slice.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 10038603f3013..95b1519023fa6 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -1578,7 +1578,7 @@ define_print_and_forward_display! { p!(write("b\"")); for &c in slice { for e in std::ascii::escape_default(c) { - p!(write("{}", e)); + p!(write("{}", e as char)); } } p!(write("\"")); @@ -1594,7 +1594,7 @@ define_print_and_forward_display! { p!(write("b\"")); for &c in slice { for e in std::ascii::escape_default(c) { - p!(write("{}", e)); + p!(write("{}", e as char)); } } p!(write("\"")); diff --git a/src/test/mir-opt/byte_slice.rs b/src/test/mir-opt/byte_slice.rs index 23faf7e16a7ed..7edfa3e1124db 100644 --- a/src/test/mir-opt/byte_slice.rs +++ b/src/test/mir-opt/byte_slice.rs @@ -8,7 +8,7 @@ fn main() { // END RUST SOURCE // START rustc.main.EraseRegions.after.mir // ... -// _1 = const b"102111111"; +// _1 = const b"foo"; // ... // _2 = [const 5u8, const 120u8]; // ... From db652fcde4bfea48150ec54b315dd104ae0f4b59 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 17 Apr 2019 17:29:38 +0200 Subject: [PATCH 13/27] Render unresolved anon consts like closures --- src/librustc/ty/print/pretty.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 95b1519023fa6..f16208503fe90 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -1,5 +1,5 @@ use crate::hir; -use crate::hir::def::Namespace; +use crate::hir::def::{Namespace, Def}; use crate::hir::map::{DefPathData, DisambiguatedDefPathData}; use crate::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use crate::middle::cstore::{ExternCrate, ExternCrateSource}; @@ -1540,9 +1540,15 @@ define_print_and_forward_display! { &'tcx ty::Const<'tcx> { let u8 = cx.tcx().types.u8; match (self.val, &self.ty.sty) { - | (ConstValue::Unevaluated(..), _) - | (ConstValue::Infer(..), _) - => p!(write("_: "), print(self.ty)), + (ConstValue::Unevaluated(did, substs), _) => { + match cx.tcx().describe_def(did) { + | Some(Def::Static(_, _)) + | Some(Def::Const(_)) + | Some(Def::AssociatedConst(_)) => p!(write("{}", cx.tcx().def_path_str(did))), + _ => p!(write("_")), + } + } + (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")), From 0528954c80631bcf4e816e8254135d1109292f4a Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 17 Apr 2019 17:50:47 +0200 Subject: [PATCH 14/27] Group common printing code during constant pretty printing --- src/librustc/ty/print/pretty.rs | 129 ++++++++++++++++++-------------- 1 file changed, 73 insertions(+), 56 deletions(-) diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index f16208503fe90..6514017a3e74d 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -1539,76 +1539,93 @@ define_print_and_forward_display! { &'tcx ty::Const<'tcx> { let u8 = cx.tcx().types.u8; - match (self.val, &self.ty.sty) { - (ConstValue::Unevaluated(did, substs), _) => { - match cx.tcx().describe_def(did) { - | Some(Def::Static(_, _)) - | Some(Def::Const(_)) - | Some(Def::AssociatedConst(_)) => p!(write("{}", cx.tcx().def_path_str(did))), - _ => p!(write("_")), + if let ty::FnDef(did, _) = self.ty.sty { + p!(write("{}", cx.tcx().def_path_str(did))); + return Ok(cx); + } + if let ConstValue::Unevaluated(did, substs) = self.val { + match cx.tcx().describe_def(did) { + | Some(Def::Static(_, _)) + | Some(Def::Const(_, false)) + | Some(Def::AssociatedConst(_)) => p!(write("{}", cx.tcx().def_path_str(did))), + _ => p!(write("_")), + } + return Ok(cx); + } + if let ConstValue::Infer(..) = self.val { + p!(write("_: "), print(self.ty)); + return Ok(cx); + } + if let ConstValue::Param(ParamConst { name, .. }) = self.val { + p!(write("{}", name)); + return Ok(cx); + } + if let ConstValue::Scalar(Scalar::Bits { bits, .. }) = self.val { + match self.ty.sty { + ty::Bool => { + p!(write("{}", if bits == 0 { "false" } else { "true" })); + return Ok(cx); + }, + ty::Float(ast::FloatTy::F32) => { + p!(write("{}f32", Single::from_bits(bits))); + return Ok(cx); + }, + ty::Float(ast::FloatTy::F64) => { + p!(write("{}f64", Double::from_bits(bits))); + return Ok(cx); + }, + ty::Uint(ui) => { + p!(write("{}{}", bits, ui)); + return Ok(cx); + }, + ty::Int(i) =>{ + let ty = cx.tcx().lift_to_global(&self.ty).unwrap(); + let size = cx.tcx().layout_of(ty::ParamEnv::empty().and(ty)) + .unwrap() + .size; + p!(write("{}{}", sign_extend(bits, size) as i128, i)); + return Ok(cx); + }, + ty::Char => { + p!(write("{:?}", ::std::char::from_u32(bits as u32).unwrap())); + return Ok(cx); } + _ => {}, } - (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 ty = cx.tcx().lift_to_global(&self.ty).unwrap(); - let size = cx.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("{}", cx.tcx().def_path_str(*did))), - (_, ty::Ref(_, ref_ty, _)) => match (self.val, &ref_ty.sty) { + } + if let ty::Ref(_, ref_ty, _) = self.ty.sty { + let byte_str = match (self.val, &ref_ty.sty) { (ConstValue::Scalar(Scalar::Ptr(ptr)), ty::Array(t, n)) if *t == u8 => { let n = n.unwrap_usize(cx.tcx()); - let slice = cx.tcx() + Some(cx.tcx() .alloc_map.lock() .unwrap_memory(ptr.alloc_id) - .get_bytes(&cx.tcx(), ptr, Size::from_bytes(n)).unwrap(); - p!(write("b\"")); - for &c in slice { - for e in std::ascii::escape_default(c) { - p!(write("{}", e as char)); - } - } - p!(write("\"")); + .get_bytes(&cx.tcx(), ptr, Size::from_bytes(n)).unwrap()) + }, + (ConstValue::Slice { data, start, end }, ty::Slice(t)) if *t == u8 => { + Some(&data.bytes[start..end]) }, (ConstValue::Slice { data, start, end }, ty::Str) => { let slice = &data.bytes[start..end]; let s = ::std::str::from_utf8(slice) .expect("non utf8 str from miri"); - p!(write("{:?}", s)) + p!(write("{:?}", s)); + return Ok(cx); }, - (ConstValue::Slice { data, start, end }, ty::Slice(t)) if *t == u8 => { - let slice = &data.bytes[start..end]; - p!(write("b\"")); - for &c in slice { - for e in std::ascii::escape_default(c) { - p!(write("{}", e as char)); - } + _ => None, + }; + if let Some(byte_str) = byte_str { + p!(write("b\"")); + for &c in byte_str { + for e in std::ascii::escape_default(c) { + p!(write("{}", e as char)); } - p!(write("\"")); - }, - _ => p!(write("{:?} : ", self.val), print(self.ty)), - }, - _ => p!(write("{:?} : ", self.val), print(self.ty)), + } + p!(write("\"")); + return Ok(cx); + } } + p!(write("{:?} : ", self.val), print(self.ty)); } ty::ParamTy { From fec79d355234aed1599674262ab5adfbde700fe7 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 17 Apr 2019 18:19:59 +0200 Subject: [PATCH 15/27] Print generic args in function calls in MIR --- src/librustc/ty/print/pretty.rs | 4 ++-- src/test/mir-opt/box_expr.rs | 2 +- src/test/mir-opt/inline-trait-method.rs | 2 +- src/test/mir-opt/inline-trait-method_2.rs | 2 +- src/test/mir-opt/issue-49232.rs | 2 +- src/test/mir-opt/unusual-item-types.rs | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 6514017a3e74d..6a5494e9d9ad9 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -1539,8 +1539,8 @@ define_print_and_forward_display! { &'tcx ty::Const<'tcx> { let u8 = cx.tcx().types.u8; - if let ty::FnDef(did, _) = self.ty.sty { - p!(write("{}", cx.tcx().def_path_str(did))); + if let ty::FnDef(did, substs) = self.ty.sty { + p!(print_value_path(did, substs)); return Ok(cx); } if let ConstValue::Unevaluated(did, substs) = self.val { diff --git a/src/test/mir-opt/box_expr.rs b/src/test/mir-opt/box_expr.rs index ee6adfefe3e36..9f55d84964405 100644 --- a/src/test/mir-opt/box_expr.rs +++ b/src/test/mir-opt/box_expr.rs @@ -52,7 +52,7 @@ impl Drop for S { // StorageDead(_2); // StorageLive(_4); // _4 = move _1; -// _3 = const std::mem::drop(move _4) -> [return: bb5, unwind: bb7]; +// _3 = const std::mem::drop::>(move _4) -> [return: bb5, unwind: bb7]; // } // // bb5: { diff --git a/src/test/mir-opt/inline-trait-method.rs b/src/test/mir-opt/inline-trait-method.rs index 0f79f43ee2df0..a2c5fb920cd30 100644 --- a/src/test/mir-opt/inline-trait-method.rs +++ b/src/test/mir-opt/inline-trait-method.rs @@ -25,7 +25,7 @@ impl X for () { // ... // bb0: { // ... -// _0 = const X::y(move _2) -> bb1; +// _0 = const ::y(move _2) -> bb1; // } // ... // END rustc.test.Inline.after.mir diff --git a/src/test/mir-opt/inline-trait-method_2.rs b/src/test/mir-opt/inline-trait-method_2.rs index 8f9f2535aa5f8..4ad4311113a3a 100644 --- a/src/test/mir-opt/inline-trait-method_2.rs +++ b/src/test/mir-opt/inline-trait-method_2.rs @@ -30,7 +30,7 @@ fn main() { // ... // bb0: { // ... -// _0 = const X::y(move _2) -> bb1; +// _0 = const ::y(move _2) -> bb1; // } // ... // END rustc.test2.Inline.after.mir diff --git a/src/test/mir-opt/issue-49232.rs b/src/test/mir-opt/issue-49232.rs index bf22f00b50552..447f3a07a6a98 100644 --- a/src/test/mir-opt/issue-49232.rs +++ b/src/test/mir-opt/issue-49232.rs @@ -93,7 +93,7 @@ fn main() { // StorageDead(_3); // StorageLive(_6); // _6 = &_2; -// _5 = const std::mem::drop(move _6) -> [return: bb19, unwind: bb4]; +// _5 = const std::mem::drop::<&i32>(move _6) -> [return: bb19, unwind: bb4]; // } // bb19: { // StorageDead(_6); diff --git a/src/test/mir-opt/unusual-item-types.rs b/src/test/mir-opt/unusual-item-types.rs index 606503151c985..93f17d976e6a1 100644 --- a/src/test/mir-opt/unusual-item-types.rs +++ b/src/test/mir-opt/unusual-item-types.rs @@ -68,7 +68,7 @@ fn main() { // } // bb7: { // _2 = &mut (*_1); -// _3 = const std::ops::Drop::drop(move _2) -> [return: bb6, unwind: bb5]; +// _3 = const as std::ops::Drop>::drop(move _2) -> [return: bb6, unwind: bb5]; // } // END rustc.ptr-real_drop_in_place.std__vec__Vec_i32_.AddMovesForPackedDrops.before.mir From 90bb861b2e11ad7a2c6c8694ddbda2794ce4beb0 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 24 Apr 2019 14:10:05 +0200 Subject: [PATCH 16/27] Fix tidy --- src/test/mir-opt/unusual-item-types.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/mir-opt/unusual-item-types.rs b/src/test/mir-opt/unusual-item-types.rs index 93f17d976e6a1..67a55101d829f 100644 --- a/src/test/mir-opt/unusual-item-types.rs +++ b/src/test/mir-opt/unusual-item-types.rs @@ -1,5 +1,6 @@ // Test that we don't ICE when trying to dump MIR for unusual item types and // that we don't create filenames containing `<` and `>` +// ignore-tidy-linelength struct A; From ecee75d114a648885cd490f3620a3e58cee64bf8 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 24 Apr 2019 14:10:31 +0200 Subject: [PATCH 17/27] Use `write_char` to skip the formatting infrastructure --- 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 6a5494e9d9ad9..0f7bc95902d3c 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -1618,7 +1618,7 @@ define_print_and_forward_display! { p!(write("b\"")); for &c in byte_str { for e in std::ascii::escape_default(c) { - p!(write("{}", e as char)); + cx.write_char(e as char)?; } } p!(write("\"")); From b816ec1eb439c6cae2f4f99327b30a126e10540c Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 24 Apr 2019 14:10:52 +0200 Subject: [PATCH 18/27] Print unevaluted constants as `_` or as their source representation --- src/librustc/ty/print/pretty.rs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 0f7bc95902d3c..54f76c98f3ceb 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -1545,10 +1545,19 @@ define_print_and_forward_display! { } if let ConstValue::Unevaluated(did, substs) = self.val { match cx.tcx().describe_def(did) { - | Some(Def::Static(_, _)) - | Some(Def::Const(_, false)) - | Some(Def::AssociatedConst(_)) => p!(write("{}", cx.tcx().def_path_str(did))), - _ => p!(write("_")), + | Some(Def::Static(_)) + | Some(Def::Const(_)) + | Some(Def::AssociatedConst(_)) => p!(print_value_path(did, substs)), + _ => if did.is_local() { + let span = cx.tcx().def_span(did); + if let Ok(snip) = cx.tcx().sess.source_map().span_to_snippet(span) { + p!(write("{}", snip)) + } else { + p!(write("_")) + } + } else { + p!(write("_")) + }, } return Ok(cx); } From 28198bb3bea7c7637738588eedda2191852f7796 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 24 Apr 2019 16:12:53 +0200 Subject: [PATCH 19/27] Update ui tests --- src/test/ui/consts/const_let_refutable.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/consts/const_let_refutable.stderr b/src/test/ui/consts/const_let_refutable.stderr index 2ca76667bd118..cdd696ee7fbff 100644 --- a/src/test/ui/consts/const_let_refutable.stderr +++ b/src/test/ui/consts/const_let_refutable.stderr @@ -4,7 +4,7 @@ error[E0005]: refutable pattern in function argument: `&[]` not covered LL | const fn slice([a, b]: &[i32]) -> i32 { | ^^^^^^ pattern `&[]` not covered -error[E0723]: can only call other `const fn` within a `const fn`, but `const std::ops::Add::add` is not stable as `const fn` +error[E0723]: can only call other `const fn` within a `const fn`, but `const <&i32 as std::ops::Add>::add` is not stable as `const fn` --> $DIR/const_let_refutable.rs:4:5 | LL | a + b From 89b2fb631ae4e5b6923441dea3e5d2fbd56a8478 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Mon, 18 Mar 2019 12:50:57 +0200 Subject: [PATCH 20/27] rustc: integrate ty::Const into ty::print as print_const. --- src/librustc/infer/error_reporting/mod.rs | 8 + src/librustc/lint/context.rs | 10 +- src/librustc/ty/print/mod.rs | 14 ++ src/librustc/ty/print/pretty.rs | 227 +++++++++++---------- src/librustc_codegen_utils/symbol_names.rs | 8 + 5 files changed, 160 insertions(+), 107 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index e4505a240379f..8ec9d42ec5f82 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -462,6 +462,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { type Region = !; type Type = !; type DynExistential = !; + type Const = !; fn tcx<'a>(&'a self) -> TyCtxt<'a, 'gcx, 'tcx> { self.tcx @@ -488,6 +489,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { Err(NonTrivialPath) } + fn print_const( + self, + _ct: &'tcx ty::Const<'tcx>, + ) -> Result { + Err(NonTrivialPath) + } + fn path_crate( self, cnum: CrateNum, diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 7e1e751e85647..b9ce42ac8f290 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -791,6 +791,7 @@ impl<'a, 'tcx> LateContext<'a, 'tcx> { type Region = (); type Type = (); type DynExistential = (); + type Const = (); fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> { self.tcx @@ -807,7 +808,14 @@ impl<'a, 'tcx> LateContext<'a, 'tcx> { fn print_dyn_existential( self, _predicates: &'tcx ty::List>, - ) -> Result { + ) -> Result { + Ok(()) + } + + fn print_const( + self, + _ct: &'tcx ty::Const<'tcx>, + ) -> Result { Ok(()) } diff --git a/src/librustc/ty/print/mod.rs b/src/librustc/ty/print/mod.rs index d5d4f64844463..53d4466cfef68 100644 --- a/src/librustc/ty/print/mod.rs +++ b/src/librustc/ty/print/mod.rs @@ -31,6 +31,7 @@ pub trait Printer<'gcx: 'tcx, 'tcx>: Sized { type Region; type Type; type DynExistential; + type Const; fn tcx(&'a self) -> TyCtxt<'a, 'gcx, 'tcx>; @@ -66,6 +67,11 @@ pub trait Printer<'gcx: 'tcx, 'tcx>: Sized { predicates: &'tcx ty::List>, ) -> Result; + fn print_const( + self, + ct: &'tcx ty::Const<'tcx>, + ) -> Result; + fn path_crate( self, cnum: CrateNum, @@ -325,3 +331,11 @@ impl<'gcx: 'tcx, 'tcx, P: Printer<'gcx, 'tcx>> Print<'gcx, 'tcx, P> cx.print_dyn_existential(self) } } + +impl<'gcx: 'tcx, 'tcx, P: Printer<'gcx, 'tcx>> Print<'gcx, 'tcx, P> for &'tcx ty::Const<'tcx> { + type Output = P::Const; + type Error = P::Error; + fn print(&self, cx: P) -> Result { + cx.print_const(self) + } +} diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 54f76c98f3ceb..7212afc08dfcd 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -173,6 +173,7 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>: Region = Self, Type = Self, DynExistential = Self, + Const = Self, > + fmt::Write { @@ -665,12 +666,10 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>: }, ty::Array(ty, sz) => { p!(write("["), print(ty), write("; ")); - match sz.val { - ConstValue::Unevaluated(..) | - ConstValue::Infer(..) => p!(write("_")), - ConstValue::Param(ParamConst { name, .. }) => - p!(write("{}", name)), - _ => p!(write("{}", sz.unwrap_usize(self.tcx()))), + if let Some(n) = sz.assert_usize(self.tcx()) { + p!(write("{}", n)); + } else { + p!(print(sz)); } p!(write("]")) } @@ -808,6 +807,113 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>: Ok(self) } + + fn pretty_print_const( + mut self, + ct: &'tcx ty::Const<'tcx>, + ) -> Result { + define_scoped_cx!(self); + + let u8 = self.tcx().types.u8; + if let ty::FnDef(did, substs) = ct.ty.sty { + p!(print_value_path(did, substs)); + return Ok(self); + } + if let ConstValue::Unevaluated(did, substs) = ct.val { + match self.tcx().describe_def(did) { + | Some(Def::Static(_)) + | Some(Def::Const(_)) + | Some(Def::AssociatedConst(_)) => p!(print_value_path(did, substs)), + _ => if did.is_local() { + let span = self.tcx().def_span(did); + if let Ok(snip) = self.tcx().sess.source_map().span_to_snippet(span) { + p!(write("{}", snip)) + } else { + p!(write("_")) + } + } else { + p!(write("_")) + }, + } + return Ok(self); + } + if let ConstValue::Infer(..) = ct.val { + p!(write("_: "), print(ct.ty)); + return Ok(self); + } + if let ConstValue::Param(ParamConst { name, .. }) = ct.val { + p!(write("{}", name)); + return Ok(self); + } + if let ConstValue::Scalar(Scalar::Bits { bits, .. }) = ct.val { + match ct.ty.sty { + ty::Bool => { + p!(write("{}", if bits == 0 { "false" } else { "true" })); + return Ok(self); + }, + ty::Float(ast::FloatTy::F32) => { + p!(write("{}f32", Single::from_bits(bits))); + return Ok(self); + }, + ty::Float(ast::FloatTy::F64) => { + p!(write("{}f64", Double::from_bits(bits))); + return Ok(self); + }, + ty::Uint(ui) => { + p!(write("{}{}", bits, ui)); + return Ok(self); + }, + ty::Int(i) =>{ + let ty = self.tcx().lift_to_global(&ct.ty).unwrap(); + let size = self.tcx().layout_of(ty::ParamEnv::empty().and(ty)) + .unwrap() + .size; + p!(write("{}{}", sign_extend(bits, size) as i128, i)); + return Ok(self); + }, + ty::Char => { + p!(write("{:?}", ::std::char::from_u32(bits as u32).unwrap())); + return Ok(self); + } + _ => {}, + } + } + if let ty::Ref(_, ref_ty, _) = ct.ty.sty { + let byte_str = match (ct.val, &ref_ty.sty) { + (ConstValue::Scalar(Scalar::Ptr(ptr)), ty::Array(t, n)) if *t == u8 => { + let n = n.unwrap_usize(self.tcx()); + 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 => { + Some(&data.bytes[start..end]) + }, + (ConstValue::Slice { data, start, end }, ty::Str) => { + let slice = &data.bytes[start..end]; + let s = ::std::str::from_utf8(slice) + .expect("non utf8 str from miri"); + p!(write("{:?}", s)); + return Ok(self); + }, + _ => None, + }; + 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("\"")); + return Ok(self); + } + } + p!(write("{:?} : ", ct.val), print(ct.ty)); + + Ok(self) + } } // HACK(eddyb) boxed to avoid moving around a large struct by-value. @@ -900,6 +1006,7 @@ impl Printer<'gcx, 'tcx> for FmtPrinter<'_, 'gcx, 'tcx, F> { type Region = Self; type Type = Self; type DynExistential = Self; + type Const = Self; fn tcx(&'a self) -> TyCtxt<'a, 'gcx, 'tcx> { self.tcx @@ -975,6 +1082,13 @@ impl Printer<'gcx, 'tcx> for FmtPrinter<'_, 'gcx, 'tcx, F> { self.pretty_print_dyn_existential(predicates) } + fn print_const( + self, + ct: &'tcx ty::Const<'tcx>, + ) -> Result { + self.pretty_print_const(ct) + } + fn path_crate( mut self, cnum: CrateNum, @@ -1448,6 +1562,7 @@ impl fmt::Display for ty::RegionKind { forward_display_to_print! { Ty<'tcx>, &'tcx ty::List>, + &'tcx ty::Const<'tcx>, // HACK(eddyb) these are exhaustive instead of generic, // because `for<'gcx: 'tcx, 'tcx>` isn't possible yet. @@ -1537,106 +1652,6 @@ define_print_and_forward_display! { p!(print_def_path(self.def_id, self.substs)); } - &'tcx ty::Const<'tcx> { - let u8 = cx.tcx().types.u8; - if let ty::FnDef(did, substs) = self.ty.sty { - p!(print_value_path(did, substs)); - return Ok(cx); - } - if let ConstValue::Unevaluated(did, substs) = self.val { - match cx.tcx().describe_def(did) { - | Some(Def::Static(_)) - | Some(Def::Const(_)) - | Some(Def::AssociatedConst(_)) => p!(print_value_path(did, substs)), - _ => if did.is_local() { - let span = cx.tcx().def_span(did); - if let Ok(snip) = cx.tcx().sess.source_map().span_to_snippet(span) { - p!(write("{}", snip)) - } else { - p!(write("_")) - } - } else { - p!(write("_")) - }, - } - return Ok(cx); - } - if let ConstValue::Infer(..) = self.val { - p!(write("_: "), print(self.ty)); - return Ok(cx); - } - if let ConstValue::Param(ParamConst { name, .. }) = self.val { - p!(write("{}", name)); - return Ok(cx); - } - if let ConstValue::Scalar(Scalar::Bits { bits, .. }) = self.val { - match self.ty.sty { - ty::Bool => { - p!(write("{}", if bits == 0 { "false" } else { "true" })); - return Ok(cx); - }, - ty::Float(ast::FloatTy::F32) => { - p!(write("{}f32", Single::from_bits(bits))); - return Ok(cx); - }, - ty::Float(ast::FloatTy::F64) => { - p!(write("{}f64", Double::from_bits(bits))); - return Ok(cx); - }, - ty::Uint(ui) => { - p!(write("{}{}", bits, ui)); - return Ok(cx); - }, - ty::Int(i) =>{ - let ty = cx.tcx().lift_to_global(&self.ty).unwrap(); - let size = cx.tcx().layout_of(ty::ParamEnv::empty().and(ty)) - .unwrap() - .size; - p!(write("{}{}", sign_extend(bits, size) as i128, i)); - return Ok(cx); - }, - ty::Char => { - p!(write("{:?}", ::std::char::from_u32(bits as u32).unwrap())); - return Ok(cx); - } - _ => {}, - } - } - if let ty::Ref(_, ref_ty, _) = self.ty.sty { - let byte_str = match (self.val, &ref_ty.sty) { - (ConstValue::Scalar(Scalar::Ptr(ptr)), ty::Array(t, n)) if *t == u8 => { - let n = n.unwrap_usize(cx.tcx()); - Some(cx.tcx() - .alloc_map.lock() - .unwrap_memory(ptr.alloc_id) - .get_bytes(&cx.tcx(), ptr, Size::from_bytes(n)).unwrap()) - }, - (ConstValue::Slice { data, start, end }, ty::Slice(t)) if *t == u8 => { - Some(&data.bytes[start..end]) - }, - (ConstValue::Slice { data, start, end }, ty::Str) => { - let slice = &data.bytes[start..end]; - let s = ::std::str::from_utf8(slice) - .expect("non utf8 str from miri"); - p!(write("{:?}", s)); - return Ok(cx); - }, - _ => None, - }; - if let Some(byte_str) = byte_str { - p!(write("b\"")); - for &c in byte_str { - for e in std::ascii::escape_default(c) { - cx.write_char(e as char)?; - } - } - p!(write("\"")); - return Ok(cx); - } - } - p!(write("{:?} : ", self.val), print(self.ty)); - } - ty::ParamTy { p!(write("{}", self.name)) } diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index 1a8647ed197b5..f2f9ac8931fee 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -391,6 +391,7 @@ impl Printer<'tcx, 'tcx> for SymbolPrinter<'_, 'tcx> { type Region = Self; type Type = Self; type DynExistential = Self; + type Const = Self; fn tcx(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> { self.tcx @@ -436,6 +437,13 @@ impl Printer<'tcx, 'tcx> for SymbolPrinter<'_, 'tcx> { Ok(self) } + fn print_const( + self, + ct: &'tcx ty::Const<'tcx>, + ) -> Result { + self.pretty_print_const(ct) + } + fn path_crate( mut self, cnum: CrateNum, From 52fa900d62753aca4354f9c6b7a426a80bc7bc62 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 3 May 2019 10:59:04 +0200 Subject: [PATCH 21/27] Break cycle during array length printing --- 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 7212afc08dfcd..53a5de689d85f 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -669,7 +669,7 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>: if let Some(n) = sz.assert_usize(self.tcx()) { p!(write("{}", n)); } else { - p!(print(sz)); + p!(write("_")); } p!(write("]")) } From fa459a08e136a269057be92af279c8290ce62cc8 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 7 May 2019 17:47:52 +0200 Subject: [PATCH 22/27] Fix rebase fallout --- src/librustc/ty/print/pretty.rs | 10 +++++----- src/librustc_mir/monomorphize/item.rs | 2 +- .../ui/const-generics/cannot-infer-const-args.stderr | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 53a5de689d85f..d8150c1895b98 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -1,5 +1,5 @@ use crate::hir; -use crate::hir::def::{Namespace, Def}; +use crate::hir::def::{Namespace, DefKind}; use crate::hir::map::{DefPathData, DisambiguatedDefPathData}; use crate::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use crate::middle::cstore::{ExternCrate, ExternCrateSource}; @@ -820,10 +820,10 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>: return Ok(self); } if let ConstValue::Unevaluated(did, substs) = ct.val { - match self.tcx().describe_def(did) { - | Some(Def::Static(_)) - | Some(Def::Const(_)) - | Some(Def::AssociatedConst(_)) => p!(print_value_path(did, substs)), + match self.tcx().def_kind(did) { + | Some(DefKind::Static) + | Some(DefKind::Const) + | Some(DefKind::AssociatedConst) => p!(print_value_path(did, substs)), _ => if did.is_local() { let span = self.tcx().def_span(did); if let Ok(snip) = self.tcx().sess.source_map().span_to_snippet(span) { diff --git a/src/librustc_mir/monomorphize/item.rs b/src/librustc_mir/monomorphize/item.rs index 6b40245d39a8e..8b44f148facf6 100644 --- a/src/librustc_mir/monomorphize/item.rs +++ b/src/librustc_mir/monomorphize/item.rs @@ -401,7 +401,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { // as well as the unprintable types of constants (see `push_type_name` for more details). pub fn push_const_name(&self, c: &Const<'tcx>, output: &mut String, debug: bool) { match c.val { - ConstValue::Scalar(..) | ConstValue::Slice(..) | ConstValue::ByRef(..) => { + ConstValue::Scalar(..) | ConstValue::Slice { .. } | ConstValue::ByRef(..) => { // FIXME(const_generics): we could probably do a better job here. write!(output, "{:?}", c).unwrap() } 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 5528c2fca6a3b..544cd05cdbebf 100644 --- a/src/test/ui/const-generics/cannot-infer-const-args.stderr +++ b/src/test/ui/const-generics/cannot-infer-const-args.stderr @@ -8,7 +8,7 @@ error[E0282]: type annotations needed --> $DIR/cannot-infer-const-args.rs:9:5 | LL | foo(); - | ^^^ cannot infer type for `fn() -> usize {foo::<_>}` + | ^^^ cannot infer type for `fn() -> usize {foo::<_: usize>}` error: aborting due to previous error From 825cfdbadcbf7877ea7bf925664ef760c364980d Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Sat, 11 May 2019 15:48:47 +0200 Subject: [PATCH 23/27] Print types for unevaluated constants --- src/librustc/ty/print/pretty.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index d8150c1895b98..6726563331844 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -829,10 +829,10 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>: if let Ok(snip) = self.tcx().sess.source_map().span_to_snippet(span) { p!(write("{}", snip)) } else { - p!(write("_")) + p!(write("_: "), print(ct.ty)) } } else { - p!(write("_")) + p!(write("_: "), print(ct.ty)) }, } return Ok(self); From dd327951eb61b95e28649768ae7e67aaba4e2ece Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Sat, 11 May 2019 15:48:57 +0200 Subject: [PATCH 24/27] Update ui tests --- src/test/ui/pattern/const-pat-ice.stderr | 2 +- src/test/ui/symbol-names/impl2.rs | 14 ++++++++++++++ src/test/ui/symbol-names/impl2.stderr | 8 ++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/symbol-names/impl2.rs create mode 100644 src/test/ui/symbol-names/impl2.stderr diff --git a/src/test/ui/pattern/const-pat-ice.stderr b/src/test/ui/pattern/const-pat-ice.stderr index 260c2e04d74f7..fabaea0535f5b 100644 --- a/src/test/ui/pattern/const-pat-ice.stderr +++ b/src/test/ui/pattern/const-pat-ice.stderr @@ -1,4 +1,4 @@ -thread 'rustc' panicked at 'assertion failed: rows.iter().all(|r| r.len() == v.len())', src/librustc_mir/hair/pattern/_match.rs:1083:5 +thread 'rustc' panicked at 'assertion failed: rows.iter().all(|r| r.len() == v.len())', src/librustc_mir/hair/pattern/_match.rs:1085:5 note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace. error: internal compiler error: unexpected panic diff --git a/src/test/ui/symbol-names/impl2.rs b/src/test/ui/symbol-names/impl2.rs new file mode 100644 index 0000000000000..d48b182f2a200 --- /dev/null +++ b/src/test/ui/symbol-names/impl2.rs @@ -0,0 +1,14 @@ +#![feature(rustc_attrs)] +#![allow(dead_code)] + +trait Foo { + fn baz(); +} + +impl Foo for [u8; 1 + 2] { + #[rustc_def_path] //~ ERROR def-path(<[u8; _] as Foo>::baz) + fn baz() { } +} + +fn main() { +} diff --git a/src/test/ui/symbol-names/impl2.stderr b/src/test/ui/symbol-names/impl2.stderr new file mode 100644 index 0000000000000..de26fed44139e --- /dev/null +++ b/src/test/ui/symbol-names/impl2.stderr @@ -0,0 +1,8 @@ +error: def-path(<[u8; _] as Foo>::baz) + --> $DIR/impl2.rs:9:5 + | +LL | #[rustc_def_path] + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + From a0275e3bf3aa72b40f8f9cb1b3b64c620569377c Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Sat, 11 May 2019 16:04:14 +0200 Subject: [PATCH 25/27] Only print integers in symbol path's constants --- src/librustc_codegen_utils/symbol_names.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index f2f9ac8931fee..864071629078a 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -96,6 +96,7 @@ use rustc::ty::print::{PrettyPrinter, Printer, Print}; use rustc::ty::query::Providers; use rustc::ty::subst::{Kind, SubstsRef, UnpackedKind}; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; +use rustc::mir::interpret::{ConstValue, Scalar}; use rustc::util::common::record_time; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_mir::monomorphize::item::{InstantiationMode, MonoItem, MonoItemExt}; @@ -438,10 +439,17 @@ impl Printer<'tcx, 'tcx> for SymbolPrinter<'_, 'tcx> { } fn print_const( - self, + mut self, ct: &'tcx ty::Const<'tcx>, ) -> Result { - self.pretty_print_const(ct) + // only print integers + if let ConstValue::Scalar(Scalar::Bits { .. }) = ct.val { + if ct.ty.is_integral() { + return self.pretty_print_const(ct); + } + } + self.write_str("_")?; + Ok(self) } fn path_crate( From e69480765028dc697d876a81b9c53b9fb50f60ab Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 24 May 2019 20:47:39 +0100 Subject: [PATCH 26/27] Fix missing tcx --- src/librustc_mir/transform/const_prop.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 05518ca48d30e..2f6793e049419 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -506,7 +506,8 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> { span, ty, user_ty: None, - literal: self.tcx.mk_const(ty::Const::from_scalar( + literal: self.tcx.mk_const(*ty::Const::from_scalar( + self.tcx, scalar, ty, )) From 0b732aa6071fd165d8f2c0972495b5e058699b47 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Sat, 25 May 2019 17:21:29 +0200 Subject: [PATCH 27/27] Update nll ui tests --- src/test/ui/consts/const_let_refutable.nll.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/consts/const_let_refutable.nll.stderr b/src/test/ui/consts/const_let_refutable.nll.stderr index 30ab1f4d5ec0d..3cc6de5bc4285 100644 --- a/src/test/ui/consts/const_let_refutable.nll.stderr +++ b/src/test/ui/consts/const_let_refutable.nll.stderr @@ -4,7 +4,7 @@ error[E0005]: refutable pattern in function argument: `&[]` not covered LL | const fn slice([a, b]: &[i32]) -> i32 { | ^^^^^^ pattern `&[]` not covered -error[E0723]: can only call other `const fn` within a `const fn`, but `const std::ops::Add::add` is not stable as `const fn` +error[E0723]: can only call other `const fn` within a `const fn`, but `const <&i32 as std::ops::Add>::add` is not stable as `const fn` --> $DIR/const_let_refutable.rs:4:5 | LL | a + b