Prepare mir::Constant for ty::Const only supporting valtrees
This commit is contained in:
parent
3ecde6f5db
commit
3127a9c60f
38 changed files with 369 additions and 153 deletions
|
@ -8,7 +8,7 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
||||||
use rustc_middle::mir::interpret::{
|
use rustc_middle::mir::interpret::{
|
||||||
read_target_uint, AllocId, Allocation, ConstValue, ErrorHandled, GlobalAlloc, Pointer, Scalar,
|
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_codegen::ir::GlobalValueData;
|
||||||
use cranelift_module::*;
|
use cranelift_module::*;
|
||||||
|
@ -39,7 +39,10 @@ impl ConstantCx {
|
||||||
pub(crate) fn check_constants(fx: &mut FunctionCx<'_, '_, '_>) -> bool {
|
pub(crate) fn check_constants(fx: &mut FunctionCx<'_, '_, '_>) -> bool {
|
||||||
let mut all_constants_ok = true;
|
let mut all_constants_ok = true;
|
||||||
for constant in &fx.mir.required_consts {
|
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 {
|
match const_.val {
|
||||||
ConstKind::Value(_) => {}
|
ConstKind::Value(_) => {}
|
||||||
ConstKind::Unevaluated(def, ref substs, promoted) => {
|
ConstKind::Unevaluated(def, ref substs, promoted) => {
|
||||||
|
@ -113,19 +116,17 @@ pub(crate) fn codegen_constant<'tcx>(
|
||||||
fx: &mut FunctionCx<'_, '_, 'tcx>,
|
fx: &mut FunctionCx<'_, '_, 'tcx>,
|
||||||
constant: &Constant<'tcx>,
|
constant: &Constant<'tcx>,
|
||||||
) -> CValue<'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 {
|
let const_val = match const_.val {
|
||||||
ConstKind::Value(const_val) => const_val,
|
ConstKind::Value(const_val) => const_val,
|
||||||
ConstKind::Unevaluated(def, ref substs, promoted) if fx.tcx.is_static(def.did) => {
|
ConstKind::Unevaluated(def, ref substs, promoted) if fx.tcx.is_static(def.did) => {
|
||||||
assert!(substs.is_empty());
|
assert!(substs.is_empty());
|
||||||
assert!(promoted.is_none());
|
assert!(promoted.is_none());
|
||||||
|
|
||||||
return codegen_static_ref(
|
return codegen_static_ref(fx, def.did, fx.layout_of(const_.ty)).to_cvalue(fx);
|
||||||
fx,
|
|
||||||
def.did,
|
|
||||||
fx.layout_of(fx.monomorphize(&constant.literal.ty)),
|
|
||||||
)
|
|
||||||
.to_cvalue(fx);
|
|
||||||
}
|
}
|
||||||
ConstKind::Unevaluated(def, ref substs, promoted) => {
|
ConstKind::Unevaluated(def, ref substs, promoted) => {
|
||||||
match fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), def, substs, promoted, None) {
|
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>(
|
pub(crate) fn mir_operand_get_const_val<'tcx>(
|
||||||
fx: &FunctionCx<'_, '_, 'tcx>,
|
fx: &FunctionCx<'_, '_, 'tcx>,
|
||||||
operand: &Operand<'tcx>,
|
operand: &Operand<'tcx>,
|
||||||
) -> Option<&'tcx Const<'tcx>> {
|
) -> Option<ConstValue<'tcx>> {
|
||||||
match operand {
|
match operand {
|
||||||
Operand::Copy(_) | Operand::Move(_) => None,
|
Operand::Copy(_) | Operand::Move(_) => None,
|
||||||
Operand::Constant(const_) => {
|
Operand::Constant(const_) => match const_.literal {
|
||||||
Some(fx.monomorphize(const_.literal).eval(fx.tcx, ParamEnv::reveal_all()))
|
ConstantSource::Ty(const_) => {
|
||||||
|
fx.monomorphize(const_).eval(fx.tcx, ParamEnv::reveal_all()).val.try_to_value()
|
||||||
}
|
}
|
||||||
|
ConstantSource::Val(val, _) => Some(val),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
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 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,
|
0 => FloatCC::Equal,
|
||||||
1 => FloatCC::LessThan,
|
1 => FloatCC::LessThan,
|
||||||
2 => FloatCC::LessThanOrEqual,
|
2 => FloatCC::LessThanOrEqual,
|
||||||
|
@ -84,7 +84,7 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
|
||||||
llvm.x86.sse2.psrli.d, (c a, o imm8) {
|
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");
|
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| {
|
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)),
|
imm8 if imm8 < 32 => fx.bcx.ins().ushr_imm(lane, i64::from(imm8 as u8)),
|
||||||
_ => fx.bcx.ins().iconst(types::I32, 0),
|
_ => 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) {
|
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");
|
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| {
|
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)),
|
imm8 if imm8 < 32 => fx.bcx.ins().ishl_imm(lane, i64::from(imm8 as u8)),
|
||||||
_ => fx.bcx.ins().iconst(types::I32, 0),
|
_ => fx.bcx.ins().iconst(types::I32, 0),
|
||||||
};
|
};
|
||||||
|
|
|
@ -85,8 +85,8 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
|
||||||
use rustc_middle::mir::interpret::*;
|
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_const = crate::constant::mir_operand_get_const_val(fx, idx).expect("simd_shuffle* idx not const");
|
||||||
|
|
||||||
let idx_bytes = match idx_const.val {
|
let idx_bytes = match idx_const {
|
||||||
ty::ConstKind::Value(ConstValue::ByRef { alloc, offset }) => {
|
ConstValue::ByRef { alloc, offset } => {
|
||||||
let ptr = Pointer::new(AllocId(0 /* dummy */), 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]) */);
|
let size = Size::from_bytes(4 * u64::from(ret_lane_count) /* size_of([u32; ret_lane_count]) */);
|
||||||
alloc.get_bytes(fx, ptr, size).unwrap()
|
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);
|
let (lane_count, _lane_ty) = base.layout().ty.simd_size_and_type(fx.tcx);
|
||||||
if idx >= lane_count.into() {
|
if idx >= lane_count.into() {
|
||||||
fx.tcx.sess.span_fatal(fx.mir.span, &format!("[simd_insert] idx {} >= lane_count {}", idx, lane_count));
|
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;
|
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);
|
let (lane_count, _lane_ty) = v.layout().ty.simd_size_and_type(fx.tcx);
|
||||||
if idx >= lane_count.into() {
|
if idx >= lane_count.into() {
|
||||||
fx.tcx.sess.span_fatal(fx.mir.span, &format!("[simd_extract] idx {} >= lane_count {}", idx, lane_count));
|
fx.tcx.sess.span_fatal(fx.mir.span, &format!("[simd_extract] idx {} >= lane_count {}", idx, lane_count));
|
||||||
|
|
|
@ -860,7 +860,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
}
|
}
|
||||||
mir::InlineAsmOperand::SymFn { ref value } => {
|
mir::InlineAsmOperand::SymFn { ref value } => {
|
||||||
let literal = self.monomorphize(value.literal);
|
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(
|
let instance = ty::Instance::resolve_for_fn_ptr(
|
||||||
bx.tcx(),
|
bx.tcx(),
|
||||||
ty::ParamEnv::reveal_all(),
|
ty::ParamEnv::reveal_all(),
|
||||||
|
|
|
@ -24,7 +24,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
&self,
|
&self,
|
||||||
constant: &mir::Constant<'tcx>,
|
constant: &mir::Constant<'tcx>,
|
||||||
) -> Result<ConstValue<'tcx>, ErrorHandled> {
|
) -> Result<ConstValue<'tcx>, 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
|
ty::ConstKind::Unevaluated(def, substs, promoted) => self
|
||||||
.cx
|
.cx
|
||||||
.tcx()
|
.tcx()
|
||||||
|
|
|
@ -47,7 +47,25 @@ pub enum ConstValue<'tcx> {
|
||||||
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
|
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
|
||||||
static_assert_size!(ConstValue<'_>, 32);
|
static_assert_size!(ConstValue<'_>, 32);
|
||||||
|
|
||||||
|
impl From<Scalar> for ConstValue<'tcx> {
|
||||||
|
fn from(s: Scalar) -> Self {
|
||||||
|
Self::Scalar(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'tcx> ConstValue<'tcx> {
|
impl<'tcx> ConstValue<'tcx> {
|
||||||
|
pub fn lift<'lifted>(self, tcx: TyCtxt<'lifted>) -> Option<ConstValue<'lifted>> {
|
||||||
|
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]
|
#[inline]
|
||||||
pub fn try_to_scalar(&self) -> Option<Scalar> {
|
pub fn try_to_scalar(&self) -> Option<Scalar> {
|
||||||
match *self {
|
match *self {
|
||||||
|
|
|
@ -11,12 +11,12 @@ use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
|
||||||
use crate::ty::print::{FmtPrinter, Printer};
|
use crate::ty::print::{FmtPrinter, Printer};
|
||||||
use crate::ty::subst::{Subst, SubstsRef};
|
use crate::ty::subst::{Subst, SubstsRef};
|
||||||
use crate::ty::{self, List, Ty, TyCtxt};
|
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 as hir;
|
||||||
use rustc_hir::def::{CtorKind, Namespace};
|
use rustc_hir::def::{CtorKind, Namespace};
|
||||||
use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
|
use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
|
||||||
use rustc_hir::{self, GeneratorKind};
|
use rustc_hir::{self, GeneratorKind};
|
||||||
use rustc_target::abi::VariantIdx;
|
use rustc_target::abi::{Size, VariantIdx};
|
||||||
|
|
||||||
use polonius_engine::Atom;
|
use polonius_engine::Atom;
|
||||||
pub use rustc_ast::Mutability;
|
pub use rustc_ast::Mutability;
|
||||||
|
@ -30,6 +30,7 @@ use rustc_span::symbol::Symbol;
|
||||||
use rustc_span::{Span, DUMMY_SP};
|
use rustc_span::{Span, DUMMY_SP};
|
||||||
use rustc_target::asm::InlineAsmRegOrRegClass;
|
use rustc_target::asm::InlineAsmRegOrRegClass;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
use std::convert::TryInto;
|
||||||
use std::fmt::{self, Debug, Display, Formatter, Write};
|
use std::fmt::{self, Debug, Display, Formatter, Write};
|
||||||
use std::ops::{ControlFlow, Index, IndexMut};
|
use std::ops::{ControlFlow, Index, IndexMut};
|
||||||
use std::slice;
|
use std::slice;
|
||||||
|
@ -2032,7 +2033,7 @@ impl<'tcx> Operand<'tcx> {
|
||||||
Operand::Constant(box Constant {
|
Operand::Constant(box Constant {
|
||||||
span,
|
span,
|
||||||
user_ty: None,
|
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 {
|
Operand::Constant(box Constant {
|
||||||
span,
|
span,
|
||||||
user_ty: None,
|
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.
|
/// Needed for NLL to impose user-given type constraints.
|
||||||
pub user_ty: Option<UserTypeAnnotationIndex>,
|
pub user_ty: Option<UserTypeAnnotationIndex>,
|
||||||
|
|
||||||
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> {
|
impl Constant<'tcx> {
|
||||||
pub fn check_static_ptr(&self, tcx: TyCtxt<'_>) -> Option<DefId> {
|
pub fn check_static_ptr(&self, tcx: TyCtxt<'_>) -> Option<DefId> {
|
||||||
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) {
|
Some(Scalar::Ptr(ptr)) => match tcx.global_alloc(ptr.alloc_id) {
|
||||||
GlobalAlloc::Static(def_id) => {
|
GlobalAlloc::Static(def_id) => {
|
||||||
assert!(!tcx.is_thread_local_static(def_id));
|
assert!(!tcx.is_thread_local_static(def_id));
|
||||||
|
@ -2422,7 +2432,92 @@ impl Constant<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn ty(&self) -> Ty<'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<interpret::ConstValue<'tcx>> {
|
||||||
|
match self {
|
||||||
|
ConstantSource::Ty(c) => c.val.try_to_value(),
|
||||||
|
ConstantSource::Val(val, _) => Some(val),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn try_to_scalar(self) -> Option<Scalar> {
|
||||||
|
self.try_to_value()?.try_to_scalar()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn try_to_scalar_int(self) -> Option<ScalarInt> {
|
||||||
|
self.try_to_value()?.try_to_scalar()?.to_int().ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn try_to_bits(self, size: Size) -> Option<u128> {
|
||||||
|
self.try_to_scalar_int()?.to_bits(size).ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn try_to_bool(self) -> Option<bool> {
|
||||||
|
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<u128> {
|
||||||
|
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<bool> {
|
||||||
|
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<u64> {
|
||||||
|
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> {
|
impl<'tcx> Display for Constant<'tcx> {
|
||||||
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
|
||||||
match self.literal.ty.kind() {
|
match self.ty().kind() {
|
||||||
ty::FnDef(..) => {}
|
ty::FnDef(..) => {}
|
||||||
_ => write!(fmt, "const ")?,
|
_ => 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> {
|
impl<'tcx> graph::DirectedGraph for Body<'tcx> {
|
||||||
type Node = BasicBlock;
|
type Node = BasicBlock;
|
||||||
}
|
}
|
||||||
|
|
|
@ -227,7 +227,7 @@ impl<'tcx> Operand<'tcx> {
|
||||||
{
|
{
|
||||||
match self {
|
match self {
|
||||||
&Operand::Copy(ref l) | &Operand::Move(ref l) => l.ty(local_decls, tcx).ty,
|
&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(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -343,5 +343,22 @@ impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> {
|
||||||
}
|
}
|
||||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||||
self.literal.visit_with(visitor)
|
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<F: TypeFolder<'tcx>>(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<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||||
|
match *self {
|
||||||
|
ConstantSource::Ty(c) => c.visit_with(visitor),
|
||||||
|
ConstantSource::Val(_, t) => t.visit_with(visitor),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -871,7 +871,10 @@ macro_rules! make_mir_visitor {
|
||||||
|
|
||||||
self.visit_span(span);
|
self.visit_span(span);
|
||||||
drop(user_ty); // no visit method for this
|
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) {
|
fn super_span(&mut self, _span: & $($mutability)? Span) {
|
||||||
|
|
|
@ -81,12 +81,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
let terminator = self.body[location.block].terminator();
|
let terminator = self.body[location.block].terminator();
|
||||||
debug!("add_moved_or_invoked_closure_note: terminator={:?}", terminator);
|
debug!("add_moved_or_invoked_closure_note: terminator={:?}", terminator);
|
||||||
if let TerminatorKind::Call {
|
if let TerminatorKind::Call {
|
||||||
func: Operand::Constant(box Constant { literal: ty::Const { ty: const_ty, .. }, .. }),
|
func: Operand::Constant(box Constant { literal, .. }),
|
||||||
args,
|
args,
|
||||||
..
|
..
|
||||||
} = &terminator.kind
|
} = &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);
|
debug!("add_moved_or_invoked_closure_note: id={:?}", id);
|
||||||
if self.infcx.tcx.parent(id) == self.infcx.tcx.lang_items().fn_once_trait() {
|
if self.infcx.tcx.parent(id) == self.infcx.tcx.lang_items().fn_once_trait() {
|
||||||
let closure = match args.first() {
|
let closure = match args.first() {
|
||||||
|
|
|
@ -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) {
|
fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
|
||||||
self.super_constant(constant, 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| {
|
self.cx.infcx.tcx.for_each_free_region(&ty, |live_region| {
|
||||||
let live_region_vid =
|
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 Some(annotation_index) = constant.user_ty {
|
||||||
if let Err(terr) = self.cx.relate_type_and_user_type(
|
if let Err(terr) = self.cx.relate_type_and_user_type(
|
||||||
constant.literal.ty,
|
constant.literal.ty(),
|
||||||
ty::Variance::Invariant,
|
ty::Variance::Invariant,
|
||||||
&UserTypeProjection { base: annotation_index, projs: vec![] },
|
&UserTypeProjection { base: annotation_index, projs: vec![] },
|
||||||
location.to_locations(),
|
location.to_locations(),
|
||||||
|
@ -308,13 +308,22 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
|
||||||
constant,
|
constant,
|
||||||
"bad constant user type {:?} vs {:?}: {:?}",
|
"bad constant user type {:?} vs {:?}: {:?}",
|
||||||
annotation,
|
annotation,
|
||||||
constant.literal.ty,
|
constant.literal.ty(),
|
||||||
terr,
|
terr,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let tcx = self.tcx();
|
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 {
|
if let Some(promoted) = promoted {
|
||||||
let check_err = |verifier: &mut TypeVerifier<'a, 'b, 'tcx>,
|
let check_err = |verifier: &mut TypeVerifier<'a, 'b, 'tcx>,
|
||||||
promoted: &Body<'tcx>,
|
promoted: &Body<'tcx>,
|
||||||
|
@ -349,7 +358,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
|
||||||
location.to_locations(),
|
location.to_locations(),
|
||||||
ConstraintCategory::Boring,
|
ConstraintCategory::Boring,
|
||||||
self.cx.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(
|
self.cx.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(
|
||||||
constant.literal.ty,
|
constant.literal.ty(),
|
||||||
def.did,
|
def.did,
|
||||||
UserSubsts { substs, user_self_ty: None },
|
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 unnormalized_ty = tcx.type_of(static_def_id);
|
||||||
let locations = location.to_locations();
|
let locations = location.to_locations();
|
||||||
let normalized_ty = self.cx.normalize(unnormalized_ty, 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(
|
if let Err(terr) = self.cx.eq_types(
|
||||||
normalized_ty,
|
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);
|
let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, substs);
|
||||||
self.cx.normalize_and_prove_instantiated_predicates(
|
self.cx.normalize_and_prove_instantiated_predicates(
|
||||||
instantiated_predicates,
|
instantiated_predicates,
|
||||||
|
|
|
@ -689,7 +689,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
let span = const_.span;
|
let span = const_.span;
|
||||||
let const_ =
|
let const_ =
|
||||||
self.subst_from_current_frame_and_normalize_erasing_regions(const_.literal);
|
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.
|
// If there was an error, set the span of the current frame to this constant.
|
||||||
// Avoiding doing this when evaluation succeeds.
|
// Avoiding doing this when evaluation succeeds.
|
||||||
self.frame_mut().loc = Err(span);
|
self.frame_mut().loc = Err(span);
|
||||||
|
|
|
@ -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
|
// * During ConstProp, with `TooGeneric` or since the `requried_consts` were not all
|
||||||
// checked yet.
|
// checked yet.
|
||||||
// * During CTFE, since promoteds in `const`/`static` initializer bodies can fail.
|
// * 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);
|
trace!("{:?}: {:?}", mir_op, *op);
|
||||||
|
@ -556,28 +557,45 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
val: &ty::Const<'tcx>,
|
val: &ty::Const<'tcx>,
|
||||||
layout: Option<TyAndLayout<'tcx>>,
|
layout: Option<TyAndLayout<'tcx>>,
|
||||||
) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
|
) -> 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<TyAndLayout<'tcx>>,
|
||||||
|
) -> 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<TyAndLayout<'tcx>>,
|
||||||
|
) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
|
||||||
|
// Other cases need layout.
|
||||||
let tag_scalar = |scalar| -> InterpResult<'tcx, _> {
|
let tag_scalar = |scalar| -> InterpResult<'tcx, _> {
|
||||||
Ok(match scalar {
|
Ok(match scalar {
|
||||||
Scalar::Ptr(ptr) => Scalar::Ptr(self.global_base_pointer(ptr)?),
|
Scalar::Ptr(ptr) => Scalar::Ptr(self.global_base_pointer(ptr)?),
|
||||||
Scalar::Int(int) => Scalar::Int(int),
|
Scalar::Int(int) => Scalar::Int(int),
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
// Early-return cases.
|
let layout = from_known_layout(self.tcx, self.param_env, layout, || self.layout_of(ty))?;
|
||||||
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 op = match val_val {
|
let op = match val_val {
|
||||||
ConstValue::ByRef { alloc, offset } => {
|
ConstValue::ByRef { alloc, offset } => {
|
||||||
let id = self.tcx.create_memory_alloc(alloc);
|
let id = self.tcx.create_memory_alloc(alloc);
|
||||||
|
|
|
@ -684,7 +684,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
|
||||||
for op in operands {
|
for op in operands {
|
||||||
match *op {
|
match *op {
|
||||||
mir::InlineAsmOperand::SymFn { ref value } => {
|
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);
|
visit_fn_use(self.tcx, fn_ty, false, source, &mut self.output);
|
||||||
}
|
}
|
||||||
mir::InlineAsmOperand::SymStatic { def_id } => {
|
mir::InlineAsmOperand::SymStatic { def_id } => {
|
||||||
|
|
|
@ -421,7 +421,7 @@ impl CloneShimBuilder<'tcx> {
|
||||||
let func = Operand::Constant(box Constant {
|
let func = Operand::Constant(box Constant {
|
||||||
span: self.span,
|
span: self.span,
|
||||||
user_ty: None,
|
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(
|
let ref_loc = self.make_place(
|
||||||
|
@ -478,7 +478,7 @@ impl CloneShimBuilder<'tcx> {
|
||||||
box Constant {
|
box Constant {
|
||||||
span: self.span,
|
span: self.span,
|
||||||
user_ty: None,
|
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 {
|
Rvalue::Use(Operand::Constant(box Constant {
|
||||||
span: self.span,
|
span: self.span,
|
||||||
user_ty: None,
|
user_ty: None,
|
||||||
literal: len,
|
literal: len.into(),
|
||||||
})),
|
})),
|
||||||
))),
|
))),
|
||||||
];
|
];
|
||||||
|
@ -768,7 +768,7 @@ fn build_call_shim<'tcx>(
|
||||||
Operand::Constant(box Constant {
|
Operand::Constant(box Constant {
|
||||||
span,
|
span,
|
||||||
user_ty: None,
|
user_ty: None,
|
||||||
literal: ty::Const::zero_sized(tcx, ty),
|
literal: ty::Const::zero_sized(tcx, ty).into(),
|
||||||
}),
|
}),
|
||||||
rcvr.into_iter().collect::<Vec<_>>(),
|
rcvr.into_iter().collect::<Vec<_>>(),
|
||||||
)
|
)
|
||||||
|
|
|
@ -246,7 +246,8 @@ where
|
||||||
};
|
};
|
||||||
|
|
||||||
// Check the qualifs of the value of `const` items.
|
// Check the qualifs of the value of `const` items.
|
||||||
if let ty::ConstKind::Unevaluated(def, _, promoted) = constant.literal.val {
|
if let Some(ct) = constant.literal.const_for_ty() {
|
||||||
|
if let ty::ConstKind::Unevaluated(def, _, promoted) = ct.val {
|
||||||
assert!(promoted.is_none());
|
assert!(promoted.is_none());
|
||||||
// Don't peek inside trait associated constants.
|
// Don't peek inside trait associated constants.
|
||||||
if cx.tcx.trait_of_item(def.did).is_none() {
|
if cx.tcx.trait_of_item(def.did).is_none() {
|
||||||
|
@ -265,6 +266,7 @@ where
|
||||||
// with type parameters, take it into account.
|
// with type parameters, take it into account.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Otherwise use the qualifs of the type.
|
// 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())
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,9 +13,9 @@ use rustc_middle::mir::visit::{
|
||||||
MutVisitor, MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor,
|
MutVisitor, MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor,
|
||||||
};
|
};
|
||||||
use rustc_middle::mir::{
|
use rustc_middle::mir::{
|
||||||
AssertKind, BasicBlock, BinOp, Body, ClearCrossCrate, Constant, Local, LocalDecl, LocalKind,
|
AssertKind, BasicBlock, BinOp, Body, ClearCrossCrate, Constant, ConstantSource, Local,
|
||||||
Location, Operand, Place, Rvalue, SourceInfo, SourceScope, SourceScopeData, Statement,
|
LocalDecl, LocalKind, Location, Operand, Place, Rvalue, SourceInfo, SourceScope,
|
||||||
StatementKind, Terminator, TerminatorKind, UnOp, RETURN_PLACE,
|
SourceScopeData, Statement, StatementKind, Terminator, TerminatorKind, UnOp, RETURN_PLACE,
|
||||||
};
|
};
|
||||||
use rustc_middle::ty::layout::{HasTyCtxt, LayoutError, TyAndLayout};
|
use rustc_middle::ty::layout::{HasTyCtxt, LayoutError, TyAndLayout};
|
||||||
use rustc_middle::ty::subst::{InternalSubsts, Subst};
|
use rustc_middle::ty::subst::{InternalSubsts, Subst};
|
||||||
|
@ -482,18 +482,21 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||||
return None;
|
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),
|
Ok(op) => Some(op),
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
let tcx = self.ecx.tcx.at(c.span);
|
let tcx = self.ecx.tcx.at(c.span);
|
||||||
let err = ConstEvalErr::new(&self.ecx, error, Some(c.span));
|
let err = ConstEvalErr::new(&self.ecx, error, Some(c.span));
|
||||||
if let Some(lint_root) = self.lint_root(source_info) {
|
if let Some(lint_root) = self.lint_root(source_info) {
|
||||||
let lint_only = match c.literal.val {
|
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
|
// Promoteds must lint and not error as the user didn't ask for them
|
||||||
ConstKind::Unevaluated(_, _, Some(_)) => true,
|
ConstKind::Unevaluated(_, _, Some(_)) => true,
|
||||||
// Out of backwards compatibility we cannot report hard errors in unused
|
// Out of backwards compatibility we cannot report hard errors in unused
|
||||||
// generic functions using associated constants of the generic parameters.
|
// generic functions using associated constants of the generic parameters.
|
||||||
_ => c.literal.needs_subst(),
|
_ => c.literal.needs_subst(),
|
||||||
|
},
|
||||||
|
ConstantSource::Val(_, ty) => ty.needs_subst(),
|
||||||
};
|
};
|
||||||
if lint_only {
|
if lint_only {
|
||||||
// Out of backwards compatibility we cannot report hard errors in unused
|
// 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 {
|
Operand::Constant(Box::new(Constant {
|
||||||
span,
|
span,
|
||||||
user_ty: None,
|
user_ty: None,
|
||||||
literal: ty::Const::from_scalar(self.tcx, scalar, ty),
|
literal: ty::Const::from_scalar(self.tcx, scalar, ty).into(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -814,11 +817,14 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||||
source_info: SourceInfo,
|
source_info: SourceInfo,
|
||||||
) {
|
) {
|
||||||
if let Rvalue::Use(Operand::Constant(c)) = rval {
|
if let Rvalue::Use(Operand::Constant(c)) = rval {
|
||||||
if !matches!(c.literal.val, ConstKind::Unevaluated(..)) {
|
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);
|
trace!("skipping replace of Rvalue::Use({:?} because it is already a const", c);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
trace!("attempting to replace {:?} with {:?}", rval, value);
|
trace!("attempting to replace {:?} with {:?}", rval, value);
|
||||||
if let Err(e) = self.ecx.const_validate_operand(
|
if let Err(e) = self.ecx.const_validate_operand(
|
||||||
|
@ -883,13 +889,17 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||||
*rval = Rvalue::Use(Operand::Constant(Box::new(Constant {
|
*rval = Rvalue::Use(Operand::Constant(Box::new(Constant {
|
||||||
span: source_info.span,
|
span: source_info.span,
|
||||||
user_ty: None,
|
user_ty: None,
|
||||||
literal: self.ecx.tcx.mk_const(ty::Const {
|
literal: self
|
||||||
|
.ecx
|
||||||
|
.tcx
|
||||||
|
.mk_const(ty::Const {
|
||||||
ty,
|
ty,
|
||||||
val: ty::ConstKind::Value(ConstValue::ByRef {
|
val: ty::ConstKind::Value(ConstValue::ByRef {
|
||||||
alloc,
|
alloc,
|
||||||
offset: Size::ZERO,
|
offset: Size::ZERO,
|
||||||
}),
|
}),
|
||||||
}),
|
})
|
||||||
|
.into(),
|
||||||
})));
|
})));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -471,7 +471,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
|
||||||
Rvalue::Use(Operand::Constant(Box::new(Constant {
|
Rvalue::Use(Operand::Constant(Box::new(Constant {
|
||||||
span,
|
span,
|
||||||
user_ty: None,
|
user_ty: None,
|
||||||
literal: ty::Const::from_bool(self.tcx, val),
|
literal: ty::Const::from_bool(self.tcx, val).into(),
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -989,7 +989,7 @@ fn insert_panic_block<'tcx>(
|
||||||
cond: Operand::Constant(box Constant {
|
cond: Operand::Constant(box Constant {
|
||||||
span: body.span,
|
span: body.span,
|
||||||
user_ty: None,
|
user_ty: None,
|
||||||
literal: ty::Const::from_bool(tcx, false),
|
literal: ty::Const::from_bool(tcx, false).into(),
|
||||||
}),
|
}),
|
||||||
expected: true,
|
expected: true,
|
||||||
msg: message,
|
msg: message,
|
||||||
|
|
|
@ -416,7 +416,7 @@ impl Inliner<'tcx> {
|
||||||
|
|
||||||
TerminatorKind::Call { func: Operand::Constant(ref f), cleanup, .. } => {
|
TerminatorKind::Call { func: Operand::Constant(ref f), cleanup, .. } => {
|
||||||
if let ty::FnDef(def_id, substs) =
|
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);
|
let substs = self.tcx.normalize_erasing_regions(self.param_env, substs);
|
||||||
if let Ok(Some(instance)) =
|
if let Ok(Some(instance)) =
|
||||||
|
@ -637,8 +637,11 @@ impl Inliner<'tcx> {
|
||||||
// `required_consts`, here we may not only have `ConstKind::Unevaluated`
|
// `required_consts`, here we may not only have `ConstKind::Unevaluated`
|
||||||
// because we are calling `subst_and_normalize_erasing_regions`.
|
// because we are calling `subst_and_normalize_erasing_regions`.
|
||||||
caller_body.required_consts.extend(
|
caller_body.required_consts.extend(
|
||||||
callee_body.required_consts.iter().copied().filter(|&constant| {
|
callee_body.required_consts.iter().copied().filter(|&ct| {
|
||||||
matches!(constant.literal.val, ConstKind::Unevaluated(_, _, _))
|
match ct.literal.const_for_ty() {
|
||||||
|
Some(ct) => matches!(ct.val, ConstKind::Unevaluated(_, _, _)),
|
||||||
|
None => true,
|
||||||
|
}
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,7 +79,7 @@ impl<'tcx, 'a> InstCombineContext<'tcx, 'a> {
|
||||||
|
|
||||||
fn try_eval_bool(&self, a: &Operand<'_>) -> Option<bool> {
|
fn try_eval_bool(&self, a: &Operand<'_>) -> Option<bool> {
|
||||||
let a = a.constant()?;
|
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".
|
/// Transform "&(*a)" ==> "a".
|
||||||
|
@ -110,12 +110,13 @@ impl<'tcx, 'a> InstCombineContext<'tcx, 'a> {
|
||||||
fn combine_len(&self, source_info: &SourceInfo, rvalue: &mut Rvalue<'tcx>) {
|
fn combine_len(&self, source_info: &SourceInfo, rvalue: &mut Rvalue<'tcx>) {
|
||||||
if let Rvalue::Len(ref place) = *rvalue {
|
if let Rvalue::Len(ref place) = *rvalue {
|
||||||
let place_ty = place.ty(self.local_decls, self.tcx).ty;
|
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) {
|
if !self.should_combine(source_info, rvalue) {
|
||||||
return;
|
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));
|
*rvalue = Rvalue::Use(Operand::Constant(box constant));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
|
||||||
Rvalue::Use(Operand::Constant(box Constant {
|
Rvalue::Use(Operand::Constant(box Constant {
|
||||||
span: terminator.source_info.span,
|
span: terminator.source_info.span,
|
||||||
user_ty: None,
|
user_ty: None,
|
||||||
literal: ty::Const::zero_sized(tcx, tcx.types.unit),
|
literal: ty::Const::zero_sized(tcx, tcx.types.unit).into(),
|
||||||
})),
|
})),
|
||||||
)),
|
)),
|
||||||
});
|
});
|
||||||
|
|
|
@ -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_f, Rvalue::Use(Operand::Constant(f_c)))),
|
||||||
StatementKind::Assign(box (lhs_s, Rvalue::Use(Operand::Constant(s_c)))),
|
StatementKind::Assign(box (lhs_s, Rvalue::Use(Operand::Constant(s_c)))),
|
||||||
) if lhs_f == lhs_s
|
) if lhs_f == lhs_s
|
||||||
&& f_c.literal.ty.is_bool()
|
&& f_c.literal.ty().is_bool()
|
||||||
&& s_c.literal.ty.is_bool()
|
&& s_c.literal.ty().is_bool()
|
||||||
&& f_c.literal.try_eval_bool(tcx, param_env).is_some()
|
&& f_c.literal.try_eval_bool(tcx, param_env).is_some()
|
||||||
&& s_c.literal.try_eval_bool(tcx, param_env).is_some() => {}
|
&& s_c.literal.try_eval_bool(tcx, param_env).is_some() => {}
|
||||||
|
|
||||||
|
|
|
@ -921,7 +921,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
|
||||||
let unit = Rvalue::Use(Operand::Constant(box Constant {
|
let unit = Rvalue::Use(Operand::Constant(box Constant {
|
||||||
span: statement.source_info.span,
|
span: statement.source_info.span,
|
||||||
user_ty: None,
|
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)
|
mem::replace(rhs, unit)
|
||||||
},
|
},
|
||||||
|
@ -998,7 +998,8 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
|
||||||
Operand::Constant(Box::new(Constant {
|
Operand::Constant(Box::new(Constant {
|
||||||
span,
|
span,
|
||||||
user_ty: None,
|
user_ty: None,
|
||||||
literal: tcx.mk_const(ty::Const {
|
literal: tcx
|
||||||
|
.mk_const(ty::Const {
|
||||||
ty,
|
ty,
|
||||||
val: ty::ConstKind::Unevaluated(
|
val: ty::ConstKind::Unevaluated(
|
||||||
def,
|
def,
|
||||||
|
@ -1011,7 +1012,8 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
|
||||||
}),
|
}),
|
||||||
Some(promoted_id),
|
Some(promoted_id),
|
||||||
),
|
),
|
||||||
}),
|
})
|
||||||
|
.into(),
|
||||||
}))
|
}))
|
||||||
};
|
};
|
||||||
let (blocks, local_decls) = self.source.basic_blocks_and_local_decls_mut();
|
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, .. }, .. }) =
|
if let Some(Terminator { kind: TerminatorKind::Call { func, destination, .. }, .. }) =
|
||||||
&block.terminator
|
&block.terminator
|
||||||
{
|
{
|
||||||
if let Operand::Constant(box Constant { literal: ty::Const { ty, .. }, .. }) = func {
|
if let Operand::Constant(box Constant { literal, .. }) = func {
|
||||||
if let ty::FnDef(def_id, _) = *ty.kind() {
|
if let ty::FnDef(def_id, _) = *literal.ty().kind() {
|
||||||
if let Some((destination_place, _)) = destination {
|
if let Some((destination_place, _)) = destination {
|
||||||
if destination_place == place {
|
if destination_place == place {
|
||||||
if is_const_fn(ccx.tcx, def_id) {
|
if is_const_fn(ccx.tcx, def_id) {
|
||||||
|
|
|
@ -14,10 +14,10 @@ impl<'a, 'tcx> RequiredConstsVisitor<'a, 'tcx> {
|
||||||
|
|
||||||
impl<'a, 'tcx> Visitor<'tcx> for RequiredConstsVisitor<'a, 'tcx> {
|
impl<'a, 'tcx> Visitor<'tcx> for RequiredConstsVisitor<'a, 'tcx> {
|
||||||
fn visit_constant(&mut self, constant: &Constant<'tcx>, _: Location) {
|
fn visit_constant(&mut self, constant: &Constant<'tcx>, _: Location) {
|
||||||
let const_kind = constant.literal.val;
|
if let Some(ct) = constant.literal.const_for_ty() {
|
||||||
|
if let ConstKind::Unevaluated(_, _, _) = ct.val {
|
||||||
if let ConstKind::Unevaluated(_, _, _) = const_kind {
|
|
||||||
self.required_consts.push(*constant);
|
self.required_consts.push(*constant);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -205,7 +205,7 @@ impl PeekCall {
|
||||||
if let mir::TerminatorKind::Call { func: Operand::Constant(func), args, .. } =
|
if let mir::TerminatorKind::Call { func: Operand::Constant(func), args, .. } =
|
||||||
&terminator.kind
|
&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 sig = tcx.fn_sig(def_id);
|
||||||
let name = tcx.item_name(def_id);
|
let name = tcx.item_name(def_id);
|
||||||
if sig.abi() != Abi::RustIntrinsic || name != sym::rustc_peek {
|
if sig.abi() != Abi::RustIntrinsic || name != sym::rustc_peek {
|
||||||
|
|
|
@ -205,12 +205,12 @@ fn find_branch_value_info<'tcx>(
|
||||||
match (left, right) {
|
match (left, right) {
|
||||||
(Constant(branch_value), Copy(to_switch_on) | Move(to_switch_on))
|
(Constant(branch_value), Copy(to_switch_on) | Move(to_switch_on))
|
||||||
| (Copy(to_switch_on) | Move(to_switch_on), Constant(branch_value)) => {
|
| (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
|
// 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() {
|
if !branch_value_ty.is_integral() && !branch_value_ty.is_char() {
|
||||||
return None;
|
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))
|
Some((branch_value_scalar, branch_value_ty, *to_switch_on))
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
|
|
|
@ -1035,7 +1035,7 @@ where
|
||||||
Operand::Constant(box Constant {
|
Operand::Constant(box Constant {
|
||||||
span: self.source_info.span,
|
span: self.source_info.span,
|
||||||
user_ty: None,
|
user_ty: None,
|
||||||
literal: ty::Const::from_usize(self.tcx(), val.into()),
|
literal: ty::Const::from_usize(self.tcx(), val.into()).into(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,8 +17,8 @@ pub fn find_self_call<'tcx>(
|
||||||
&body[block].terminator
|
&body[block].terminator
|
||||||
{
|
{
|
||||||
debug!("find_self_call: func={:?}", func);
|
debug!("find_self_call: func={:?}", func);
|
||||||
if let Operand::Constant(box Constant { literal: ty::Const { ty, .. }, .. }) = func {
|
if let Operand::Constant(box Constant { literal, .. }) = func {
|
||||||
if let ty::FnDef(def_id, substs) = *ty.kind() {
|
if let ty::FnDef(def_id, substs) = *literal.ty().kind() {
|
||||||
if let Some(ty::AssocItem { fn_has_self_parameter: true, .. }) =
|
if let Some(ty::AssocItem { fn_has_self_parameter: true, .. }) =
|
||||||
tcx.opt_associated_item(def_id)
|
tcx.opt_associated_item(def_id)
|
||||||
{
|
{
|
||||||
|
|
|
@ -439,7 +439,7 @@ impl Visitor<'tcx> for ExtraComments<'tcx> {
|
||||||
fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
|
fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
|
||||||
self.super_constant(constant, location);
|
self.super_constant(constant, location);
|
||||||
let Constant { span, user_ty, literal } = constant;
|
let Constant { span, user_ty, literal } = constant;
|
||||||
match literal.ty.kind() {
|
match literal.ty().kind() {
|
||||||
ty::Int(_) | ty::Uint(_) | ty::Bool | ty::Char => {}
|
ty::Int(_) | ty::Uint(_) | ty::Bool | ty::Char => {}
|
||||||
// Unit type
|
// Unit type
|
||||||
ty::Tuple(tys) if tys.is_empty() => {}
|
ty::Tuple(tys) if tys.is_empty() => {}
|
||||||
|
@ -449,7 +449,12 @@ impl Visitor<'tcx> for ExtraComments<'tcx> {
|
||||||
if let Some(user_ty) = user_ty {
|
if let Some(user_ty) = user_ty {
|
||||||
self.push(&format!("+ 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))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,7 +68,7 @@ impl<'tcx> CFG<'tcx> {
|
||||||
Rvalue::Use(Operand::Constant(box Constant {
|
Rvalue::Use(Operand::Constant(box Constant {
|
||||||
span: source_info.span,
|
span: source_info.span,
|
||||||
user_ty: None,
|
user_ty: None,
|
||||||
literal: ty::Const::zero_sized(tcx, tcx.types.unit),
|
literal: ty::Const::zero_sized(tcx, tcx.types.unit).into(),
|
||||||
})),
|
})),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
crate fn as_constant(&mut self, expr: &Expr<'_, 'tcx>) -> Constant<'tcx> {
|
crate fn as_constant(&mut self, expr: &Expr<'_, 'tcx>) -> Constant<'tcx> {
|
||||||
let this = self;
|
let this = self;
|
||||||
let Expr { ty, temp_lifetime: _, span, ref kind } = *expr;
|
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::Scope { region_scope: _, lint_level: _, value } => this.as_constant(value),
|
||||||
ExprKind::Literal { literal, user_ty, const_id: _ } => {
|
ExprKind::Literal { literal, user_ty, const_id: _ } => {
|
||||||
let user_ty = user_ty.map(|user_ty| {
|
let user_ty = user_ty.map(|user_ty| {
|
||||||
|
@ -22,11 +22,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
assert_eq!(literal.ty, ty);
|
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 } => {
|
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),
|
_ => span_bug!(span, "expression is not a valid constant {:?}", kind),
|
||||||
}
|
}
|
||||||
|
|
|
@ -219,7 +219,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
block.and(Rvalue::Use(Operand::Constant(box Constant {
|
block.and(Rvalue::Use(Operand::Constant(box Constant {
|
||||||
span: expr_span,
|
span: expr_span,
|
||||||
user_ty: None,
|
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 { .. }
|
ExprKind::Yield { .. }
|
||||||
|
|
|
@ -146,7 +146,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
Constant {
|
Constant {
|
||||||
span: expr_span,
|
span: expr_span,
|
||||||
user_ty: None,
|
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 {
|
Constant {
|
||||||
span: expr_span,
|
span: expr_span,
|
||||||
user_ty: None,
|
user_ty: None,
|
||||||
literal: ty::Const::from_bool(this.tcx, false),
|
literal: ty::Const::from_bool(this.tcx, false).into(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -429,7 +429,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
// Need to experiment.
|
// Need to experiment.
|
||||||
user_ty: None,
|
user_ty: None,
|
||||||
|
|
||||||
literal: method,
|
literal: method.into(),
|
||||||
}),
|
}),
|
||||||
args: vec![val, expect],
|
args: vec![val, expect],
|
||||||
destination: Some((eq_result, eq_block)),
|
destination: Some((eq_result, eq_block)),
|
||||||
|
|
|
@ -30,6 +30,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
span: Span,
|
span: Span,
|
||||||
literal: &'tcx ty::Const<'tcx>,
|
literal: &'tcx ty::Const<'tcx>,
|
||||||
) -> Operand<'tcx> {
|
) -> Operand<'tcx> {
|
||||||
|
let literal = literal.into();
|
||||||
let constant = box Constant { span, user_ty: None, literal };
|
let constant = box Constant { span, user_ty: None, literal };
|
||||||
Operand::Constant(constant)
|
Operand::Constant(constant)
|
||||||
}
|
}
|
||||||
|
@ -57,7 +58,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
Constant {
|
Constant {
|
||||||
span: source_info.span,
|
span: source_info.span,
|
||||||
user_ty: None,
|
user_ty: None,
|
||||||
literal: ty::Const::from_usize(self.tcx, value),
|
literal: ty::Const::from_usize(self.tcx, value).into(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
temp
|
temp
|
||||||
|
|
|
@ -377,7 +377,10 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
|
||||||
let local = self.place_to_local(span, p)?;
|
let local = self.place_to_local(span, p)?;
|
||||||
Ok(self.locals[local])
|
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")?,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue