about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-05-25 16:08:11 +0000
committerbors <bors@rust-lang.org>2019-05-25 16:08:11 +0000
commitf492693982d1e252f5411ae3e4d560ab0dfea48a (patch)
tree0de87039ac27ace7a63b3e1f5fb84ff6d426045f /src
parent02f5786a324c40b2d8b2d0df98456e48fb45d30c (diff)
parent0b732aa6071fd165d8f2c0972495b5e058699b47 (diff)
Auto merge of #59276 - oli-obk:cleanups, r=eddyb
Cleanup (pretty) printing of `ty::Const`

r? @eddyb

addresses https://github.com/rust-lang/rust/pull/59178/files/5cd28066214a4a255bac6655c20bf05cb95730fd#r266243236 and https://github.com/rust-lang/rust/pull/59178/files/5cd28066214a4a255bac6655c20bf05cb95730fd#r266243336
Diffstat (limited to 'src')
-rw-r--r--src/librustc/infer/error_reporting/mod.rs8
-rw-r--r--src/librustc/infer/freshen.rs2
-rw-r--r--src/librustc/lint/context.rs10
-rw-r--r--src/librustc/mir/interpret/error.rs2
-rw-r--r--src/librustc/mir/interpret/value.rs26
-rw-r--r--src/librustc/mir/mod.rs111
-rw-r--r--src/librustc/traits/project.rs3
-rw-r--r--src/librustc/traits/query/normalize.rs3
-rw-r--r--src/librustc/ty/context.rs19
-rw-r--r--src/librustc/ty/fold.rs2
-rw-r--r--src/librustc/ty/print/mod.rs14
-rw-r--r--src/librustc/ty/print/pretty.rs144
-rw-r--r--src/librustc/ty/structural_impls.rs17
-rw-r--r--src/librustc/ty/sty.rs21
-rw-r--r--src/librustc_codegen_ssa/mir/constant.rs6
-rw-r--r--src/librustc_codegen_ssa/mir/operand.rs14
-rw-r--r--src/librustc_codegen_utils/symbol_names.rs16
-rw-r--r--src/librustc_mir/build/matches/mod.rs4
-rw-r--r--src/librustc_mir/build/matches/test.rs11
-rw-r--r--src/librustc_mir/build/misc.rs4
-rw-r--r--src/librustc_mir/const_eval.rs46
-rw-r--r--src/librustc_mir/hair/constant.rs18
-rw-r--r--src/librustc_mir/hair/cx/expr.rs23
-rw-r--r--src/librustc_mir/hair/cx/mod.rs12
-rw-r--r--src/librustc_mir/hair/pattern/_match.rs133
-rw-r--r--src/librustc_mir/hair/pattern/mod.rs65
-rw-r--r--src/librustc_mir/interpret/operand.rs17
-rw-r--r--src/librustc_mir/monomorphize/collector.rs8
-rw-r--r--src/librustc_mir/monomorphize/item.rs2
-rw-r--r--src/librustc_mir/shim.rs12
-rw-r--r--src/librustc_mir/transform/const_prop.rs5
-rw-r--r--src/librustc_mir/transform/elaborate_drops.rs4
-rw-r--r--src/librustc_mir/transform/generator.rs4
-rw-r--r--src/librustc_mir/util/elaborate_drops.rs4
-rw-r--r--src/librustc_typeck/check/mod.rs2
-rw-r--r--src/librustdoc/clean/mod.rs11
-rw-r--r--src/test/mir-opt/box_expr.rs2
-rw-r--r--src/test/mir-opt/byte_slice.rs15
-rw-r--r--src/test/mir-opt/inline-trait-method.rs2
-rw-r--r--src/test/mir-opt/inline-trait-method_2.rs2
-rw-r--r--src/test/mir-opt/issue-49232.rs2
-rw-r--r--src/test/mir-opt/unusual-item-types.rs3
-rw-r--r--src/test/ui/const-generics/cannot-infer-const-args.stderr2
-rw-r--r--src/test/ui/consts/const_let_refutable.nll.stderr2
-rw-r--r--src/test/ui/consts/const_let_refutable.stderr2
-rw-r--r--src/test/ui/pattern/const-pat-ice.stderr2
-rw-r--r--src/test/ui/pattern/slice-pattern-const-2.rs4
-rw-r--r--src/test/ui/pattern/slice-pattern-const-2.stderr20
-rw-r--r--src/test/ui/symbol-names/impl2.rs14
-rw-r--r--src/test/ui/symbol-names/impl2.stderr8
50 files changed, 487 insertions, 396 deletions
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<Self::Const, Self::Error> {
+                Err(NonTrivialPath)
+            }
+
             fn path_crate(
                 self,
                 cnum: CrateNum,
diff --git a/src/librustc/infer/freshen.rs b/src/librustc/infer/freshen.rs
index 679635bef13..8f52ef7a3f3 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/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<ty::ExistentialPredicate<'tcx>>,
-                ) -> Result<Self::DynExistential, Self::Error> {
+            ) -> Result<Self::DynExistential, Self::Error> {
+                Ok(())
+            }
+
+            fn print_const(
+                self,
+                _ct: &'tcx ty::Const<'tcx>,
+            ) -> Result<Self::Const, Self::Error> {
                 Ok(())
             }
 
diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs
index 5c6fc6f49f0..9c2fd399ee0 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<RawConst<'tcx>, ErrorHandled>;
-pub type ConstEvalResult<'tcx> = Result<ty::Const<'tcx>, 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/interpret/value.rs b/src/librustc/mir/interpret/value.rs
index 6b6f7f7a307..72545f23f8e 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<str>`,
-    /// 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<Pointer> {
         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/mir/mod.rs b/src/librustc/mir/mod.rs
index 6de4350c2aa..84aff8101a0 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};
@@ -1662,28 +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| {
-                        let mut s = String::new();
-                        let c = ty::Const {
-                            val: ConstValue::Scalar(
-                                Scalar::Bits {
-                                    bits: u,
-                                    size: size.bytes() as u8,
-                                }.into(),
-                            ),
-                            ty: switch_ty,
-                        };
-                        fmt_const_val(&mut s, c).unwrap();
-                        s.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(_),
@@ -2331,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),
         })
     }
 
@@ -2827,67 +2820,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/traits/project.rs b/src/librustc/traits/project.rs
index 67e76f7625c..b1c4e409112 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 9940249da8b..d09a9c10786 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 d83b2ce842a..a56fe7d7003 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<Self::Lifted> {
-        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/fold.rs b/src/librustc/ty/fold.rs
index dbf9047f775..dae28d51efc 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)
     }
 }
 
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<ty::ExistentialPredicate<'tcx>>,
     ) -> Result<Self::DynExistential, Self::Error>;
 
+    fn print_const(
+        self,
+        ct: &'tcx ty::Const<'tcx>,
+    ) -> Result<Self::Const, Self::Error>;
+
     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<Self::Output, Self::Error> {
+        cx.print_const(self)
+    }
+}
diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs
index 06db4b9b65b..67265633318 100644
--- a/src/librustc/ty/print/pretty.rs
+++ b/src/librustc/ty/print/pretty.rs
@@ -1,12 +1,16 @@
 use crate::hir;
-use crate::hir::def::Namespace;
+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};
 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::{kw, InternedString};
 
@@ -169,6 +173,7 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>:
         Region = Self,
         Type = Self,
         DynExistential = Self,
+        Const = Self,
     > +
     fmt::Write
 {
@@ -661,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!(write("_"));
                 }
                 p!(write("]"))
             }
@@ -804,6 +807,113 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>:
 
         Ok(self)
     }
+
+    fn pretty_print_const(
+        mut self,
+        ct: &'tcx ty::Const<'tcx>,
+    ) -> Result<Self::Const, Self::Error> {
+        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().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) {
+                        p!(write("{}", snip))
+                    } else {
+                        p!(write("_: "), print(ct.ty))
+                    }
+                } else {
+                    p!(write("_: "), print(ct.ty))
+                },
+            }
+            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.
@@ -896,6 +1006,7 @@ impl<F: fmt::Write> 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
@@ -971,6 +1082,13 @@ impl<F: fmt::Write> 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::Const, Self::Error> {
+        self.pretty_print_const(ct)
+    }
+
     fn path_crate(
         mut self,
         cnum: CrateNum,
@@ -1444,6 +1562,7 @@ impl fmt::Display for ty::RegionKind {
 forward_display_to_print! {
     Ty<'tcx>,
     &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
+    &'tcx ty::Const<'tcx>,
 
     // HACK(eddyb) these are exhaustive instead of generic,
     // because `for<'gcx: 'tcx, 'tcx>` isn't possible yet.
