diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index b0639cf9e15..23ad5267c56 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -8,7 +8,7 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::interpret::{ read_target_uint, AllocId, Allocation, ConstValue, ErrorHandled, GlobalAlloc, Pointer, Scalar, }; -use rustc_middle::ty::{Const, ConstKind}; +use rustc_middle::ty::ConstKind; use cranelift_codegen::ir::GlobalValueData; use cranelift_module::*; @@ -39,7 +39,10 @@ impl ConstantCx { pub(crate) fn check_constants(fx: &mut FunctionCx<'_, '_, '_>) -> bool { let mut all_constants_ok = true; for constant in &fx.mir.required_consts { - let const_ = fx.monomorphize(constant.literal); + let const_ = match fx.monomorphize(constant.literal) { + ConstantSource::Ty(ct) => ct, + ConstantSource::Val(..) => continue, + }; match const_.val { ConstKind::Value(_) => {} ConstKind::Unevaluated(def, ref substs, promoted) => { @@ -113,19 +116,17 @@ pub(crate) fn codegen_constant<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, constant: &Constant<'tcx>, ) -> CValue<'tcx> { - let const_ = fx.monomorphize(constant.literal); + let const_ = match fx.monomorphize(constant.literal) { + ConstantSource::Ty(ct) => ct, + ConstantSource::Val(val, ty) => return codegen_const_value(fx, val, ty), + }; let const_val = match const_.val { ConstKind::Value(const_val) => const_val, ConstKind::Unevaluated(def, ref substs, promoted) if fx.tcx.is_static(def.did) => { assert!(substs.is_empty()); assert!(promoted.is_none()); - return codegen_static_ref( - fx, - def.did, - fx.layout_of(fx.monomorphize(&constant.literal.ty)), - ) - .to_cvalue(fx); + return codegen_static_ref(fx, def.did, fx.layout_of(const_.ty)).to_cvalue(fx); } ConstKind::Unevaluated(def, ref substs, promoted) => { match fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), def, substs, promoted, None) { @@ -422,11 +423,14 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant pub(crate) fn mir_operand_get_const_val<'tcx>( fx: &FunctionCx<'_, '_, 'tcx>, operand: &Operand<'tcx>, -) -> Option<&'tcx Const<'tcx>> { +) -> Option> { match operand { Operand::Copy(_) | Operand::Move(_) => None, - Operand::Constant(const_) => { - Some(fx.monomorphize(const_.literal).eval(fx.tcx, ParamEnv::reveal_all())) - } + Operand::Constant(const_) => match const_.literal { + ConstantSource::Ty(const_) => { + fx.monomorphize(const_).eval(fx.tcx, ParamEnv::reveal_all()).val.try_to_value() + } + ConstantSource::Val(val, _) => Some(val), + }, } } diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs index 0692da397eb..83c91f789cd 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs @@ -53,7 +53,7 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>( }; llvm.x86.sse2.cmp.ps | llvm.x86.sse2.cmp.pd, (c x, c y, o kind) { let kind_const = crate::constant::mir_operand_get_const_val(fx, kind).expect("llvm.x86.sse2.cmp.* kind not const"); - let flt_cc = match kind_const.val.try_to_bits(Size::from_bytes(1)).unwrap_or_else(|| panic!("kind not scalar: {:?}", kind_const)) { + let flt_cc = match kind_const.try_to_bits(Size::from_bytes(1)).unwrap_or_else(|| panic!("kind not scalar: {:?}", kind_const)) { 0 => FloatCC::Equal, 1 => FloatCC::LessThan, 2 => FloatCC::LessThanOrEqual, @@ -84,7 +84,7 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>( llvm.x86.sse2.psrli.d, (c a, o imm8) { let imm8 = crate::constant::mir_operand_get_const_val(fx, imm8).expect("llvm.x86.sse2.psrli.d imm8 not const"); simd_for_each_lane(fx, a, ret, |fx, _lane_layout, res_lane_layout, lane| { - let res_lane = match imm8.val.try_to_bits(Size::from_bytes(4)).unwrap_or_else(|| panic!("imm8 not scalar: {:?}", imm8)) { + let res_lane = match imm8.try_to_bits(Size::from_bytes(4)).unwrap_or_else(|| panic!("imm8 not scalar: {:?}", imm8)) { imm8 if imm8 < 32 => fx.bcx.ins().ushr_imm(lane, i64::from(imm8 as u8)), _ => fx.bcx.ins().iconst(types::I32, 0), }; @@ -94,7 +94,7 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>( llvm.x86.sse2.pslli.d, (c a, o imm8) { let imm8 = crate::constant::mir_operand_get_const_val(fx, imm8).expect("llvm.x86.sse2.psrli.d imm8 not const"); simd_for_each_lane(fx, a, ret, |fx, _lane_layout, res_lane_layout, lane| { - let res_lane = match imm8.val.try_to_bits(Size::from_bytes(4)).unwrap_or_else(|| panic!("imm8 not scalar: {:?}", imm8)) { + let res_lane = match imm8.try_to_bits(Size::from_bytes(4)).unwrap_or_else(|| panic!("imm8 not scalar: {:?}", imm8)) { imm8 if imm8 < 32 => fx.bcx.ins().ishl_imm(lane, i64::from(imm8 as u8)), _ => fx.bcx.ins().iconst(types::I32, 0), }; diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs index 1f8eeb1e714..d17136080fe 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs @@ -85,8 +85,8 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( use rustc_middle::mir::interpret::*; let idx_const = crate::constant::mir_operand_get_const_val(fx, idx).expect("simd_shuffle* idx not const"); - let idx_bytes = match idx_const.val { - ty::ConstKind::Value(ConstValue::ByRef { alloc, offset }) => { + let idx_bytes = match idx_const { + ConstValue::ByRef { alloc, offset } => { let ptr = Pointer::new(AllocId(0 /* dummy */), offset); let size = Size::from_bytes(4 * u64::from(ret_lane_count) /* size_of([u32; ret_lane_count]) */); alloc.get_bytes(fx, ptr, size).unwrap() @@ -130,7 +130,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( ); }; - let idx = idx_const.val.try_to_bits(Size::from_bytes(4 /* u32*/)).unwrap_or_else(|| panic!("kind not scalar: {:?}", idx_const)); + let idx = idx_const.try_to_bits(Size::from_bytes(4 /* u32*/)).unwrap_or_else(|| panic!("kind not scalar: {:?}", idx_const)); let (lane_count, _lane_ty) = base.layout().ty.simd_size_and_type(fx.tcx); if idx >= lane_count.into() { fx.tcx.sess.span_fatal(fx.mir.span, &format!("[simd_insert] idx {} >= lane_count {}", idx, lane_count)); @@ -159,7 +159,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( return; }; - let idx = idx_const.val.try_to_bits(Size::from_bytes(4 /* u32*/)).unwrap_or_else(|| panic!("kind not scalar: {:?}", idx_const)); + let idx = idx_const.try_to_bits(Size::from_bytes(4 /* u32*/)).unwrap_or_else(|| panic!("kind not scalar: {:?}", idx_const)); let (lane_count, _lane_ty) = v.layout().ty.simd_size_and_type(fx.tcx); if idx >= lane_count.into() { fx.tcx.sess.span_fatal(fx.mir.span, &format!("[simd_extract] idx {} >= lane_count {}", idx, lane_count)); diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index fc4fc08bb0a..04225ddd36f 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -860,7 +860,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } mir::InlineAsmOperand::SymFn { ref value } => { let literal = self.monomorphize(value.literal); - if let ty::FnDef(def_id, substs) = *literal.ty.kind() { + if let ty::FnDef(def_id, substs) = *literal.ty().kind() { let instance = ty::Instance::resolve_for_fn_ptr( bx.tcx(), ty::ParamEnv::reveal_all(), diff --git a/compiler/rustc_codegen_ssa/src/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs index 114f6a4032a..d73e2325a8b 100644 --- a/compiler/rustc_codegen_ssa/src/mir/constant.rs +++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs @@ -24,7 +24,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { &self, constant: &mir::Constant<'tcx>, ) -> Result, ErrorHandled> { - match self.monomorphize(constant.literal).val { + let ct = self.monomorphize(constant.literal); + let ct = match ct { + mir::ConstantSource::Ty(ct) => ct, + mir::ConstantSource::Val(val, _) => return Ok(val), + }; + match ct.val { ty::ConstKind::Unevaluated(def, substs, promoted) => self .cx .tcx() diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs index c7b1005fffc..cddcc7d576a 100644 --- a/compiler/rustc_middle/src/mir/interpret/value.rs +++ b/compiler/rustc_middle/src/mir/interpret/value.rs @@ -47,7 +47,25 @@ pub enum ConstValue<'tcx> { #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] static_assert_size!(ConstValue<'_>, 32); +impl From for ConstValue<'tcx> { + fn from(s: Scalar) -> Self { + Self::Scalar(s) + } +} + impl<'tcx> ConstValue<'tcx> { + pub fn lift<'lifted>(self, tcx: TyCtxt<'lifted>) -> Option> { + Some(match self { + ConstValue::Scalar(s) => ConstValue::Scalar(s), + ConstValue::Slice { data, start, end } => { + ConstValue::Slice { data: tcx.lift(data)?, start, end } + } + ConstValue::ByRef { alloc, offset } => { + ConstValue::ByRef { alloc: tcx.lift(alloc)?, offset } + } + }) + } + #[inline] pub fn try_to_scalar(&self) -> Option { match *self { diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 44794628e46..20ba82a8e86 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -11,12 +11,12 @@ use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; use crate::ty::print::{FmtPrinter, Printer}; use crate::ty::subst::{Subst, SubstsRef}; use crate::ty::{self, List, Ty, TyCtxt}; -use crate::ty::{AdtDef, InstanceDef, Region, UserTypeAnnotationIndex}; +use crate::ty::{AdtDef, InstanceDef, Region, ScalarInt, UserTypeAnnotationIndex}; use rustc_hir as hir; use rustc_hir::def::{CtorKind, Namespace}; use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX}; use rustc_hir::{self, GeneratorKind}; -use rustc_target::abi::VariantIdx; +use rustc_target::abi::{Size, VariantIdx}; use polonius_engine::Atom; pub use rustc_ast::Mutability; @@ -30,6 +30,7 @@ use rustc_span::symbol::Symbol; use rustc_span::{Span, DUMMY_SP}; use rustc_target::asm::InlineAsmRegOrRegClass; use std::borrow::Cow; +use std::convert::TryInto; use std::fmt::{self, Debug, Display, Formatter, Write}; use std::ops::{ControlFlow, Index, IndexMut}; use std::slice; @@ -2032,7 +2033,7 @@ impl<'tcx> Operand<'tcx> { Operand::Constant(box Constant { span, user_ty: None, - literal: ty::Const::zero_sized(tcx, ty), + literal: ConstantSource::Ty(ty::Const::zero_sized(tcx, ty)), }) } @@ -2063,7 +2064,7 @@ impl<'tcx> Operand<'tcx> { Operand::Constant(box Constant { span, user_ty: None, - literal: ty::Const::from_scalar(tcx, val, ty), + literal: ConstantSource::Val(val.into(), ty), }) } @@ -2405,12 +2406,21 @@ pub struct Constant<'tcx> { /// Needed for NLL to impose user-given type constraints. pub user_ty: Option, - pub literal: &'tcx ty::Const<'tcx>, + pub literal: ConstantSource<'tcx>, +} + +#[derive(Clone, Copy, PartialEq, PartialOrd, TyEncodable, TyDecodable, Hash, HashStable, Debug)] +pub enum ConstantSource<'tcx> { + /// This constant came from the type system + Ty(&'tcx ty::Const<'tcx>), + /// This constant cannot go back into the type system, as it represents + /// something the type system cannot handle (e.g. pointers). + Val(interpret::ConstValue<'tcx>, Ty<'tcx>), } impl Constant<'tcx> { pub fn check_static_ptr(&self, tcx: TyCtxt<'_>) -> Option { - match self.literal.val.try_to_scalar() { + match self.literal.const_for_ty()?.val.try_to_scalar() { Some(Scalar::Ptr(ptr)) => match tcx.global_alloc(ptr.alloc_id) { GlobalAlloc::Static(def_id) => { assert!(!tcx.is_thread_local_static(def_id)); @@ -2422,7 +2432,92 @@ impl Constant<'tcx> { } } pub fn ty(&self) -> Ty<'tcx> { - self.literal.ty + self.literal.ty() + } +} + +impl From<&'tcx ty::Const<'tcx>> for ConstantSource<'tcx> { + fn from(ct: &'tcx ty::Const<'tcx>) -> Self { + Self::Ty(ct) + } +} + +impl ConstantSource<'tcx> { + /// Returns `None` if the constant is not trivially safe for use in the type system. + pub fn const_for_ty(&self) -> Option<&'tcx ty::Const<'tcx>> { + match self { + ConstantSource::Ty(c) => Some(c), + ConstantSource::Val(..) => None, + } + } + + pub fn ty(&self) -> Ty<'tcx> { + match self { + ConstantSource::Ty(c) => c.ty, + ConstantSource::Val(_, ty) => ty, + } + } + + #[inline] + pub fn try_to_value(self) -> Option> { + match self { + ConstantSource::Ty(c) => c.val.try_to_value(), + ConstantSource::Val(val, _) => Some(val), + } + } + + #[inline] + pub fn try_to_scalar(self) -> Option { + self.try_to_value()?.try_to_scalar() + } + + #[inline] + pub fn try_to_scalar_int(self) -> Option { + self.try_to_value()?.try_to_scalar()?.to_int().ok() + } + + #[inline] + pub fn try_to_bits(self, size: Size) -> Option { + self.try_to_scalar_int()?.to_bits(size).ok() + } + + #[inline] + pub fn try_to_bool(self) -> Option { + self.try_to_scalar_int()?.try_into().ok() + } + + #[inline] + pub fn try_eval_bits( + &self, + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + ty: Ty<'tcx>, + ) -> Option { + match self { + Self::Ty(ct) => ct.try_eval_bits(tcx, param_env, ty), + Self::Val(val, t) => { + assert_eq!(*t, ty); + let size = + tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size; + val.try_to_bits(size) + } + } + } + + #[inline] + pub fn try_eval_bool(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Option { + match self { + Self::Ty(ct) => ct.try_eval_bool(tcx, param_env), + Self::Val(val, _) => val.try_to_bool(), + } + } + + #[inline] + pub fn try_eval_usize(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Option { + match self { + Self::Ty(ct) => ct.try_eval_usize(tcx, param_env), + Self::Val(val, _) => val.try_to_machine_usize(tcx), + } } } @@ -2609,11 +2704,14 @@ impl<'tcx> Debug for Constant<'tcx> { impl<'tcx> Display for Constant<'tcx> { fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { - match self.literal.ty.kind() { + match self.ty().kind() { ty::FnDef(..) => {} _ => write!(fmt, "const ")?, } - pretty_print_const(self.literal, fmt, true) + match self.literal { + ConstantSource::Ty(c) => pretty_print_const(c, fmt, true), + ConstantSource::Val(val, ty) => pretty_print_const_value(val, ty, fmt, true), + } } } @@ -2632,6 +2730,23 @@ fn pretty_print_const( }) } +fn pretty_print_const_value( + val: interpret::ConstValue<'tcx>, + ty: Ty<'tcx>, + fmt: &mut Formatter<'_>, + print_types: bool, +) -> fmt::Result { + use crate::ty::print::PrettyPrinter; + ty::tls::with(|tcx| { + let val = val.lift(tcx).unwrap(); + let ty = tcx.lift(ty).unwrap(); + let mut cx = FmtPrinter::new(tcx, fmt, Namespace::ValueNS); + cx.print_alloc_ids = true; + cx.pretty_print_const_value(val, ty, print_types)?; + Ok(()) + }) +} + impl<'tcx> graph::DirectedGraph for Body<'tcx> { type Node = BasicBlock; } diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs index 3961fd938be..6e819145976 100644 --- a/compiler/rustc_middle/src/mir/tcx.rs +++ b/compiler/rustc_middle/src/mir/tcx.rs @@ -227,7 +227,7 @@ impl<'tcx> Operand<'tcx> { { match self { &Operand::Copy(ref l) | &Operand::Move(ref l) => l.ty(local_decls, tcx).ty, - &Operand::Constant(ref c) => c.literal.ty, + &Operand::Constant(ref c) => c.literal.ty(), } } } diff --git a/compiler/rustc_middle/src/mir/type_foldable.rs b/compiler/rustc_middle/src/mir/type_foldable.rs index 6fabddbd149..4ad69a2cb98 100644 --- a/compiler/rustc_middle/src/mir/type_foldable.rs +++ b/compiler/rustc_middle/src/mir/type_foldable.rs @@ -343,5 +343,22 @@ impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> { } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { self.literal.visit_with(visitor) + // FIXME: should this be visiting the `user_ty`, too? + } +} + +impl<'tcx> TypeFoldable<'tcx> for ConstantSource<'tcx> { + fn super_fold_with>(self, folder: &mut F) -> Self { + match self { + ConstantSource::Ty(c) => ConstantSource::Ty(c.fold_with(folder)), + ConstantSource::Val(v, t) => ConstantSource::Val(v, t.fold_with(folder)), + } + } + + fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { + match *self { + ConstantSource::Ty(c) => c.visit_with(visitor), + ConstantSource::Val(_, t) => t.visit_with(visitor), + } } } diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 4e81612c0b9..9015e771864 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -871,7 +871,10 @@ macro_rules! make_mir_visitor { self.visit_span(span); drop(user_ty); // no visit method for this - self.visit_const(literal, location); + match literal { + ConstantSource::Ty(ct) => self.visit_const(ct, location), + ConstantSource::Val(_, t) => self.visit_ty(t, TyContext::Location(location)), + } } fn super_span(&mut self, _span: & $($mutability)? Span) { diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs index 04ea3cbd8b6..bc15b3972c9 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs @@ -81,12 +81,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let terminator = self.body[location.block].terminator(); debug!("add_moved_or_invoked_closure_note: terminator={:?}", terminator); if let TerminatorKind::Call { - func: Operand::Constant(box Constant { literal: ty::Const { ty: const_ty, .. }, .. }), + func: Operand::Constant(box Constant { literal, .. }), args, .. } = &terminator.kind { - if let ty::FnDef(id, _) = *const_ty.kind() { + if let ty::FnDef(id, _) = *literal.ty().kind() { debug!("add_moved_or_invoked_closure_note: id={:?}", id); if self.infcx.tcx.parent(id) == self.infcx.tcx.lang_items().fn_once_trait() { let closure = match args.first() { diff --git a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs index ab7e75bf4f1..d744db064b6 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs @@ -282,7 +282,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) { self.super_constant(constant, location); - let ty = self.sanitize_type(constant, constant.literal.ty); + let ty = self.sanitize_type(constant, constant.literal.ty()); self.cx.infcx.tcx.for_each_free_region(&ty, |live_region| { let live_region_vid = @@ -296,7 +296,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { if let Some(annotation_index) = constant.user_ty { if let Err(terr) = self.cx.relate_type_and_user_type( - constant.literal.ty, + constant.literal.ty(), ty::Variance::Invariant, &UserTypeProjection { base: annotation_index, projs: vec![] }, location.to_locations(), @@ -308,13 +308,22 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { constant, "bad constant user type {:?} vs {:?}: {:?}", annotation, - constant.literal.ty, + constant.literal.ty(), terr, ); } } else { let tcx = self.tcx(); - if let ty::ConstKind::Unevaluated(def, substs, promoted) = constant.literal.val { + let maybe_uneval = match constant.literal { + ConstantSource::Ty(ct) => match ct.val { + ty::ConstKind::Unevaluated(def, substs, promoted) => { + Some((def, substs, promoted)) + } + _ => None, + }, + _ => None, + }; + if let Some((def, substs, promoted)) = maybe_uneval { if let Some(promoted) = promoted { let check_err = |verifier: &mut TypeVerifier<'a, 'b, 'tcx>, promoted: &Body<'tcx>, @@ -349,7 +358,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { location.to_locations(), ConstraintCategory::Boring, self.cx.param_env.and(type_op::ascribe_user_type::AscribeUserType::new( - constant.literal.ty, + constant.literal.ty(), def.did, UserSubsts { substs, user_self_ty: None }, )), @@ -367,7 +376,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { let unnormalized_ty = tcx.type_of(static_def_id); let locations = location.to_locations(); let normalized_ty = self.cx.normalize(unnormalized_ty, locations); - let literal_ty = constant.literal.ty.builtin_deref(true).unwrap().ty; + let literal_ty = constant.literal.ty().builtin_deref(true).unwrap().ty; if let Err(terr) = self.cx.eq_types( normalized_ty, @@ -379,7 +388,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { } } - if let ty::FnDef(def_id, substs) = *constant.literal.ty.kind() { + if let ty::FnDef(def_id, substs) = *constant.literal.ty().kind() { let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, substs); self.cx.normalize_and_prove_instantiated_predicates( instantiated_predicates, diff --git a/compiler/rustc_mir/src/interpret/eval_context.rs b/compiler/rustc_mir/src/interpret/eval_context.rs index 6b796eb3721..149a9f81ea0 100644 --- a/compiler/rustc_mir/src/interpret/eval_context.rs +++ b/compiler/rustc_mir/src/interpret/eval_context.rs @@ -689,7 +689,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let span = const_.span; let const_ = self.subst_from_current_frame_and_normalize_erasing_regions(const_.literal); - self.const_to_op(const_, None).map_err(|err| { + self.mir_const_to_op(&const_, None).map_err(|err| { // If there was an error, set the span of the current frame to this constant. // Avoiding doing this when evaluation succeeds. self.frame_mut().loc = Err(span); diff --git a/compiler/rustc_mir/src/interpret/operand.rs b/compiler/rustc_mir/src/interpret/operand.rs index 2c4aba19e4a..69ab2abaf27 100644 --- a/compiler/rustc_mir/src/interpret/operand.rs +++ b/compiler/rustc_mir/src/interpret/operand.rs @@ -532,7 +532,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // * During ConstProp, with `TooGeneric` or since the `requried_consts` were not all // checked yet. // * During CTFE, since promoteds in `const`/`static` initializer bodies can fail. - self.const_to_op(val, layout)? + + self.mir_const_to_op(&val, layout)? } }; trace!("{:?}: {:?}", mir_op, *op); @@ -556,28 +557,45 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { val: &ty::Const<'tcx>, layout: Option>, ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> { + match val.val { + ty::ConstKind::Param(_) | ty::ConstKind::Bound(..) => throw_inval!(TooGeneric), + ty::ConstKind::Error(_) => throw_inval!(AlreadyReported(ErrorReported)), + ty::ConstKind::Unevaluated(def, substs, promoted) => { + let instance = self.resolve(def, substs)?; + Ok(self.eval_to_allocation(GlobalId { instance, promoted })?.into()) + } + ty::ConstKind::Infer(..) | ty::ConstKind::Placeholder(..) => { + span_bug!(self.cur_span(), "const_to_op: Unexpected ConstKind {:?}", val) + } + ty::ConstKind::Value(val_val) => self.const_val_to_op(val_val, val.ty, layout), + } + } + + crate fn mir_const_to_op( + &self, + val: &mir::ConstantSource<'tcx>, + layout: Option>, + ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> { + match val { + mir::ConstantSource::Ty(ct) => self.const_to_op(ct, layout), + mir::ConstantSource::Val(val, ty) => self.const_val_to_op(*val, ty, None), + } + } + + crate fn const_val_to_op( + &self, + val_val: ConstValue<'tcx>, + ty: Ty<'tcx>, + layout: Option>, + ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> { + // Other cases need layout. let tag_scalar = |scalar| -> InterpResult<'tcx, _> { Ok(match scalar { Scalar::Ptr(ptr) => Scalar::Ptr(self.global_base_pointer(ptr)?), Scalar::Int(int) => Scalar::Int(int), }) }; - // Early-return cases. - let val_val = match val.val { - ty::ConstKind::Param(_) | ty::ConstKind::Bound(..) => throw_inval!(TooGeneric), - ty::ConstKind::Error(_) => throw_inval!(AlreadyReported(ErrorReported)), - ty::ConstKind::Unevaluated(def, substs, promoted) => { - let instance = self.resolve(def, substs)?; - return Ok(self.eval_to_allocation(GlobalId { instance, promoted })?.into()); - } - ty::ConstKind::Infer(..) | ty::ConstKind::Placeholder(..) => { - span_bug!(self.cur_span(), "const_to_op: Unexpected ConstKind {:?}", val) - } - ty::ConstKind::Value(val_val) => val_val, - }; - // Other cases need layout. - let layout = - from_known_layout(self.tcx, self.param_env, layout, || self.layout_of(val.ty))?; + let layout = from_known_layout(self.tcx, self.param_env, layout, || self.layout_of(ty))?; let op = match val_val { ConstValue::ByRef { alloc, offset } => { let id = self.tcx.create_memory_alloc(alloc); diff --git a/compiler/rustc_mir/src/monomorphize/collector.rs b/compiler/rustc_mir/src/monomorphize/collector.rs index 20cb989196a..911224d8c1f 100644 --- a/compiler/rustc_mir/src/monomorphize/collector.rs +++ b/compiler/rustc_mir/src/monomorphize/collector.rs @@ -684,7 +684,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { for op in operands { match *op { mir::InlineAsmOperand::SymFn { ref value } => { - let fn_ty = self.monomorphize(value.literal.ty); + let fn_ty = self.monomorphize(value.literal.ty()); visit_fn_use(self.tcx, fn_ty, false, source, &mut self.output); } mir::InlineAsmOperand::SymStatic { def_id } => { diff --git a/compiler/rustc_mir/src/shim.rs b/compiler/rustc_mir/src/shim.rs index 0dbd7ce7f1d..796d024771d 100644 --- a/compiler/rustc_mir/src/shim.rs +++ b/compiler/rustc_mir/src/shim.rs @@ -421,7 +421,7 @@ impl CloneShimBuilder<'tcx> { let func = Operand::Constant(box Constant { span: self.span, user_ty: None, - literal: ty::Const::zero_sized(tcx, func_ty), + literal: ty::Const::zero_sized(tcx, func_ty).into(), }); let ref_loc = self.make_place( @@ -478,7 +478,7 @@ impl CloneShimBuilder<'tcx> { box Constant { span: self.span, user_ty: None, - literal: ty::Const::from_usize(self.tcx, value), + literal: ty::Const::from_usize(self.tcx, value).into(), } } @@ -509,7 +509,7 @@ impl CloneShimBuilder<'tcx> { Rvalue::Use(Operand::Constant(box Constant { span: self.span, user_ty: None, - literal: len, + literal: len.into(), })), ))), ]; @@ -768,7 +768,7 @@ fn build_call_shim<'tcx>( Operand::Constant(box Constant { span, user_ty: None, - literal: ty::Const::zero_sized(tcx, ty), + literal: ty::Const::zero_sized(tcx, ty).into(), }), rcvr.into_iter().collect::>(), ) diff --git a/compiler/rustc_mir/src/transform/check_consts/qualifs.rs b/compiler/rustc_mir/src/transform/check_consts/qualifs.rs index 13d7166b4b5..748f65cba22 100644 --- a/compiler/rustc_mir/src/transform/check_consts/qualifs.rs +++ b/compiler/rustc_mir/src/transform/check_consts/qualifs.rs @@ -246,25 +246,27 @@ where }; // Check the qualifs of the value of `const` items. - if let ty::ConstKind::Unevaluated(def, _, promoted) = constant.literal.val { - assert!(promoted.is_none()); - // Don't peek inside trait associated constants. - if cx.tcx.trait_of_item(def.did).is_none() { - let qualifs = if let Some((did, param_did)) = def.as_const_arg() { - cx.tcx.at(constant.span).mir_const_qualif_const_arg((did, param_did)) - } else { - cx.tcx.at(constant.span).mir_const_qualif(def.did) - }; + if let Some(ct) = constant.literal.const_for_ty() { + if let ty::ConstKind::Unevaluated(def, _, promoted) = ct.val { + assert!(promoted.is_none()); + // Don't peek inside trait associated constants. + if cx.tcx.trait_of_item(def.did).is_none() { + let qualifs = if let Some((did, param_did)) = def.as_const_arg() { + cx.tcx.at(constant.span).mir_const_qualif_const_arg((did, param_did)) + } else { + cx.tcx.at(constant.span).mir_const_qualif(def.did) + }; - if !Q::in_qualifs(&qualifs) { - return false; + if !Q::in_qualifs(&qualifs) { + return false; + } + + // Just in case the type is more specific than + // the definition, e.g., impl associated const + // with type parameters, take it into account. } - - // Just in case the type is more specific than - // the definition, e.g., impl associated const - // with type parameters, take it into account. } } // Otherwise use the qualifs of the type. - Q::in_any_value_of_ty(cx, constant.literal.ty) + Q::in_any_value_of_ty(cx, constant.literal.ty()) } diff --git a/compiler/rustc_mir/src/transform/const_prop.rs b/compiler/rustc_mir/src/transform/const_prop.rs index 9d03b1b027e..0d5c8953bc6 100644 --- a/compiler/rustc_mir/src/transform/const_prop.rs +++ b/compiler/rustc_mir/src/transform/const_prop.rs @@ -13,9 +13,9 @@ use rustc_middle::mir::visit::{ MutVisitor, MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor, }; use rustc_middle::mir::{ - AssertKind, BasicBlock, BinOp, Body, ClearCrossCrate, Constant, Local, LocalDecl, LocalKind, - Location, Operand, Place, Rvalue, SourceInfo, SourceScope, SourceScopeData, Statement, - StatementKind, Terminator, TerminatorKind, UnOp, RETURN_PLACE, + AssertKind, BasicBlock, BinOp, Body, ClearCrossCrate, Constant, ConstantSource, Local, + LocalDecl, LocalKind, Location, Operand, Place, Rvalue, SourceInfo, SourceScope, + SourceScopeData, Statement, StatementKind, Terminator, TerminatorKind, UnOp, RETURN_PLACE, }; use rustc_middle::ty::layout::{HasTyCtxt, LayoutError, TyAndLayout}; use rustc_middle::ty::subst::{InternalSubsts, Subst}; @@ -482,18 +482,21 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { return None; } - match self.ecx.const_to_op(c.literal, None) { + match self.ecx.mir_const_to_op(&c.literal, None) { Ok(op) => Some(op), Err(error) => { let tcx = self.ecx.tcx.at(c.span); let err = ConstEvalErr::new(&self.ecx, error, Some(c.span)); if let Some(lint_root) = self.lint_root(source_info) { - let lint_only = match c.literal.val { - // Promoteds must lint and not error as the user didn't ask for them - ConstKind::Unevaluated(_, _, Some(_)) => true, - // Out of backwards compatibility we cannot report hard errors in unused - // generic functions using associated constants of the generic parameters. - _ => c.literal.needs_subst(), + let lint_only = match c.literal { + ConstantSource::Ty(ct) => match ct.val { + // Promoteds must lint and not error as the user didn't ask for them + ConstKind::Unevaluated(_, _, Some(_)) => true, + // Out of backwards compatibility we cannot report hard errors in unused + // generic functions using associated constants of the generic parameters. + _ => c.literal.needs_subst(), + }, + ConstantSource::Val(_, ty) => ty.needs_subst(), }; if lint_only { // Out of backwards compatibility we cannot report hard errors in unused @@ -803,7 +806,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { Operand::Constant(Box::new(Constant { span, user_ty: None, - literal: ty::Const::from_scalar(self.tcx, scalar, ty), + literal: ty::Const::from_scalar(self.tcx, scalar, ty).into(), })) } @@ -814,9 +817,12 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { source_info: SourceInfo, ) { if let Rvalue::Use(Operand::Constant(c)) = rval { - if !matches!(c.literal.val, ConstKind::Unevaluated(..)) { - trace!("skipping replace of Rvalue::Use({:?} because it is already a const", c); - return; + match c.literal { + ConstantSource::Ty(c) if matches!(c.val, ConstKind::Unevaluated(..)) => {} + _ => { + trace!("skipping replace of Rvalue::Use({:?} because it is already a const", c); + return; + } } } @@ -883,13 +889,17 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { *rval = Rvalue::Use(Operand::Constant(Box::new(Constant { span: source_info.span, user_ty: None, - literal: self.ecx.tcx.mk_const(ty::Const { - ty, - val: ty::ConstKind::Value(ConstValue::ByRef { - alloc, - offset: Size::ZERO, - }), - }), + literal: self + .ecx + .tcx + .mk_const(ty::Const { + ty, + val: ty::ConstKind::Value(ConstValue::ByRef { + alloc, + offset: Size::ZERO, + }), + }) + .into(), }))); } } diff --git a/compiler/rustc_mir/src/transform/elaborate_drops.rs b/compiler/rustc_mir/src/transform/elaborate_drops.rs index 3d435f6d0e7..c0fcfb620ff 100644 --- a/compiler/rustc_mir/src/transform/elaborate_drops.rs +++ b/compiler/rustc_mir/src/transform/elaborate_drops.rs @@ -471,7 +471,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { Rvalue::Use(Operand::Constant(Box::new(Constant { span, user_ty: None, - literal: ty::Const::from_bool(self.tcx, val), + literal: ty::Const::from_bool(self.tcx, val).into(), }))) } diff --git a/compiler/rustc_mir/src/transform/generator.rs b/compiler/rustc_mir/src/transform/generator.rs index f299b6ecc28..c85e9b9b932 100644 --- a/compiler/rustc_mir/src/transform/generator.rs +++ b/compiler/rustc_mir/src/transform/generator.rs @@ -989,7 +989,7 @@ fn insert_panic_block<'tcx>( cond: Operand::Constant(box Constant { span: body.span, user_ty: None, - literal: ty::Const::from_bool(tcx, false), + literal: ty::Const::from_bool(tcx, false).into(), }), expected: true, msg: message, diff --git a/compiler/rustc_mir/src/transform/inline.rs b/compiler/rustc_mir/src/transform/inline.rs index cf85503b3d5..dd06daecd5d 100644 --- a/compiler/rustc_mir/src/transform/inline.rs +++ b/compiler/rustc_mir/src/transform/inline.rs @@ -416,7 +416,7 @@ impl Inliner<'tcx> { TerminatorKind::Call { func: Operand::Constant(ref f), cleanup, .. } => { if let ty::FnDef(def_id, substs) = - *callsite.callee.subst_mir(self.tcx, &f.literal.ty).kind() + *callsite.callee.subst_mir(self.tcx, &f.literal.ty()).kind() { let substs = self.tcx.normalize_erasing_regions(self.param_env, substs); if let Ok(Some(instance)) = @@ -637,8 +637,11 @@ impl Inliner<'tcx> { // `required_consts`, here we may not only have `ConstKind::Unevaluated` // because we are calling `subst_and_normalize_erasing_regions`. caller_body.required_consts.extend( - callee_body.required_consts.iter().copied().filter(|&constant| { - matches!(constant.literal.val, ConstKind::Unevaluated(_, _, _)) + callee_body.required_consts.iter().copied().filter(|&ct| { + match ct.literal.const_for_ty() { + Some(ct) => matches!(ct.val, ConstKind::Unevaluated(_, _, _)), + None => true, + } }), ); } diff --git a/compiler/rustc_mir/src/transform/instcombine.rs b/compiler/rustc_mir/src/transform/instcombine.rs index bad82fe893e..7aaf0224164 100644 --- a/compiler/rustc_mir/src/transform/instcombine.rs +++ b/compiler/rustc_mir/src/transform/instcombine.rs @@ -79,7 +79,7 @@ impl<'tcx, 'a> InstCombineContext<'tcx, 'a> { fn try_eval_bool(&self, a: &Operand<'_>) -> Option { let a = a.constant()?; - if a.literal.ty.is_bool() { a.literal.val.try_to_bool() } else { None } + if a.literal.ty().is_bool() { a.literal.try_to_bool() } else { None } } /// Transform "&(*a)" ==> "a". @@ -110,12 +110,13 @@ impl<'tcx, 'a> InstCombineContext<'tcx, 'a> { fn combine_len(&self, source_info: &SourceInfo, rvalue: &mut Rvalue<'tcx>) { if let Rvalue::Len(ref place) = *rvalue { let place_ty = place.ty(self.local_decls, self.tcx).ty; - if let ty::Array(_, len) = place_ty.kind() { + if let ty::Array(_, len) = *place_ty.kind() { if !self.should_combine(source_info, rvalue) { return; } - let constant = Constant { span: source_info.span, literal: len, user_ty: None }; + let constant = + Constant { span: source_info.span, literal: len.into(), user_ty: None }; *rvalue = Rvalue::Use(Operand::Constant(box constant)); } } diff --git a/compiler/rustc_mir/src/transform/lower_intrinsics.rs b/compiler/rustc_mir/src/transform/lower_intrinsics.rs index d6a73360616..e6ee474285e 100644 --- a/compiler/rustc_mir/src/transform/lower_intrinsics.rs +++ b/compiler/rustc_mir/src/transform/lower_intrinsics.rs @@ -33,7 +33,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics { Rvalue::Use(Operand::Constant(box Constant { span: terminator.source_info.span, user_ty: None, - literal: ty::Const::zero_sized(tcx, tcx.types.unit), + literal: ty::Const::zero_sized(tcx, tcx.types.unit).into(), })), )), }); diff --git a/compiler/rustc_mir/src/transform/match_branches.rs b/compiler/rustc_mir/src/transform/match_branches.rs index 15c2c3a160f..d04a7011ab0 100644 --- a/compiler/rustc_mir/src/transform/match_branches.rs +++ b/compiler/rustc_mir/src/transform/match_branches.rs @@ -93,8 +93,8 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification { StatementKind::Assign(box (lhs_f, Rvalue::Use(Operand::Constant(f_c)))), StatementKind::Assign(box (lhs_s, Rvalue::Use(Operand::Constant(s_c)))), ) if lhs_f == lhs_s - && f_c.literal.ty.is_bool() - && s_c.literal.ty.is_bool() + && f_c.literal.ty().is_bool() + && s_c.literal.ty().is_bool() && f_c.literal.try_eval_bool(tcx, param_env).is_some() && s_c.literal.try_eval_bool(tcx, param_env).is_some() => {} diff --git a/compiler/rustc_mir/src/transform/promote_consts.rs b/compiler/rustc_mir/src/transform/promote_consts.rs index f60570483ce..7db790cf32b 100644 --- a/compiler/rustc_mir/src/transform/promote_consts.rs +++ b/compiler/rustc_mir/src/transform/promote_consts.rs @@ -921,7 +921,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { let unit = Rvalue::Use(Operand::Constant(box Constant { span: statement.source_info.span, user_ty: None, - literal: ty::Const::zero_sized(self.tcx, self.tcx.types.unit), + literal: ty::Const::zero_sized(self.tcx, self.tcx.types.unit).into(), })); mem::replace(rhs, unit) }, @@ -998,20 +998,22 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { Operand::Constant(Box::new(Constant { span, user_ty: None, - literal: tcx.mk_const(ty::Const { - ty, - val: ty::ConstKind::Unevaluated( - def, - InternalSubsts::for_item(tcx, def.did, |param, _| { - if let ty::GenericParamDefKind::Lifetime = param.kind { - tcx.lifetimes.re_erased.into() - } else { - tcx.mk_param_from_def(param) - } - }), - Some(promoted_id), - ), - }), + literal: tcx + .mk_const(ty::Const { + ty, + val: ty::ConstKind::Unevaluated( + def, + InternalSubsts::for_item(tcx, def.did, |param, _| { + if let ty::GenericParamDefKind::Lifetime = param.kind { + tcx.lifetimes.re_erased.into() + } else { + tcx.mk_param_from_def(param) + } + }), + Some(promoted_id), + ), + }) + .into(), })) }; let (blocks, local_decls) = self.source.basic_blocks_and_local_decls_mut(); @@ -1250,8 +1252,8 @@ crate fn is_const_fn_in_array_repeat_expression<'tcx>( if let Some(Terminator { kind: TerminatorKind::Call { func, destination, .. }, .. }) = &block.terminator { - if let Operand::Constant(box Constant { literal: ty::Const { ty, .. }, .. }) = func { - if let ty::FnDef(def_id, _) = *ty.kind() { + if let Operand::Constant(box Constant { literal, .. }) = func { + if let ty::FnDef(def_id, _) = *literal.ty().kind() { if let Some((destination_place, _)) = destination { if destination_place == place { if is_const_fn(ccx.tcx, def_id) { diff --git a/compiler/rustc_mir/src/transform/required_consts.rs b/compiler/rustc_mir/src/transform/required_consts.rs index a63ab30a68f..2b518bd3a48 100644 --- a/compiler/rustc_mir/src/transform/required_consts.rs +++ b/compiler/rustc_mir/src/transform/required_consts.rs @@ -14,10 +14,10 @@ impl<'a, 'tcx> RequiredConstsVisitor<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for RequiredConstsVisitor<'a, 'tcx> { fn visit_constant(&mut self, constant: &Constant<'tcx>, _: Location) { - let const_kind = constant.literal.val; - - if let ConstKind::Unevaluated(_, _, _) = const_kind { - self.required_consts.push(*constant); + if let Some(ct) = constant.literal.const_for_ty() { + if let ConstKind::Unevaluated(_, _, _) = ct.val { + self.required_consts.push(*constant); + } } } } diff --git a/compiler/rustc_mir/src/transform/rustc_peek.rs b/compiler/rustc_mir/src/transform/rustc_peek.rs index 7598be4e4a1..a6b8f20f6d4 100644 --- a/compiler/rustc_mir/src/transform/rustc_peek.rs +++ b/compiler/rustc_mir/src/transform/rustc_peek.rs @@ -205,7 +205,7 @@ impl PeekCall { if let mir::TerminatorKind::Call { func: Operand::Constant(func), args, .. } = &terminator.kind { - if let ty::FnDef(def_id, substs) = *func.literal.ty.kind() { + if let ty::FnDef(def_id, substs) = *func.literal.ty().kind() { let sig = tcx.fn_sig(def_id); let name = tcx.item_name(def_id); if sig.abi() != Abi::RustIntrinsic || name != sym::rustc_peek { diff --git a/compiler/rustc_mir/src/transform/simplify_comparison_integral.rs b/compiler/rustc_mir/src/transform/simplify_comparison_integral.rs index 32df40ebf9e..9f473f3bae5 100644 --- a/compiler/rustc_mir/src/transform/simplify_comparison_integral.rs +++ b/compiler/rustc_mir/src/transform/simplify_comparison_integral.rs @@ -205,12 +205,12 @@ fn find_branch_value_info<'tcx>( match (left, right) { (Constant(branch_value), Copy(to_switch_on) | Move(to_switch_on)) | (Copy(to_switch_on) | Move(to_switch_on), Constant(branch_value)) => { - let branch_value_ty = branch_value.literal.ty; + let branch_value_ty = branch_value.literal.ty(); // we only want to apply this optimization if we are matching on integrals (and chars), as it is not possible to switch on floats if !branch_value_ty.is_integral() && !branch_value_ty.is_char() { return None; }; - let branch_value_scalar = branch_value.literal.val.try_to_scalar()?; + let branch_value_scalar = branch_value.literal.try_to_scalar()?; Some((branch_value_scalar, branch_value_ty, *to_switch_on)) } _ => None, diff --git a/compiler/rustc_mir/src/util/elaborate_drops.rs b/compiler/rustc_mir/src/util/elaborate_drops.rs index b22dadcd7d2..e9190d7ebef 100644 --- a/compiler/rustc_mir/src/util/elaborate_drops.rs +++ b/compiler/rustc_mir/src/util/elaborate_drops.rs @@ -1035,7 +1035,7 @@ where Operand::Constant(box Constant { span: self.source_info.span, user_ty: None, - literal: ty::Const::from_usize(self.tcx(), val.into()), + literal: ty::Const::from_usize(self.tcx(), val.into()).into(), }) } diff --git a/compiler/rustc_mir/src/util/find_self_call.rs b/compiler/rustc_mir/src/util/find_self_call.rs index 5b146eeb87c..ddda98d1616 100644 --- a/compiler/rustc_mir/src/util/find_self_call.rs +++ b/compiler/rustc_mir/src/util/find_self_call.rs @@ -17,8 +17,8 @@ pub fn find_self_call<'tcx>( &body[block].terminator { debug!("find_self_call: func={:?}", func); - if let Operand::Constant(box Constant { literal: ty::Const { ty, .. }, .. }) = func { - if let ty::FnDef(def_id, substs) = *ty.kind() { + if let Operand::Constant(box Constant { literal, .. }) = func { + if let ty::FnDef(def_id, substs) = *literal.ty().kind() { if let Some(ty::AssocItem { fn_has_self_parameter: true, .. }) = tcx.opt_associated_item(def_id) { diff --git a/compiler/rustc_mir/src/util/pretty.rs b/compiler/rustc_mir/src/util/pretty.rs index 247a0beccaf..8e38a87a8f4 100644 --- a/compiler/rustc_mir/src/util/pretty.rs +++ b/compiler/rustc_mir/src/util/pretty.rs @@ -439,7 +439,7 @@ impl Visitor<'tcx> for ExtraComments<'tcx> { fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) { self.super_constant(constant, location); let Constant { span, user_ty, literal } = constant; - match literal.ty.kind() { + match literal.ty().kind() { ty::Int(_) | ty::Uint(_) | ty::Bool | ty::Char => {} // Unit type ty::Tuple(tys) if tys.is_empty() => {} @@ -449,7 +449,12 @@ impl Visitor<'tcx> for ExtraComments<'tcx> { if let Some(user_ty) = user_ty { self.push(&format!("+ user_ty: {:?}", user_ty)); } - self.push(&format!("+ literal: {:?}", literal)); + match literal { + ConstantSource::Ty(literal) => self.push(&format!("+ literal: {:?}", literal)), + ConstantSource::Val(val, ty) => { + self.push(&format!("+ literal: {:?}, {}", val, ty)) + } + } } } } diff --git a/compiler/rustc_mir_build/src/build/cfg.rs b/compiler/rustc_mir_build/src/build/cfg.rs index 42e2b242d77..e562e52f841 100644 --- a/compiler/rustc_mir_build/src/build/cfg.rs +++ b/compiler/rustc_mir_build/src/build/cfg.rs @@ -68,7 +68,7 @@ impl<'tcx> CFG<'tcx> { Rvalue::Use(Operand::Constant(box Constant { span: source_info.span, user_ty: None, - literal: ty::Const::zero_sized(tcx, tcx.types.unit), + literal: ty::Const::zero_sized(tcx, tcx.types.unit).into(), })), ); } diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs index 727aedb0ef8..c8f9993def3 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs @@ -11,7 +11,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { crate fn as_constant(&mut self, expr: &Expr<'_, 'tcx>) -> Constant<'tcx> { let this = self; let Expr { ty, temp_lifetime: _, span, ref kind } = *expr; - match kind { + match *kind { ExprKind::Scope { region_scope: _, lint_level: _, value } => this.as_constant(value), ExprKind::Literal { literal, user_ty, const_id: _ } => { let user_ty = user_ty.map(|user_ty| { @@ -22,11 +22,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }) }); assert_eq!(literal.ty, ty); - Constant { span, user_ty, literal } + Constant { span, user_ty, literal: literal.into() } } - ExprKind::StaticRef { literal, .. } => Constant { span, user_ty: None, literal }, + ExprKind::StaticRef { literal, .. } => Constant { span, user_ty: None, literal: literal.into() }, ExprKind::ConstBlock { value } => { - Constant { span: span, user_ty: None, literal: value } + Constant { span: span, user_ty: None, literal: value.into() } } _ => span_bug!(span, "expression is not a valid constant {:?}", kind), } diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index d73e5eef70c..65531b60818 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -219,7 +219,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block.and(Rvalue::Use(Operand::Constant(box Constant { span: expr_span, user_ty: None, - literal: ty::Const::zero_sized(this.tcx, this.tcx.types.unit), + literal: ty::Const::zero_sized(this.tcx, this.tcx.types.unit).into(), }))) } ExprKind::Yield { .. } diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index 47f75825fb6..1dc6506e30d 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -146,7 +146,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Constant { span: expr_span, user_ty: None, - literal: ty::Const::from_bool(this.tcx, true), + literal: ty::Const::from_bool(this.tcx, true).into(), }, ); @@ -157,7 +157,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Constant { span: expr_span, user_ty: None, - literal: ty::Const::from_bool(this.tcx, false), + literal: ty::Const::from_bool(this.tcx, false).into(), }, ); diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs index 48abaa8d35f..7f26c0e5d76 100644 --- a/compiler/rustc_mir_build/src/build/matches/test.rs +++ b/compiler/rustc_mir_build/src/build/matches/test.rs @@ -429,7 +429,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Need to experiment. user_ty: None, - literal: method, + literal: method.into(), }), args: vec![val, expect], destination: Some((eq_result, eq_block)), diff --git a/compiler/rustc_mir_build/src/build/misc.rs b/compiler/rustc_mir_build/src/build/misc.rs index 62c217a12aa..a1126d1c3d5 100644 --- a/compiler/rustc_mir_build/src/build/misc.rs +++ b/compiler/rustc_mir_build/src/build/misc.rs @@ -30,6 +30,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { span: Span, literal: &'tcx ty::Const<'tcx>, ) -> Operand<'tcx> { + let literal = literal.into(); let constant = box Constant { span, user_ty: None, literal }; Operand::Constant(constant) } @@ -57,7 +58,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Constant { span: source_info.span, user_ty: None, - literal: ty::Const::from_usize(self.tcx, value), + literal: ty::Const::from_usize(self.tcx, value).into(), }, ); temp diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index f4983dd7531..5ace45e4c7c 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -377,7 +377,10 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { let local = self.place_to_local(span, p)?; Ok(self.locals[local]) } - mir::Operand::Constant(ct) => Ok(self.add_node(Node::Leaf(ct.literal), span)), + mir::Operand::Constant(ct) => match ct.literal { + mir::ConstantSource::Ty(ct) => Ok(self.add_node(Node::Leaf(ct), span)), + mir::ConstantSource::Val(..) => self.error(Some(span), "unsupported constant")?, + }, } }