about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBen Lewis <benlewisj@gmail.com>2020-02-15 11:56:23 +1300
committerBen Lewis <benlewisj@gmail.com>2020-02-15 11:56:23 +1300
commitc423a8649c0bac16fd4d1b9cbea657e4245bb5ac (patch)
tree0955bf073db63900684d694eea8a6939c92d1b53
parente168dcd254d0a6a0cbaad5f2c054ce5116a07119 (diff)
downloadrust-c423a8649c0bac16fd4d1b9cbea657e4245bb5ac.tar.gz
rust-c423a8649c0bac16fd4d1b9cbea657e4245bb5ac.zip
Change const eval to return `ConstValue`, instead of `Const` as the type inside it shouldn't be used.
-rw-r--r--src/librustc/mir/interpret/error.rs3
-rw-r--r--src/librustc/mir/interpret/value.rs33
-rw-r--r--src/librustc/ty/mod.rs6
-rw-r--r--src/librustc/ty/sty.rs4
-rw-r--r--src/librustc_codegen_llvm/consts.rs8
-rw-r--r--src/librustc_codegen_llvm/intrinsic.rs3
-rw-r--r--src/librustc_codegen_ssa/mir/constant.rs8
-rw-r--r--src/librustc_codegen_ssa/mir/operand.rs2
-rw-r--r--src/librustc_mir/const_eval.rs6
-rw-r--r--src/librustc_mir/const_eval/eval_queries.rs18
-rw-r--r--src/librustc_mir/interpret/eval_context.rs4
-rw-r--r--src/librustc_mir/interpret/intrinsics.rs22
-rw-r--r--src/librustc_mir/interpret/operand.rs4
-rw-r--r--src/librustc_mir/monomorphize/collector.rs32
-rw-r--r--src/librustc_mir_build/hair/cx/expr.rs12
-rw-r--r--src/librustc_mir_build/hair/pattern/mod.rs9
-rw-r--r--src/librustc_typeck/check/expr.rs9
-rw-r--r--src/librustc_typeck/check/mod.rs17
-rw-r--r--src/librustdoc/clean/mod.rs6
-rw-r--r--src/librustdoc/clean/utils.rs19
20 files changed, 145 insertions, 80 deletions
diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs
index e747eee30f9..a23ff6bd66d 100644
--- a/src/librustc/mir/interpret/error.rs
+++ b/src/librustc/mir/interpret/error.rs
@@ -2,6 +2,7 @@ use super::{CheckInAllocMsg, Pointer, RawConst, ScalarMaybeUndef};
 
 use crate::hir::map::definitions::DefPathData;
 use crate::mir;
+use crate::mir::interpret::ConstValue;
 use crate::ty::layout::{Align, LayoutError, Size};
 use crate::ty::query::TyCtxtAt;
 use crate::ty::{self, layout, Ty};
@@ -40,7 +41,7 @@ CloneTypeFoldableImpls! {
 }
 
 pub type ConstEvalRawResult<'tcx> = Result<RawConst<'tcx>, ErrorHandled>;
-pub type ConstEvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, ErrorHandled>;
+pub type ConstEvalResult<'tcx> = Result<ConstValue<'tcx>, ErrorHandled>;
 
 #[derive(Debug)]
 pub struct ConstEvalErr<'tcx> {
diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs
index 2be36ad418a..538d955762e 100644
--- a/src/librustc/mir/interpret/value.rs
+++ b/src/librustc/mir/interpret/value.rs
@@ -7,7 +7,7 @@ use std::fmt;
 
 use crate::ty::{
     layout::{HasDataLayout, Size},
-    Ty,
+    ParamEnv, Ty, TyCtxt,
 };
 
 use super::{sign_extend, truncate, AllocId, Allocation, InterpResult, Pointer, PointerArithmetic};
@@ -66,6 +66,32 @@ impl<'tcx> ConstValue<'tcx> {
             ConstValue::Scalar(val) => Some(val),
         }
     }
