diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index e4505a24037..8ec9d42ec5f 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 7e1e751e856..b9ce42ac8f2 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 d5d4f648444..53d4466cfef 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 54f76c98f3c..7212afc08df 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 1a8647ed197..f2f9ac8931f 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,