Get rid of special const intrinsic query in favour of const_eval
This commit is contained in:
parent
5670d048c0
commit
0de9485038
14 changed files with 117 additions and 130 deletions
|
@ -213,6 +213,15 @@ fn print_backtrace(backtrace: &mut Backtrace) {
|
||||||
eprintln!("\n\nAn error occurred in miri:\n{:?}", backtrace);
|
eprintln!("\n\nAn error occurred in miri:\n{:?}", backtrace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<ErrorHandled> for InterpErrorInfo<'tcx> {
|
||||||
|
fn from(err: ErrorHandled) -> Self {
|
||||||
|
match err {
|
||||||
|
ErrorHandled::Reported => err_inval!(ReferencedConstant),
|
||||||
|
ErrorHandled::TooGeneric => err_inval!(TooGeneric),
|
||||||
|
}.into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'tcx> From<InterpError<'tcx>> for InterpErrorInfo<'tcx> {
|
impl<'tcx> From<InterpError<'tcx>> for InterpErrorInfo<'tcx> {
|
||||||
fn from(kind: InterpError<'tcx>) -> Self {
|
fn from(kind: InterpError<'tcx>) -> Self {
|
||||||
let backtrace = match env::var("RUSTC_CTFE_BACKTRACE") {
|
let backtrace = match env::var("RUSTC_CTFE_BACKTRACE") {
|
||||||
|
|
|
@ -462,15 +462,6 @@ rustc_queries! {
|
||||||
no_force
|
no_force
|
||||||
desc { "extract field of const" }
|
desc { "extract field of const" }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Produces an absolute path representation of the given type. See also the documentation
|
|
||||||
/// on `std::any::type_name`.
|
|
||||||
query type_name(key: Ty<'tcx>) -> &'tcx ty::Const<'tcx> {
|
|
||||||
eval_always
|
|
||||||
no_force
|
|
||||||
desc { "get absolute path of type" }
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeChecking {
|
TypeChecking {
|
||||||
|
|
|
@ -15,6 +15,7 @@ use rustc_codegen_ssa::glue;
|
||||||
use rustc_codegen_ssa::base::{to_immediate, wants_msvc_seh, compare_simd_types};
|
use rustc_codegen_ssa::base::{to_immediate, wants_msvc_seh, compare_simd_types};
|
||||||
use rustc::ty::{self, Ty};
|
use rustc::ty::{self, Ty};
|
||||||
use rustc::ty::layout::{self, LayoutOf, HasTyCtxt, Primitive};
|
use rustc::ty::layout::{self, LayoutOf, HasTyCtxt, Primitive};
|
||||||
|
use rustc::mir::interpret::GlobalId;
|
||||||
use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
|
use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
|
||||||
use rustc::hir;
|
use rustc::hir;
|
||||||
use syntax::ast::{self, FloatTy};
|
use syntax::ast::{self, FloatTy};
|
||||||
|
@ -81,13 +82,14 @@ fn get_simple_intrinsic(cx: &CodegenCx<'ll, '_>, name: &str) -> Option<&'ll Valu
|
||||||
impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
|
impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
|
||||||
fn codegen_intrinsic_call(
|
fn codegen_intrinsic_call(
|
||||||
&mut self,
|
&mut self,
|
||||||
callee_ty: Ty<'tcx>,
|
instance: ty::Instance<'tcx>,
|
||||||
fn_ty: &FnType<'tcx, Ty<'tcx>>,
|
fn_ty: &FnType<'tcx, Ty<'tcx>>,
|
||||||
args: &[OperandRef<'tcx, &'ll Value>],
|
args: &[OperandRef<'tcx, &'ll Value>],
|
||||||
llresult: &'ll Value,
|
llresult: &'ll Value,
|
||||||
span: Span,
|
span: Span,
|
||||||
) {
|
) {
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
|
let callee_ty = instance.ty(tcx);
|
||||||
|
|
||||||
let (def_id, substs) = match callee_ty.sty {
|
let (def_id, substs) = match callee_ty.sty {
|
||||||
ty::FnDef(def_id, substs) => (def_id, substs),
|
ty::FnDef(def_id, substs) => (def_id, substs),
|
||||||
|
@ -133,10 +135,6 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
|
||||||
let llfn = self.get_intrinsic(&("llvm.debugtrap"));
|
let llfn = self.get_intrinsic(&("llvm.debugtrap"));
|
||||||
self.call(llfn, &[], None)
|
self.call(llfn, &[], None)
|
||||||
}
|
}
|
||||||
"size_of" => {
|
|
||||||
let tp_ty = substs.type_at(0);
|
|
||||||
self.const_usize(self.size_of(tp_ty).bytes())
|
|
||||||
}
|
|
||||||
"va_start" => {
|
"va_start" => {
|
||||||
self.va_start(args[0].immediate())
|
self.va_start(args[0].immediate())
|
||||||
}
|
}
|
||||||
|
@ -188,10 +186,6 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
|
||||||
self.const_usize(self.size_of(tp_ty).bytes())
|
self.const_usize(self.size_of(tp_ty).bytes())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"min_align_of" => {
|
|
||||||
let tp_ty = substs.type_at(0);
|
|
||||||
self.const_usize(self.align_of(tp_ty).bytes())
|
|
||||||
}
|
|
||||||
"min_align_of_val" => {
|
"min_align_of_val" => {
|
||||||
let tp_ty = substs.type_at(0);
|
let tp_ty = substs.type_at(0);
|
||||||
if let OperandValue::Pair(_, meta) = args[0].val {
|
if let OperandValue::Pair(_, meta) = args[0].val {
|
||||||
|
@ -201,18 +195,19 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
|
||||||
self.const_usize(self.align_of(tp_ty).bytes())
|
self.const_usize(self.align_of(tp_ty).bytes())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"pref_align_of" => {
|
"size_of" |
|
||||||
let tp_ty = substs.type_at(0);
|
"pref_align_of" |
|
||||||
self.const_usize(self.layout_of(tp_ty).align.pref.bytes())
|
"min_align_of" |
|
||||||
}
|
"needs_drop" |
|
||||||
|
"type_id" |
|
||||||
"type_name" => {
|
"type_name" => {
|
||||||
let tp_ty = substs.type_at(0);
|
let gid = GlobalId {
|
||||||
let ty_name = self.tcx.type_name(tp_ty);
|
instance,
|
||||||
|
promoted: None,
|
||||||
|
};
|
||||||
|
let ty_name = self.tcx.const_eval(ty::ParamEnv::reveal_all().and(gid)).unwrap();
|
||||||
OperandRef::from_const(self, ty_name).immediate_or_packed_pair(self)
|
OperandRef::from_const(self, ty_name).immediate_or_packed_pair(self)
|
||||||
}
|
}
|
||||||
"type_id" => {
|
|
||||||
self.const_u64(self.tcx.type_id_hash(substs.type_at(0)))
|
|
||||||
}
|
|
||||||
"init" => {
|
"init" => {
|
||||||
let ty = substs.type_at(0);
|
let ty = substs.type_at(0);
|
||||||
if !self.layout_of(ty).is_zst() {
|
if !self.layout_of(ty).is_zst() {
|
||||||
|
@ -235,11 +230,6 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
|
||||||
"uninit" | "forget" => {
|
"uninit" | "forget" => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
"needs_drop" => {
|
|
||||||
let tp_ty = substs.type_at(0);
|
|
||||||
|
|
||||||
self.const_bool(self.type_needs_drop(tp_ty))
|
|
||||||
}
|
|
||||||
"offset" => {
|
"offset" => {
|
||||||
let ptr = args[0].immediate();
|
let ptr = args[0].immediate();
|
||||||
let offset = args[1].immediate();
|
let offset = args[1].immediate();
|
||||||
|
|
|
@ -667,8 +667,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
}).collect();
|
}).collect();
|
||||||
|
|
||||||
|
|
||||||
let callee_ty = instance.as_ref().unwrap().ty(bx.tcx());
|
bx.codegen_intrinsic_call(*instance.as_ref().unwrap(), &fn_ty, &args, dest,
|
||||||
bx.codegen_intrinsic_call(callee_ty, &fn_ty, &args, dest,
|
|
||||||
terminator.source_info.span);
|
terminator.source_info.span);
|
||||||
|
|
||||||
if let ReturnDest::IndirectOperand(dst, _) = ret_dest {
|
if let ReturnDest::IndirectOperand(dst, _) = ret_dest {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use super::BackendTypes;
|
use super::BackendTypes;
|
||||||
use crate::mir::operand::OperandRef;
|
use crate::mir::operand::OperandRef;
|
||||||
use rustc::ty::Ty;
|
use rustc::ty::{self, Ty};
|
||||||
use rustc_target::abi::call::FnType;
|
use rustc_target::abi::call::FnType;
|
||||||
use syntax_pos::Span;
|
use syntax_pos::Span;
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ pub trait IntrinsicCallMethods<'tcx>: BackendTypes {
|
||||||
/// add them to librustc_codegen_llvm/context.rs
|
/// add them to librustc_codegen_llvm/context.rs
|
||||||
fn codegen_intrinsic_call(
|
fn codegen_intrinsic_call(
|
||||||
&mut self,
|
&mut self,
|
||||||
callee_ty: Ty<'tcx>,
|
instance: ty::Instance<'tcx>,
|
||||||
fn_ty: &FnType<'tcx, Ty<'tcx>>,
|
fn_ty: &FnType<'tcx, Ty<'tcx>>,
|
||||||
args: &[OperandRef<'tcx, Self::Value>],
|
args: &[OperandRef<'tcx, Self::Value>],
|
||||||
llresult: Self::Value,
|
llresult: Self::Value,
|
||||||
|
|
|
@ -15,6 +15,7 @@ use rustc::ty::{self, Ty, TyCtxt, subst::Subst};
|
||||||
use rustc::ty::layout::{self, LayoutOf, VariantIdx};
|
use rustc::ty::layout::{self, LayoutOf, VariantIdx};
|
||||||
use rustc::traits::Reveal;
|
use rustc::traits::Reveal;
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
|
use crate::interpret::eval_nullary_intrinsic;
|
||||||
|
|
||||||
use syntax::source_map::{Span, DUMMY_SP};
|
use syntax::source_map::{Span, DUMMY_SP};
|
||||||
|
|
||||||
|
@ -602,6 +603,23 @@ pub fn const_eval_provider<'tcx>(
|
||||||
other => return other,
|
other => return other,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We call `const_eval` for zero arg intrinsics, too, in order to cache their value.
|
||||||
|
// Catch such calls and evaluate them instead of trying to load a constant's MIR.
|
||||||
|
if let ty::InstanceDef::Intrinsic(def_id) = key.value.instance.def {
|
||||||
|
let ty = key.value.instance.ty(tcx);
|
||||||
|
let substs = match ty.sty {
|
||||||
|
ty::FnDef(_, substs) => substs,
|
||||||
|
_ => bug!("intrinsic with type {:?}", ty),
|
||||||
|
};
|
||||||
|
return eval_nullary_intrinsic(tcx, key.param_env, def_id, substs)
|
||||||
|
.map_err(|error| {
|
||||||
|
let span = tcx.def_span(def_id);
|
||||||
|
let error = ConstEvalErr { error: error.kind, stacktrace: vec![], span };
|
||||||
|
error.report_as_error(tcx.at(span), "could not evaluate nullary intrinsic")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
tcx.const_eval_raw(key).and_then(|val| {
|
tcx.const_eval_raw(key).and_then(|val| {
|
||||||
validate_and_turn_into_const(tcx, val, key)
|
validate_and_turn_into_const(tcx, val, key)
|
||||||
})
|
})
|
||||||
|
|
|
@ -14,7 +14,6 @@ use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
|
||||||
use rustc::ty::query::TyCtxtAt;
|
use rustc::ty::query::TyCtxtAt;
|
||||||
use rustc_data_structures::indexed_vec::IndexVec;
|
use rustc_data_structures::indexed_vec::IndexVec;
|
||||||
use rustc::mir::interpret::{
|
use rustc::mir::interpret::{
|
||||||
ErrorHandled,
|
|
||||||
GlobalId, Scalar, Pointer, FrameInfo, AllocId,
|
GlobalId, Scalar, Pointer, FrameInfo, AllocId,
|
||||||
InterpResult, truncate, sign_extend,
|
InterpResult, truncate, sign_extend,
|
||||||
};
|
};
|
||||||
|
@ -672,14 +671,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
// Our result will later be validated anyway, and there seems no good reason
|
// Our result will later be validated anyway, and there seems no good reason
|
||||||
// to have to fail early here. This is also more consistent with
|
// to have to fail early here. This is also more consistent with
|
||||||
// `Memory::get_static_alloc` which has to use `const_eval_raw` to avoid cycles.
|
// `Memory::get_static_alloc` which has to use `const_eval_raw` to avoid cycles.
|
||||||
let val = self.tcx.const_eval_raw(param_env.and(gid)).map_err(|err| {
|
let val = self.tcx.const_eval_raw(param_env.and(gid))?;
|
||||||
match err {
|
|
||||||
ErrorHandled::Reported =>
|
|
||||||
err_inval!(ReferencedConstant),
|
|
||||||
ErrorHandled::TooGeneric =>
|
|
||||||
err_inval!(TooGeneric),
|
|
||||||
}
|
|
||||||
})?;
|
|
||||||
self.raw_const_to_mplace(val)
|
self.raw_const_to_mplace(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,17 +5,18 @@
|
||||||
use syntax::symbol::Symbol;
|
use syntax::symbol::Symbol;
|
||||||
use rustc::ty;
|
use rustc::ty;
|
||||||
use rustc::ty::layout::{LayoutOf, Primitive, Size};
|
use rustc::ty::layout::{LayoutOf, Primitive, Size};
|
||||||
|
use rustc::ty::subst::SubstsRef;
|
||||||
|
use rustc::hir::def_id::DefId;
|
||||||
|
use rustc::ty::TyCtxt;
|
||||||
use rustc::mir::BinOp;
|
use rustc::mir::BinOp;
|
||||||
use rustc::mir::interpret::{InterpResult, Scalar};
|
use rustc::mir::interpret::{InterpResult, Scalar, GlobalId, ConstValue};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
Machine, PlaceTy, OpTy, InterpCx, Immediate,
|
Machine, PlaceTy, OpTy, InterpCx,
|
||||||
};
|
};
|
||||||
|
|
||||||
mod type_name;
|
mod type_name;
|
||||||
|
|
||||||
pub use type_name::*;
|
|
||||||
|
|
||||||
fn numeric_intrinsic<'tcx, Tag>(
|
fn numeric_intrinsic<'tcx, Tag>(
|
||||||
name: &str,
|
name: &str,
|
||||||
bits: u128,
|
bits: u128,
|
||||||
|
@ -37,6 +38,50 @@ fn numeric_intrinsic<'tcx, Tag>(
|
||||||
Ok(Scalar::from_uint(bits_out, size))
|
Ok(Scalar::from_uint(bits_out, size))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The logic for all nullary intrinsics is implemented here. These intrinsics don't get evaluated
|
||||||
|
/// inside an `InterpCx` and instead have their value computed directly from rustc internal info.
|
||||||
|
crate fn eval_nullary_intrinsic<'tcx>(
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
def_id: DefId,
|
||||||
|
substs: SubstsRef<'tcx>,
|
||||||
|
) -> InterpResult<'tcx, &'tcx ty::Const<'tcx>> {
|
||||||
|
let tp_ty = substs.type_at(0);
|
||||||
|
let name = &*tcx.item_name(def_id).as_str();
|
||||||
|
Ok(match name {
|
||||||
|
"type_name" => {
|
||||||
|
let alloc = type_name::alloc_type_name(tcx, tp_ty);
|
||||||
|
tcx.mk_const(ty::Const {
|
||||||
|
val: ConstValue::Slice {
|
||||||
|
data: alloc,
|
||||||
|
start: 0,
|
||||||
|
end: alloc.len(),
|
||||||
|
},
|
||||||
|
ty: tcx.mk_static_str(),
|
||||||
|
})
|
||||||
|
},
|
||||||
|
"needs_drop" => ty::Const::from_bool(tcx, tp_ty.needs_drop(tcx, param_env)),
|
||||||
|
"size_of" |
|
||||||
|
"min_align_of" |
|
||||||
|
"pref_align_of" => {
|
||||||
|
let layout = tcx.layout_of(param_env.and(tp_ty)).map_err(|e| err_inval!(Layout(e)))?;
|
||||||
|
let n = match name {
|
||||||
|
"pref_align_of" => layout.align.pref.bytes(),
|
||||||
|
"min_align_of" => layout.align.abi.bytes(),
|
||||||
|
"size_of" => layout.size.bytes(),
|
||||||
|
_ => bug!(),
|
||||||
|
};
|
||||||
|
ty::Const::from_usize(tcx, n)
|
||||||
|
},
|
||||||
|
"type_id" => ty::Const::from_bits(
|
||||||
|
tcx,
|
||||||
|
tcx.type_id_hash(tp_ty).into(),
|
||||||
|
param_env.and(tcx.types.u64),
|
||||||
|
),
|
||||||
|
other => bug!("`{}` is not a zero arg intrinsic", other),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
/// Returns `true` if emulation happened.
|
/// Returns `true` if emulation happened.
|
||||||
pub fn emulate_intrinsic(
|
pub fn emulate_intrinsic(
|
||||||
|
@ -49,41 +94,19 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
|
|
||||||
let intrinsic_name = &self.tcx.item_name(instance.def_id()).as_str()[..];
|
let intrinsic_name = &self.tcx.item_name(instance.def_id()).as_str()[..];
|
||||||
match intrinsic_name {
|
match intrinsic_name {
|
||||||
"min_align_of" => {
|
"min_align_of" |
|
||||||
let elem_ty = substs.type_at(0);
|
"pref_align_of" |
|
||||||
let elem_align = self.layout_of(elem_ty)?.align.abi.bytes();
|
"needs_drop" |
|
||||||
let align_val = Scalar::from_uint(elem_align, dest.layout.size);
|
"size_of" |
|
||||||
self.write_scalar(align_val, dest)?;
|
"type_id" |
|
||||||
}
|
|
||||||
|
|
||||||
"needs_drop" => {
|
|
||||||
let ty = substs.type_at(0);
|
|
||||||
let ty_needs_drop = ty.needs_drop(self.tcx.tcx, self.param_env);
|
|
||||||
let val = Scalar::from_bool(ty_needs_drop);
|
|
||||||
self.write_scalar(val, dest)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
"size_of" => {
|
|
||||||
let ty = substs.type_at(0);
|
|
||||||
let size = self.layout_of(ty)?.size.bytes() as u128;
|
|
||||||
let size_val = Scalar::from_uint(size, dest.layout.size);
|
|
||||||
self.write_scalar(size_val, dest)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
"type_id" => {
|
|
||||||
let ty = substs.type_at(0);
|
|
||||||
let type_id = self.tcx.type_id_hash(ty) as u128;
|
|
||||||
let id_val = Scalar::from_uint(type_id, dest.layout.size);
|
|
||||||
self.write_scalar(id_val, dest)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
"type_name" => {
|
"type_name" => {
|
||||||
let alloc = alloc_type_name(self.tcx.tcx, substs.type_at(0));
|
let gid = GlobalId {
|
||||||
let name_id = self.tcx.alloc_map.lock().create_memory_alloc(alloc);
|
instance,
|
||||||
let id_ptr = self.memory.tag_static_base_pointer(name_id.into());
|
promoted: None,
|
||||||
let alloc_len = alloc.size.bytes();
|
};
|
||||||
let name_val = Immediate::new_slice(Scalar::Ptr(id_ptr), alloc_len, self);
|
let val = self.tcx.const_eval(self.param_env.and(gid))?;
|
||||||
self.write_immediate(name_val, dest)?;
|
let val = self.eval_const_to_op(val, None)?;
|
||||||
|
self.copy_op(val, dest)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
| "ctpop"
|
| "ctpop"
|
||||||
|
|
|
@ -7,7 +7,7 @@ use rustc::ty::{
|
||||||
use rustc::hir::map::{DefPathData, DisambiguatedDefPathData};
|
use rustc::hir::map::{DefPathData, DisambiguatedDefPathData};
|
||||||
use rustc::hir::def_id::CrateNum;
|
use rustc::hir::def_id::CrateNum;
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
use rustc::mir::interpret::{Allocation, ConstValue};
|
use rustc::mir::interpret::Allocation;
|
||||||
|
|
||||||
struct AbsolutePathPrinter<'tcx> {
|
struct AbsolutePathPrinter<'tcx> {
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
|
@ -213,22 +213,11 @@ impl Write for AbsolutePathPrinter<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Produces an absolute path representation of the given type. See also the documentation on
|
|
||||||
/// `std::any::type_name`
|
|
||||||
pub fn type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> &'tcx ty::Const<'tcx> {
|
|
||||||
let alloc = alloc_type_name(tcx, ty);
|
|
||||||
tcx.mk_const(ty::Const {
|
|
||||||
val: ConstValue::Slice {
|
|
||||||
data: alloc,
|
|
||||||
start: 0,
|
|
||||||
end: alloc.len(),
|
|
||||||
},
|
|
||||||
ty: tcx.mk_static_str(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Directly returns an `Allocation` containing an absolute path representation of the given type.
|
/// Directly returns an `Allocation` containing an absolute path representation of the given type.
|
||||||
pub(super) fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> &'tcx Allocation {
|
crate fn alloc_type_name<'tcx>(
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
ty: Ty<'tcx>
|
||||||
|
) -> &'tcx Allocation {
|
||||||
let path = AbsolutePathPrinter { tcx, path: String::new() }.print_type(ty).unwrap().path;
|
let path = AbsolutePathPrinter { tcx, path: String::new() }.print_type(ty).unwrap().path;
|
||||||
let alloc = Allocation::from_byte_aligned_bytes(path.into_bytes());
|
let alloc = Allocation::from_byte_aligned_bytes(path.into_bytes());
|
||||||
tcx.intern_const_alloc(alloc)
|
tcx.intern_const_alloc(alloc)
|
||||||
|
|
|
@ -34,6 +34,6 @@ pub use self::visitor::{ValueVisitor, MutValueVisitor};
|
||||||
|
|
||||||
pub use self::validity::RefTracking;
|
pub use self::validity::RefTracking;
|
||||||
|
|
||||||
pub(super) use self::intrinsics::type_name;
|
|
||||||
|
|
||||||
pub use self::intern::intern_const_alloc_recursive;
|
pub use self::intern::intern_const_alloc_recursive;
|
||||||
|
|
||||||
|
crate use self::intrinsics::eval_nullary_intrinsic;
|
||||||
|
|
|
@ -59,5 +59,4 @@ pub fn provide(providers: &mut Providers<'_>) {
|
||||||
let (param_env, (value, field)) = param_env_and_value.into_parts();
|
let (param_env, (value, field)) = param_env_and_value.into_parts();
|
||||||
const_eval::const_field(tcx, param_env, None, field, value)
|
const_eval::const_field(tcx, param_env, None, field, value)
|
||||||
};
|
};
|
||||||
providers.type_name = interpret::type_name;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,11 @@ note: ...which requires const-evaluating `Foo::bytes::{{constant}}#0`...
|
||||||
|
|
|
|
||||||
LL | intrinsics::size_of::<T>()
|
LL | intrinsics::size_of::<T>()
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
note: ...which requires const-evaluating + checking `std::intrinsics::size_of`...
|
||||||
|
--> $SRC_DIR/libcore/intrinsics.rs:LL:COL
|
||||||
|
|
|
||||||
|
LL | pub fn size_of<T>() -> usize;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= note: ...which requires computing layout of `Foo`...
|
= note: ...which requires computing layout of `Foo`...
|
||||||
= note: ...which requires normalizing `ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: All, def_id: None }, value: [u8; _] }`...
|
= note: ...which requires normalizing `ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: All, def_id: None }, value: [u8; _] }`...
|
||||||
= note: ...which again requires const-evaluating + checking `Foo::bytes::{{constant}}#0`, completing the cycle
|
= note: ...which again requires const-evaluating + checking `Foo::bytes::{{constant}}#0`, completing the cycle
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
error[E0391]: cycle detected when const-evaluating + checking `Foo::bytes::{{constant}}#0`
|
|
||||||
--> $DIR/issue-44415.rs:6:17
|
|
||||||
|
|
|
||||||
LL | bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
|
|
||||||
| ^^^^^^
|
|
||||||
|
|
|
||||||
note: ...which requires const-evaluating + checking `Foo::bytes::{{constant}}#0`...
|
|
||||||
--> $DIR/issue-44415.rs:6:17
|
|
||||||
|
|
|
||||||
LL | bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
|
|
||||||
| ^^^^^^
|
|
||||||
note: ...which requires const-evaluating `Foo::bytes::{{constant}}#0`...
|
|
||||||
--> $DIR/issue-44415.rs:6:26
|
|
||||||
|
|
|
||||||
LL | bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
= note: ...which requires computing layout of `Foo`...
|
|
||||||
= note: ...which requires normalizing `ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: All, def_id: None }, value: [u8; _] }`...
|
|
||||||
= note: ...which again requires const-evaluating + checking `Foo::bytes::{{constant}}#0`, completing the cycle
|
|
||||||
note: cycle used when processing `Foo`
|
|
||||||
--> $DIR/issue-44415.rs:5:1
|
|
||||||
|
|
|
||||||
LL | struct Foo {
|
|
||||||
| ^^^^^^^^^^
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0391`.
|
|
Loading…
Add table
Add a link
Reference in a new issue