+
+    pub fn try_to_bits(&self, size: Size) -> Option<u128> {
+        self.try_to_scalar()?.to_bits(size).ok()
+    }
+
+    pub fn try_to_bits_for_ty(
+        &self,
+        tcx: TyCtxt<'tcx>,
+        param_env: ParamEnv<'tcx>,
+        ty: Ty<'tcx>,
+    ) -> Option<u128> {
+        let size = tcx.layout_of(param_env.with_reveal_all().and(ty)).ok()?.size;
+        self.try_to_bits(size)
+    }
+
+    pub fn from_bool(b: bool) -> Self {
+        ConstValue::Scalar(Scalar::from_bool(b))
+    }
+
+    pub fn from_u64(i: u64) -> Self {
+        ConstValue::Scalar(Scalar::from_u64(i))
+    }
+
+    pub fn from_machine_usize(cx: &impl HasDataLayout, i: u64) -> Self {
+        ConstValue::Scalar(Scalar::from_machine_usize(cx, i))
+    }
 }
 
 /// A `Scalar` represents an immediate, primitive value existing outside of a
@@ -288,6 +314,11 @@ impl<'tcx, Tag> Scalar<Tag> {
     }
 
     #[inline]
+    pub fn from_machine_usize(cx: &impl HasDataLayout, i: u64) -> Self {
+        Self::from_uint(i, cx.data_layout().pointer_size)
+    }
+
+    #[inline]
     pub fn try_from_int(i: impl Into<i128>, size: Size) -> Option<Self> {
         let i = i.into();
         // `into` performed sign extension, we have to truncate
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index ad51c60ab01..605baae6c24 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -2380,10 +2380,10 @@ impl<'tcx> AdtDef {
         let repr_type = self.repr.discr_type();
         match tcx.const_eval_poly(expr_did) {
             Ok(val) => {
-                // FIXME: Find the right type and use it instead of `val.ty` here
-                if let Some(b) = val.try_eval_bits(tcx, param_env, val.ty) {
+                let ty = repr_type.to_ty(tcx);
+                if let Some(b) = val.try_to_bits_for_ty(tcx, param_env, ty) {
                     trace!("discriminants: {} ({:?})", b, repr_type);
-                    Some(Discr { val: b, ty: val.ty })
+                    Some(Discr { val: b, ty })
                 } else {
                     info!("invalid enum discriminant: {:#?}", val);
                     crate::mir::interpret::struct_error(
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index 0718853b1df..57b55c0f897 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -2471,7 +2471,9 @@ impl<'tcx> Const<'tcx> {
 
             // try to resolve e.g. associated constants to their definition on an impl, and then
             // evaluate the const.
-            tcx.const_eval_resolve(param_env, did, substs, promoted, None).ok()
+            tcx.const_eval_resolve(param_env, did, substs, promoted, None)
+                .ok()
+                .map(|val| tcx.mk_const(Const { val: ConstKind::Value(val), ty: self.ty }))
         };
 
         match self.val {
diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs
index 38090cb26bc..09a84aff168 100644
--- a/src/librustc_codegen_llvm/consts.rs
+++ b/src/librustc_codegen_llvm/consts.rs
@@ -78,11 +78,9 @@ pub fn codegen_static_initializer(
     cx: &CodegenCx<'ll, 'tcx>,
     def_id: DefId,
 ) -> Result<(&'ll Value, &'tcx Allocation), ErrorHandled> {
-    let static_ = cx.tcx.const_eval_poly(def_id)?;
-
-    let alloc = match static_.val {
-        ty::ConstKind::Value(ConstValue::ByRef { alloc, offset }) if offset.bytes() == 0 => alloc,
-        _ => bug!("static const eval returned {:#?}", static_),
+    let alloc = match cx.tcx.const_eval_poly(def_id)? {
+        ConstValue::ByRef { alloc, offset } if offset.bytes() == 0 => alloc,
+        val => bug!("static const eval returned {:#?}", val),
     };
     Ok((const_alloc_to_llvm(cx, alloc), alloc))
 }
diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs
index 031837c1efb..341a4a77c3c 100644
--- a/src/librustc_codegen_llvm/intrinsic.rs
+++ b/src/librustc_codegen_llvm/intrinsic.rs
@@ -193,7 +193,8 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
                     .tcx
                     .const_eval_instance(ty::ParamEnv::reveal_all(), instance, None)
                     .unwrap();
-                OperandRef::from_const(self, ty_name).immediate_or_packed_pair(self)
+                let const_ = ty::Const { val: ty::ConstKind::Value(ty_name), ty: ret_ty };
+                OperandRef::from_const(self, &const_).immediate_or_packed_pair(self)
             }
             "init" => {
                 let ty = substs.type_at(0);
diff --git a/src/librustc_codegen_ssa/mir/constant.rs b/src/librustc_codegen_ssa/mir/constant.rs
index 3ce916d7812..d7e87419c17 100644
--- a/src/librustc_codegen_ssa/mir/constant.rs
+++ b/src/librustc_codegen_ssa/mir/constant.rs
@@ -30,7 +30,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             }
             _ => {
                 let val = self.eval_mir_constant(constant)?;
-                Ok(OperandRef::from_const(bx, val))
+                Ok(OperandRef::from_const(bx, &val))
             }
         }
     }
@@ -45,6 +45,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 self.cx
                     .tcx()
                     .const_eval_resolve(ty::ParamEnv::reveal_all(), def_id, substs, promoted, None)
+                    .map(|val| {
+                        self.cx.tcx().mk_const(ty::Const {
+                            val: ty::ConstKind::Value(val),
+                            ty: constant.literal.ty,
+                        })
+                    })
                     .map_err(|err| {
                         if promoted.is_none() {
                             self.cx
diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs
index a33cd2ddad9..7745606b841 100644
--- a/src/librustc_codegen_ssa/mir/operand.rs
+++ b/src/librustc_codegen_ssa/mir/operand.rs
@@ -66,7 +66,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
 
     pub fn from_const<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
         bx: &mut Bx,
-        val: &'tcx ty::Const<'tcx>,
+        val: &ty::Const<'tcx>,
     ) -> Self {
         let layout = bx.layout_of(val.ty);
 
diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs
index aad0e162935..5e6db565a7d 100644
--- a/src/librustc_mir/const_eval.rs
+++ b/src/librustc_mir/const_eval.rs
@@ -40,7 +40,8 @@ pub(crate) fn const_field<'tcx>(
     let field = ecx.operand_field(down, field.index() as u64).unwrap();
     // and finally move back to the const world, always normalizing because
     // this is not called for statics.
-    op_to_const(&ecx, field)
+    let val = op_to_const(&ecx, field);
+    tcx.mk_const(ty::Const { val: ty::ConstKind::Value(val), ty: op.layout.ty })
 }
 
 pub(crate) fn const_caller_location<'tcx>(
@@ -84,7 +85,8 @@ pub(crate) fn destructure_const<'tcx>(
     let down = ecx.operand_downcast(op, variant).unwrap();
     let fields_iter = (0..field_count).map(|i| {
         let field_op = ecx.operand_field(down, i).unwrap();
-        op_to_const(&ecx, field_op)
+        let val = op_to_const(&ecx, field_op);
+        tcx.mk_const(ty::Const { val: ty::ConstKind::Value(val), ty: field_op.layout.ty })
     });
     let fields = tcx.arena.alloc_from_iter(fields_iter);
 
diff --git a/src/librustc_mir/const_eval/eval_queries.rs b/src/librustc_mir/const_eval/eval_queries.rs
index 2e8e4dac237..6ac828521f3 100644
--- a/src/librustc_mir/const_eval/eval_queries.rs
+++ b/src/librustc_mir/const_eval/eval_queries.rs
@@ -97,7 +97,7 @@ pub(super) fn mk_eval_cx<'mir, 'tcx>(
 pub(super) fn op_to_const<'tcx>(
     ecx: &CompileTimeEvalContext<'_, 'tcx>,
     op: OpTy<'tcx>,
-) -> &'tcx ty::Const<'tcx> {
+) -> ConstValue<'tcx> {
     // We do not have value optimizations for everything.
     // Only scalars and slices, since they are very common.
     // Note that further down we turn scalars of undefined bits back to `ByRef`. These can result
@@ -144,7 +144,7 @@ pub(super) fn op_to_const<'tcx>(
             ConstValue::Scalar(Scalar::zst())
         }
     };
-    let val = match immediate {
+    match immediate {
         Ok(mplace) => to_const_value(mplace),
         // see comment on `let try_as_immediate` above
         Err(ImmTy { imm: Immediate::Scalar(x), .. }) => match x {
@@ -166,8 +166,7 @@ pub(super) fn op_to_const<'tcx>(
             let len: usize = len.try_into().unwrap();
             ConstValue::Slice { data, start, end: start + len }
         }
-    };
-    ecx.tcx.mk_const(ty::Const { val: ty::ConstKind::Value(val), ty: op.layout.ty })
+    }
 }
 
 fn validate_and_turn_into_const<'tcx>(
@@ -195,13 +194,10 @@ fn validate_and_turn_into_const<'tcx>(
         // whether they become immediates.
         if is_static || cid.promoted.is_some() {
             let ptr = mplace.ptr.assert_ptr();
-            Ok(tcx.mk_const(ty::Const {
-                val: ty::ConstKind::Value(ConstValue::ByRef {
-                    alloc: ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id),
-                    offset: ptr.offset,
-                }),
-                ty: mplace.layout.ty,
-            }))
+            Ok(ConstValue::ByRef {
+                alloc: ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id),
+                offset: ptr.offset,
+            })
         } else {
             Ok(op_to_const(&ecx, mplace.into()))
         }
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index 206d3d15673..fc4ba4d6cd9 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -756,6 +756,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     pub(super) fn const_eval(
         &self,
         gid: GlobalId<'tcx>,
+        ty: Ty<'tcx>,
     ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
         // For statics we pick `ParamEnv::reveal_all`, because statics don't have generics
         // and thus don't care about the parameter environment. While we could just use
@@ -777,7 +778,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         // recursion deeper than one level, because the `tcx.const_eval` above is guaranteed to not
         // return `ConstValue::Unevaluated`, which is the only way that `eval_const_to_op` will call
         // `ecx.const_eval`.
-        self.eval_const_to_op(val, None)
+        let const_ = ty::Const { val: ty::ConstKind::Value(val), ty };
+        self.eval_const_to_op(&const_, None)
     }
 
     pub fn const_eval_raw(
diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs
index 1085b85d7cd..1b1481580a9 100644
--- a/src/librustc_mir/interpret/intrinsics.rs
+++ b/src/librustc_mir/interpret/intrinsics.rs
@@ -48,22 +48,15 @@ crate fn eval_nullary_intrinsic<'tcx>(
     param_env: ty::ParamEnv<'tcx>,
     def_id: DefId,
     substs: SubstsRef<'tcx>,
-) -> InterpResult<'tcx, &'tcx ty::Const<'tcx>> {
+) -> InterpResult<'tcx, ConstValue<'tcx>> {
     let tp_ty = substs.type_at(0);
     let name = tcx.item_name(def_id);
     Ok(match name {
         sym::type_name => {
             let alloc = type_name::alloc_type_name(tcx, tp_ty);
-            tcx.mk_const(ty::Const {
-                val: ty::ConstKind::Value(ConstValue::Slice {
-                    data: alloc,
-                    start: 0,
-                    end: alloc.len(),
-                }),
-                ty: tcx.mk_static_str(),
-            })
+            ConstValue::Slice { data: alloc, start: 0, end: alloc.len() }
         }
-        sym::needs_drop => ty::Const::from_bool(tcx, tp_ty.needs_drop(tcx, param_env)),
+        sym::needs_drop => ConstValue::from_bool(tp_ty.needs_drop(tcx, param_env)),
         sym::size_of | sym::min_align_of | sym::pref_align_of => {
             let layout = tcx.layout_of(param_env.and(tp_ty)).map_err(|e| err_inval!(Layout(e)))?;
             let n = match name {
@@ -72,11 +65,9 @@ crate fn eval_nullary_intrinsic<'tcx>(
                 sym::size_of => layout.size.bytes(),
                 _ => bug!(),
             };
-            ty::Const::from_usize(tcx, n)
-        }
-        sym::type_id => {
-            ty::Const::from_bits(tcx, tcx.type_id_hash(tp_ty).into(), param_env.and(tcx.types.u64))
+            ConstValue::from_machine_usize(&tcx, n)
         }
+        sym::type_id => ConstValue::from_u64(tcx.type_id_hash(tp_ty).into()),
         other => bug!("`{}` is not a zero arg intrinsic", other),
     })
 }
@@ -119,7 +110,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             | sym::type_id
             | sym::type_name => {
                 let gid = GlobalId { instance, promoted: None };
-                let val = self.const_eval(gid)?;
+                let ty = instance.ty_env(*self.tcx, self.param_env);
+                let val = self.const_eval(gid, ty)?;
                 self.copy_op(val, dest)?;
             }
 
diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs
index d1c08da6cbe..14b8a341e26 100644
--- a/src/librustc_mir/interpret/operand.rs
+++ b/src/librustc_mir/interpret/operand.rs
@@ -518,7 +518,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     /// "universe" (param_env).
     crate fn eval_const_to_op(
         &self,
-        val: &'tcx ty::Const<'tcx>,
+        val: &ty::Const<'tcx>,
         layout: Option<TyLayout<'tcx>>,
     ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
         let tag_scalar = |scalar| match scalar {
@@ -536,7 +536,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 // potentially requiring the current static to be evaluated again. This is not a
                 // problem here, because we are building an operand which means an actual read is
                 // happening.
-                return Ok(OpTy::from(self.const_eval(GlobalId { instance, promoted })?));
+                return Ok(self.const_eval(GlobalId { instance, promoted }, val.ty)?);
             }
             ty::ConstKind::Infer(..)
             | ty::ConstKind::Bound(..)
diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs
index dd2071a6c59..0fa7d6a9b72 100644
--- a/src/librustc_mir/monomorphize/collector.rs
+++ b/src/librustc_mir/monomorphize/collector.rs
@@ -357,7 +357,7 @@ fn collect_items_rec<'tcx>(
             recursion_depth_reset = None;
 
             if let Ok(val) = tcx.const_eval_poly(def_id) {
-                collect_const(tcx, val, InternalSubsts::empty(), &mut neighbors);
+                collect_const_value(tcx, val, &mut neighbors);
             }
         }
         MonoItem::Fn(instance) => {
@@ -971,7 +971,7 @@ impl ItemLikeVisitor<'v> for RootCollector<'_, 'v> {
                 let def_id = self.tcx.hir().local_def_id(item.hir_id);
 
                 if let Ok(val) = self.tcx.const_eval_poly(def_id) {
-                    collect_const(self.tcx, val, InternalSubsts::empty(), &mut self.output);
+                    collect_const_value(self.tcx, val, &mut self.output);
                 }
             }
             hir::ItemKind::Fn(..) => {
@@ -1185,18 +1185,10 @@ fn collect_const<'tcx>(
         tcx.subst_and_normalize_erasing_regions(param_substs, param_env, &constant);
 
     match substituted_constant.val {
-        ty::ConstKind::Value(ConstValue::Scalar(Scalar::Ptr(ptr))) => {
-            collect_miri(tcx, ptr.alloc_id, output)
-        }
-        ty::ConstKind::Value(ConstValue::Slice { data: alloc, start: _, end: _ })
-        | ty::ConstKind::Value(ConstValue::ByRef { alloc, .. }) => {
-            for &((), id) in alloc.relocations().values() {
-                collect_miri(tcx, id, output);
-            }
-        }
+        ty::ConstKind::Value(val) => collect_const_value(tcx, val, output),
         ty::ConstKind::Unevaluated(def_id, substs, promoted) => {
             match tcx.const_eval_resolve(param_env, def_id, substs, promoted, None) {
-                Ok(val) => collect_const(tcx, val, param_substs, output),
+                Ok(val) => collect_const_value(tcx, val, output),
                 Err(ErrorHandled::Reported) => {}
                 Err(ErrorHandled::TooGeneric) => {
                     span_bug!(tcx.def_span(def_id), "collection encountered polymorphic constant",)
@@ -1206,3 +1198,19 @@ fn collect_const<'tcx>(
         _ => {}
     }
 }
+
+fn collect_const_value<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    value: ConstValue<'tcx>,
+    output: &mut Vec<MonoItem<'tcx>>,
+) {
+    match value {
+        ConstValue::Scalar(Scalar::Ptr(ptr)) => collect_miri(tcx, ptr.alloc_id, output),
+        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_build/hair/cx/expr.rs b/src/librustc_mir_build/hair/cx/expr.rs
index d6786ea2479..74006c88371 100644
--- a/src/librustc_mir_build/hair/cx/expr.rs
+++ b/src/librustc_mir_build/hair/cx/expr.rs
@@ -418,7 +418,17 @@ fn make_mirror_unadjusted<'a, 'tcx>(
                 None,
                 Some(span),
             ) {
-                Ok(cv) => cv.eval_usize(cx.tcx, ty::ParamEnv::reveal_all()),
+                Ok(cv) => {
+                    if let Some(count) = cv.try_to_bits_for_ty(
+                        cx.tcx,
+                        ty::ParamEnv::reveal_all(),
+                        cx.tcx.types.usize,
+                    ) {
+                        count as u64
+                    } else {
+                        bug!("repeat count constant value can't be converted to usize");
+                    }
+                }
                 Err(ErrorHandled::Reported) => 0,
                 Err(ErrorHandled::TooGeneric) => {
                     let span = cx.tcx.def_span(def_id);
diff --git a/src/librustc_mir_build/hair/pattern/mod.rs b/src/librustc_mir_build/hair/pattern/mod.rs
index bd8a9877719..f403b1432c4 100644
--- a/src/librustc_mir_build/hair/pattern/mod.rs
+++ b/src/librustc_mir_build/hair/pattern/mod.rs
@@ -769,7 +769,12 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
                     Some(span),
                 ) {
                     Ok(value) => {
-                        let pattern = self.const_to_pat(value, id, span);
+                        let const_ = self.tcx.mk_const(ty::Const {
+                            val: ty::ConstKind::Value(value),
+                            ty: self.tables.node_type(id),
+                        });
+
+                        let pattern = self.const_to_pat(&const_, id, span);
                         if !is_associated_const {
                             return pattern;
                         }
@@ -789,7 +794,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
                                         user_ty_span: span,
                                     },
                                 }),
-                                ty: value.ty,
+                                ty: const_.ty,
                             }
                         } else {
                             pattern
diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs
index 90b7b300da9..dc9d5003a41 100644
--- a/src/librustc_typeck/check/expr.rs
+++ b/src/librustc_typeck/check/expr.rs
@@ -25,7 +25,7 @@ use rustc::ty;
 use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
 use rustc::ty::Ty;
 use rustc::ty::TypeFoldable;
-use rustc::ty::{AdtKind, Visibility};
+use rustc::ty::{AdtKind, ConstKind, Visibility};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, DiagnosticId};
 use rustc_hir as hir;
@@ -1011,7 +1011,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let count = if self.const_param_def_id(count).is_some() {
             Ok(self.to_const(count, tcx.type_of(count_def_id)))
         } else {
-            tcx.const_eval_poly(count_def_id)
+            tcx.const_eval_poly(count_def_id).map(|val| {
+                tcx.mk_const(ty::Const {
+                    val: ConstKind::Value(val),
+                    ty: tcx.type_of(count_def_id),
+                })
+            })
         };
 
         let uty = match expected {
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index a825856e38a..7862154a0be 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -1832,18 +1832,17 @@ fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: DefId, span: Span)
     // `#[link_section]` may contain arbitrary, or even undefined bytes, but it is
     // the consumer's responsibility to ensure all bytes that have been read
     // have defined values.
-    if let Ok(static_) = tcx.const_eval_poly(id) {
-        let alloc = if let ty::ConstKind::Value(ConstValue::ByRef { alloc, .. }) = static_.val {
-            alloc
-        } else {
-            bug!("Matching on non-ByRef static")
-        };
-        if alloc.relocations().len() != 0 {
-            let msg = "statics with a custom `#[link_section]` must be a \
+    match tcx.const_eval_poly(id) {
+        Ok(ConstValue::ByRef { alloc, .. }) => {
+            if alloc.relocations().len() != 0 {
+                let msg = "statics with a custom `#[link_section]` must be a \
                        simple list of bytes on the wasm target with no \
                        extra levels of indirection such as references";
-            tcx.sess.span_err(span, msg);
+                tcx.sess.span_err(span, msg);
+            }
         }
+        Ok(_) => bug!("Matching on non-ByRef static"),
+        Err(_) => {}
     }
 }
 
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 87edc88611f..79019d0b950 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1332,7 +1332,11 @@ impl Clean<Type> for hir::Ty<'_> {
             TyKind::Array(ref ty, ref length) => {
                 let def_id = cx.tcx.hir().local_def_id(length.hir_id);
                 let length = match cx.tcx.const_eval_poly(def_id) {
-                    Ok(length) => print_const(cx, length),
+                    Ok(length) => {
+                        let const_ =
+                            ty::Const { val: ty::ConstKind::Value(length), ty: cx.tcx.types.usize };
+                        print_const(cx, &const_)
+                    }
                     Err(_) => cx
                         .sess()
                         .source_map()
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index ef357056504..f8c657477f7 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -487,15 +487,18 @@ pub fn print_const(cx: &DocContext<'_>, n: &ty::Const<'_>) -> String {
 }
 
 pub fn print_evaluated_const(cx: &DocContext<'_>, def_id: DefId) -> Option<String> {
-    let value =
-        cx.tcx.const_eval_poly(def_id).ok().and_then(|value| match (value.val, &value.ty.kind) {
-            (_, ty::Ref(..)) => None,
-            (ty::ConstKind::Value(ConstValue::Scalar(_)), ty::Adt(_, _)) => None,
-            (ty::ConstKind::Value(ConstValue::Scalar(_)), _) => {
-                Some(print_const_with_custom_print_scalar(cx, value))
+    let value = cx.tcx.const_eval_poly(def_id).ok().and_then(|val| {
+        let ty = cx.tcx.type_of(def_id);
+        match (val, &ty.kind) {
+            (_, &ty::Ref(..)) => None,
+            (ConstValue::Scalar(_), &ty::Adt(_, _)) => None,
+            (ConstValue::Scalar(_), _) => {
+                let const_ = ty::Const { val: ty::ConstKind::Value(val), ty };
+                Some(print_const_with_custom_print_scalar(cx, &const_))
             }
             _ => None,
-        });
+        }
+    });
 
     value
 }
@@ -510,7 +513,7 @@ fn format_integer_with_underscore_sep(num: &str) -> String {
         .collect()
 }
 
-fn print_const_with_custom_print_scalar(cx: &DocContext<'_>, ct: &'tcx ty::Const<'tcx>) -> String {
+fn print_const_with_custom_print_scalar(cx: &DocContext<'_>, ct: &ty::Const<'tcx>) -> String {
     // Use a slightly different format for integer types which always shows the actual value.
     // For all other types, fallback to the original `pretty_print_const`.
     match (ct.val, &ct.ty.kind) {