Rollup merge of #69181 - skinny121:const-eval-return, r=oli-obk
Change const eval to just return the value As discussed in https://github.com/rust-lang/rust/pull/68505#discussion_r370956535, the type of consts shouldn't be returned from const eval queries. r? @eddyb cc @nikomatsakis
This commit is contained in:
commit
391e7e26ae
25 changed files with 179 additions and 115 deletions
|
@ -2,6 +2,7 @@ use super::{CheckInAllocMsg, Pointer, RawConst, ScalarMaybeUndef};
|
||||||
|
|
||||||
use crate::hir::map::definitions::DefPathData;
|
use crate::hir::map::definitions::DefPathData;
|
||||||
use crate::mir;
|
use crate::mir;
|
||||||
|
use crate::mir::interpret::ConstValue;
|
||||||
use crate::ty::layout::{Align, LayoutError, Size};
|
use crate::ty::layout::{Align, LayoutError, Size};
|
||||||
use crate::ty::query::TyCtxtAt;
|
use crate::ty::query::TyCtxtAt;
|
||||||
use crate::ty::{self, layout, Ty};
|
use crate::ty::{self, layout, Ty};
|
||||||
|
@ -40,7 +41,7 @@ CloneTypeFoldableImpls! {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type ConstEvalRawResult<'tcx> = Result<RawConst<'tcx>, ErrorHandled>;
|
pub type ConstEvalRawResult<'tcx> = Result<RawConst<'tcx>, ErrorHandled>;
|
||||||
pub type ConstEvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, ErrorHandled>;
|
pub type ConstEvalResult<'tcx> = Result<ConstValue<'tcx>, ErrorHandled>;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ConstEvalErr<'tcx> {
|
pub struct ConstEvalErr<'tcx> {
|
||||||
|
|
|
@ -7,7 +7,7 @@ use std::fmt;
|
||||||
|
|
||||||
use crate::ty::{
|
use crate::ty::{
|
||||||
layout::{HasDataLayout, Size},
|
layout::{HasDataLayout, Size},
|
||||||
Ty,
|
ParamEnv, Ty, TyCtxt,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{sign_extend, truncate, AllocId, Allocation, InterpResult, Pointer, PointerArithmetic};
|
use super::{sign_extend, truncate, AllocId, Allocation, InterpResult, Pointer, PointerArithmetic};
|
||||||
|
@ -66,6 +66,32 @@ impl<'tcx> ConstValue<'tcx> {
|
||||||
ConstValue::Scalar(val) => Some(val),
|
ConstValue::Scalar(val) => Some(val),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn try_to_bits(&self, size: Size) -> Option<u128> {
|
||||||
|
self.try_to_scalar()?.to_bits(size).ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn try_to_bits_for_ty(
|
||||||
|
&self,
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
param_env: ParamEnv<'tcx>,
|
||||||
|
ty: Ty<'tcx>,
|
||||||
|
) -> Option<u128> {
|
||||||
|
let size = tcx.layout_of(param_env.with_reveal_all().and(ty)).ok()?.size;
|
||||||
|
self.try_to_bits(size)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_bool(b: bool) -> Self {
|
||||||
|
ConstValue::Scalar(Scalar::from_bool(b))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_u64(i: u64) -> Self {
|
||||||
|
ConstValue::Scalar(Scalar::from_u64(i))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_machine_usize(i: u64, cx: &impl HasDataLayout) -> Self {
|
||||||
|
ConstValue::Scalar(Scalar::from_machine_usize(i, cx))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A `Scalar` represents an immediate, primitive value existing outside of a
|
/// A `Scalar` represents an immediate, primitive value existing outside of a
|
||||||
|
@ -287,6 +313,11 @@ impl<'tcx, Tag> Scalar<Tag> {
|
||||||
Scalar::Raw { data: i as u128, size: 8 }
|
Scalar::Raw { data: i as u128, size: 8 }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn from_machine_usize(i: u64, cx: &impl HasDataLayout) -> Self {
|
||||||
|
Self::from_uint(i, cx.data_layout().pointer_size)
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn try_from_int(i: impl Into<i128>, size: Size) -> Option<Self> {
|
pub fn try_from_int(i: impl Into<i128>, size: Size) -> Option<Self> {
|
||||||
let i = i.into();
|
let i = i.into();
|
||||||
|
@ -306,6 +337,11 @@ impl<'tcx, Tag> Scalar<Tag> {
|
||||||
.unwrap_or_else(|| bug!("Signed value {:#x} does not fit in {} bits", i, size.bits()))
|
.unwrap_or_else(|| bug!("Signed value {:#x} does not fit in {} bits", i, size.bits()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn from_machine_isize(i: i64, cx: &impl HasDataLayout) -> Self {
|
||||||
|
Self::from_int(i, cx.data_layout().pointer_size)
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_f32(f: Single) -> Self {
|
pub fn from_f32(f: Single) -> Self {
|
||||||
// We trust apfloat to give us properly truncated data.
|
// We trust apfloat to give us properly truncated data.
|
||||||
|
|
|
@ -519,7 +519,7 @@ rustc_queries! {
|
||||||
/// Extracts a field of a (variant of a) const.
|
/// Extracts a field of a (variant of a) const.
|
||||||
query const_field(
|
query const_field(
|
||||||
key: ty::ParamEnvAnd<'tcx, (&'tcx ty::Const<'tcx>, mir::Field)>
|
key: ty::ParamEnvAnd<'tcx, (&'tcx ty::Const<'tcx>, mir::Field)>
|
||||||
) -> &'tcx ty::Const<'tcx> {
|
) -> ConstValue<'tcx> {
|
||||||
no_force
|
no_force
|
||||||
desc { "extract field of const" }
|
desc { "extract field of const" }
|
||||||
}
|
}
|
||||||
|
@ -533,7 +533,7 @@ rustc_queries! {
|
||||||
desc { "destructure constant" }
|
desc { "destructure constant" }
|
||||||
}
|
}
|
||||||
|
|
||||||
query const_caller_location(key: (rustc_span::Symbol, u32, u32)) -> &'tcx ty::Const<'tcx> {
|
query const_caller_location(key: (rustc_span::Symbol, u32, u32)) -> ConstValue<'tcx> {
|
||||||
no_force
|
no_force
|
||||||
desc { "get a &core::panic::Location referring to a span" }
|
desc { "get a &core::panic::Location referring to a span" }
|
||||||
}
|
}
|
||||||
|
|
|
@ -2388,10 +2388,10 @@ impl<'tcx> AdtDef {
|
||||||
let repr_type = self.repr.discr_type();
|
let repr_type = self.repr.discr_type();
|
||||||
match tcx.const_eval_poly(expr_did) {
|
match tcx.const_eval_poly(expr_did) {
|
||||||
Ok(val) => {
|
Ok(val) => {
|
||||||
// FIXME: Find the right type and use it instead of `val.ty` here
|
let ty = repr_type.to_ty(tcx);
|
||||||
if let Some(b) = val.try_eval_bits(tcx, param_env, val.ty) {
|
if let Some(b) = val.try_to_bits_for_ty(tcx, param_env, ty) {
|
||||||
trace!("discriminants: {} ({:?})", b, repr_type);
|
trace!("discriminants: {} ({:?})", b, repr_type);
|
||||||
Some(Discr { val: b, ty: val.ty })
|
Some(Discr { val: b, ty })
|
||||||
} else {
|
} else {
|
||||||
info!("invalid enum discriminant: {:#?}", val);
|
info!("invalid enum discriminant: {:#?}", val);
|
||||||
crate::mir::interpret::struct_error(
|
crate::mir::interpret::struct_error(
|
||||||
|
|
|
@ -14,7 +14,7 @@ use crate::middle::resolve_lifetime::{ObjectLifetimeDefault, Region, ResolveLife
|
||||||
use crate::middle::stability::{self, DeprecationEntry};
|
use crate::middle::stability::{self, DeprecationEntry};
|
||||||
use crate::mir;
|
use crate::mir;
|
||||||
use crate::mir::interpret::GlobalId;
|
use crate::mir::interpret::GlobalId;
|
||||||
use crate::mir::interpret::{ConstEvalRawResult, ConstEvalResult};
|
use crate::mir::interpret::{ConstEvalRawResult, ConstEvalResult, ConstValue};
|
||||||
use crate::mir::interpret::{LitToConstError, LitToConstInput};
|
use crate::mir::interpret::{LitToConstError, LitToConstInput};
|
||||||
use crate::mir::mono::CodegenUnit;
|
use crate::mir::mono::CodegenUnit;
|
||||||
use crate::session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
|
use crate::session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
|
||||||
|
|
|
@ -2417,9 +2417,14 @@ pub struct Const<'tcx> {
|
||||||
static_assert_size!(Const<'_>, 48);
|
static_assert_size!(Const<'_>, 48);
|
||||||
|
|
||||||
impl<'tcx> Const<'tcx> {
|
impl<'tcx> Const<'tcx> {
|
||||||
|
#[inline]
|
||||||
|
pub fn from_value(tcx: TyCtxt<'tcx>, val: ConstValue<'tcx>, ty: Ty<'tcx>) -> &'tcx Self {
|
||||||
|
tcx.mk_const(Self { val: ConstKind::Value(val), ty })
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_scalar(tcx: TyCtxt<'tcx>, val: Scalar, ty: Ty<'tcx>) -> &'tcx Self {
|
pub fn from_scalar(tcx: TyCtxt<'tcx>, val: Scalar, ty: Ty<'tcx>) -> &'tcx Self {
|
||||||
tcx.mk_const(Self { val: ConstKind::Value(ConstValue::Scalar(val)), ty })
|
Self::from_value(tcx, ConstValue::Scalar(val), ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -2473,7 +2478,9 @@ impl<'tcx> Const<'tcx> {
|
||||||
|
|
||||||
// try to resolve e.g. associated constants to their definition on an impl, and then
|
// try to resolve e.g. associated constants to their definition on an impl, and then
|
||||||
// evaluate the const.
|
// evaluate the const.
|
||||||
tcx.const_eval_resolve(param_env, did, substs, promoted, None).ok()
|
tcx.const_eval_resolve(param_env, did, substs, promoted, None)
|
||||||
|
.ok()
|
||||||
|
.map(|val| Const::from_value(tcx, val, self.ty))
|
||||||
};
|
};
|
||||||
|
|
||||||
match self.val {
|
match self.val {
|
||||||
|
|
|
@ -78,11 +78,9 @@ pub fn codegen_static_initializer(
|
||||||
cx: &CodegenCx<'ll, 'tcx>,
|
cx: &CodegenCx<'ll, 'tcx>,
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
) -> Result<(&'ll Value, &'tcx Allocation), ErrorHandled> {
|
) -> Result<(&'ll Value, &'tcx Allocation), ErrorHandled> {
|
||||||
let static_ = cx.tcx.const_eval_poly(def_id)?;
|
let alloc = match cx.tcx.const_eval_poly(def_id)? {
|
||||||
|
ConstValue::ByRef { alloc, offset } if offset.bytes() == 0 => alloc,
|
||||||
let alloc = match static_.val {
|
val => bug!("static const eval returned {:#?}", val),
|
||||||
ty::ConstKind::Value(ConstValue::ByRef { alloc, offset }) if offset.bytes() == 0 => alloc,
|
|
||||||
_ => bug!("static const eval returned {:#?}", static_),
|
|
||||||
};
|
};
|
||||||
Ok((const_alloc_to_llvm(cx, alloc), alloc))
|
Ok((const_alloc_to_llvm(cx, alloc), alloc))
|
||||||
}
|
}
|
||||||
|
|
|
@ -193,7 +193,7 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
|
||||||
.tcx
|
.tcx
|
||||||
.const_eval_instance(ty::ParamEnv::reveal_all(), instance, None)
|
.const_eval_instance(ty::ParamEnv::reveal_all(), instance, None)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
OperandRef::from_const(self, ty_name).immediate_or_packed_pair(self)
|
OperandRef::from_const(self, ty_name, ret_ty).immediate_or_packed_pair(self)
|
||||||
}
|
}
|
||||||
"init" => {
|
"init" => {
|
||||||
let ty = substs.type_at(0);
|
let ty = substs.type_at(0);
|
||||||
|
|
|
@ -991,7 +991,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
caller.line as u32,
|
caller.line as u32,
|
||||||
caller.col_display as u32 + 1,
|
caller.col_display as u32 + 1,
|
||||||
));
|
));
|
||||||
OperandRef::from_const(bx, const_loc)
|
OperandRef::from_const(bx, const_loc, bx.tcx().caller_location_ty())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::mir::operand::OperandRef;
|
use crate::mir::operand::OperandRef;
|
||||||
use crate::traits::*;
|
use crate::traits::*;
|
||||||
use rustc::mir;
|
use rustc::mir;
|
||||||
use rustc::mir::interpret::ErrorHandled;
|
use rustc::mir::interpret::{ConstValue, ErrorHandled};
|
||||||
use rustc::ty::layout::{self, HasTyCtxt};
|
use rustc::ty::layout::{self, HasTyCtxt};
|
||||||
use rustc::ty::{self, Ty};
|
use rustc::ty::{self, Ty};
|
||||||
use rustc_index::vec::Idx;
|
use rustc_index::vec::Idx;
|
||||||
|
@ -30,7 +30,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let val = self.eval_mir_constant(constant)?;
|
let val = self.eval_mir_constant(constant)?;
|
||||||
Ok(OperandRef::from_const(bx, val))
|
let ty = self.monomorphize(&constant.literal.ty);
|
||||||
|
Ok(OperandRef::from_const(bx, val.clone(), ty))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,7 +39,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
pub fn eval_mir_constant(
|
pub fn eval_mir_constant(
|
||||||
&mut self,
|
&mut self,
|
||||||
constant: &mir::Constant<'tcx>,
|
constant: &mir::Constant<'tcx>,
|
||||||
) -> Result<&'tcx ty::Const<'tcx>, ErrorHandled> {
|
) -> Result<ConstValue<'tcx>, ErrorHandled> {
|
||||||
match constant.literal.val {
|
match constant.literal.val {
|
||||||
ty::ConstKind::Unevaluated(def_id, substs, promoted) => {
|
ty::ConstKind::Unevaluated(def_id, substs, promoted) => {
|
||||||
let substs = self.monomorphize(&substs);
|
let substs = self.monomorphize(&substs);
|
||||||
|
@ -55,7 +56,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
err
|
err
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
_ => Ok(self.monomorphize(&constant.literal)),
|
ty::ConstKind::Value(value) => Ok(value),
|
||||||
|
_ => {
|
||||||
|
let const_ = self.monomorphize(&constant.literal);
|
||||||
|
if let ty::ConstKind::Value(value) = const_.val {
|
||||||
|
Ok(value)
|
||||||
|
} else {
|
||||||
|
span_bug!(constant.span, "encountered bad ConstKind in codegen: {:?}", const_);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,21 +74,22 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
bx: &Bx,
|
bx: &Bx,
|
||||||
span: Span,
|
span: Span,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
constant: Result<&'tcx ty::Const<'tcx>, ErrorHandled>,
|
constant: Result<ConstValue<'tcx>, ErrorHandled>,
|
||||||
) -> (Bx::Value, Ty<'tcx>) {
|
) -> (Bx::Value, Ty<'tcx>) {
|
||||||
constant
|
constant
|
||||||
.map(|c| {
|
.map(|val| {
|
||||||
let field_ty = c.ty.builtin_index().unwrap();
|
let field_ty = ty.builtin_index().unwrap();
|
||||||
let fields = match c.ty.kind {
|
let fields = match ty.kind {
|
||||||
ty::Array(_, n) => n.eval_usize(bx.tcx(), ty::ParamEnv::reveal_all()),
|
ty::Array(_, n) => n.eval_usize(bx.tcx(), ty::ParamEnv::reveal_all()),
|
||||||
_ => bug!("invalid simd shuffle type: {}", c.ty),
|
_ => bug!("invalid simd shuffle type: {}", ty),
|
||||||
};
|
};
|
||||||
|
let c = ty::Const::from_value(bx.tcx(), val, ty);
|
||||||
let values: Vec<_> = (0..fields)
|
let values: Vec<_> = (0..fields)
|
||||||
.map(|field| {
|
.map(|field| {
|
||||||
let field = bx.tcx().const_field(
|
let field = bx.tcx().const_field(
|
||||||
ty::ParamEnv::reveal_all().and((&c, mir::Field::new(field as usize))),
|
ty::ParamEnv::reveal_all().and((&c, mir::Field::new(field as usize))),
|
||||||
);
|
);
|
||||||
if let Some(prim) = field.val.try_to_scalar() {
|
if let Some(prim) = field.try_to_scalar() {
|
||||||
let layout = bx.layout_of(field_ty);
|
let layout = bx.layout_of(field_ty);
|
||||||
let scalar = match layout.abi {
|
let scalar = match layout.abi {
|
||||||
layout::Abi::Scalar(ref x) => x,
|
layout::Abi::Scalar(ref x) => x,
|
||||||
|
|
|
@ -8,8 +8,8 @@ use crate::MemFlags;
|
||||||
|
|
||||||
use rustc::mir;
|
use rustc::mir;
|
||||||
use rustc::mir::interpret::{ConstValue, ErrorHandled, Pointer, Scalar};
|
use rustc::mir::interpret::{ConstValue, ErrorHandled, Pointer, Scalar};
|
||||||
use rustc::ty;
|
|
||||||
use rustc::ty::layout::{self, Align, LayoutOf, Size, TyLayout};
|
use rustc::ty::layout::{self, Align, LayoutOf, Size, TyLayout};
|
||||||
|
use rustc::ty::Ty;
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
|
@ -66,20 +66,16 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
|
||||||
|
|
||||||
pub fn from_const<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
|
pub fn from_const<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
|
||||||
bx: &mut Bx,
|
bx: &mut Bx,
|
||||||
val: &'tcx ty::Const<'tcx>,
|
val: ConstValue<'tcx>,
|
||||||
|
ty: Ty<'tcx>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let layout = bx.layout_of(val.ty);
|
let layout = bx.layout_of(ty);
|
||||||
|
|
||||||
if layout.is_zst() {
|
if layout.is_zst() {
|
||||||
return OperandRef::new_zst(bx, layout);
|
return OperandRef::new_zst(bx, layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
let val_val = match val.val {
|
let val = match val {
|
||||||
ty::ConstKind::Value(val_val) => val_val,
|
|
||||||
_ => bug!("encountered bad ConstKind in codegen"),
|
|
||||||
};
|
|
||||||
|
|
||||||
let val = match val_val {
|
|
||||||
ConstValue::Scalar(x) => {
|
ConstValue::Scalar(x) => {
|
||||||
let scalar = match layout.abi {
|
let scalar = match layout.abi {
|
||||||
layout::Abi::Scalar(ref x) => x,
|
layout::Abi::Scalar(ref x) => x,
|
||||||
|
|
|
@ -26,7 +26,7 @@ pub(crate) fn const_field<'tcx>(
|
||||||
variant: Option<VariantIdx>,
|
variant: Option<VariantIdx>,
|
||||||
field: mir::Field,
|
field: mir::Field,
|
||||||
value: &'tcx ty::Const<'tcx>,
|
value: &'tcx ty::Const<'tcx>,
|
||||||
) -> &'tcx ty::Const<'tcx> {
|
) -> ConstValue<'tcx> {
|
||||||
trace!("const_field: {:?}, {:?}", field, value);
|
trace!("const_field: {:?}, {:?}", field, value);
|
||||||
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
|
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
|
||||||
// get the operand again
|
// get the operand again
|
||||||
|
@ -46,19 +46,13 @@ pub(crate) fn const_field<'tcx>(
|
||||||
pub(crate) fn const_caller_location<'tcx>(
|
pub(crate) fn const_caller_location<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
(file, line, col): (Symbol, u32, u32),
|
(file, line, col): (Symbol, u32, u32),
|
||||||
) -> &'tcx ty::Const<'tcx> {
|
) -> ConstValue<'tcx> {
|
||||||
trace!("const_caller_location: {}:{}:{}", file, line, col);
|
trace!("const_caller_location: {}:{}:{}", file, line, col);
|
||||||
let mut ecx = mk_eval_cx(tcx, DUMMY_SP, ty::ParamEnv::reveal_all(), false);
|
let mut ecx = mk_eval_cx(tcx, DUMMY_SP, ty::ParamEnv::reveal_all(), false);
|
||||||
|
|
||||||
let loc_ty = tcx.caller_location_ty();
|
|
||||||
let loc_place = ecx.alloc_caller_location(file, line, col);
|
let loc_place = ecx.alloc_caller_location(file, line, col);
|
||||||
intern_const_alloc_recursive(&mut ecx, InternKind::Constant, loc_place, false).unwrap();
|
intern_const_alloc_recursive(&mut ecx, InternKind::Constant, loc_place, false).unwrap();
|
||||||
let loc_const = ty::Const {
|
ConstValue::Scalar(loc_place.ptr.into())
|
||||||
ty: loc_ty,
|
|
||||||
val: ty::ConstKind::Value(ConstValue::Scalar(loc_place.ptr.into())),
|
|
||||||
};
|
|
||||||
|
|
||||||
tcx.mk_const(loc_const)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// this function uses `unwrap` copiously, because an already validated constant
|
// this function uses `unwrap` copiously, because an already validated constant
|
||||||
|
@ -84,7 +78,8 @@ pub(crate) fn destructure_const<'tcx>(
|
||||||
let down = ecx.operand_downcast(op, variant).unwrap();
|
let down = ecx.operand_downcast(op, variant).unwrap();
|
||||||
let fields_iter = (0..field_count).map(|i| {
|
let fields_iter = (0..field_count).map(|i| {
|
||||||
let field_op = ecx.operand_field(down, i).unwrap();
|
let field_op = ecx.operand_field(down, i).unwrap();
|
||||||
op_to_const(&ecx, field_op)
|
let val = op_to_const(&ecx, field_op);
|
||||||
|
ty::Const::from_value(tcx, val, field_op.layout.ty)
|
||||||
});
|
});
|
||||||
let fields = tcx.arena.alloc_from_iter(fields_iter);
|
let fields = tcx.arena.alloc_from_iter(fields_iter);
|
||||||
|
|
||||||
|
|
|
@ -97,7 +97,7 @@ pub(super) fn mk_eval_cx<'mir, 'tcx>(
|
||||||
pub(super) fn op_to_const<'tcx>(
|
pub(super) fn op_to_const<'tcx>(
|
||||||
ecx: &CompileTimeEvalContext<'_, 'tcx>,
|
ecx: &CompileTimeEvalContext<'_, 'tcx>,
|
||||||
op: OpTy<'tcx>,
|
op: OpTy<'tcx>,
|
||||||
) -> &'tcx ty::Const<'tcx> {
|
) -> ConstValue<'tcx> {
|
||||||
// We do not have value optimizations for everything.
|
// We do not have value optimizations for everything.
|
||||||
// Only scalars and slices, since they are very common.
|
// Only scalars and slices, since they are very common.
|
||||||
// Note that further down we turn scalars of undefined bits back to `ByRef`. These can result
|
// Note that further down we turn scalars of undefined bits back to `ByRef`. These can result
|
||||||
|
@ -144,7 +144,7 @@ pub(super) fn op_to_const<'tcx>(
|
||||||
ConstValue::Scalar(Scalar::zst())
|
ConstValue::Scalar(Scalar::zst())
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let val = match immediate {
|
match immediate {
|
||||||
Ok(mplace) => to_const_value(mplace),
|
Ok(mplace) => to_const_value(mplace),
|
||||||
// see comment on `let try_as_immediate` above
|
// see comment on `let try_as_immediate` above
|
||||||
Err(ImmTy { imm: Immediate::Scalar(x), .. }) => match x {
|
Err(ImmTy { imm: Immediate::Scalar(x), .. }) => match x {
|
||||||
|
@ -166,8 +166,7 @@ pub(super) fn op_to_const<'tcx>(
|
||||||
let len: usize = len.try_into().unwrap();
|
let len: usize = len.try_into().unwrap();
|
||||||
ConstValue::Slice { data, start, end: start + len }
|
ConstValue::Slice { data, start, end: start + len }
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
ecx.tcx.mk_const(ty::Const { val: ty::ConstKind::Value(val), ty: op.layout.ty })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate_and_turn_into_const<'tcx>(
|
fn validate_and_turn_into_const<'tcx>(
|
||||||
|
@ -195,13 +194,10 @@ fn validate_and_turn_into_const<'tcx>(
|
||||||
// whether they become immediates.
|
// whether they become immediates.
|
||||||
if is_static || cid.promoted.is_some() {
|
if is_static || cid.promoted.is_some() {
|
||||||
let ptr = mplace.ptr.assert_ptr();
|
let ptr = mplace.ptr.assert_ptr();
|
||||||
Ok(tcx.mk_const(ty::Const {
|
Ok(ConstValue::ByRef {
|
||||||
val: ty::ConstKind::Value(ConstValue::ByRef {
|
|
||||||
alloc: ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id),
|
alloc: ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id),
|
||||||
offset: ptr.offset,
|
offset: ptr.offset,
|
||||||
}),
|
})
|
||||||
ty: mplace.layout.ty,
|
|
||||||
}))
|
|
||||||
} else {
|
} else {
|
||||||
Ok(op_to_const(&ecx, mplace.into()))
|
Ok(op_to_const(&ecx, mplace.into()))
|
||||||
}
|
}
|
||||||
|
|
|
@ -756,6 +756,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
pub(super) fn const_eval(
|
pub(super) fn const_eval(
|
||||||
&self,
|
&self,
|
||||||
gid: GlobalId<'tcx>,
|
gid: GlobalId<'tcx>,
|
||||||
|
ty: Ty<'tcx>,
|
||||||
) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
|
) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
|
||||||
// For statics we pick `ParamEnv::reveal_all`, because statics don't have generics
|
// For statics we pick `ParamEnv::reveal_all`, because statics don't have generics
|
||||||
// and thus don't care about the parameter environment. While we could just use
|
// and thus don't care about the parameter environment. While we could just use
|
||||||
|
@ -777,7 +778,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
// recursion deeper than one level, because the `tcx.const_eval` above is guaranteed to not
|
// recursion deeper than one level, because the `tcx.const_eval` above is guaranteed to not
|
||||||
// return `ConstValue::Unevaluated`, which is the only way that `eval_const_to_op` will call
|
// return `ConstValue::Unevaluated`, which is the only way that `eval_const_to_op` will call
|
||||||
// `ecx.const_eval`.
|
// `ecx.const_eval`.
|
||||||
self.eval_const_to_op(val, None)
|
let const_ = ty::Const { val: ty::ConstKind::Value(val), ty };
|
||||||
|
self.eval_const_to_op(&const_, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn const_eval_raw(
|
pub fn const_eval_raw(
|
||||||
|
|
|
@ -48,22 +48,15 @@ crate fn eval_nullary_intrinsic<'tcx>(
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
substs: SubstsRef<'tcx>,
|
substs: SubstsRef<'tcx>,
|
||||||
) -> InterpResult<'tcx, &'tcx ty::Const<'tcx>> {
|
) -> InterpResult<'tcx, ConstValue<'tcx>> {
|
||||||
let tp_ty = substs.type_at(0);
|
let tp_ty = substs.type_at(0);
|
||||||
let name = tcx.item_name(def_id);
|
let name = tcx.item_name(def_id);
|
||||||
Ok(match name {
|
Ok(match name {
|
||||||
sym::type_name => {
|
sym::type_name => {
|
||||||
let alloc = type_name::alloc_type_name(tcx, tp_ty);
|
let alloc = type_name::alloc_type_name(tcx, tp_ty);
|
||||||
tcx.mk_const(ty::Const {
|
ConstValue::Slice { data: alloc, start: 0, end: alloc.len() }
|
||||||
val: ty::ConstKind::Value(ConstValue::Slice {
|
|
||||||
data: alloc,
|
|
||||||
start: 0,
|
|
||||||
end: alloc.len(),
|
|
||||||
}),
|
|
||||||
ty: tcx.mk_static_str(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
sym::needs_drop => ty::Const::from_bool(tcx, tp_ty.needs_drop(tcx, param_env)),
|
sym::needs_drop => ConstValue::from_bool(tp_ty.needs_drop(tcx, param_env)),
|
||||||
sym::size_of | sym::min_align_of | sym::pref_align_of => {
|
sym::size_of | sym::min_align_of | sym::pref_align_of => {
|
||||||
let layout = tcx.layout_of(param_env.and(tp_ty)).map_err(|e| err_inval!(Layout(e)))?;
|
let layout = tcx.layout_of(param_env.and(tp_ty)).map_err(|e| err_inval!(Layout(e)))?;
|
||||||
let n = match name {
|
let n = match name {
|
||||||
|
@ -72,11 +65,9 @@ crate fn eval_nullary_intrinsic<'tcx>(
|
||||||
sym::size_of => layout.size.bytes(),
|
sym::size_of => layout.size.bytes(),
|
||||||
_ => bug!(),
|
_ => bug!(),
|
||||||
};
|
};
|
||||||
ty::Const::from_usize(tcx, n)
|
ConstValue::from_machine_usize(n, &tcx)
|
||||||
}
|
|
||||||
sym::type_id => {
|
|
||||||
ty::Const::from_bits(tcx, tcx.type_id_hash(tp_ty).into(), param_env.and(tcx.types.u64))
|
|
||||||
}
|
}
|
||||||
|
sym::type_id => ConstValue::from_u64(tcx.type_id_hash(tp_ty).into()),
|
||||||
other => bug!("`{}` is not a zero arg intrinsic", other),
|
other => bug!("`{}` is not a zero arg intrinsic", other),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -119,7 +110,14 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
| sym::type_id
|
| sym::type_id
|
||||||
| sym::type_name => {
|
| sym::type_name => {
|
||||||
let gid = GlobalId { instance, promoted: None };
|
let gid = GlobalId { instance, promoted: None };
|
||||||
let val = self.const_eval(gid)?;
|
let ty = match intrinsic_name {
|
||||||
|
sym::min_align_of | sym::pref_align_of | sym::size_of => self.tcx.types.usize,
|
||||||
|
sym::needs_drop => self.tcx.types.bool,
|
||||||
|
sym::type_id => self.tcx.types.u64,
|
||||||
|
sym::type_name => self.tcx.mk_static_str(),
|
||||||
|
_ => span_bug!(span, "Already checked for nullary intrinsics"),
|
||||||
|
};
|
||||||
|
let val = self.const_eval(gid, ty)?;
|
||||||
self.copy_op(val, dest)?;
|
self.copy_op(val, dest)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -518,7 +518,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
/// "universe" (param_env).
|
/// "universe" (param_env).
|
||||||
crate fn eval_const_to_op(
|
crate fn eval_const_to_op(
|
||||||
&self,
|
&self,
|
||||||
val: &'tcx ty::Const<'tcx>,
|
val: &ty::Const<'tcx>,
|
||||||
layout: Option<TyLayout<'tcx>>,
|
layout: Option<TyLayout<'tcx>>,
|
||||||
) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
|
) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
|
||||||
let tag_scalar = |scalar| match scalar {
|
let tag_scalar = |scalar| match scalar {
|
||||||
|
@ -536,7 +536,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
// potentially requiring the current static to be evaluated again. This is not a
|
// potentially requiring the current static to be evaluated again. This is not a
|
||||||
// problem here, because we are building an operand which means an actual read is
|
// problem here, because we are building an operand which means an actual read is
|
||||||
// happening.
|
// happening.
|
||||||
return Ok(OpTy::from(self.const_eval(GlobalId { instance, promoted })?));
|
return Ok(self.const_eval(GlobalId { instance, promoted }, val.ty)?);
|
||||||
}
|
}
|
||||||
ty::ConstKind::Infer(..)
|
ty::ConstKind::Infer(..)
|
||||||
| ty::ConstKind::Bound(..)
|
| ty::ConstKind::Bound(..)
|
||||||
|
|
|
@ -357,7 +357,7 @@ fn collect_items_rec<'tcx>(
|
||||||
recursion_depth_reset = None;
|
recursion_depth_reset = None;
|
||||||
|
|
||||||
if let Ok(val) = tcx.const_eval_poly(def_id) {
|
if let Ok(val) = tcx.const_eval_poly(def_id) {
|
||||||
collect_const(tcx, val, InternalSubsts::empty(), &mut neighbors);
|
collect_const_value(tcx, val, &mut neighbors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MonoItem::Fn(instance) => {
|
MonoItem::Fn(instance) => {
|
||||||
|
@ -971,7 +971,7 @@ impl ItemLikeVisitor<'v> for RootCollector<'_, 'v> {
|
||||||
let def_id = self.tcx.hir().local_def_id(item.hir_id);
|
let def_id = self.tcx.hir().local_def_id(item.hir_id);
|
||||||
|
|
||||||
if let Ok(val) = self.tcx.const_eval_poly(def_id) {
|
if let Ok(val) = self.tcx.const_eval_poly(def_id) {
|
||||||
collect_const(self.tcx, val, InternalSubsts::empty(), &mut self.output);
|
collect_const_value(self.tcx, val, &mut self.output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hir::ItemKind::Fn(..) => {
|
hir::ItemKind::Fn(..) => {
|
||||||
|
@ -1185,18 +1185,10 @@ fn collect_const<'tcx>(
|
||||||
tcx.subst_and_normalize_erasing_regions(param_substs, param_env, &constant);
|
tcx.subst_and_normalize_erasing_regions(param_substs, param_env, &constant);
|
||||||
|
|
||||||
match substituted_constant.val {
|
match substituted_constant.val {
|
||||||
ty::ConstKind::Value(ConstValue::Scalar(Scalar::Ptr(ptr))) => {
|
ty::ConstKind::Value(val) => collect_const_value(tcx, val, output),
|
||||||
collect_miri(tcx, ptr.alloc_id, output)
|
|
||||||
}
|
|
||||||
ty::ConstKind::Value(ConstValue::Slice { data: alloc, start: _, end: _ })
|
|
||||||
| ty::ConstKind::Value(ConstValue::ByRef { alloc, .. }) => {
|
|
||||||
for &((), id) in alloc.relocations().values() {
|
|
||||||
collect_miri(tcx, id, output);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ty::ConstKind::Unevaluated(def_id, substs, promoted) => {
|
ty::ConstKind::Unevaluated(def_id, substs, promoted) => {
|
||||||
match tcx.const_eval_resolve(param_env, def_id, substs, promoted, None) {
|
match tcx.const_eval_resolve(param_env, def_id, substs, promoted, None) {
|
||||||
Ok(val) => collect_const(tcx, val, param_substs, output),
|
Ok(val) => collect_const_value(tcx, val, output),
|
||||||
Err(ErrorHandled::Reported) => {}
|
Err(ErrorHandled::Reported) => {}
|
||||||
Err(ErrorHandled::TooGeneric) => {
|
Err(ErrorHandled::TooGeneric) => {
|
||||||
span_bug!(tcx.def_span(def_id), "collection encountered polymorphic constant",)
|
span_bug!(tcx.def_span(def_id), "collection encountered polymorphic constant",)
|
||||||
|
@ -1206,3 +1198,19 @@ fn collect_const<'tcx>(
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn collect_const_value<'tcx>(
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
value: ConstValue<'tcx>,
|
||||||
|
output: &mut Vec<MonoItem<'tcx>>,
|
||||||
|
) {
|
||||||
|
match value {
|
||||||
|
ConstValue::Scalar(Scalar::Ptr(ptr)) => collect_miri(tcx, ptr.alloc_id, output),
|
||||||
|
ConstValue::Slice { data: alloc, start: _, end: _ } | ConstValue::ByRef { alloc, .. } => {
|
||||||
|
for &((), id) in alloc.relocations().values() {
|
||||||
|
collect_miri(tcx, id, output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -65,7 +65,7 @@ crate fn lit_to_const<'tcx>(
|
||||||
ast::LitKind::Char(c) => ConstValue::Scalar(Scalar::from_char(c)),
|
ast::LitKind::Char(c) => ConstValue::Scalar(Scalar::from_char(c)),
|
||||||
ast::LitKind::Err(_) => return Err(LitToConstError::Reported),
|
ast::LitKind::Err(_) => return Err(LitToConstError::Reported),
|
||||||
};
|
};
|
||||||
Ok(tcx.mk_const(ty::Const { val: ty::ConstKind::Value(lit), ty }))
|
Ok(ty::Const::from_value(tcx, lit, ty))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_float<'tcx>(num: Symbol, fty: ast::FloatTy, neg: bool) -> Result<ConstValue<'tcx>, ()> {
|
fn parse_float<'tcx>(num: Symbol, fty: ast::FloatTy, neg: bool) -> Result<ConstValue<'tcx>, ()> {
|
||||||
|
|
|
@ -418,7 +418,17 @@ fn make_mirror_unadjusted<'a, 'tcx>(
|
||||||
None,
|
None,
|
||||||
Some(span),
|
Some(span),
|
||||||
) {
|
) {
|
||||||
Ok(cv) => cv.eval_usize(cx.tcx, ty::ParamEnv::reveal_all()),
|
Ok(cv) => {
|
||||||
|
if let Some(count) = cv.try_to_bits_for_ty(
|
||||||
|
cx.tcx,
|
||||||
|
ty::ParamEnv::reveal_all(),
|
||||||
|
cx.tcx.types.usize,
|
||||||
|
) {
|
||||||
|
count as u64
|
||||||
|
} else {
|
||||||
|
bug!("repeat count constant value can't be converted to usize");
|
||||||
|
}
|
||||||
|
}
|
||||||
Err(ErrorHandled::Reported) => 0,
|
Err(ErrorHandled::Reported) => 0,
|
||||||
Err(ErrorHandled::TooGeneric) => {
|
Err(ErrorHandled::TooGeneric) => {
|
||||||
let span = cx.tcx.def_span(def_id);
|
let span = cx.tcx.def_span(def_id);
|
||||||
|
|
|
@ -343,12 +343,11 @@ impl<'tcx> PatternFolder<'tcx> for LiteralExpander<'tcx> {
|
||||||
ty: rty,
|
ty: rty,
|
||||||
span: pat.span,
|
span: pat.span,
|
||||||
kind: box PatKind::Constant {
|
kind: box PatKind::Constant {
|
||||||
value: self.tcx.mk_const(Const {
|
value: Const::from_value(
|
||||||
val: ty::ConstKind::Value(
|
self.tcx,
|
||||||
self.fold_const_value_deref(*val, rty, crty),
|
self.fold_const_value_deref(*val, rty, crty),
|
||||||
|
rty,
|
||||||
),
|
),
|
||||||
ty: rty,
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -769,7 +769,10 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
||||||
Some(span),
|
Some(span),
|
||||||
) {
|
) {
|
||||||
Ok(value) => {
|
Ok(value) => {
|
||||||
let pattern = self.const_to_pat(value, id, span);
|
let const_ =
|
||||||
|
ty::Const::from_value(self.tcx, value, self.tables.node_type(id));
|
||||||
|
|
||||||
|
let pattern = self.const_to_pat(&const_, id, span);
|
||||||
if !is_associated_const {
|
if !is_associated_const {
|
||||||
return pattern;
|
return pattern;
|
||||||
}
|
}
|
||||||
|
@ -789,7 +792,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
||||||
user_ty_span: span,
|
user_ty_span: span,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
ty: value.ty,
|
ty: const_.ty,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
pattern
|
pattern
|
||||||
|
|
|
@ -1012,6 +1012,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
Ok(self.to_const(count, tcx.type_of(count_def_id)))
|
Ok(self.to_const(count, tcx.type_of(count_def_id)))
|
||||||
} else {
|
} else {
|
||||||
tcx.const_eval_poly(count_def_id)
|
tcx.const_eval_poly(count_def_id)
|
||||||
|
.map(|val| ty::Const::from_value(tcx, val, tcx.type_of(count_def_id)))
|
||||||
};
|
};
|
||||||
|
|
||||||
let uty = match expected {
|
let uty = match expected {
|
||||||
|
|
|
@ -1832,12 +1832,8 @@ fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: DefId, span: Span)
|
||||||
// `#[link_section]` may contain arbitrary, or even undefined bytes, but it is
|
// `#[link_section]` may contain arbitrary, or even undefined bytes, but it is
|
||||||
// the consumer's responsibility to ensure all bytes that have been read
|
// the consumer's responsibility to ensure all bytes that have been read
|
||||||
// have defined values.
|
// have defined values.
|
||||||
if let Ok(static_) = tcx.const_eval_poly(id) {
|
match tcx.const_eval_poly(id) {
|
||||||
let alloc = if let ty::ConstKind::Value(ConstValue::ByRef { alloc, .. }) = static_.val {
|
Ok(ConstValue::ByRef { alloc, .. }) => {
|
||||||
alloc
|
|
||||||
} else {
|
|
||||||
bug!("Matching on non-ByRef static")
|
|
||||||
};
|
|
||||||
if alloc.relocations().len() != 0 {
|
if alloc.relocations().len() != 0 {
|
||||||
let msg = "statics with a custom `#[link_section]` must be a \
|
let msg = "statics with a custom `#[link_section]` must be a \
|
||||||
simple list of bytes on the wasm target with no \
|
simple list of bytes on the wasm target with no \
|
||||||
|
@ -1845,6 +1841,9 @@ fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: DefId, span: Span)
|
||||||
tcx.sess.span_err(span, msg);
|
tcx.sess.span_err(span, msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Ok(_) => bug!("Matching on non-ByRef static"),
|
||||||
|
Err(_) => {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_on_unimplemented(tcx: TyCtxt<'_>, trait_def_id: DefId, item: &hir::Item<'_>) {
|
fn check_on_unimplemented(tcx: TyCtxt<'_>, trait_def_id: DefId, item: &hir::Item<'_>) {
|
||||||
|
|
|
@ -1332,7 +1332,9 @@ impl Clean<Type> for hir::Ty<'_> {
|
||||||
TyKind::Array(ref ty, ref length) => {
|
TyKind::Array(ref ty, ref length) => {
|
||||||
let def_id = cx.tcx.hir().local_def_id(length.hir_id);
|
let def_id = cx.tcx.hir().local_def_id(length.hir_id);
|
||||||
let length = match cx.tcx.const_eval_poly(def_id) {
|
let length = match cx.tcx.const_eval_poly(def_id) {
|
||||||
Ok(length) => print_const(cx, length),
|
Ok(length) => {
|
||||||
|
print_const(cx, ty::Const::from_value(cx.tcx, length, cx.tcx.types.usize))
|
||||||
|
}
|
||||||
Err(_) => cx
|
Err(_) => cx
|
||||||
.sess()
|
.sess()
|
||||||
.source_map()
|
.source_map()
|
||||||
|
|
|
@ -457,7 +457,7 @@ pub fn name_from_pat(p: &hir::Pat) -> String {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn print_const(cx: &DocContext<'_>, n: &ty::Const<'_>) -> String {
|
pub fn print_const(cx: &DocContext<'_>, n: &'tcx ty::Const<'_>) -> String {
|
||||||
match n.val {
|
match n.val {
|
||||||
ty::ConstKind::Unevaluated(def_id, _, promoted) => {
|
ty::ConstKind::Unevaluated(def_id, _, promoted) => {
|
||||||
let mut s = if let Some(hir_id) = cx.tcx.hir().as_local_hir_id(def_id) {
|
let mut s = if let Some(hir_id) = cx.tcx.hir().as_local_hir_id(def_id) {
|
||||||
|
@ -487,14 +487,17 @@ pub fn print_const(cx: &DocContext<'_>, n: &ty::Const<'_>) -> String {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn print_evaluated_const(cx: &DocContext<'_>, def_id: DefId) -> Option<String> {
|
pub fn print_evaluated_const(cx: &DocContext<'_>, def_id: DefId) -> Option<String> {
|
||||||
let value =
|
let value = cx.tcx.const_eval_poly(def_id).ok().and_then(|val| {
|
||||||
cx.tcx.const_eval_poly(def_id).ok().and_then(|value| match (value.val, &value.ty.kind) {
|
let ty = cx.tcx.type_of(def_id);
|
||||||
(_, ty::Ref(..)) => None,
|
match (val, &ty.kind) {
|
||||||
(ty::ConstKind::Value(ConstValue::Scalar(_)), ty::Adt(_, _)) => None,
|
(_, &ty::Ref(..)) => None,
|
||||||
(ty::ConstKind::Value(ConstValue::Scalar(_)), _) => {
|
(ConstValue::Scalar(_), &ty::Adt(_, _)) => None,
|
||||||
Some(print_const_with_custom_print_scalar(cx, value))
|
(ConstValue::Scalar(_), _) => {
|
||||||
|
let const_ = ty::Const::from_value(cx.tcx, val, ty);
|
||||||
|
Some(print_const_with_custom_print_scalar(cx, const_))
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
value
|
value
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue