]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc/ty/print/pretty.rs
Group common printing code during constant pretty printing
[rust.git] / src / librustc / ty / print / pretty.rs
index 91b708d7dbe10339d00813f79f85cfd108a4f57b..6514017a3e74dddbcb12044eeb00437017502d60 100644 (file)
@@ -1,14 +1,18 @@
 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};
 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::ty::layout::Size;
+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::{keywords, InternedString};
+use syntax::symbol::{kw, InternedString};
 
 use std::cell::Cell;
 use std::fmt::{self, Write as _};
@@ -253,8 +257,8 @@ fn try_print_visible_def_path(
             // 2. for an extern inferred from a path or an indirect crate,
             //    where there is no explicit `extern crate`, we just prepend
             //    the crate name.
-            match *self.tcx().extern_crate(def_id) {
-                Some(ExternCrate {
+            match self.tcx().extern_crate(def_id) {
+                Some(&ExternCrate {
                     src: ExternCrateSource::Extern(def_id),
                     direct: true,
                     span,
@@ -980,7 +984,7 @@ fn path_crate(
             if self.tcx.sess.rust_2018() {
                 // We add the `crate::` keyword on Rust 2018, only when desired.
                 if SHOULD_PREFIX_WITH_CRATE.with(|flag| flag.get()) {
-                    write!(self, "{}", keywords::Crate.name())?;
+                    write!(self, "{}", kw::Crate)?;
                     self.empty_path = false;
                 }
             }
@@ -1140,14 +1144,16 @@ fn region_should_not_be_omitted(
 
         match *region {
             ty::ReEarlyBound(ref data) => {
-                data.name != "" && data.name != "'_"
+                data.name.as_symbol() != kw::Invalid &&
+                data.name.as_symbol() != kw::UnderscoreLifetime
             }
 
             ty::ReLateBound(_, br) |
             ty::ReFree(ty::FreeRegion { bound_region: br, .. }) |
             ty::RePlaceholder(ty::Placeholder { name: br, .. }) => {
                 if let ty::BrNamed(_, name) = br {
-                    if name != "" && name != "'_" {
+                    if name.as_symbol() != kw::Invalid &&
+                       name.as_symbol() != kw::UnderscoreLifetime {
                         return true;
                     }
                 }
@@ -1203,7 +1209,7 @@ pub fn pretty_print_region(
         // `explain_region()` or `note_and_explain_region()`.
         match *region {
             ty::ReEarlyBound(ref data) => {
-                if data.name != "" {
+                if data.name.as_symbol() != kw::Invalid {
                     p!(write("{}", data.name));
                     return Ok(self);
                 }
@@ -1212,7 +1218,8 @@ pub fn pretty_print_region(
             ty::ReFree(ty::FreeRegion { bound_region: br, .. }) |
             ty::RePlaceholder(ty::Placeholder { name: br, .. }) => {
                 if let ty::BrNamed(_, name) = br {
-                    if name != "" && name != "'_" {
+                    if name.as_symbol() != kw::Invalid &&
+                       name.as_symbol() != kw::UnderscoreLifetime {
                         p!(write("{}", name));
                         return Ok(self);
                     }
@@ -1531,12 +1538,94 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 
     &'tcx ty::Const<'tcx> {
-        match self.val {
-            ConstValue::Unevaluated(..) |
-            ConstValue::Infer(..) => p!(write("_")),
-            ConstValue::Param(ParamConst { name, .. }) => p!(write("{}", name)),
-            _ => p!(write("{:?}", self)),
+        let u8 = cx.tcx().types.u8;
+        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);
+                }
+                _ => {},
+            }
+        }
+        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) {
+                        p!(write("{}", e as char));
+                    }
+                }
+                p!(write("\""));
+                return Ok(cx);
+            }
         }
+        p!(write("{:?} : ", self.val), print(self.ty));
     }
 
     ty::ParamTy {