@@ -1533,15 +1652,6 @@ 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::ParamTy {
         p!(write("{}", self.name))
     }
diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs
index cf04d6eac3a..0daa567052d 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 {
@@ -788,16 +787,6 @@ BraceStructLiftImpl! {
     }
 }
 
-impl<'a, 'tcx> Lift<'tcx> for ConstVid<'a> {
-    type Lifted = ConstVid<'tcx>;
-    fn lift_to_tcx<'b, 'gcx>(&self, _: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
-        Some(ConstVid {
-            index: self.index,
-            phantom: PhantomData,
-        })
-    }
-}
-
 ///////////////////////////////////////////////////////////////////////////
 // TypeFoldable implementations.
 //
@@ -1356,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)),
         }
@@ -1369,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 0b5a6fce5cb..a2b2fc7a445 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -2207,18 +2207,19 @@ pub struct Const<'tcx> {
 }
 
 #[cfg(target_arch = "x86_64")]
-static_assert_size!(Const<'_>, 48);
+static_assert_size!(Const<'_>, 40);
 
 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 3f8dc420cf4..eaa1dd186a5 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<ty::Const<'tcx>, 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<ty::Const<'tcx>, 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 3db05b7214d..ec471a1323e 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;
@@ -67,7 +67,7 @@ impl<'a, 'tcx: 'a, V: CodegenObject> OperandRef<'tcx, V> {
 
     pub fn from_const<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
         bx: &mut Bx,
-        val: ty::Const<'tcx>
+        val: &'tcx ty::Const<'tcx>
     ) -> Result<Self, ErrorHandled> {
         let layout = bx.layout_of(val.ty);
 
@@ -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_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs
index 1a8647ed197..86407162907 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};
@@ -391,6 +392,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 +438,20 @@ impl Printer<'tcx, 'tcx> for SymbolPrinter<'_, 'tcx> {
         Ok(self)
     }
 
+    fn print_const(
+        mut self,
+        ct: &'tcx ty::Const<'tcx>,
+    ) -> Result<Self::Const, Self::Error> {
+        // 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(
         mut self,
         cnum: CrateNum,
diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs
index 58ca35abcb1..8c2ef082c33 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<u128>,
-        indices: FxHashMap<ty::Const<'tcx>, 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 a5834b02ffc..0995a2f7fdf 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<u128>,
-                                     indices: &mut FxHashMap<ty::Const<'tcx>, 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<bool> {
         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<ty::Const<'tcx>, usize>,
+        indices: &FxHashMap<&'tcx ty::Const<'tcx>, usize>,
     ) -> Option<bool> {
         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 d71a13dec5a..daf59d7a135 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 866b6492d10..776d4c24241 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;
@@ -65,7 +66,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,17 +80,24 @@ 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()),
-        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,10 +109,28 @@ 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,
+            }
+        },
     };
-    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 +476,8 @@ pub fn const_field<'a, 'tcx>(
     param_env: ty::ParamEnv<'tcx>,
     variant: Option<VariantIdx>,
     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 +499,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 caadc6055b5..d2c86d36238 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<ty::Const<'tcx>, LitToConstError> {
+) -> Result<&'tcx ty::Const<'tcx>, LitToConstError> {
     use syntax::ast::*;
 
     let trunc = |n| {
@@ -33,16 +33,18 @@ 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());
-            return Ok(ty::Const {
-                val: 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);
+            return Ok(tcx.mk_const(ty::Const {
+                val: ConstValue::Slice{ data: allocation, start: 0, end: s.len() },
                 ty: tcx.types.err,
-            });
+            }));
         },
         LitKind::ByteStr(ref data) => {
             let id = tcx.allocate_bytes(data);
@@ -71,7 +73,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 d623f149988..ca457b0ac7c 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 e8070b21bb8..c993a02a6de 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 fd4416fc2b7..29e9c425685 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),
         }
@@ -255,10 +257,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 +425,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.
@@ -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,
                     ),
                     _ => {},
                 }
