diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index e747eee30f90d..a23ff6bd66d4b 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, ErrorHandled>; -pub type ConstEvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, ErrorHandled>; +pub type ConstEvalResult<'tcx> = Result, ErrorHandled>; #[derive(Debug)] pub struct ConstEvalErr<'tcx> { diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs index 2be36ad418a5b..2c146b5d7b426 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 { + 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 { + 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(i: u64, cx: &impl HasDataLayout) -> Self { + ConstValue::Scalar(Scalar::from_machine_usize(i, cx)) + } } /// A `Scalar` represents an immediate, primitive value existing outside of a @@ -287,6 +313,11 @@ impl<'tcx, Tag> Scalar { Scalar::Raw { data: i as u128, size: 8 } } + #[inline] + pub fn from_machine_usize(i: u64, cx: &impl HasDataLayout) -> Self { + Self::from_uint(i, cx.data_layout().pointer_size) + } + #[inline] pub fn try_from_int(i: impl Into, size: Size) -> Option { let i = i.into(); @@ -306,6 +337,11 @@ impl<'tcx, Tag> Scalar { .unwrap_or_else(|| bug!("Signed value {:#x} does not fit in {} bits", i, size.bits())) } + #[inline] + pub fn from_machine_isize(i: i64, cx: &impl HasDataLayout) -> Self { + Self::from_int(i, cx.data_layout().pointer_size) + } + #[inline] pub fn from_f32(f: Single) -> Self { // We trust apfloat to give us properly truncated data. diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index 11b079806af2d..d9bf93dd6793c 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -517,7 +517,7 @@ rustc_queries! { /// Extracts a field of a (variant of a) const. query const_field( key: ty::ParamEnvAnd<'tcx, (&'tcx ty::Const<'tcx>, mir::Field)> - ) -> &'tcx ty::Const<'tcx> { + ) -> ConstValue<'tcx> { no_force desc { "extract field of const" } } @@ -531,7 +531,7 @@ rustc_queries! { desc { "destructure constant" } } - query const_caller_location(key: (rustc_span::Symbol, u32, u32)) -> &'tcx ty::Const<'tcx> { + query const_caller_location(key: (rustc_span::Symbol, u32, u32)) -> ConstValue<'tcx> { no_force desc { "get a &core::panic::Location referring to a span" } } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index ad51c60ab0178..605baae6c24fa 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/query/mod.rs b/src/librustc/ty/query/mod.rs index ddaaab412a477..33312e730f209 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -14,7 +14,7 @@ use crate::middle::resolve_lifetime::{ObjectLifetimeDefault, Region, ResolveLife use crate::middle::stability::{self, DeprecationEntry}; use crate::mir; use crate::mir::interpret::GlobalId; -use crate::mir::interpret::{ConstEvalRawResult, ConstEvalResult}; +use crate::mir::interpret::{ConstEvalRawResult, ConstEvalResult, ConstValue}; use crate::mir::interpret::{LitToConstError, LitToConstInput}; use crate::mir::mono::CodegenUnit; use crate::session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion}; diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 0718853b1df59..a23c44d1921e1 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -2415,9 +2415,14 @@ pub struct Const<'tcx> { static_assert_size!(Const<'_>, 48); impl<'tcx> Const<'tcx> { + #[inline] + pub fn from_value(tcx: TyCtxt<'tcx>, val: ConstValue<'tcx>, ty: Ty<'tcx>) -> &'tcx Self { + tcx.mk_const(Self { val: ConstKind::Value(val), ty }) + } + #[inline] pub fn from_scalar(tcx: TyCtxt<'tcx>, val: Scalar, ty: Ty<'tcx>) -> &'tcx Self { - tcx.mk_const(Self { val: ConstKind::Value(ConstValue::Scalar(val)), ty }) + Self::from_value(tcx, ConstValue::Scalar(val), ty) } #[inline] @@ -2471,7 +2476,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| Const::from_value(tcx, val, self.ty)) }; match self.val { diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs index 38090cb26bc41..09a84aff16811 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 031837c1efbe8..3d1e72e1c73d7 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -193,7 +193,7 @@ 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) + OperandRef::from_const(self, ty_name, ret_ty).immediate_or_packed_pair(self) } "init" => { let ty = substs.type_at(0); diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index 916c15eb1b6ea..d684f842ddc69 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -991,7 +991,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { caller.line as u32, caller.col_display as u32 + 1, )); - OperandRef::from_const(bx, const_loc) + OperandRef::from_const(bx, const_loc, bx.tcx().caller_location_ty()) }) } diff --git a/src/librustc_codegen_ssa/mir/constant.rs b/src/librustc_codegen_ssa/mir/constant.rs index 3ce916d781279..9ceb75a603bc4 100644 --- a/src/librustc_codegen_ssa/mir/constant.rs +++ b/src/librustc_codegen_ssa/mir/constant.rs @@ -1,7 +1,7 @@ use crate::mir::operand::OperandRef; use crate::traits::*; use rustc::mir; -use rustc::mir::interpret::ErrorHandled; +use rustc::mir::interpret::{ConstValue, ErrorHandled}; use rustc::ty::layout::{self, HasTyCtxt}; use rustc::ty::{self, Ty}; use rustc_index::vec::Idx; @@ -30,7 +30,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } _ => { let val = self.eval_mir_constant(constant)?; - Ok(OperandRef::from_const(bx, val)) + let ty = self.monomorphize(&constant.literal.ty); + Ok(OperandRef::from_const(bx, val.clone(), ty)) } } } @@ -38,7 +39,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { pub fn eval_mir_constant( &mut self, constant: &mir::Constant<'tcx>, - ) -> Result<&'tcx ty::Const<'tcx>, ErrorHandled> { + ) -> Result, ErrorHandled> { match constant.literal.val { ty::ConstKind::Unevaluated(def_id, substs, promoted) => { let substs = self.monomorphize(&substs); @@ -55,7 +56,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { err }) } - _ => Ok(self.monomorphize(&constant.literal)), + ty::ConstKind::Value(value) => Ok(value), + _ => { + let const_ = self.monomorphize(&constant.literal); + if let ty::ConstKind::Value(value) = const_.val { + Ok(value) + } else { + span_bug!(constant.span, "encountered bad ConstKind in codegen: {:?}", const_); + } + } } } @@ -65,21 +74,22 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx: &Bx, span: Span, ty: Ty<'tcx>, - constant: Result<&'tcx ty::Const<'tcx>, ErrorHandled>, + constant: Result, ErrorHandled>, ) -> (Bx::Value, Ty<'tcx>) { constant - .map(|c| { - let field_ty = c.ty.builtin_index().unwrap(); - let fields = match c.ty.kind { + .map(|val| { + let field_ty = ty.builtin_index().unwrap(); + let fields = match ty.kind { ty::Array(_, n) => n.eval_usize(bx.tcx(), ty::ParamEnv::reveal_all()), - _ => bug!("invalid simd shuffle type: {}", c.ty), + _ => bug!("invalid simd shuffle type: {}", ty), }; + let c = ty::Const::from_value(bx.tcx(), val, ty); let values: Vec<_> = (0..fields) .map(|field| { let field = bx.tcx().const_field( ty::ParamEnv::reveal_all().and((&c, mir::Field::new(field as usize))), ); - if let Some(prim) = field.val.try_to_scalar() { + if let Some(prim) = field.try_to_scalar() { let layout = bx.layout_of(field_ty); let scalar = match layout.abi { layout::Abi::Scalar(ref x) => x, diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs index a33cd2ddad97b..07c8829e7d883 100644 --- a/src/librustc_codegen_ssa/mir/operand.rs +++ b/src/librustc_codegen_ssa/mir/operand.rs @@ -8,8 +8,8 @@ use crate::MemFlags; use rustc::mir; use rustc::mir::interpret::{ConstValue, ErrorHandled, Pointer, Scalar}; -use rustc::ty; use rustc::ty::layout::{self, Align, LayoutOf, Size, TyLayout}; +use rustc::ty::Ty; use std::fmt; @@ -66,20 +66,16 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { pub fn from_const>( bx: &mut Bx, - val: &'tcx ty::Const<'tcx>, + val: ConstValue<'tcx>, + ty: Ty<'tcx>, ) -> Self { - let layout = bx.layout_of(val.ty); + let layout = bx.layout_of(ty); if layout.is_zst() { return OperandRef::new_zst(bx, layout); } - let val_val = match val.val { - ty::ConstKind::Value(val_val) => val_val, - _ => bug!("encountered bad ConstKind in codegen"), - }; - - let val = match val_val { + let val = match val { ConstValue::Scalar(x) => { let scalar = match layout.abi { layout::Abi::Scalar(ref x) => x, diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index aad0e1629359a..04e2558a308b3 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -26,7 +26,7 @@ pub(crate) fn const_field<'tcx>( variant: Option, field: mir::Field, value: &'tcx ty::Const<'tcx>, -) -> &'tcx ty::Const<'tcx> { +) -> ConstValue<'tcx> { trace!("const_field: {:?}, {:?}", field, value); let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false); // get the operand again @@ -46,19 +46,13 @@ pub(crate) fn const_field<'tcx>( pub(crate) fn const_caller_location<'tcx>( tcx: TyCtxt<'tcx>, (file, line, col): (Symbol, u32, u32), -) -> &'tcx ty::Const<'tcx> { +) -> ConstValue<'tcx> { trace!("const_caller_location: {}:{}:{}", file, line, col); let mut ecx = mk_eval_cx(tcx, DUMMY_SP, ty::ParamEnv::reveal_all(), false); - let loc_ty = tcx.caller_location_ty(); let loc_place = ecx.alloc_caller_location(file, line, col); intern_const_alloc_recursive(&mut ecx, InternKind::Constant, loc_place, false).unwrap(); - let loc_const = ty::Const { - ty: loc_ty, - val: ty::ConstKind::Value(ConstValue::Scalar(loc_place.ptr.into())), - }; - - tcx.mk_const(loc_const) + ConstValue::Scalar(loc_place.ptr.into()) } // this function uses `unwrap` copiously, because an already validated constant @@ -84,7 +78,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); + ty::Const::from_value(tcx, val, 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 2e8e4dac237bc..6ac828521f326 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 206d3d156735e..fc4ba4d6cd978 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 1085b85d7cde3..04f0f92d67ff2 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(n, &tcx) } + 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,14 @@ 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 = match intrinsic_name { + sym::min_align_of | sym::pref_align_of | sym::size_of => self.tcx.types.usize, + sym::needs_drop => self.tcx.types.bool, + sym::type_id => self.tcx.types.u64, + sym::type_name => self.tcx.mk_static_str(), + _ => span_bug!(span, "Already checked for nullary intrinsics"), + }; + 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 d1c08da6cbee5..14b8a341e26a0 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>, ) -> 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 dd2071a6c596a..0fa7d6a9b7223 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>, +) { + 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/constant.rs b/src/librustc_mir_build/hair/constant.rs index 266f4738c50a6..e594e1eeed07e 100644 --- a/src/librustc_mir_build/hair/constant.rs +++ b/src/librustc_mir_build/hair/constant.rs @@ -65,7 +65,7 @@ crate fn lit_to_const<'tcx>( ast::LitKind::Char(c) => ConstValue::Scalar(Scalar::from_char(c)), ast::LitKind::Err(_) => return Err(LitToConstError::Reported), }; - Ok(tcx.mk_const(ty::Const { val: ty::ConstKind::Value(lit), ty })) + Ok(ty::Const::from_value(tcx, lit, ty)) } fn parse_float<'tcx>(num: Symbol, fty: ast::FloatTy, neg: bool) -> Result, ()> { diff --git a/src/librustc_mir_build/hair/cx/expr.rs b/src/librustc_mir_build/hair/cx/expr.rs index d6786ea247973..74006c883716c 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/_match.rs b/src/librustc_mir_build/hair/pattern/_match.rs index 7ed6c81eb63bd..85f03629b646a 100644 --- a/src/librustc_mir_build/hair/pattern/_match.rs +++ b/src/librustc_mir_build/hair/pattern/_match.rs @@ -343,12 +343,11 @@ impl<'tcx> PatternFolder<'tcx> for LiteralExpander<'tcx> { ty: rty, span: pat.span, kind: box PatKind::Constant { - value: self.tcx.mk_const(Const { - val: ty::ConstKind::Value( - self.fold_const_value_deref(*val, rty, crty), - ), - ty: rty, - }), + value: Const::from_value( + self.tcx, + self.fold_const_value_deref(*val, rty, crty), + rty, + ), }, }, }, diff --git a/src/librustc_mir_build/hair/pattern/mod.rs b/src/librustc_mir_build/hair/pattern/mod.rs index bd8a9877719e4..9101174646959 100644 --- a/src/librustc_mir_build/hair/pattern/mod.rs +++ b/src/librustc_mir_build/hair/pattern/mod.rs @@ -769,7 +769,10 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { Some(span), ) { Ok(value) => { - let pattern = self.const_to_pat(value, id, span); + let const_ = + ty::Const::from_value(self.tcx, value, self.tables.node_type(id)); + + let pattern = self.const_to_pat(&const_, id, span); if !is_associated_const { return pattern; } @@ -789,7 +792,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 90b7b300da9d5..e694d845a9b78 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -1012,6 +1012,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Ok(self.to_const(count, tcx.type_of(count_def_id))) } else { tcx.const_eval_poly(count_def_id) + .map(|val| ty::Const::from_value(tcx, val, 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 a825856e38aa0..7862154a0be6f 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 87edc88611f3a..67c9b9565db00 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1332,7 +1332,9 @@ impl Clean 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) => { + print_const(cx, ty::Const::from_value(cx.tcx, length, cx.tcx.types.usize)) + } Err(_) => cx .sess() .source_map() diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index ef35705650452..704583467b4f3 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -457,7 +457,7 @@ pub fn name_from_pat(p: &hir::Pat) -> String { } } -pub fn print_const(cx: &DocContext<'_>, n: &ty::Const<'_>) -> String { +pub fn print_const(cx: &DocContext<'_>, n: &'tcx ty::Const<'_>) -> String { match n.val { ty::ConstKind::Unevaluated(def_id, _, promoted) => { let mut s = if let Some(hir_id) = cx.tcx.hir().as_local_hir_id(def_id) { @@ -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 { - 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::from_value(cx.tcx, val, ty); + Some(print_const_with_custom_print_scalar(cx, const_)) } _ => None, - }); + } + }); value }