@@ -1424,49 +1426,24 @@ 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<Pattern<'tcx>>,
     suffix: &[Pattern<'tcx>]
 ) -> Result<bool, ErrorReported> {
     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(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 0576bb53d8f..1c47f850ddb 100644
--- a/src/librustc_mir/hair/pattern/mod.rs
+++ b/src/librustc_mir/hair/pattern/mod.rs
@@ -10,13 +10,13 @@ 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::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;
@@ -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 } => {
-                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 } => {
@@ -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<Ordering> {
     trace!("compare_const_vals: {:?}, {:?}", a, b);
@@ -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 a674389a936..e26b147ea58 100644
--- a/src/librustc_mir/interpret/operand.rs
+++ b/src/librustc_mir/interpret/operand.rs
@@ -512,7 +512,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)
@@ -532,7 +532,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<TyLayout<'tcx>>,
     ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
         let op = match val.val {
@@ -545,11 +545,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 91cf0fbb9b4..b90db7646d4 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,17 +1248,17 @@ 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<MonoItem<'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/librustc_mir/monomorphize/item.rs b/src/librustc_mir/monomorphize/item.rs
index 6b40245d39a..8b44f148fac 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/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
index b9224d973fe..8be660ae17a 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 8f3dd72c4f2..2f6793e0494 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<Const<'tcx>> {
         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)
             },
@@ -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,
                 ))
diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs
index 023a61588c4..6320cb44248 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 780b3c9686b..ab2f2933a96 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 98ca7c32675..ac5ebc5e251 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 655bf5722ae..b5bb62a0f46 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 9c3f522d847..fb0caa55ffb 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -2956,7 +2956,7 @@ impl<'tcx> Clean<Type> 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) {
@@ -4136,12 +4136,15 @@ 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();
                 s.truncate(n);
+                if s.ends_with(": ") {
+                    let n = s.len() - ": ".len();
+                    s.truncate(n);
+                }
             }
             s
         },
diff --git a/src/test/mir-opt/box_expr.rs b/src/test/mir-opt/box_expr.rs
index ee6adfefe3e..9f55d849644 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::<std::boxed::Box<S>>(move _4) -> [return: bb5, unwind: bb7];
 //     }
 //
 //     bb5: {
diff --git a/src/test/mir-opt/byte_slice.rs b/src/test/mir-opt/byte_slice.rs
new file mode 100644
index 00000000000..7edfa3e1124
--- /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 b"foo";
+// ...
+// _2 = [const 5u8, const 120u8];
+// ...
+// END rustc.main.EraseRegions.after.mir
diff --git a/src/test/mir-opt/inline-trait-method.rs b/src/test/mir-opt/inline-trait-method.rs
index 0f79f43ee2d..a2c5fb920cd 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 <dyn X as X>::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 8f9f2535aa5..4ad4311113a 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 <dyn X as X>::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 bf22f00b505..447f3a07a6a 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 606503151c9..67a55101d82 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;
 
@@ -68,7 +69,7 @@ fn main() {
 // }
 // bb7: {
 //     _2 = &mut (*_1);
-//     _3 = const std::ops::Drop::drop(move _2) -> [return: bb6, unwind: bb5];
+//     _3 = const <std::vec::Vec<i32> 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
 
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 5528c2fca6a..544cd05cdbe 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
 
diff --git a/src/test/ui/consts/const_let_refutable.nll.stderr b/src/test/ui/consts/const_let_refutable.nll.stderr
index 30ab1f4d5ec..3cc6de5bc42 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
diff --git a/src/test/ui/consts/const_let_refutable.stderr b/src/test/ui/consts/const_let_refutable.stderr
index 2ca76667bd1..cdd696ee7fb 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
diff --git a/src/test/ui/pattern/const-pat-ice.stderr b/src/test/ui/pattern/const-pat-ice.stderr
index 260c2e04d74..fabaea0535f 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/pattern/slice-pattern-const-2.rs b/src/test/ui/pattern/slice-pattern-const-2.rs
index 6cfef115d08..a36c550f530 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 e2c408a90e4..0c7401269df 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
 
diff --git a/src/test/ui/symbol-names/impl2.rs b/src/test/ui/symbol-names/impl2.rs
new file mode 100644
index 00000000000..d48b182f2a2
--- /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 00000000000..de26fed4413
--- /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
+