implement valtrees as the type-system representation for constant values
This commit is contained in:
parent
edab34ab2a
commit
705d818bd5
116 changed files with 1606 additions and 1032 deletions
|
@ -127,7 +127,7 @@ pub(crate) fn codegen_constant<'tcx>(
|
||||||
ConstantKind::Val(val, ty) => return codegen_const_value(fx, val, ty),
|
ConstantKind::Val(val, ty) => return codegen_const_value(fx, val, ty),
|
||||||
};
|
};
|
||||||
let const_val = match const_.kind() {
|
let const_val = match const_.kind() {
|
||||||
ConstKind::Value(const_val) => const_val,
|
ConstKind::Value(valtree) => fx.tcx.valtree_to_const_val((const_.ty(), valtree)),
|
||||||
ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted })
|
ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted })
|
||||||
if fx.tcx.is_static(def.did) =>
|
if fx.tcx.is_static(def.did) =>
|
||||||
{
|
{
|
||||||
|
@ -468,9 +468,10 @@ pub(crate) fn mir_operand_get_const_val<'tcx>(
|
||||||
) -> Option<ConstValue<'tcx>> {
|
) -> Option<ConstValue<'tcx>> {
|
||||||
match operand {
|
match operand {
|
||||||
Operand::Constant(const_) => match const_.literal {
|
Operand::Constant(const_) => match const_.literal {
|
||||||
ConstantKind::Ty(const_) => {
|
ConstantKind::Ty(const_) => fx
|
||||||
fx.monomorphize(const_).eval(fx.tcx, ParamEnv::reveal_all()).kind().try_to_value()
|
.monomorphize(const_)
|
||||||
}
|
.eval_for_mir(fx.tcx, ParamEnv::reveal_all())
|
||||||
|
.try_to_value(fx.tcx),
|
||||||
ConstantKind::Val(val, _) => Some(val),
|
ConstantKind::Val(val, _) => Some(val),
|
||||||
},
|
},
|
||||||
// FIXME(rust-lang/rust#85105): Casts like `IMM8 as u32` result in the const being stored
|
// FIXME(rust-lang/rust#85105): Casts like `IMM8 as u32` result in the const being stored
|
||||||
|
|
|
@ -38,7 +38,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
self.cx.tcx().sess.span_err(constant.span, "erroneous constant encountered");
|
self.cx.tcx().sess.span_err(constant.span, "erroneous constant encountered");
|
||||||
err
|
err
|
||||||
}),
|
}),
|
||||||
ty::ConstKind::Value(value) => Ok(value),
|
ty::ConstKind::Value(val) => Ok(self.cx.tcx().valtree_to_const_val((ct.ty(), val))),
|
||||||
err => span_bug!(
|
err => span_bug!(
|
||||||
constant.span,
|
constant.span,
|
||||||
"encountered bad ConstKind after monomorphizing: {:?}",
|
"encountered bad ConstKind after monomorphizing: {:?}",
|
||||||
|
@ -58,14 +58,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
constant
|
constant
|
||||||
.map(|val| {
|
.map(|val| {
|
||||||
let field_ty = ty.builtin_index().unwrap();
|
let field_ty = ty.builtin_index().unwrap();
|
||||||
let c = ty::Const::from_value(bx.tcx(), val, ty);
|
let c = mir::ConstantKind::from_value(val, ty);
|
||||||
let values: Vec<_> = bx
|
let values: Vec<_> = bx
|
||||||
.tcx()
|
.tcx()
|
||||||
.destructure_const(ty::ParamEnv::reveal_all().and(c))
|
.destructure_mir_constant(ty::ParamEnv::reveal_all(), c)
|
||||||
.fields
|
.fields
|
||||||
.iter()
|
.iter()
|
||||||
.map(|field| {
|
.map(|field| {
|
||||||
if let Some(prim) = field.kind().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 Abi::Scalar(scalar) = layout.abi else {
|
let Abi::Scalar(scalar) = layout.abi else {
|
||||||
bug!("from_const: invalid ByVal layout: {:#?}", layout);
|
bug!("from_const: invalid ByVal layout: {:#?}", layout);
|
||||||
|
|
|
@ -196,7 +196,7 @@ pub(super) fn op_to_const<'tcx>(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(skip(tcx), level = "debug")]
|
#[instrument(skip(tcx), level = "debug")]
|
||||||
fn turn_into_const_value<'tcx>(
|
pub(crate) fn turn_into_const_value<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
constant: ConstAlloc<'tcx>,
|
constant: ConstAlloc<'tcx>,
|
||||||
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
|
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
|
||||||
|
@ -222,6 +222,7 @@ fn turn_into_const_value<'tcx>(
|
||||||
const_val
|
const_val
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(skip(tcx), level = "debug")]
|
||||||
pub fn eval_to_const_value_raw_provider<'tcx>(
|
pub fn eval_to_const_value_raw_provider<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
|
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
|
||||||
|
@ -256,6 +257,7 @@ pub fn eval_to_const_value_raw_provider<'tcx>(
|
||||||
tcx.eval_to_allocation_raw(key).map(|val| turn_into_const_value(tcx, val, key))
|
tcx.eval_to_allocation_raw(key).map(|val| turn_into_const_value(tcx, val, key))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(skip(tcx), level = "debug")]
|
||||||
pub fn eval_to_allocation_raw_provider<'tcx>(
|
pub fn eval_to_allocation_raw_provider<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
|
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
// Not in interpret to make sure we do not use private implementation details
|
// Not in interpret to make sure we do not use private implementation details
|
||||||
|
|
||||||
use std::convert::TryFrom;
|
|
||||||
|
|
||||||
use rustc_hir::Mutability;
|
use rustc_hir::Mutability;
|
||||||
use rustc_middle::mir;
|
use rustc_middle::mir;
|
||||||
use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId};
|
use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId};
|
||||||
use rustc_middle::ty::{self, TyCtxt};
|
use rustc_middle::ty::{self, TyCtxt};
|
||||||
use rustc_span::{source_map::DUMMY_SP, symbol::Symbol};
|
use rustc_span::{source_map::DUMMY_SP, symbol::Symbol};
|
||||||
|
use rustc_target::abi::VariantIdx;
|
||||||
|
|
||||||
use crate::interpret::{
|
use crate::interpret::{
|
||||||
intern_const_alloc_recursive, ConstValue, InternKind, InterpCx, InterpResult, MemPlaceMeta,
|
intern_const_alloc_recursive, ConstValue, InternKind, InterpCx, InterpResult, MemPlaceMeta,
|
||||||
|
@ -25,6 +24,12 @@ pub use fn_queries::*;
|
||||||
pub use machine::*;
|
pub use machine::*;
|
||||||
pub(crate) use valtrees::{const_to_valtree_inner, valtree_to_const_value};
|
pub(crate) use valtrees::{const_to_valtree_inner, valtree_to_const_value};
|
||||||
|
|
||||||
|
pub(crate) enum ValTreeCreationError {
|
||||||
|
NonSupportedType,
|
||||||
|
Other,
|
||||||
|
}
|
||||||
|
pub(crate) type ValTreeCreationResult<'tcx> = Result<ty::ValTree<'tcx>, ValTreeCreationError>;
|
||||||
|
|
||||||
pub(crate) fn const_caller_location(
|
pub(crate) fn const_caller_location(
|
||||||
tcx: TyCtxt<'_>,
|
tcx: TyCtxt<'_>,
|
||||||
(file, line, col): (Symbol, u32, u32),
|
(file, line, col): (Symbol, u32, u32),
|
||||||
|
@ -39,16 +44,6 @@ pub(crate) fn const_caller_location(
|
||||||
ConstValue::Scalar(Scalar::from_maybe_pointer(loc_place.ptr, &tcx))
|
ConstValue::Scalar(Scalar::from_maybe_pointer(loc_place.ptr, &tcx))
|
||||||
}
|
}
|
||||||
|
|
||||||
// We forbid type-level constants that contain more than `VALTREE_MAX_NODES` nodes.
|
|
||||||
const VALTREE_MAX_NODES: usize = 1000;
|
|
||||||
|
|
||||||
pub(crate) enum ValTreeCreationError {
|
|
||||||
NodesOverflow,
|
|
||||||
NonSupportedType,
|
|
||||||
Other,
|
|
||||||
}
|
|
||||||
pub(crate) type ValTreeCreationResult<'tcx> = Result<ty::ValTree<'tcx>, ValTreeCreationError>;
|
|
||||||
|
|
||||||
/// Evaluates a constant and turns it into a type-level constant value.
|
/// Evaluates a constant and turns it into a type-level constant value.
|
||||||
pub(crate) fn eval_to_valtree<'tcx>(
|
pub(crate) fn eval_to_valtree<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
|
@ -56,6 +51,8 @@ pub(crate) fn eval_to_valtree<'tcx>(
|
||||||
cid: GlobalId<'tcx>,
|
cid: GlobalId<'tcx>,
|
||||||
) -> EvalToValTreeResult<'tcx> {
|
) -> EvalToValTreeResult<'tcx> {
|
||||||
let const_alloc = tcx.eval_to_allocation_raw(param_env.and(cid))?;
|
let const_alloc = tcx.eval_to_allocation_raw(param_env.and(cid))?;
|
||||||
|
|
||||||
|
// FIXME Need to provide a span to `eval_to_valtree`
|
||||||
let ecx = mk_eval_cx(
|
let ecx = mk_eval_cx(
|
||||||
tcx, DUMMY_SP, param_env,
|
tcx, DUMMY_SP, param_env,
|
||||||
// It is absolutely crucial for soundness that
|
// It is absolutely crucial for soundness that
|
||||||
|
@ -65,65 +62,89 @@ pub(crate) fn eval_to_valtree<'tcx>(
|
||||||
let place = ecx.raw_const_to_mplace(const_alloc).unwrap();
|
let place = ecx.raw_const_to_mplace(const_alloc).unwrap();
|
||||||
debug!(?place);
|
debug!(?place);
|
||||||
|
|
||||||
let mut num_nodes = 0;
|
let valtree_result = const_to_valtree_inner(&ecx, &place);
|
||||||
let valtree_result = const_to_valtree_inner(&ecx, &place, &mut num_nodes);
|
|
||||||
|
|
||||||
match valtree_result {
|
match valtree_result {
|
||||||
Ok(valtree) => Ok(Some(valtree)),
|
Ok(valtree) => Ok(Some(valtree)),
|
||||||
Err(err) => {
|
Err(_) => Ok(None),
|
||||||
let did = cid.instance.def_id();
|
|
||||||
let s = cid.display(tcx);
|
|
||||||
match err {
|
|
||||||
ValTreeCreationError::NodesOverflow => {
|
|
||||||
let msg = format!("maximum number of nodes exceeded in constant {}", &s);
|
|
||||||
let mut diag = match tcx.hir().span_if_local(did) {
|
|
||||||
Some(span) => tcx.sess.struct_span_err(span, &msg),
|
|
||||||
None => tcx.sess.struct_err(&msg),
|
|
||||||
};
|
|
||||||
diag.emit();
|
|
||||||
|
|
||||||
Ok(None)
|
|
||||||
}
|
|
||||||
ValTreeCreationError::NonSupportedType | ValTreeCreationError::Other => Ok(None),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This function should never fail for validated constants. However, it is also invoked from the
|
/// Tries to destructure constants of type Array or Adt into the constants
|
||||||
/// pretty printer which might attempt to format invalid constants and in that case it might fail.
|
/// of its fields.
|
||||||
pub(crate) fn try_destructure_const<'tcx>(
|
pub(crate) fn try_destructure_const<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
const_: ty::Const<'tcx>,
|
||||||
val: ty::Const<'tcx>,
|
) -> Option<mir::DestructuredConst<'tcx>> {
|
||||||
) -> InterpResult<'tcx, mir::DestructuredConst<'tcx>> {
|
if let ty::ConstKind::Value(valtree) = const_.val() {
|
||||||
trace!("destructure_const: {:?}", val);
|
let branches = match valtree {
|
||||||
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
|
ty::ValTree::Branch(b) => b,
|
||||||
let op = ecx.const_to_op(val, None)?;
|
_ => return None,
|
||||||
// We go to `usize` as we cannot allocate anything bigger anyway.
|
|
||||||
let (field_count, variant, down) = match val.ty().kind() {
|
|
||||||
ty::Array(_, len) => (usize::try_from(len.eval_usize(tcx, param_env)).unwrap(), None, op),
|
|
||||||
// Checks if we have any variants, to avoid downcasting to a non-existing variant (when
|
|
||||||
// there are no variants `read_discriminant` successfully returns a non-existing variant
|
|
||||||
// index).
|
|
||||||
ty::Adt(def, _) if def.variants().is_empty() => throw_ub!(Unreachable),
|
|
||||||
ty::Adt(def, _) => {
|
|
||||||
let variant = ecx.read_discriminant(&op)?.1;
|
|
||||||
let down = ecx.operand_downcast(&op, variant)?;
|
|
||||||
(def.variant(variant).fields.len(), Some(variant), down)
|
|
||||||
}
|
|
||||||
ty::Tuple(substs) => (substs.len(), None, op),
|
|
||||||
_ => bug!("cannot destructure constant {:?}", val),
|
|
||||||
};
|
};
|
||||||
let fields = (0..field_count)
|
|
||||||
.map(|i| {
|
let (fields, variant) = match const_.ty().kind() {
|
||||||
let field_op = ecx.operand_field(&down, i)?;
|
ty::Array(inner_ty, _) | ty::Slice(inner_ty) => {
|
||||||
let val = op_to_const(&ecx, &field_op);
|
// construct the consts for the elements of the array/slice
|
||||||
Ok(ty::Const::from_value(tcx, val, field_op.layout.ty))
|
let field_consts = branches
|
||||||
|
.iter()
|
||||||
|
.map(|b| {
|
||||||
|
tcx.mk_const(ty::ConstS { kind: ty::ConstKind::Value(*b), ty: *inner_ty })
|
||||||
})
|
})
|
||||||
.collect::<InterpResult<'tcx, Vec<_>>>()?;
|
.collect::<Vec<_>>();
|
||||||
let fields = tcx.arena.alloc_from_iter(fields);
|
debug!(?field_consts);
|
||||||
Ok(mir::DestructuredConst { variant, fields })
|
|
||||||
|
(field_consts, None)
|
||||||
|
}
|
||||||
|
ty::Adt(def, _) if def.variants().is_empty() => bug!("unreachable"),
|
||||||
|
ty::Adt(def, substs) => {
|
||||||
|
let variant_idx = if def.is_enum() {
|
||||||
|
VariantIdx::from_u32(branches[0].unwrap_leaf().try_to_u32().ok()?)
|
||||||
|
} else {
|
||||||
|
VariantIdx::from_u32(0)
|
||||||
|
};
|
||||||
|
let fields = &def.variant(variant_idx).fields;
|
||||||
|
let mut field_consts = Vec::with_capacity(fields.len());
|
||||||
|
|
||||||
|
// Note: First element inValTree corresponds to variant of enum
|
||||||
|
let mut valtree_idx = if def.is_enum() { 1 } else { 0 };
|
||||||
|
for field in fields {
|
||||||
|
let field_ty = field.ty(tcx, substs);
|
||||||
|
let field_valtree = branches[valtree_idx]; // first element of branches is variant
|
||||||
|
let field_const = tcx.mk_const(ty::ConstS {
|
||||||
|
kind: ty::ConstKind::Value(field_valtree),
|
||||||
|
ty: field_ty,
|
||||||
|
});
|
||||||
|
field_consts.push(field_const);
|
||||||
|
valtree_idx += 1;
|
||||||
|
}
|
||||||
|
debug!(?field_consts);
|
||||||
|
|
||||||
|
(field_consts, Some(variant_idx))
|
||||||
|
}
|
||||||
|
ty::Tuple(elem_tys) => {
|
||||||
|
let fields = elem_tys
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(i, elem_ty)| {
|
||||||
|
let elem_valtree = branches[i];
|
||||||
|
tcx.mk_const(ty::ConstS {
|
||||||
|
kind: ty::ConstKind::Value(elem_valtree),
|
||||||
|
ty: elem_ty,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
(fields, None)
|
||||||
|
}
|
||||||
|
_ => bug!("cannot destructure constant {:?}", const_),
|
||||||
|
};
|
||||||
|
|
||||||
|
let fields = tcx.arena.alloc_from_iter(fields.into_iter());
|
||||||
|
|
||||||
|
Some(mir::DestructuredConst { variant, fields })
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(skip(tcx), level = "debug")]
|
#[instrument(skip(tcx), level = "debug")]
|
||||||
|
@ -143,8 +164,8 @@ pub(crate) fn try_destructure_mir_constant<'tcx>(
|
||||||
throw_ub!(Unreachable)
|
throw_ub!(Unreachable)
|
||||||
}
|
}
|
||||||
ty::Adt(def, _) => {
|
ty::Adt(def, _) => {
|
||||||
let variant = ecx.read_discriminant(&op).unwrap().1;
|
let variant = ecx.read_discriminant(&op)?.1;
|
||||||
let down = ecx.operand_downcast(&op, variant).unwrap();
|
let down = ecx.operand_downcast(&op, variant)?;
|
||||||
(def.variants()[variant].fields.len(), Some(variant), down)
|
(def.variants()[variant].fields.len(), Some(variant), down)
|
||||||
}
|
}
|
||||||
ty::Tuple(substs) => (substs.len(), None, op),
|
ty::Tuple(substs) => (substs.len(), None, op),
|
||||||
|
@ -163,43 +184,6 @@ pub(crate) fn try_destructure_mir_constant<'tcx>(
|
||||||
Ok(mir::DestructuredMirConstant { variant, fields })
|
Ok(mir::DestructuredMirConstant { variant, fields })
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(skip(tcx), level = "debug")]
|
|
||||||
pub(crate) fn deref_const<'tcx>(
|
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
|
||||||
val: ty::Const<'tcx>,
|
|
||||||
) -> ty::Const<'tcx> {
|
|
||||||
trace!("deref_const: {:?}", val);
|
|
||||||
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
|
|
||||||
let op = ecx.const_to_op(val, None).unwrap();
|
|
||||||
let mplace = ecx.deref_operand(&op).unwrap();
|
|
||||||
if let Some(alloc_id) = mplace.ptr.provenance {
|
|
||||||
assert_eq!(
|
|
||||||
tcx.get_global_alloc(alloc_id).unwrap().unwrap_memory().inner().mutability,
|
|
||||||
Mutability::Not,
|
|
||||||
"deref_const cannot be used with mutable allocations as \
|
|
||||||
that could allow pattern matching to observe mutable statics",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let ty = match mplace.meta {
|
|
||||||
MemPlaceMeta::None => mplace.layout.ty,
|
|
||||||
MemPlaceMeta::Poison => bug!("poison metadata in `deref_const`: {:#?}", mplace),
|
|
||||||
// In case of unsized types, figure out the real type behind.
|
|
||||||
MemPlaceMeta::Meta(scalar) => match mplace.layout.ty.kind() {
|
|
||||||
ty::Str => bug!("there's no sized equivalent of a `str`"),
|
|
||||||
ty::Slice(elem_ty) => tcx.mk_array(*elem_ty, scalar.to_machine_usize(&tcx).unwrap()),
|
|
||||||
_ => bug!(
|
|
||||||
"type {} should not have metadata, but had {:?}",
|
|
||||||
mplace.layout.ty,
|
|
||||||
mplace.meta
|
|
||||||
),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
tcx.mk_const(ty::ConstS { kind: ty::ConstKind::Value(op_to_const(&ecx, &mplace.into())), ty })
|
|
||||||
}
|
|
||||||
|
|
||||||
#[instrument(skip(tcx), level = "debug")]
|
#[instrument(skip(tcx), level = "debug")]
|
||||||
pub(crate) fn deref_mir_constant<'tcx>(
|
pub(crate) fn deref_mir_constant<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
|
@ -213,14 +197,14 @@ pub(crate) fn deref_mir_constant<'tcx>(
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
tcx.get_global_alloc(alloc_id).unwrap().unwrap_memory().0 .0.mutability,
|
tcx.get_global_alloc(alloc_id).unwrap().unwrap_memory().0 .0.mutability,
|
||||||
Mutability::Not,
|
Mutability::Not,
|
||||||
"deref_const cannot be used with mutable allocations as \
|
"deref_mir_constant cannot be used with mutable allocations as \
|
||||||
that could allow pattern matching to observe mutable statics",
|
that could allow pattern matching to observe mutable statics",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let ty = match mplace.meta {
|
let ty = match mplace.meta {
|
||||||
MemPlaceMeta::None => mplace.layout.ty,
|
MemPlaceMeta::None => mplace.layout.ty,
|
||||||
MemPlaceMeta::Poison => bug!("poison metadata in `deref_const`: {:#?}", mplace),
|
MemPlaceMeta::Poison => bug!("poison metadata in `deref_mir_constant`: {:#?}", mplace),
|
||||||
// In case of unsized types, figure out the real type behind.
|
// In case of unsized types, figure out the real type behind.
|
||||||
MemPlaceMeta::Meta(scalar) => match mplace.layout.ty.kind() {
|
MemPlaceMeta::Meta(scalar) => match mplace.layout.ty.kind() {
|
||||||
ty::Str => bug!("there's no sized equivalent of a `str`"),
|
ty::Str => bug!("there's no sized equivalent of a `str`"),
|
||||||
|
|
|
@ -1,24 +1,21 @@
|
||||||
use super::eval_queries::{mk_eval_cx, op_to_const};
|
use super::eval_queries::{mk_eval_cx, op_to_const};
|
||||||
use super::machine::CompileTimeEvalContext;
|
use super::machine::CompileTimeEvalContext;
|
||||||
use super::{ValTreeCreationError, ValTreeCreationResult, VALTREE_MAX_NODES};
|
use super::{ValTreeCreationError, ValTreeCreationResult};
|
||||||
use crate::interpret::{
|
use crate::interpret::{
|
||||||
intern_const_alloc_recursive, ConstValue, ImmTy, Immediate, InternKind, MemPlaceMeta,
|
intern_const_alloc_recursive, ConstValue, ImmTy, Immediate, InternKind, MemPlaceMeta,
|
||||||
MemoryKind, PlaceTy, Scalar, ScalarMaybeUninit,
|
MemoryKind, PlaceTy, Scalar, ScalarMaybeUninit,
|
||||||
};
|
};
|
||||||
|
use crate::interpret::{MPlaceTy, Value};
|
||||||
|
use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt};
|
||||||
use rustc_span::source_map::DUMMY_SP;
|
use rustc_span::source_map::DUMMY_SP;
|
||||||
use rustc_target::abi::{Align, VariantIdx};
|
use rustc_target::abi::{Align, VariantIdx};
|
||||||
|
|
||||||
use crate::interpret::MPlaceTy;
|
|
||||||
use crate::interpret::Value;
|
|
||||||
use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt};
|
|
||||||
|
|
||||||
#[instrument(skip(ecx), level = "debug")]
|
#[instrument(skip(ecx), level = "debug")]
|
||||||
fn branches<'tcx>(
|
fn branches<'tcx>(
|
||||||
ecx: &CompileTimeEvalContext<'tcx, 'tcx>,
|
ecx: &CompileTimeEvalContext<'tcx, 'tcx>,
|
||||||
place: &MPlaceTy<'tcx>,
|
place: &MPlaceTy<'tcx>,
|
||||||
n: usize,
|
n: usize,
|
||||||
variant: Option<VariantIdx>,
|
variant: Option<VariantIdx>,
|
||||||
num_nodes: &mut usize,
|
|
||||||
) -> ValTreeCreationResult<'tcx> {
|
) -> ValTreeCreationResult<'tcx> {
|
||||||
let place = match variant {
|
let place = match variant {
|
||||||
Some(variant) => ecx.mplace_downcast(&place, variant).unwrap(),
|
Some(variant) => ecx.mplace_downcast(&place, variant).unwrap(),
|
||||||
|
@ -30,7 +27,7 @@ fn branches<'tcx>(
|
||||||
let mut fields = Vec::with_capacity(n);
|
let mut fields = Vec::with_capacity(n);
|
||||||
for i in 0..n {
|
for i in 0..n {
|
||||||
let field = ecx.mplace_field(&place, i).unwrap();
|
let field = ecx.mplace_field(&place, i).unwrap();
|
||||||
let valtree = const_to_valtree_inner(ecx, &field, num_nodes)?;
|
let valtree = const_to_valtree_inner(ecx, &field)?;
|
||||||
fields.push(Some(valtree));
|
fields.push(Some(valtree));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,11 +39,6 @@ fn branches<'tcx>(
|
||||||
.collect::<Option<Vec<_>>>()
|
.collect::<Option<Vec<_>>>()
|
||||||
.expect("should have already checked for errors in ValTree creation");
|
.expect("should have already checked for errors in ValTree creation");
|
||||||
|
|
||||||
// Have to account for ZSTs here
|
|
||||||
if branches.len() == 0 {
|
|
||||||
*num_nodes += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(ty::ValTree::Branch(ecx.tcx.arena.alloc_from_iter(branches)))
|
Ok(ty::ValTree::Branch(ecx.tcx.arena.alloc_from_iter(branches)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +46,6 @@ fn branches<'tcx>(
|
||||||
fn slice_branches<'tcx>(
|
fn slice_branches<'tcx>(
|
||||||
ecx: &CompileTimeEvalContext<'tcx, 'tcx>,
|
ecx: &CompileTimeEvalContext<'tcx, 'tcx>,
|
||||||
place: &MPlaceTy<'tcx>,
|
place: &MPlaceTy<'tcx>,
|
||||||
num_nodes: &mut usize,
|
|
||||||
) -> ValTreeCreationResult<'tcx> {
|
) -> ValTreeCreationResult<'tcx> {
|
||||||
let n = place
|
let n = place
|
||||||
.len(&ecx.tcx.tcx)
|
.len(&ecx.tcx.tcx)
|
||||||
|
@ -63,7 +54,7 @@ fn slice_branches<'tcx>(
|
||||||
let mut elems = Vec::with_capacity(n as usize);
|
let mut elems = Vec::with_capacity(n as usize);
|
||||||
for i in 0..n {
|
for i in 0..n {
|
||||||
let place_elem = ecx.mplace_index(place, i).unwrap();
|
let place_elem = ecx.mplace_index(place, i).unwrap();
|
||||||
let valtree = const_to_valtree_inner(ecx, &place_elem, num_nodes)?;
|
let valtree = const_to_valtree_inner(ecx, &place_elem)?;
|
||||||
elems.push(valtree);
|
elems.push(valtree);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,18 +65,12 @@ fn slice_branches<'tcx>(
|
||||||
pub(crate) fn const_to_valtree_inner<'tcx>(
|
pub(crate) fn const_to_valtree_inner<'tcx>(
|
||||||
ecx: &CompileTimeEvalContext<'tcx, 'tcx>,
|
ecx: &CompileTimeEvalContext<'tcx, 'tcx>,
|
||||||
place: &MPlaceTy<'tcx>,
|
place: &MPlaceTy<'tcx>,
|
||||||
num_nodes: &mut usize,
|
|
||||||
) -> ValTreeCreationResult<'tcx> {
|
) -> ValTreeCreationResult<'tcx> {
|
||||||
if *num_nodes >= VALTREE_MAX_NODES {
|
|
||||||
return Err(ValTreeCreationError::NodesOverflow);
|
|
||||||
}
|
|
||||||
|
|
||||||
let ty = place.layout.ty;
|
let ty = place.layout.ty;
|
||||||
debug!("ty kind: {:?}", ty.kind());
|
debug!("ty kind: {:?}", ty.kind());
|
||||||
|
|
||||||
match ty.kind() {
|
match ty.kind() {
|
||||||
ty::FnDef(..) => {
|
ty::FnDef(..) => {
|
||||||
*num_nodes += 1;
|
|
||||||
Ok(ty::ValTree::zst())
|
Ok(ty::ValTree::zst())
|
||||||
}
|
}
|
||||||
ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char => {
|
ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char => {
|
||||||
|
@ -93,7 +78,6 @@ pub(crate) fn const_to_valtree_inner<'tcx>(
|
||||||
return Err(ValTreeCreationError::Other);
|
return Err(ValTreeCreationError::Other);
|
||||||
};
|
};
|
||||||
let val = val.to_scalar().unwrap();
|
let val = val.to_scalar().unwrap();
|
||||||
*num_nodes += 1;
|
|
||||||
|
|
||||||
Ok(ty::ValTree::Leaf(val.assert_int()))
|
Ok(ty::ValTree::Leaf(val.assert_int()))
|
||||||
}
|
}
|
||||||
|
@ -110,11 +94,11 @@ pub(crate) fn const_to_valtree_inner<'tcx>(
|
||||||
};
|
};
|
||||||
debug!(?derefd_place);
|
debug!(?derefd_place);
|
||||||
|
|
||||||
const_to_valtree_inner(ecx, &derefd_place, num_nodes)
|
const_to_valtree_inner(ecx, &derefd_place)
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::Str | ty::Slice(_) | ty::Array(_, _) => {
|
ty::Str | ty::Slice(_) | ty::Array(_, _) => {
|
||||||
slice_branches(ecx, place, num_nodes)
|
slice_branches(ecx, place)
|
||||||
}
|
}
|
||||||
// Trait objects are not allowed in type level constants, as we have no concept for
|
// Trait objects are not allowed in type level constants, as we have no concept for
|
||||||
// resolving their backing type, even if we can do that at const eval time. We may
|
// resolving their backing type, even if we can do that at const eval time. We may
|
||||||
|
@ -123,7 +107,7 @@ pub(crate) fn const_to_valtree_inner<'tcx>(
|
||||||
ty::Dynamic(..) => Err(ValTreeCreationError::NonSupportedType),
|
ty::Dynamic(..) => Err(ValTreeCreationError::NonSupportedType),
|
||||||
|
|
||||||
ty::Tuple(elem_tys) => {
|
ty::Tuple(elem_tys) => {
|
||||||
branches(ecx, place, elem_tys.len(), None, num_nodes)
|
branches(ecx, place, elem_tys.len(), None)
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::Adt(def, _) => {
|
ty::Adt(def, _) => {
|
||||||
|
@ -136,7 +120,7 @@ pub(crate) fn const_to_valtree_inner<'tcx>(
|
||||||
let Ok((_, variant)) = ecx.read_discriminant(&place.into()) else {
|
let Ok((_, variant)) = ecx.read_discriminant(&place.into()) else {
|
||||||
return Err(ValTreeCreationError::Other);
|
return Err(ValTreeCreationError::Other);
|
||||||
};
|
};
|
||||||
branches(ecx, place, def.variant(variant).fields.len(), def.is_enum().then_some(variant), num_nodes)
|
branches(ecx, place, def.variant(variant).fields.len(), def.is_enum().then_some(variant))
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::Never
|
ty::Never
|
||||||
|
@ -234,13 +218,9 @@ fn create_pointee_place<'tcx>(
|
||||||
// Get the size of the memory behind the DST
|
// Get the size of the memory behind the DST
|
||||||
let dst_size = unsized_inner_ty_size.checked_mul(num_elems as u64, &tcx).unwrap();
|
let dst_size = unsized_inner_ty_size.checked_mul(num_elems as u64, &tcx).unwrap();
|
||||||
|
|
||||||
let ptr = ecx
|
let size = size_of_sized_part.checked_add(dst_size, &tcx).unwrap();
|
||||||
.allocate_ptr(
|
let align = Align::from_bytes(size.bytes().next_power_of_two()).unwrap();
|
||||||
size_of_sized_part.checked_add(dst_size, &tcx).unwrap(),
|
let ptr = ecx.allocate_ptr(size, align, MemoryKind::Stack).unwrap();
|
||||||
Align::from_bytes(1).unwrap(),
|
|
||||||
MemoryKind::Stack,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
debug!(?ptr);
|
debug!(?ptr);
|
||||||
|
|
||||||
let place = MPlaceTy::from_aligned_ptr_with_meta(
|
let place = MPlaceTy::from_aligned_ptr_with_meta(
|
||||||
|
@ -262,7 +242,7 @@ fn create_pointee_place<'tcx>(
|
||||||
#[instrument(skip(tcx), level = "debug")]
|
#[instrument(skip(tcx), level = "debug")]
|
||||||
pub fn valtree_to_const_value<'tcx>(
|
pub fn valtree_to_const_value<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
ty: Ty<'tcx>,
|
param_env_ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
|
||||||
valtree: ty::ValTree<'tcx>,
|
valtree: ty::ValTree<'tcx>,
|
||||||
) -> ConstValue<'tcx> {
|
) -> ConstValue<'tcx> {
|
||||||
// Basic idea: We directly construct `Scalar` values from trivial `ValTree`s
|
// Basic idea: We directly construct `Scalar` values from trivial `ValTree`s
|
||||||
|
@ -272,8 +252,8 @@ pub fn valtree_to_const_value<'tcx>(
|
||||||
// create inner `MPlace`s which are filled recursively.
|
// create inner `MPlace`s which are filled recursively.
|
||||||
// FIXME Does this need an example?
|
// FIXME Does this need an example?
|
||||||
|
|
||||||
let mut ecx = mk_eval_cx(tcx, DUMMY_SP, ty::ParamEnv::empty(), false);
|
let (param_env, ty) = param_env_ty.into_parts();
|
||||||
let param_env_ty = ty::ParamEnv::empty().and(ty);
|
let mut ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
|
||||||
|
|
||||||
match ty.kind() {
|
match ty.kind() {
|
||||||
ty::FnDef(..) => {
|
ty::FnDef(..) => {
|
||||||
|
@ -336,7 +316,6 @@ pub fn valtree_to_const_value<'tcx>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME Needs a better/correct name
|
|
||||||
#[instrument(skip(ecx), level = "debug")]
|
#[instrument(skip(ecx), level = "debug")]
|
||||||
fn valtree_into_mplace<'tcx>(
|
fn valtree_into_mplace<'tcx>(
|
||||||
ecx: &mut CompileTimeEvalContext<'tcx, 'tcx>,
|
ecx: &mut CompileTimeEvalContext<'tcx, 'tcx>,
|
||||||
|
|
|
@ -637,7 +637,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
ty::ConstKind::Infer(..) | ty::ConstKind::Placeholder(..) => {
|
ty::ConstKind::Infer(..) | ty::ConstKind::Placeholder(..) => {
|
||||||
span_bug!(self.cur_span(), "const_to_op: Unexpected ConstKind {:?}", c)
|
span_bug!(self.cur_span(), "const_to_op: Unexpected ConstKind {:?}", c)
|
||||||
}
|
}
|
||||||
ty::ConstKind::Value(val) => self.const_val_to_op(val, c.ty(), layout),
|
ty::ConstKind::Value(valtree) => {
|
||||||
|
let ty = val.ty();
|
||||||
|
let const_val = self.tcx.valtree_to_const_val((ty, valtree));
|
||||||
|
self.const_val_to_op(const_val, ty, layout)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@ pub mod interpret;
|
||||||
pub mod transform;
|
pub mod transform;
|
||||||
pub mod util;
|
pub mod util;
|
||||||
|
|
||||||
|
use rustc_middle::ty;
|
||||||
use rustc_middle::ty::query::Providers;
|
use rustc_middle::ty::query::Providers;
|
||||||
|
|
||||||
pub fn provide(providers: &mut Providers) {
|
pub fn provide(providers: &mut Providers) {
|
||||||
|
@ -41,10 +42,7 @@ pub fn provide(providers: &mut Providers) {
|
||||||
providers.eval_to_const_value_raw = const_eval::eval_to_const_value_raw_provider;
|
providers.eval_to_const_value_raw = const_eval::eval_to_const_value_raw_provider;
|
||||||
providers.eval_to_allocation_raw = const_eval::eval_to_allocation_raw_provider;
|
providers.eval_to_allocation_raw = const_eval::eval_to_allocation_raw_provider;
|
||||||
providers.const_caller_location = const_eval::const_caller_location;
|
providers.const_caller_location = const_eval::const_caller_location;
|
||||||
providers.try_destructure_const = |tcx, param_env_and_val| {
|
providers.try_destructure_const = |tcx, val| const_eval::try_destructure_const(tcx, val);
|
||||||
let (param_env, c) = param_env_and_val.into_parts();
|
|
||||||
const_eval::try_destructure_const(tcx, param_env, c).ok()
|
|
||||||
};
|
|
||||||
providers.eval_to_valtree = |tcx, param_env_and_value| {
|
providers.eval_to_valtree = |tcx, param_env_and_value| {
|
||||||
let (param_env, raw) = param_env_and_value.into_parts();
|
let (param_env, raw) = param_env_and_value.into_parts();
|
||||||
const_eval::eval_to_valtree(tcx, param_env, raw)
|
const_eval::eval_to_valtree(tcx, param_env, raw)
|
||||||
|
@ -53,11 +51,8 @@ pub fn provide(providers: &mut Providers) {
|
||||||
let (param_env, value) = param_env_and_value.into_parts();
|
let (param_env, value) = param_env_and_value.into_parts();
|
||||||
const_eval::try_destructure_mir_constant(tcx, param_env, value).ok()
|
const_eval::try_destructure_mir_constant(tcx, param_env, value).ok()
|
||||||
};
|
};
|
||||||
providers.valtree_to_const_val =
|
providers.valtree_to_const_val = |tcx, (ty, valtree)| {
|
||||||
|tcx, (ty, valtree)| const_eval::valtree_to_const_value(tcx, ty, valtree);
|
const_eval::valtree_to_const_value(tcx, ty::ParamEnv::empty().and(ty), valtree)
|
||||||
providers.deref_const = |tcx, param_env_and_value| {
|
|
||||||
let (param_env, value) = param_env_and_value.into_parts();
|
|
||||||
const_eval::deref_const(tcx, param_env, value)
|
|
||||||
};
|
};
|
||||||
providers.deref_mir_constant = |tcx, param_env_and_value| {
|
providers.deref_mir_constant = |tcx, param_env_and_value| {
|
||||||
let (param_env, value) = param_env_and_value.into_parts();
|
let (param_env, value) = param_env_and_value.into_parts();
|
||||||
|
|
|
@ -765,7 +765,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
|
||||||
let unit = Rvalue::Use(Operand::Constant(Box::new(Constant {
|
let unit = Rvalue::Use(Operand::Constant(Box::new(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).into(),
|
literal: ConstantKind::zero_sized(self.tcx.types.unit),
|
||||||
})));
|
})));
|
||||||
mem::replace(rhs, unit)
|
mem::replace(rhs, unit)
|
||||||
},
|
},
|
||||||
|
@ -835,12 +835,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
|
||||||
let mut promoted_operand = |ty, span| {
|
let mut promoted_operand = |ty, span| {
|
||||||
promoted.span = span;
|
promoted.span = span;
|
||||||
promoted.local_decls[RETURN_PLACE] = LocalDecl::new(ty, span);
|
promoted.local_decls[RETURN_PLACE] = LocalDecl::new(ty, span);
|
||||||
|
let _const = tcx.mk_const(ty::ConstS {
|
||||||
Operand::Constant(Box::new(Constant {
|
|
||||||
span,
|
|
||||||
user_ty: None,
|
|
||||||
literal: tcx
|
|
||||||
.mk_const(ty::ConstS {
|
|
||||||
ty,
|
ty,
|
||||||
kind: ty::ConstKind::Unevaluated(ty::Unevaluated {
|
kind: ty::ConstKind::Unevaluated(ty::Unevaluated {
|
||||||
def,
|
def,
|
||||||
|
@ -853,8 +848,12 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
|
||||||
}),
|
}),
|
||||||
promoted: Some(promoted_id),
|
promoted: Some(promoted_id),
|
||||||
}),
|
}),
|
||||||
})
|
});
|
||||||
.into(),
|
|
||||||
|
Operand::Constant(Box::new(Constant {
|
||||||
|
span,
|
||||||
|
user_ty: None,
|
||||||
|
literal: ConstantKind::from_const(_const, tcx),
|
||||||
}))
|
}))
|
||||||
};
|
};
|
||||||
let (blocks, local_decls) = self.source.basic_blocks_and_local_decls_mut();
|
let (blocks, local_decls) = self.source.basic_blocks_and_local_decls_mut();
|
||||||
|
|
|
@ -20,7 +20,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
|
||||||
use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues};
|
use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues};
|
||||||
use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue};
|
use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue};
|
||||||
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType};
|
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType};
|
||||||
use rustc_middle::mir::interpret::{ErrorHandled, EvalToConstValueResult};
|
use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult};
|
||||||
use rustc_middle::traits::select;
|
use rustc_middle::traits::select;
|
||||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||||
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
|
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
|
||||||
|
@ -1616,6 +1616,28 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
u
|
u
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn try_const_eval_resolve(
|
||||||
|
&self,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
unevaluated: ty::Unevaluated<'tcx>,
|
||||||
|
ty: Ty<'tcx>,
|
||||||
|
span: Option<Span>,
|
||||||
|
) -> Result<ty::Const<'tcx>, ErrorHandled> {
|
||||||
|
match self.const_eval_resolve(param_env, unevaluated, span) {
|
||||||
|
Ok(Some(val)) => Ok(ty::Const::from_value(self.tcx, val, ty)),
|
||||||
|
Ok(None) => {
|
||||||
|
let tcx = self.tcx;
|
||||||
|
let def_id = unevaluated.def.did;
|
||||||
|
span_bug!(
|
||||||
|
tcx.def_span(def_id),
|
||||||
|
"unable to construct a constant value for the unevaluated constant {:?}",
|
||||||
|
unevaluated
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Err(err) => Err(err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Resolves and evaluates a constant.
|
/// Resolves and evaluates a constant.
|
||||||
///
|
///
|
||||||
/// The constant can be located on a trait like `<A as B>::C`, in which case the given
|
/// The constant can be located on a trait like `<A as B>::C`, in which case the given
|
||||||
|
@ -1634,7 +1656,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
unevaluated: ty::Unevaluated<'tcx>,
|
unevaluated: ty::Unevaluated<'tcx>,
|
||||||
span: Option<Span>,
|
span: Option<Span>,
|
||||||
) -> EvalToConstValueResult<'tcx> {
|
) -> EvalToValTreeResult<'tcx> {
|
||||||
let substs = self.resolve_vars_if_possible(unevaluated.substs);
|
let substs = self.resolve_vars_if_possible(unevaluated.substs);
|
||||||
debug!(?substs);
|
debug!(?substs);
|
||||||
|
|
||||||
|
@ -1658,7 +1680,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
|
|
||||||
// The return value is the evaluated value which doesn't contain any reference to inference
|
// The return value is the evaluated value which doesn't contain any reference to inference
|
||||||
// variables, thus we don't need to substitute back the original values.
|
// variables, thus we don't need to substitute back the original values.
|
||||||
self.tcx.const_eval_resolve(param_env_erased, unevaluated, span)
|
self.tcx.const_eval_resolve_for_typeck(param_env_erased, unevaluated, span)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `ty_or_const_infer_var_changed` is equivalent to one of these two:
|
/// `ty_or_const_infer_var_changed` is equivalent to one of these two:
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use super::{ErrorHandled, EvalToConstValueResult, GlobalId};
|
use super::{ErrorHandled, EvalToConstValueResult, EvalToValTreeResult, GlobalId};
|
||||||
|
|
||||||
use crate::mir;
|
use crate::mir;
|
||||||
use crate::ty::fold::TypeFoldable;
|
use crate::ty::fold::TypeFoldable;
|
||||||
|
@ -11,6 +11,10 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
/// Evaluates a constant without providing any substitutions. This is useful to evaluate consts
|
/// Evaluates a constant without providing any substitutions. This is useful to evaluate consts
|
||||||
/// that can't take any generic arguments like statics, const items or enum discriminants. If a
|
/// that can't take any generic arguments like statics, const items or enum discriminants. If a
|
||||||
/// generic parameter is used within the constant `ErrorHandled::ToGeneric` will be returned.
|
/// generic parameter is used within the constant `ErrorHandled::ToGeneric` will be returned.
|
||||||
|
///
|
||||||
|
/// Note: Returns a `ConstValue`, which isn't supposed to be used in the type system. In order to
|
||||||
|
/// evaluate to a type-system level constant value use `const_eval_poly_for_typeck`.
|
||||||
|
#[instrument(skip(self), level = "debug")]
|
||||||
pub fn const_eval_poly(self, def_id: DefId) -> EvalToConstValueResult<'tcx> {
|
pub fn const_eval_poly(self, def_id: DefId) -> EvalToConstValueResult<'tcx> {
|
||||||
// In some situations def_id will have substitutions within scope, but they aren't allowed
|
// In some situations def_id will have substitutions within scope, but they aren't allowed
|
||||||
// to be used. So we can't use `Instance::mono`, instead we feed unresolved substitutions
|
// to be used. So we can't use `Instance::mono`, instead we feed unresolved substitutions
|
||||||
|
@ -23,6 +27,22 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
self.const_eval_global_id(param_env, cid, None)
|
self.const_eval_global_id(param_env, cid, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Evaluates a constant without providing any substitutions. This is useful to evaluate consts
|
||||||
|
/// that can't take any generic arguments like statics, const items or enum discriminants. If a
|
||||||
|
/// generic parameter is used within the constant `ErrorHandled::ToGeneric` will be returned.
|
||||||
|
#[instrument(skip(self), level = "debug")]
|
||||||
|
pub fn const_eval_poly_for_typeck(self, def_id: DefId) -> EvalToValTreeResult<'tcx> {
|
||||||
|
// In some situations def_id will have substitutions within scope, but they aren't allowed
|
||||||
|
// to be used. So we can't use `Instance::mono`, instead we feed unresolved substitutions
|
||||||
|
// into `const_eval` which will return `ErrorHandled::ToGeneric` if any of them are
|
||||||
|
// encountered.
|
||||||
|
let substs = InternalSubsts::identity_for_item(self, def_id);
|
||||||
|
let instance = ty::Instance::new(def_id, substs);
|
||||||
|
let cid = GlobalId { instance, promoted: None };
|
||||||
|
let param_env = self.param_env(def_id).with_reveal_all_normalized(self);
|
||||||
|
self.const_eval_global_id_for_typeck(param_env, cid, None)
|
||||||
|
}
|
||||||
|
|
||||||
/// Resolves and evaluates a constant.
|
/// Resolves and evaluates a constant.
|
||||||
///
|
///
|
||||||
/// The constant can be located on a trait like `<A as B>::C`, in which case the given
|
/// The constant can be located on a trait like `<A as B>::C`, in which case the given
|
||||||
|
@ -59,6 +79,33 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(level = "debug", skip(self))]
|
||||||
|
pub fn const_eval_resolve_for_typeck(
|
||||||
|
self,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
ct: ty::Unevaluated<'tcx>,
|
||||||
|
span: Option<Span>,
|
||||||
|
) -> EvalToValTreeResult<'tcx> {
|
||||||
|
// Cannot resolve `Unevaluated` constants that contain inference
|
||||||
|
// variables. We reject those here since `resolve_opt_const_arg`
|
||||||
|
// would fail otherwise.
|
||||||
|
//
|
||||||
|
// When trying to evaluate constants containing inference variables,
|
||||||
|
// use `Infcx::const_eval_resolve` instead.
|
||||||
|
if ct.substs.has_infer_types_or_consts() {
|
||||||
|
bug!("did not expect inference variables here");
|
||||||
|
}
|
||||||
|
|
||||||
|
match ty::Instance::resolve_opt_const_arg(self, param_env, ct.def, ct.substs) {
|
||||||
|
Ok(Some(instance)) => {
|
||||||
|
let cid = GlobalId { instance, promoted: ct.promoted };
|
||||||
|
self.const_eval_global_id_for_typeck(param_env, cid, span)
|
||||||
|
}
|
||||||
|
Ok(None) => Err(ErrorHandled::TooGeneric),
|
||||||
|
Err(error_reported) => Err(ErrorHandled::Reported(error_reported)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn const_eval_instance(
|
pub fn const_eval_instance(
|
||||||
self,
|
self,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
@ -68,7 +115,8 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
self.const_eval_global_id(param_env, GlobalId { instance, promoted: None }, span)
|
self.const_eval_global_id(param_env, GlobalId { instance, promoted: None }, span)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Evaluate a constant.
|
/// Evaluate a constant to a `ConstValue`.
|
||||||
|
#[instrument(skip(self), level = "debug")]
|
||||||
pub fn const_eval_global_id(
|
pub fn const_eval_global_id(
|
||||||
self,
|
self,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
@ -86,6 +134,27 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Evaluate a constant to a type-level constant.
|
||||||
|
#[instrument(skip(self), level = "debug")]
|
||||||
|
pub fn const_eval_global_id_for_typeck(
|
||||||
|
self,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
cid: GlobalId<'tcx>,
|
||||||
|
span: Option<Span>,
|
||||||
|
) -> EvalToValTreeResult<'tcx> {
|
||||||
|
let param_env = param_env.with_const();
|
||||||
|
debug!(?param_env);
|
||||||
|
// Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should
|
||||||
|
// improve caching of queries.
|
||||||
|
let inputs = self.erase_regions(param_env.and(cid));
|
||||||
|
debug!(?inputs);
|
||||||
|
if let Some(span) = span {
|
||||||
|
self.at(span).eval_to_valtree(inputs)
|
||||||
|
} else {
|
||||||
|
self.eval_to_valtree(inputs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Evaluate a static's initializer, returning the allocation of the initializer's memory.
|
/// Evaluate a static's initializer, returning the allocation of the initializer's memory.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn eval_static_initializer(
|
pub fn eval_static_initializer(
|
||||||
|
@ -125,11 +194,8 @@ impl<'tcx> TyCtxtAt<'tcx> {
|
||||||
impl<'tcx> TyCtxt<'tcx> {
|
impl<'tcx> TyCtxt<'tcx> {
|
||||||
/// Destructure a type-level constant ADT or array into its variant index and its field values.
|
/// Destructure a type-level constant ADT or array into its variant index and its field values.
|
||||||
/// Panics if the destructuring fails, use `try_destructure_const` for fallible version.
|
/// Panics if the destructuring fails, use `try_destructure_const` for fallible version.
|
||||||
pub fn destructure_const(
|
pub fn destructure_const(self, const_: ty::Const<'tcx>) -> mir::DestructuredConst<'tcx> {
|
||||||
self,
|
self.try_destructure_const(const_).unwrap()
|
||||||
param_env_and_val: ty::ParamEnvAnd<'tcx, ty::Const<'tcx>>,
|
|
||||||
) -> mir::DestructuredConst<'tcx> {
|
|
||||||
self.try_destructure_const(param_env_and_val).unwrap()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Destructure a mir constant ADT or array into its variant index and its field values.
|
/// Destructure a mir constant ADT or array into its variant index and its field values.
|
||||||
|
|
|
@ -78,6 +78,7 @@ impl<'tcx> ConstValue<'tcx> {
|
||||||
Some(self.try_to_scalar()?.assert_int())
|
Some(self.try_to_scalar()?.assert_int())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
pub fn try_to_bits(&self, size: Size) -> Option<u128> {
|
pub fn try_to_bits(&self, size: Size) -> Option<u128> {
|
||||||
self.try_to_scalar_int()?.to_bits(size).ok()
|
self.try_to_scalar_int()?.to_bits(size).ok()
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,9 @@
|
||||||
//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/mir/index.html
|
//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/mir/index.html
|
||||||
|
|
||||||
use crate::mir::coverage::{CodeRegion, CoverageKind};
|
use crate::mir::coverage::{CodeRegion, CoverageKind};
|
||||||
use crate::mir::interpret::{ConstAllocation, ConstValue, GlobalAlloc, LitToConstInput, Scalar};
|
use crate::mir::interpret::{
|
||||||
|
AllocRange, ConstAllocation, ConstValue, GlobalAlloc, LitToConstInput, Scalar,
|
||||||
|
};
|
||||||
use crate::mir::visit::MirVisitable;
|
use crate::mir::visit::MirVisitable;
|
||||||
use crate::ty::adjustment::PointerCast;
|
use crate::ty::adjustment::PointerCast;
|
||||||
use crate::ty::codec::{TyDecoder, TyEncoder};
|
use crate::ty::codec::{TyDecoder, TyEncoder};
|
||||||
|
@ -1444,7 +1446,11 @@ impl<'tcx> BasicBlockData<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn visitable(&self, index: usize) -> &dyn MirVisitable<'tcx> {
|
pub fn visitable(&self, index: usize) -> &dyn MirVisitable<'tcx> {
|
||||||
if index < self.statements.len() { &self.statements[index] } else { &self.terminator }
|
if index < self.statements.len() {
|
||||||
|
&self.statements[index]
|
||||||
|
} else {
|
||||||
|
&self.terminator
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2465,7 +2471,11 @@ impl<'tcx> Operand<'tcx> {
|
||||||
/// find as the `func` in a [`TerminatorKind::Call`].
|
/// find as the `func` in a [`TerminatorKind::Call`].
|
||||||
pub fn const_fn_def(&self) -> Option<(DefId, SubstsRef<'tcx>)> {
|
pub fn const_fn_def(&self) -> Option<(DefId, SubstsRef<'tcx>)> {
|
||||||
let const_ty = self.constant()?.literal.ty();
|
let const_ty = self.constant()?.literal.ty();
|
||||||
if let ty::FnDef(def_id, substs) = *const_ty.kind() { Some((def_id, substs)) } else { None }
|
if let ty::FnDef(def_id, substs) = *const_ty.kind() {
|
||||||
|
Some((def_id, substs))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2953,22 +2963,9 @@ impl<'tcx> Constant<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> From<ty::Const<'tcx>> for ConstantKind<'tcx> {
|
|
||||||
#[inline]
|
|
||||||
fn from(ct: ty::Const<'tcx>) -> Self {
|
|
||||||
match ct.kind() {
|
|
||||||
ty::ConstKind::Value(cv) => {
|
|
||||||
// FIXME Once valtrees are introduced we need to convert those
|
|
||||||
// into `ConstValue` instances here
|
|
||||||
Self::Val(cv, ct.ty())
|
|
||||||
}
|
|
||||||
_ => Self::Ty(ct),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> ConstantKind<'tcx> {
|
impl<'tcx> ConstantKind<'tcx> {
|
||||||
/// Returns `None` if the constant is not trivially safe for use in the type system.
|
/// Returns `None` if the constant is not trivially safe for use in the type system.
|
||||||
|
#[inline]
|
||||||
pub fn const_for_ty(&self) -> Option<ty::Const<'tcx>> {
|
pub fn const_for_ty(&self) -> Option<ty::Const<'tcx>> {
|
||||||
match self {
|
match self {
|
||||||
ConstantKind::Ty(c) => Some(*c),
|
ConstantKind::Ty(c) => Some(*c),
|
||||||
|
@ -2976,6 +2973,7 @@ impl<'tcx> ConstantKind<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
pub fn ty(&self) -> Ty<'tcx> {
|
pub fn ty(&self) -> Ty<'tcx> {
|
||||||
match self {
|
match self {
|
||||||
ConstantKind::Ty(c) => c.ty(),
|
ConstantKind::Ty(c) => c.ty(),
|
||||||
|
@ -2983,10 +2981,10 @@ impl<'tcx> ConstantKind<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn try_val(&self) -> Option<ConstValue<'tcx>> {
|
pub fn try_val(&self, tcx: TyCtxt<'tcx>) -> Option<ConstValue<'tcx>> {
|
||||||
match self {
|
match self {
|
||||||
ConstantKind::Ty(c) => match c.kind() {
|
ConstantKind::Ty(c) => match c.kind() {
|
||||||
ty::ConstKind::Value(v) => Some(v),
|
ty::ConstKind::Value(v) => Some(tcx.valtree_to_const_val((c.ty(), v))),
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
ConstantKind::Val(v, _) => Some(*v),
|
ConstantKind::Val(v, _) => Some(*v),
|
||||||
|
@ -2994,21 +2992,33 @@ impl<'tcx> ConstantKind<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn try_to_value(self) -> Option<interpret::ConstValue<'tcx>> {
|
pub fn try_to_value(self, tcx: TyCtxt<'tcx>) -> Option<interpret::ConstValue<'tcx>> {
|
||||||
match self {
|
match self {
|
||||||
ConstantKind::Ty(c) => c.kind().try_to_value(),
|
ConstantKind::Ty(c) => match c.kind() {
|
||||||
|
ty::ConstKind::Value(valtree) => Some(tcx.valtree_to_const_val((c.ty(), valtree))),
|
||||||
|
_ => None,
|
||||||
|
},
|
||||||
ConstantKind::Val(val, _) => Some(val),
|
ConstantKind::Val(val, _) => Some(val),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn try_to_scalar(self) -> Option<Scalar> {
|
pub fn try_to_scalar(self) -> Option<Scalar> {
|
||||||
self.try_to_value()?.try_to_scalar()
|
match self {
|
||||||
|
ConstantKind::Ty(c) => match c.val() {
|
||||||
|
ty::ConstKind::Value(valtree) => match valtree {
|
||||||
|
ty::ValTree::Leaf(scalar_int) => Some(Scalar::Int(scalar_int)),
|
||||||
|
ty::ValTree::Branch(_) => None,
|
||||||
|
},
|
||||||
|
_ => None,
|
||||||
|
},
|
||||||
|
ConstantKind::Val(val, _) => val.try_to_scalar(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn try_to_scalar_int(self) -> Option<ScalarInt> {
|
pub fn try_to_scalar_int(self) -> Option<ScalarInt> {
|
||||||
Some(self.try_to_value()?.try_to_scalar()?.assert_int())
|
Some(self.try_to_scalar()?.assert_int())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -3025,9 +3035,7 @@ impl<'tcx> ConstantKind<'tcx> {
|
||||||
pub fn eval(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self {
|
pub fn eval(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self {
|
||||||
match self {
|
match self {
|
||||||
Self::Ty(c) => {
|
Self::Ty(c) => {
|
||||||
// FIXME Need to use a different evaluation function that directly returns a `ConstValue`
|
if let Some(val) = c.kind().try_eval_for_mir(tcx, param_env) {
|
||||||
// if evaluation succeeds and does not create a ValTree first
|
|
||||||
if let Some(val) = c.kind().try_eval(tcx, param_env) {
|
|
||||||
match val {
|
match val {
|
||||||
Ok(val) => Self::Val(val, c.ty()),
|
Ok(val) => Self::Val(val, c.ty()),
|
||||||
Err(_) => Self::Ty(tcx.const_error(self.ty())),
|
Err(_) => Self::Ty(tcx.const_error(self.ty())),
|
||||||
|
@ -3081,6 +3089,11 @@ impl<'tcx> ConstantKind<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn from_value(val: ConstValue<'tcx>, ty: Ty<'tcx>) -> Self {
|
||||||
|
Self::Val(val, ty)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn from_bits(
|
pub fn from_bits(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
bits: u128,
|
bits: u128,
|
||||||
|
@ -3097,11 +3110,13 @@ impl<'tcx> ConstantKind<'tcx> {
|
||||||
Self::Val(cv, param_env_ty.value)
|
Self::Val(cv, param_env_ty.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn from_bool(tcx: TyCtxt<'tcx>, v: bool) -> Self {
|
pub fn from_bool(tcx: TyCtxt<'tcx>, v: bool) -> Self {
|
||||||
let cv = ConstValue::from_bool(v);
|
let cv = ConstValue::from_bool(v);
|
||||||
Self::Val(cv, tcx.types.bool)
|
Self::Val(cv, tcx.types.bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn zero_sized(ty: Ty<'tcx>) -> Self {
|
pub fn zero_sized(ty: Ty<'tcx>) -> Self {
|
||||||
let cv = ConstValue::Scalar(Scalar::ZST);
|
let cv = ConstValue::Scalar(Scalar::ZST);
|
||||||
Self::Val(cv, ty)
|
Self::Val(cv, ty)
|
||||||
|
@ -3112,6 +3127,12 @@ impl<'tcx> ConstantKind<'tcx> {
|
||||||
Self::from_bits(tcx, n as u128, ty::ParamEnv::empty().and(ty))
|
Self::from_bits(tcx, n as u128, ty::ParamEnv::empty().and(ty))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn from_scalar(_tcx: TyCtxt<'tcx>, s: Scalar, ty: Ty<'tcx>) -> Self {
|
||||||
|
let val = ConstValue::Scalar(s);
|
||||||
|
Self::Val(val, ty)
|
||||||
|
}
|
||||||
|
|
||||||
/// Literals are converted to `ConstantKindVal`, const generic parameters are eagerly
|
/// Literals are converted to `ConstantKindVal`, const generic parameters are eagerly
|
||||||
/// converted to a constant, everything else becomes `Unevaluated`.
|
/// converted to a constant, everything else becomes `Unevaluated`.
|
||||||
pub fn from_anon_const(
|
pub fn from_anon_const(
|
||||||
|
@ -3199,8 +3220,10 @@ impl<'tcx> ConstantKind<'tcx> {
|
||||||
}
|
}
|
||||||
_ => expr,
|
_ => expr,
|
||||||
};
|
};
|
||||||
|
debug!("expr.kind: {:?}", expr.kind);
|
||||||
|
|
||||||
let ty = tcx.type_of(def.def_id_for_type_of());
|
let ty = tcx.type_of(def.def_id_for_type_of());
|
||||||
|
debug!(?ty);
|
||||||
|
|
||||||
// FIXME(const_generics): We currently have to special case parameters because `min_const_generics`
|
// FIXME(const_generics): We currently have to special case parameters because `min_const_generics`
|
||||||
// does not provide the parents generics to anonymous constants. We still allow generic const
|
// does not provide the parents generics to anonymous constants. We still allow generic const
|
||||||
|
@ -3224,6 +3247,7 @@ impl<'tcx> ConstantKind<'tcx> {
|
||||||
kind: ty::ConstKind::Param(ty::ParamConst::new(index, name)),
|
kind: ty::ConstKind::Param(ty::ParamConst::new(index, name)),
|
||||||
ty,
|
ty,
|
||||||
});
|
});
|
||||||
|
debug!(?ty_const);
|
||||||
|
|
||||||
return Self::Ty(ty_const);
|
return Self::Ty(ty_const);
|
||||||
}
|
}
|
||||||
|
@ -3253,8 +3277,12 @@ impl<'tcx> ConstantKind<'tcx> {
|
||||||
debug!(?span, ?param_env);
|
debug!(?span, ?param_env);
|
||||||
|
|
||||||
match tcx.const_eval_resolve(param_env, uneval, Some(span)) {
|
match tcx.const_eval_resolve(param_env, uneval, Some(span)) {
|
||||||
Ok(val) => Self::Val(val, ty),
|
Ok(val) => {
|
||||||
|
debug!("evaluated const value: {:?}", val);
|
||||||
|
Self::Val(val, ty)
|
||||||
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
|
debug!("error encountered during evaluation");
|
||||||
// Error was handled in `const_eval_resolve`. Here we just create a
|
// Error was handled in `const_eval_resolve`. Here we just create a
|
||||||
// new unevaluated const and error hard later in codegen
|
// new unevaluated const and error hard later in codegen
|
||||||
let ty_const = tcx.mk_const(ty::ConstS {
|
let ty_const = tcx.mk_const(ty::ConstS {
|
||||||
|
@ -3265,11 +3293,22 @@ impl<'tcx> ConstantKind<'tcx> {
|
||||||
}),
|
}),
|
||||||
ty,
|
ty,
|
||||||
});
|
});
|
||||||
|
debug!(?ty_const);
|
||||||
|
|
||||||
Self::Ty(ty_const)
|
Self::Ty(ty_const)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_const(c: ty::Const<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
|
||||||
|
match c.val() {
|
||||||
|
ty::ConstKind::Value(valtree) => {
|
||||||
|
let const_val = tcx.valtree_to_const_val((c.ty(), valtree));
|
||||||
|
Self::Val(const_val, c.ty())
|
||||||
|
}
|
||||||
|
_ => Self::Ty(c),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A collection of projections into user types.
|
/// A collection of projections into user types.
|
||||||
|
@ -3485,20 +3524,182 @@ fn pretty_print_const<'tcx>(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn pretty_print_byte_str(fmt: &mut Formatter<'_>, byte_str: &[u8]) -> fmt::Result {
|
||||||
|
fmt.write_str("b\"")?;
|
||||||
|
for &c in byte_str {
|
||||||
|
for e in std::ascii::escape_default(c) {
|
||||||
|
fmt.write_char(e as char)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.write_str("\"")?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn comma_sep<'tcx>(fmt: &mut Formatter<'_>, elems: Vec<ConstantKind<'tcx>>) -> fmt::Result {
|
||||||
|
let mut first = true;
|
||||||
|
for elem in elems {
|
||||||
|
if !first {
|
||||||
|
fmt.write_str(", ")?;
|
||||||
|
}
|
||||||
|
fmt.write_str(&format!("{}", elem))?;
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn pretty_print_const_value<'tcx>(
|
fn pretty_print_const_value<'tcx>(
|
||||||
val: interpret::ConstValue<'tcx>,
|
ct: ConstValue<'tcx>,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
fmt: &mut Formatter<'_>,
|
fmt: &mut Formatter<'_>,
|
||||||
print_types: bool,
|
print_ty: bool,
|
||||||
) -> fmt::Result {
|
) -> fmt::Result {
|
||||||
use crate::ty::print::PrettyPrinter;
|
use crate::ty::print::PrettyPrinter;
|
||||||
|
|
||||||
ty::tls::with(|tcx| {
|
ty::tls::with(|tcx| {
|
||||||
let val = tcx.lift(val).unwrap();
|
let ct = tcx.lift(ct).unwrap();
|
||||||
let ty = tcx.lift(ty).unwrap();
|
let ty = tcx.lift(ty).unwrap();
|
||||||
|
|
||||||
|
if tcx.sess.verbose() {
|
||||||
|
fmt.write_str(&format!("ConstValue({:?}: {})", ct, ty))?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let u8_type = tcx.types.u8;
|
||||||
|
match (ct, ty.kind()) {
|
||||||
|
// Byte/string slices, printed as (byte) string literals.
|
||||||
|
(ConstValue::Slice { data, start, end }, ty::Ref(_, inner, _)) => {
|
||||||
|
match inner.kind() {
|
||||||
|
ty::Slice(t) => {
|
||||||
|
if *t == u8_type {
|
||||||
|
// The `inspect` here is okay since we checked the bounds, and there are
|
||||||
|
// no relocations (we have an active slice reference here). We don't use
|
||||||
|
// this result to affect interpreter execution.
|
||||||
|
let byte_str = data
|
||||||
|
.inner()
|
||||||
|
.inspect_with_uninit_and_ptr_outside_interpreter(start..end);
|
||||||
|
pretty_print_byte_str(fmt, byte_str)?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ty::Str => {
|
||||||
|
// The `inspect` here is okay since we checked the bounds, and there are no
|
||||||
|
// relocations (we have an active `str` reference here). We don't use this
|
||||||
|
// result to affect interpreter execution.
|
||||||
|
let slice = data
|
||||||
|
.inner()
|
||||||
|
.inspect_with_uninit_and_ptr_outside_interpreter(start..end);
|
||||||
|
fmt.write_str(&format!("{:?}", String::from_utf8_lossy(slice)))?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(ConstValue::ByRef { alloc, offset }, ty::Array(t, n)) if *t == u8_type => {
|
||||||
|
let n = n.val().try_to_bits(tcx.data_layout.pointer_size).unwrap();
|
||||||
|
// cast is ok because we already checked for pointer size (32 or 64 bit) above
|
||||||
|
let range = AllocRange { start: offset, size: Size::from_bytes(n) };
|
||||||
|
let byte_str = alloc.inner().get_bytes(&tcx, range).unwrap();
|
||||||
|
fmt.write_str("*")?;
|
||||||
|
pretty_print_byte_str(fmt, byte_str)?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
// Aggregates, printed as array/tuple/struct/variant construction syntax.
|
||||||
|
//
|
||||||
|
// NB: the `has_param_types_or_consts` check ensures that we can use
|
||||||
|
// the `destructure_const` query with an empty `ty::ParamEnv` without
|
||||||
|
// introducing ICEs (e.g. via `layout_of`) from missing bounds.
|
||||||
|
// E.g. `transmute([0usize; 2]): (u8, *mut T)` needs to know `T: Sized`
|
||||||
|
// to be able to destructure the tuple into `(0u8, *mut T)
|
||||||
|
//
|
||||||
|
// FIXME(eddyb) for `--emit=mir`/`-Z dump-mir`, we should provide the
|
||||||
|
// correct `ty::ParamEnv` to allow printing *all* constant values.
|
||||||
|
(_, ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) if !ty.has_param_types_or_consts() => {
|
||||||
|
let ct = tcx.lift(ct).unwrap();
|
||||||
|
let ty = tcx.lift(ty).unwrap();
|
||||||
|
if let Some(contents) = tcx.try_destructure_mir_constant(
|
||||||
|
ty::ParamEnv::reveal_all().and(ConstantKind::Val(ct, ty)),
|
||||||
|
) {
|
||||||
|
let fields = contents.fields.iter().copied().collect::<Vec<_>>();
|
||||||
|
match *ty.kind() {
|
||||||
|
ty::Array(..) => {
|
||||||
|
fmt.write_str("[")?;
|
||||||
|
comma_sep(fmt, fields)?;
|
||||||
|
fmt.write_str("]")?;
|
||||||
|
}
|
||||||
|
ty::Tuple(..) => {
|
||||||
|
fmt.write_str("(")?;
|
||||||
|
comma_sep(fmt, fields)?;
|
||||||
|
if contents.fields.len() == 1 {
|
||||||
|
fmt.write_str(",")?;
|
||||||
|
}
|
||||||
|
fmt.write_str(")")?;
|
||||||
|
}
|
||||||
|
ty::Adt(def, _) if def.variants().is_empty() => {
|
||||||
|
fmt.write_str(&format!("{{unreachable(): {}}}", ty))?;
|
||||||
|
}
|
||||||
|
ty::Adt(def, substs) => {
|
||||||
|
let variant_idx = contents
|
||||||
|
.variant
|
||||||
|
.expect("destructed mir constant of adt without variant idx");
|
||||||
|
let variant_def = &def.variant(variant_idx);
|
||||||
|
let substs = tcx.lift(substs).unwrap();
|
||||||
let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS);
|
let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS);
|
||||||
cx.print_alloc_ids = true;
|
cx.print_alloc_ids = true;
|
||||||
let cx = cx.pretty_print_const_value(val, ty, print_types)?;
|
let cx = cx.print_value_path(variant_def.def_id, substs)?;
|
||||||
fmt.write_str(&cx.into_buffer())?;
|
fmt.write_str(&cx.into_buffer())?;
|
||||||
|
|
||||||
|
match variant_def.ctor_kind {
|
||||||
|
CtorKind::Const => {}
|
||||||
|
CtorKind::Fn => {
|
||||||
|
fmt.write_str("(")?;
|
||||||
|
comma_sep(fmt, fields)?;
|
||||||
|
fmt.write_str(")")?;
|
||||||
|
}
|
||||||
|
CtorKind::Fictive => {
|
||||||
|
fmt.write_str(" {{ ")?;
|
||||||
|
let mut first = true;
|
||||||
|
for (field_def, field) in iter::zip(&variant_def.fields, fields)
|
||||||
|
{
|
||||||
|
if !first {
|
||||||
|
fmt.write_str(", ")?;
|
||||||
|
}
|
||||||
|
fmt.write_str(&format!("{}: {}", field_def.name, field))?;
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
fmt.write_str(" }}")?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
return Ok(());
|
||||||
|
} else {
|
||||||
|
// Fall back to debug pretty printing for invalid constants.
|
||||||
|
fmt.write_str(&format!("{:?}", ct))?;
|
||||||
|
if print_ty {
|
||||||
|
fmt.write_str(&format!(": {}", ty))?;
|
||||||
|
}
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
|
}
|
||||||
|
(ConstValue::Scalar(scalar), _) => {
|
||||||
|
let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS);
|
||||||
|
cx.print_alloc_ids = true;
|
||||||
|
let ty = tcx.lift(ty).unwrap();
|
||||||
|
cx = cx.pretty_print_const_scalar(scalar, ty, print_ty)?;
|
||||||
|
fmt.write_str(&cx.into_buffer())?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
// FIXME(oli-obk): also pretty print arrays and other aggregate constants by reading
|
||||||
|
// their fields instead of just dumping the memory.
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
// fallback
|
||||||
|
fmt.write_str(&format!("{:?}", ct))?;
|
||||||
|
if print_ty {
|
||||||
|
fmt.write_str(&format!(": {}", ty))?;
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -454,7 +454,12 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
|
||||||
ConstValue::ByRef { .. } => format!("ByRef(..)"),
|
ConstValue::ByRef { .. } => format!("ByRef(..)"),
|
||||||
};
|
};
|
||||||
|
|
||||||
let kind = match literal {
|
let fmt_valtree = |valtree: &ty::ValTree<'tcx>| match valtree {
|
||||||
|
ty::ValTree::Leaf(leaf) => format!("ValTree::Leaf({:?})", leaf),
|
||||||
|
ty::ValTree::Branch(_) => format!("ValTree::Branch(..)"),
|
||||||
|
};
|
||||||
|
|
||||||
|
let val = match literal {
|
||||||
ConstantKind::Ty(ct) => match ct.kind() {
|
ConstantKind::Ty(ct) => match ct.kind() {
|
||||||
ty::ConstKind::Param(p) => format!("Param({})", p),
|
ty::ConstKind::Param(p) => format!("Param({})", p),
|
||||||
ty::ConstKind::Unevaluated(uv) => format!(
|
ty::ConstKind::Unevaluated(uv) => format!(
|
||||||
|
@ -463,7 +468,7 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
|
||||||
uv.substs,
|
uv.substs,
|
||||||
uv.promoted,
|
uv.promoted,
|
||||||
),
|
),
|
||||||
ty::ConstKind::Value(val) => format!("Value({})", fmt_val(&val)),
|
ty::ConstKind::Value(val) => format!("Value({})", fmt_valtree(&val)),
|
||||||
ty::ConstKind::Error(_) => "Error".to_string(),
|
ty::ConstKind::Error(_) => "Error".to_string(),
|
||||||
// These variants shouldn't exist in the MIR.
|
// These variants shouldn't exist in the MIR.
|
||||||
ty::ConstKind::Placeholder(_)
|
ty::ConstKind::Placeholder(_)
|
||||||
|
@ -665,7 +670,8 @@ pub fn write_allocations<'tcx>(
|
||||||
) -> impl DoubleEndedIterator<Item = AllocId> + '_ {
|
) -> impl DoubleEndedIterator<Item = AllocId> + '_ {
|
||||||
alloc.inner().relocations().values().map(|id| *id)
|
alloc.inner().relocations().values().map(|id| *id)
|
||||||
}
|
}
|
||||||
fn alloc_ids_from_const(val: ConstValue<'_>) -> impl Iterator<Item = AllocId> + '_ {
|
|
||||||
|
fn alloc_ids_from_const_val(val: ConstValue<'_>) -> impl Iterator<Item = AllocId> + '_ {
|
||||||
match val {
|
match val {
|
||||||
ConstValue::Scalar(interpret::Scalar::Ptr(ptr, _)) => {
|
ConstValue::Scalar(interpret::Scalar::Ptr(ptr, _)) => {
|
||||||
Either::Left(Either::Left(std::iter::once(ptr.provenance)))
|
Either::Left(Either::Left(std::iter::once(ptr.provenance)))
|
||||||
|
@ -681,17 +687,11 @@ pub fn write_allocations<'tcx>(
|
||||||
struct CollectAllocIds(BTreeSet<AllocId>);
|
struct CollectAllocIds(BTreeSet<AllocId>);
|
||||||
|
|
||||||
impl<'tcx> Visitor<'tcx> for CollectAllocIds {
|
impl<'tcx> Visitor<'tcx> for CollectAllocIds {
|
||||||
fn visit_const(&mut self, c: ty::Const<'tcx>, _loc: Location) {
|
|
||||||
if let ty::ConstKind::Value(val) = c.kind() {
|
|
||||||
self.0.extend(alloc_ids_from_const(val));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_constant(&mut self, c: &Constant<'tcx>, loc: Location) {
|
fn visit_constant(&mut self, c: &Constant<'tcx>, loc: Location) {
|
||||||
match c.literal {
|
match c.literal {
|
||||||
ConstantKind::Ty(c) => self.visit_const(c, loc),
|
ConstantKind::Ty(c) => self.visit_const(c, loc),
|
||||||
ConstantKind::Val(val, _) => {
|
ConstantKind::Val(val, _) => {
|
||||||
self.0.extend(alloc_ids_from_const(val));
|
self.0.extend(alloc_ids_from_const_val(val));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//! Values computed by queries that use MIR.
|
//! Values computed by queries that use MIR.
|
||||||
|
|
||||||
use crate::mir::{self, Body, Promoted};
|
use crate::mir::{Body, ConstantKind, Promoted};
|
||||||
use crate::ty::{self, OpaqueHiddenType, Ty, TyCtxt};
|
use crate::ty::{self, OpaqueHiddenType, Ty, TyCtxt};
|
||||||
use rustc_data_structures::stable_map::FxHashMap;
|
use rustc_data_structures::stable_map::FxHashMap;
|
||||||
use rustc_data_structures::vec_map::VecMap;
|
use rustc_data_structures::vec_map::VecMap;
|
||||||
|
@ -427,7 +427,7 @@ pub struct DestructuredConst<'tcx> {
|
||||||
#[derive(Copy, Clone, Debug, HashStable)]
|
#[derive(Copy, Clone, Debug, HashStable)]
|
||||||
pub struct DestructuredMirConstant<'tcx> {
|
pub struct DestructuredMirConstant<'tcx> {
|
||||||
pub variant: Option<VariantIdx>,
|
pub variant: Option<VariantIdx>,
|
||||||
pub fields: &'tcx [mir::ConstantKind<'tcx>],
|
pub fields: &'tcx [ConstantKind<'tcx>],
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Coverage information summarized from a MIR if instrumented for source code coverage (see
|
/// Coverage information summarized from a MIR if instrumented for source code coverage (see
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::mir;
|
||||||
use crate::mir::interpret::Scalar;
|
use crate::mir::interpret::Scalar;
|
||||||
use crate::ty::{self, Ty, TyCtxt};
|
use crate::ty::{self, Ty, TyCtxt};
|
||||||
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
|
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
|
||||||
|
@ -676,7 +677,7 @@ impl<'tcx> TerminatorKind<'tcx> {
|
||||||
.values
|
.values
|
||||||
.iter()
|
.iter()
|
||||||
.map(|&u| {
|
.map(|&u| {
|
||||||
ty::Const::from_scalar(tcx, Scalar::from_uint(u, size), switch_ty)
|
mir::ConstantKind::from_scalar(tcx, Scalar::from_uint(u, size), switch_ty)
|
||||||
.to_string()
|
.to_string()
|
||||||
.into()
|
.into()
|
||||||
})
|
})
|
||||||
|
|
|
@ -968,7 +968,6 @@ rustc_queries! {
|
||||||
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>
|
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>
|
||||||
) -> EvalToValTreeResult<'tcx> {
|
) -> EvalToValTreeResult<'tcx> {
|
||||||
desc { "evaluate type-level constant" }
|
desc { "evaluate type-level constant" }
|
||||||
remap_env_constness
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts a type level constant value into `ConstValue`
|
/// Converts a type level constant value into `ConstValue`
|
||||||
|
@ -980,7 +979,7 @@ rustc_queries! {
|
||||||
/// field values or return `None` if constant is invalid.
|
/// field values or return `None` if constant is invalid.
|
||||||
///
|
///
|
||||||
/// Use infallible `TyCtxt::destructure_const` when you know that constant is valid.
|
/// Use infallible `TyCtxt::destructure_const` when you know that constant is valid.
|
||||||
query try_destructure_const(key: ty::ParamEnvAnd<'tcx, ty::Const<'tcx>>) -> Option<mir::DestructuredConst<'tcx>> {
|
query try_destructure_const(key: ty::Const<'tcx>) -> Option<mir::DestructuredConst<'tcx>> {
|
||||||
desc { "destructure type level constant"}
|
desc { "destructure type level constant"}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -991,15 +990,6 @@ rustc_queries! {
|
||||||
remap_env_constness
|
remap_env_constness
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Dereference a constant reference or raw pointer and turn the result into a constant
|
|
||||||
/// again.
|
|
||||||
query deref_const(
|
|
||||||
key: ty::ParamEnvAnd<'tcx, ty::Const<'tcx>>
|
|
||||||
) -> ty::Const<'tcx> {
|
|
||||||
desc { "deref constant" }
|
|
||||||
remap_env_constness
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Dereference a constant reference or raw pointer and turn the result into a constant
|
/// Dereference a constant reference or raw pointer and turn the result into a constant
|
||||||
/// again.
|
/// again.
|
||||||
query deref_mir_constant(
|
query deref_mir_constant(
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
//! its name suggest, is to provide an abstraction boundary for creating
|
//! its name suggest, is to provide an abstraction boundary for creating
|
||||||
//! interned Chalk types.
|
//! interned Chalk types.
|
||||||
|
|
||||||
use rustc_middle::mir::interpret::ConstValue;
|
|
||||||
use rustc_middle::ty::{self, AdtDef, TyCtxt};
|
use rustc_middle::ty::{self, AdtDef, TyCtxt};
|
||||||
|
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
|
@ -62,7 +61,7 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
|
||||||
type InternedType = Box<chalk_ir::TyData<Self>>;
|
type InternedType = Box<chalk_ir::TyData<Self>>;
|
||||||
type InternedLifetime = Box<chalk_ir::LifetimeData<Self>>;
|
type InternedLifetime = Box<chalk_ir::LifetimeData<Self>>;
|
||||||
type InternedConst = Box<chalk_ir::ConstData<Self>>;
|
type InternedConst = Box<chalk_ir::ConstData<Self>>;
|
||||||
type InternedConcreteConst = ConstValue<'tcx>;
|
type InternedConcreteConst = ty::ValTree<'tcx>;
|
||||||
type InternedGenericArg = Box<chalk_ir::GenericArgData<Self>>;
|
type InternedGenericArg = Box<chalk_ir::GenericArgData<Self>>;
|
||||||
type InternedGoal = Box<chalk_ir::GoalData<Self>>;
|
type InternedGoal = Box<chalk_ir::GoalData<Self>>;
|
||||||
type InternedGoals = Vec<chalk_ir::Goal<Self>>;
|
type InternedGoals = Vec<chalk_ir::Goal<Self>>;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::mir::interpret::ConstValue;
|
use crate::mir::interpret::LitToConstInput;
|
||||||
use crate::mir::interpret::{LitToConstInput, Scalar};
|
use crate::mir::ConstantKind;
|
||||||
use crate::ty::{
|
use crate::ty::{
|
||||||
self, InlineConstSubsts, InlineConstSubstsParts, InternalSubsts, ParamEnv, ParamEnvAnd, Ty,
|
self, InlineConstSubsts, InlineConstSubstsParts, InternalSubsts, ParamEnv, ParamEnvAnd, Ty,
|
||||||
TyCtxt, TypeFoldable,
|
TyCtxt, TypeFoldable,
|
||||||
|
@ -195,14 +195,13 @@ impl<'tcx> Const<'tcx> {
|
||||||
|
|
||||||
/// Interns the given value as a constant.
|
/// Interns the given value as a constant.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_value(tcx: TyCtxt<'tcx>, val: ConstValue<'tcx>, ty: Ty<'tcx>) -> Self {
|
pub fn from_value(tcx: TyCtxt<'tcx>, val: ty::ValTree<'tcx>, ty: Ty<'tcx>) -> Self {
|
||||||
tcx.mk_const(ConstS { kind: ConstKind::Value(val), ty })
|
tcx.mk_const(ConstS { kind: ConstKind::Value(val), ty })
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
pub fn from_scalar_int(tcx: TyCtxt<'tcx>, i: ScalarInt, ty: Ty<'tcx>) -> Self {
|
||||||
/// Interns the given scalar as a constant.
|
let valtree = ty::ValTree::from_scalar_int(i);
|
||||||
pub fn from_scalar(tcx: TyCtxt<'tcx>, val: Scalar, ty: Ty<'tcx>) -> Self {
|
Self::from_value(tcx, valtree, ty)
|
||||||
Self::from_value(tcx, ConstValue::Scalar(val), ty)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -212,13 +211,14 @@ impl<'tcx> Const<'tcx> {
|
||||||
.layout_of(ty)
|
.layout_of(ty)
|
||||||
.unwrap_or_else(|e| panic!("could not compute layout for {:?}: {:?}", ty, e))
|
.unwrap_or_else(|e| panic!("could not compute layout for {:?}: {:?}", ty, e))
|
||||||
.size;
|
.size;
|
||||||
Self::from_scalar(tcx, Scalar::from_uint(bits, size), ty.value)
|
Self::from_scalar_int(tcx, ScalarInt::try_from_uint(bits, size).unwrap(), ty.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Creates an interned zst constant.
|
/// Creates an interned zst constant.
|
||||||
pub fn zero_sized(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Self {
|
pub fn zero_sized(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Self {
|
||||||
Self::from_scalar(tcx, Scalar::ZST, ty)
|
let valtree = ty::ValTree::zst();
|
||||||
|
Self::from_value(tcx, valtree, ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -263,16 +263,31 @@ impl<'tcx> Const<'tcx> {
|
||||||
/// Tries to evaluate the constant if it is `Unevaluated`. If that doesn't succeed, return the
|
/// Tries to evaluate the constant if it is `Unevaluated`. If that doesn't succeed, return the
|
||||||
/// unevaluated constant.
|
/// unevaluated constant.
|
||||||
pub fn eval(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Const<'tcx> {
|
pub fn eval(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Const<'tcx> {
|
||||||
if let Some(val) = self.kind().try_eval(tcx, param_env) {
|
if let Some(val) = self.kind().try_eval_for_typeck(tcx, param_env) {
|
||||||
match val {
|
match val {
|
||||||
Ok(val) => Const::from_value(tcx, val, self.ty()),
|
Ok(val) => Const::from_value(tcx, val, self.ty()),
|
||||||
Err(ErrorGuaranteed { .. }) => tcx.const_error(self.ty()),
|
Err(ErrorGuaranteed { .. }) => tcx.const_error(self.ty()),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// Either the constant isn't evaluatable or ValTree creation failed.
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
/// Tries to evaluate the constant if it is `Unevaluated` and creates a ConstValue if the
|
||||||
|
/// evaluation succeeds. If it doesn't succeed, returns the unevaluated constant.
|
||||||
|
pub fn eval_for_mir(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> ConstantKind<'tcx> {
|
||||||
|
if let Some(val) = self.val().try_eval_for_mir(tcx, param_env) {
|
||||||
|
match val {
|
||||||
|
Ok(const_val) => ConstantKind::from_value(const_val, self.ty()),
|
||||||
|
Err(ErrorGuaranteed { .. }) => ConstantKind::Ty(tcx.const_error(self.ty())),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ConstantKind::Ty(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type.
|
/// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type.
|
||||||
pub fn eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>) -> u128 {
|
pub fn eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>) -> u128 {
|
||||||
|
|
|
@ -63,7 +63,7 @@ pub enum ConstKind<'tcx> {
|
||||||
Unevaluated(Unevaluated<'tcx>),
|
Unevaluated(Unevaluated<'tcx>),
|
||||||
|
|
||||||
/// Used to hold computed value.
|
/// Used to hold computed value.
|
||||||
Value(ConstValue<'tcx>),
|
Value(ty::ValTree<'tcx>),
|
||||||
|
|
||||||
/// A placeholder for a const which could not be computed; this is
|
/// A placeholder for a const which could not be computed; this is
|
||||||
/// propagated to avoid useless error messages.
|
/// propagated to avoid useless error messages.
|
||||||
|
@ -75,7 +75,7 @@ static_assert_size!(ConstKind<'_>, 40);
|
||||||
|
|
||||||
impl<'tcx> ConstKind<'tcx> {
|
impl<'tcx> ConstKind<'tcx> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn try_to_value(self) -> Option<ConstValue<'tcx>> {
|
pub fn try_to_value(self) -> Option<ty::ValTree<'tcx>> {
|
||||||
if let ConstKind::Value(val) = self { Some(val) } else { None }
|
if let ConstKind::Value(val) = self { Some(val) } else { None }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,7 +86,7 @@ impl<'tcx> ConstKind<'tcx> {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn try_to_scalar_int(self) -> Option<ScalarInt> {
|
pub fn try_to_scalar_int(self) -> Option<ScalarInt> {
|
||||||
Some(self.try_to_value()?.try_to_scalar()?.assert_int())
|
self.try_to_value()?.try_to_scalar_int()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -115,23 +115,65 @@ pub enum InferConst<'tcx> {
|
||||||
Fresh(u32),
|
Fresh(u32),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum EvalMode {
|
||||||
|
Typeck,
|
||||||
|
Mir,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum EvalResult<'tcx> {
|
||||||
|
ValTree(ty::ValTree<'tcx>),
|
||||||
|
ConstVal(ConstValue<'tcx>),
|
||||||
|
}
|
||||||
|
|
||||||
impl<'tcx> ConstKind<'tcx> {
|
impl<'tcx> ConstKind<'tcx> {
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Tries to evaluate the constant if it is `Unevaluated`. If that doesn't succeed, return the
|
/// Tries to evaluate the constant if it is `Unevaluated`. If that doesn't succeed, return the
|
||||||
/// unevaluated constant.
|
/// unevaluated constant.
|
||||||
pub fn eval(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Self {
|
pub fn eval(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Self {
|
||||||
self.try_eval(tcx, param_env).and_then(Result::ok).map_or(self, ConstKind::Value)
|
self.try_eval_for_typeck(tcx, param_env).and_then(Result::ok).map_or(self, ConstKind::Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Tries to evaluate the constant if it is `Unevaluated`. If that isn't possible or necessary
|
/// Tries to evaluate the constant if it is `Unevaluated`. If that isn't possible or necessary
|
||||||
/// return `None`.
|
/// return `None`.
|
||||||
// FIXME(@lcnr): Completely rework the evaluation/normalization system for `ty::Const` once valtrees are merged.
|
// FIXME(@lcnr): Completely rework the evaluation/normalization system for `ty::Const` once valtrees are merged.
|
||||||
pub fn try_eval(
|
pub fn try_eval_for_mir(
|
||||||
self,
|
self,
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
param_env: ParamEnv<'tcx>,
|
param_env: ParamEnv<'tcx>,
|
||||||
) -> Option<Result<ConstValue<'tcx>, ErrorGuaranteed>> {
|
) -> Option<Result<ConstValue<'tcx>, ErrorGuaranteed>> {
|
||||||
|
match self.try_eval_inner(tcx, param_env, EvalMode::Mir) {
|
||||||
|
Some(Ok(EvalResult::ValTree(_))) => unreachable!(),
|
||||||
|
Some(Ok(EvalResult::ConstVal(v))) => Some(Ok(v)),
|
||||||
|
Some(Err(e)) => Some(Err(e)),
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
/// Tries to evaluate the constant if it is `Unevaluated`. If that isn't possible or necessary
|
||||||
|
/// return `None`.
|
||||||
|
// FIXME(@lcnr): Completely rework the evaluation/normalization system for `ty::Const` once valtrees are merged.
|
||||||
|
pub fn try_eval_for_typeck(
|
||||||
|
self,
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
param_env: ParamEnv<'tcx>,
|
||||||
|
) -> Option<Result<ty::ValTree<'tcx>, ErrorGuaranteed>> {
|
||||||
|
match self.try_eval_inner(tcx, param_env, EvalMode::Typeck) {
|
||||||
|
Some(Ok(EvalResult::ValTree(v))) => Some(Ok(v)),
|
||||||
|
Some(Ok(EvalResult::ConstVal(_))) => unreachable!(),
|
||||||
|
Some(Err(e)) => Some(Err(e)),
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn try_eval_inner(
|
||||||
|
self,
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
param_env: ParamEnv<'tcx>,
|
||||||
|
eval_mode: EvalMode,
|
||||||
|
) -> Option<Result<EvalResult<'tcx>, ErrorGuaranteed>> {
|
||||||
if let ConstKind::Unevaluated(unevaluated) = self {
|
if let ConstKind::Unevaluated(unevaluated) = self {
|
||||||
use crate::mir::interpret::ErrorHandled;
|
use crate::mir::interpret::ErrorHandled;
|
||||||
|
|
||||||
|
@ -166,15 +208,30 @@ impl<'tcx> ConstKind<'tcx> {
|
||||||
let (param_env, unevaluated) = param_env_and.into_parts();
|
let (param_env, unevaluated) = param_env_and.into_parts();
|
||||||
// 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.
|
||||||
|
match eval_mode {
|
||||||
|
EvalMode::Typeck => {
|
||||||
|
match tcx.const_eval_resolve_for_typeck(param_env, unevaluated, None) {
|
||||||
|
// NOTE(eddyb) `val` contains no lifetimes/types/consts,
|
||||||
|
// and we use the original type, so nothing from `substs`
|
||||||
|
// (which may be identity substs, see above),
|
||||||
|
// can leak through `val` into the const we return.
|
||||||
|
Ok(val) => Some(Ok(EvalResult::ValTree(val?))),
|
||||||
|
Err(ErrorHandled::TooGeneric | ErrorHandled::Linted) => None,
|
||||||
|
Err(ErrorHandled::Reported(e)) => Some(Err(e)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EvalMode::Mir => {
|
||||||
match tcx.const_eval_resolve(param_env, unevaluated, None) {
|
match tcx.const_eval_resolve(param_env, unevaluated, None) {
|
||||||
// NOTE(eddyb) `val` contains no lifetimes/types/consts,
|
// NOTE(eddyb) `val` contains no lifetimes/types/consts,
|
||||||
// and we use the original type, so nothing from `substs`
|
// and we use the original type, so nothing from `substs`
|
||||||
// (which may be identity substs, see above),
|
// (which may be identity substs, see above),
|
||||||
// can leak through `val` into the const we return.
|
// can leak through `val` into the const we return.
|
||||||
Ok(val) => Some(Ok(val)),
|
Ok(val) => Some(Ok(EvalResult::ConstVal(val))),
|
||||||
Err(ErrorHandled::TooGeneric | ErrorHandled::Linted) => None,
|
Err(ErrorHandled::TooGeneric | ErrorHandled::Linted) => None,
|
||||||
Err(ErrorHandled::Reported(e)) => Some(Err(e)),
|
Err(ErrorHandled::Reported(e)) => Some(Err(e)),
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
use super::ScalarInt;
|
use super::ScalarInt;
|
||||||
|
use crate::mir::interpret::{AllocId, Scalar};
|
||||||
|
use crate::ty::{self, Ty, TyCtxt};
|
||||||
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
|
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Hash, TyEncodable, TyDecodable, Eq, PartialEq, Ord, PartialOrd)]
|
#[derive(Copy, Clone, Debug, Hash, TyEncodable, TyDecodable, Eq, PartialEq, Ord, PartialOrd)]
|
||||||
|
@ -50,4 +52,61 @@ impl<'tcx> ValTree<'tcx> {
|
||||||
_ => bug!("expected branch, got {:?}", self),
|
_ => bug!("expected branch, got {:?}", self),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_raw_bytes<'a>(tcx: TyCtxt<'tcx>, bytes: &'a [u8]) -> Self {
|
||||||
|
let branches = bytes.iter().map(|b| Self::Leaf(ScalarInt::from(*b)));
|
||||||
|
let interned = tcx.arena.alloc_from_iter(branches);
|
||||||
|
|
||||||
|
Self::Branch(interned)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_scalar_int(i: ScalarInt) -> Self {
|
||||||
|
Self::Leaf(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn try_to_scalar(self) -> Option<Scalar<AllocId>> {
|
||||||
|
self.try_to_scalar_int().map(Scalar::Int)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn try_to_scalar_int(self) -> Option<ScalarInt> {
|
||||||
|
match self {
|
||||||
|
Self::Leaf(s) => Some(s),
|
||||||
|
Self::Branch(_) => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn try_to_machine_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
|
||||||
|
self.try_to_scalar_int().map(|s| s.try_to_machine_usize(tcx).ok()).flatten()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the values inside the ValTree as a slice of bytes. This only works for
|
||||||
|
/// constants with types &str and &[u8].
|
||||||
|
pub fn try_to_raw_bytes(self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<&'tcx [u8]> {
|
||||||
|
match ty.kind() {
|
||||||
|
ty::Ref(_, inner_ty, _) => match inner_ty.kind() {
|
||||||
|
ty::Str => {
|
||||||
|
let leafs = self
|
||||||
|
.unwrap_branch()
|
||||||
|
.into_iter()
|
||||||
|
.map(|v| v.unwrap_leaf().try_to_u8().unwrap())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
return Some(tcx.arena.alloc_from_iter(leafs.into_iter()));
|
||||||
|
}
|
||||||
|
ty::Slice(slice_ty) if *slice_ty == tcx.types.u8 => {
|
||||||
|
let leafs = self
|
||||||
|
.unwrap_branch()
|
||||||
|
.into_iter()
|
||||||
|
.map(|v| v.unwrap_leaf().try_to_u8().unwrap())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
return Some(tcx.arena.alloc_from_iter(leafs.into_iter()));
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ use crate::lint::{struct_lint_level, LintDiagnosticBuilder, LintLevelSource};
|
||||||
use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
|
use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
|
||||||
use crate::middle::resolve_lifetime;
|
use crate::middle::resolve_lifetime;
|
||||||
use crate::middle::stability;
|
use crate::middle::stability;
|
||||||
use crate::mir::interpret::{self, Allocation, ConstAllocation, ConstValue, Scalar};
|
use crate::mir::interpret::{self, Allocation, ConstAllocation};
|
||||||
use crate::mir::{
|
use crate::mir::{
|
||||||
Body, BorrowCheckResult, Field, Local, Place, PlaceElem, ProjectionKind, Promoted,
|
Body, BorrowCheckResult, Field, Local, Place, PlaceElem, ProjectionKind, Promoted,
|
||||||
};
|
};
|
||||||
|
@ -991,7 +991,7 @@ impl<'tcx> CommonConsts<'tcx> {
|
||||||
|
|
||||||
CommonConsts {
|
CommonConsts {
|
||||||
unit: mk_const(ty::ConstS {
|
unit: mk_const(ty::ConstS {
|
||||||
kind: ty::ConstKind::Value(ConstValue::Scalar(Scalar::ZST)),
|
kind: ty::ConstKind::Value(ty::ValTree::zst()),
|
||||||
ty: types.unit,
|
ty: types.unit,
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
|
@ -1186,11 +1186,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
};
|
};
|
||||||
debug!("layout_scalar_valid_range: attr={:?}", attr);
|
debug!("layout_scalar_valid_range: attr={:?}", attr);
|
||||||
if let Some(
|
if let Some(
|
||||||
&[
|
&[ast::NestedMetaItem::Literal(ast::Lit { kind: ast::LitKind::Int(a, _), .. })],
|
||||||
ast::NestedMetaItem::Literal(ast::Lit {
|
|
||||||
kind: ast::LitKind::Int(a, _), ..
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
) = attr.meta_item_list().as_deref()
|
) = attr.meta_item_list().as_deref()
|
||||||
{
|
{
|
||||||
Bound::Included(a)
|
Bound::Included(a)
|
||||||
|
@ -2248,7 +2244,11 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
/// `*r == kind`.
|
/// `*r == kind`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn reuse_or_mk_region(self, r: Region<'tcx>, kind: RegionKind) -> Region<'tcx> {
|
pub fn reuse_or_mk_region(self, r: Region<'tcx>, kind: RegionKind) -> Region<'tcx> {
|
||||||
if *r == kind { r } else { self.mk_region(kind) }
|
if *r == kind {
|
||||||
|
r
|
||||||
|
} else {
|
||||||
|
self.mk_region(kind)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(rustc::usage_of_ty_tykind)]
|
#[allow(rustc::usage_of_ty_tykind)]
|
||||||
|
@ -2268,7 +2268,11 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
pred: Predicate<'tcx>,
|
pred: Predicate<'tcx>,
|
||||||
binder: Binder<'tcx, PredicateKind<'tcx>>,
|
binder: Binder<'tcx, PredicateKind<'tcx>>,
|
||||||
) -> Predicate<'tcx> {
|
) -> Predicate<'tcx> {
|
||||||
if pred.kind() != binder { self.mk_predicate(binder) } else { pred }
|
if pred.kind() != binder {
|
||||||
|
self.mk_predicate(binder)
|
||||||
|
} else {
|
||||||
|
pred
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mk_mach_int(self, tm: IntTy) -> Ty<'tcx> {
|
pub fn mk_mach_int(self, tm: IntTy) -> Ty<'tcx> {
|
||||||
|
@ -2413,7 +2417,11 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn mk_diverging_default(self) -> Ty<'tcx> {
|
pub fn mk_diverging_default(self) -> Ty<'tcx> {
|
||||||
if self.features().never_type_fallback { self.types.never } else { self.types.unit }
|
if self.features().never_type_fallback {
|
||||||
|
self.types.never
|
||||||
|
} else {
|
||||||
|
self.types.unit
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -2564,11 +2572,9 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
eps: &[ty::Binder<'tcx, ExistentialPredicate<'tcx>>],
|
eps: &[ty::Binder<'tcx, ExistentialPredicate<'tcx>>],
|
||||||
) -> &'tcx List<ty::Binder<'tcx, ExistentialPredicate<'tcx>>> {
|
) -> &'tcx List<ty::Binder<'tcx, ExistentialPredicate<'tcx>>> {
|
||||||
assert!(!eps.is_empty());
|
assert!(!eps.is_empty());
|
||||||
assert!(
|
assert!(eps
|
||||||
eps.array_windows()
|
.array_windows()
|
||||||
.all(|[a, b]| a.skip_binder().stable_cmp(self, &b.skip_binder())
|
.all(|[a, b]| a.skip_binder().stable_cmp(self, &b.skip_binder()) != Ordering::Greater));
|
||||||
!= Ordering::Greater)
|
|
||||||
);
|
|
||||||
self._intern_poly_existential_predicates(eps)
|
self._intern_poly_existential_predicates(eps)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2601,29 +2607,49 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn intern_substs(self, ts: &[GenericArg<'tcx>]) -> &'tcx List<GenericArg<'tcx>> {
|
pub fn intern_substs(self, ts: &[GenericArg<'tcx>]) -> &'tcx List<GenericArg<'tcx>> {
|
||||||
if ts.is_empty() { List::empty() } else { self._intern_substs(ts) }
|
if ts.is_empty() {
|
||||||
|
List::empty()
|
||||||
|
} else {
|
||||||
|
self._intern_substs(ts)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn intern_projs(self, ps: &[ProjectionKind]) -> &'tcx List<ProjectionKind> {
|
pub fn intern_projs(self, ps: &[ProjectionKind]) -> &'tcx List<ProjectionKind> {
|
||||||
if ps.is_empty() { List::empty() } else { self._intern_projs(ps) }
|
if ps.is_empty() {
|
||||||
|
List::empty()
|
||||||
|
} else {
|
||||||
|
self._intern_projs(ps)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn intern_place_elems(self, ts: &[PlaceElem<'tcx>]) -> &'tcx List<PlaceElem<'tcx>> {
|
pub fn intern_place_elems(self, ts: &[PlaceElem<'tcx>]) -> &'tcx List<PlaceElem<'tcx>> {
|
||||||
if ts.is_empty() { List::empty() } else { self._intern_place_elems(ts) }
|
if ts.is_empty() {
|
||||||
|
List::empty()
|
||||||
|
} else {
|
||||||
|
self._intern_place_elems(ts)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn intern_canonical_var_infos(
|
pub fn intern_canonical_var_infos(
|
||||||
self,
|
self,
|
||||||
ts: &[CanonicalVarInfo<'tcx>],
|
ts: &[CanonicalVarInfo<'tcx>],
|
||||||
) -> CanonicalVarInfos<'tcx> {
|
) -> CanonicalVarInfos<'tcx> {
|
||||||
if ts.is_empty() { List::empty() } else { self._intern_canonical_var_infos(ts) }
|
if ts.is_empty() {
|
||||||
|
List::empty()
|
||||||
|
} else {
|
||||||
|
self._intern_canonical_var_infos(ts)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn intern_bound_variable_kinds(
|
pub fn intern_bound_variable_kinds(
|
||||||
self,
|
self,
|
||||||
ts: &[ty::BoundVariableKind],
|
ts: &[ty::BoundVariableKind],
|
||||||
) -> &'tcx List<ty::BoundVariableKind> {
|
) -> &'tcx List<ty::BoundVariableKind> {
|
||||||
if ts.is_empty() { List::empty() } else { self._intern_bound_variable_kinds(ts) }
|
if ts.is_empty() {
|
||||||
|
List::empty()
|
||||||
|
} else {
|
||||||
|
self._intern_bound_variable_kinds(ts)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mk_fn_sig<I>(
|
pub fn mk_fn_sig<I>(
|
||||||
|
|
|
@ -369,7 +369,6 @@ impl<'tcx> Instance<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// This should be kept up to date with `resolve`.
|
// This should be kept up to date with `resolve`.
|
||||||
#[instrument(level = "debug", skip(tcx))]
|
|
||||||
pub fn resolve_opt_const_arg(
|
pub fn resolve_opt_const_arg(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
|
|
@ -2161,9 +2161,14 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the possibly-auto-generated MIR of a `(DefId, Subst)` pair.
|
/// Returns the possibly-auto-generated MIR of a `(DefId, Subst)` pair.
|
||||||
|
#[instrument(skip(self), level = "debug")]
|
||||||
pub fn instance_mir(self, instance: ty::InstanceDef<'tcx>) -> &'tcx Body<'tcx> {
|
pub fn instance_mir(self, instance: ty::InstanceDef<'tcx>) -> &'tcx Body<'tcx> {
|
||||||
match instance {
|
match instance {
|
||||||
ty::InstanceDef::Item(def) => match self.def_kind(def.did) {
|
ty::InstanceDef::Item(def) => {
|
||||||
|
debug!("calling def_kind on def: {:?}", def);
|
||||||
|
let def_kind = self.def_kind(def.did);
|
||||||
|
debug!("returned from def_kind: {:?}", def_kind);
|
||||||
|
match def_kind {
|
||||||
DefKind::Const
|
DefKind::Const
|
||||||
| DefKind::Static(..)
|
| DefKind::Static(..)
|
||||||
| DefKind::AssocConst
|
| DefKind::AssocConst
|
||||||
|
@ -2176,7 +2181,8 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
assert_eq!(def.const_param_did, None);
|
assert_eq!(def.const_param_did, None);
|
||||||
self.optimized_mir(def.did)
|
self.optimized_mir(def.did)
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
}
|
||||||
ty::InstanceDef::VtableShim(..)
|
ty::InstanceDef::VtableShim(..)
|
||||||
| ty::InstanceDef::ReifyShim(..)
|
| ty::InstanceDef::ReifyShim(..)
|
||||||
| ty::InstanceDef::Intrinsic(..)
|
| ty::InstanceDef::Intrinsic(..)
|
||||||
|
|
|
@ -98,7 +98,6 @@ pub trait Printer<'tcx>: Sized {
|
||||||
|
|
||||||
// Defaults (should not be overridden):
|
// Defaults (should not be overridden):
|
||||||
|
|
||||||
#[instrument(skip(self), level = "debug")]
|
|
||||||
fn default_print_def_path(
|
fn default_print_def_path(
|
||||||
self,
|
self,
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
|
@ -302,6 +301,7 @@ impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for ty::Region<'_> {
|
||||||
impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for Ty<'tcx> {
|
impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for Ty<'tcx> {
|
||||||
type Output = P::Type;
|
type Output = P::Type;
|
||||||
type Error = P::Error;
|
type Error = P::Error;
|
||||||
|
|
||||||
fn print(&self, cx: P) -> Result<Self::Output, Self::Error> {
|
fn print(&self, cx: P) -> Result<Self::Output, Self::Error> {
|
||||||
cx.print_type(*self)
|
cx.print_type(*self)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::mir::interpret::{AllocRange, ConstValue, GlobalAlloc, Pointer, Provenance, Scalar};
|
use crate::mir::interpret::{AllocRange, GlobalAlloc, Pointer, Provenance, Scalar};
|
||||||
use crate::ty::subst::{GenericArg, GenericArgKind, Subst};
|
use crate::ty::subst::{GenericArg, GenericArgKind, Subst};
|
||||||
use crate::ty::{
|
use crate::ty::{
|
||||||
self, ConstInt, DefIdTree, ParamConst, ScalarInt, Term, Ty, TyCtxt, TypeFoldable,
|
self, ConstInt, DefIdTree, ParamConst, ScalarInt, Term, Ty, TyCtxt, TypeFoldable,
|
||||||
|
@ -607,7 +607,11 @@ pub trait PrettyPrinter<'tcx>:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if verbose { p!(write("{:?}", infer_ty)) } else { p!(write("{}", infer_ty)) }
|
if verbose {
|
||||||
|
p!(write("{:?}", infer_ty))
|
||||||
|
} else {
|
||||||
|
p!(write("{}", infer_ty))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ty::Error(_) => p!("[type error]"),
|
ty::Error(_) => p!("[type error]"),
|
||||||
|
@ -1224,7 +1228,7 @@ pub trait PrettyPrinter<'tcx>:
|
||||||
}
|
}
|
||||||
ty::ConstKind::Param(ParamConst { name, .. }) => p!(write("{}", name)),
|
ty::ConstKind::Param(ParamConst { name, .. }) => p!(write("{}", name)),
|
||||||
ty::ConstKind::Value(value) => {
|
ty::ConstKind::Value(value) => {
|
||||||
return self.pretty_print_const_value(value, ct.ty(), print_ty);
|
return self.pretty_print_const_valtree(value, ct.ty(), print_ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::ConstKind::Bound(debruijn, bound_var) => {
|
ty::ConstKind::Bound(debruijn, bound_var) => {
|
||||||
|
@ -1262,7 +1266,7 @@ pub trait PrettyPrinter<'tcx>:
|
||||||
ty::Ref(_, inner, _) => {
|
ty::Ref(_, inner, _) => {
|
||||||
if let ty::Array(elem, len) = inner.kind() {
|
if let ty::Array(elem, len) = inner.kind() {
|
||||||
if let ty::Uint(ty::UintTy::U8) = elem.kind() {
|
if let ty::Uint(ty::UintTy::U8) = elem.kind() {
|
||||||
if let ty::ConstKind::Value(ConstValue::Scalar(int)) = len.kind() {
|
if let ty::ConstKind::Value(ty::ValTree::Leaf(int)) = len.kind() {
|
||||||
match self.tcx().get_global_alloc(alloc_id) {
|
match self.tcx().get_global_alloc(alloc_id) {
|
||||||
Some(GlobalAlloc::Memory(alloc)) => {
|
Some(GlobalAlloc::Memory(alloc)) => {
|
||||||
let len = int.assert_bits(self.tcx().data_layout.pointer_size);
|
let len = int.assert_bits(self.tcx().data_layout.pointer_size);
|
||||||
|
@ -1331,7 +1335,11 @@ pub trait PrettyPrinter<'tcx>:
|
||||||
ty::Uint(_) | ty::Int(_) => {
|
ty::Uint(_) | ty::Int(_) => {
|
||||||
let int =
|
let int =
|
||||||
ConstInt::new(int, matches!(ty.kind(), ty::Int(_)), ty.is_ptr_sized_integral());
|
ConstInt::new(int, matches!(ty.kind(), ty::Int(_)), ty.is_ptr_sized_integral());
|
||||||
if print_ty { p!(write("{:#?}", int)) } else { p!(write("{:?}", int)) }
|
if print_ty {
|
||||||
|
p!(write("{:#?}", int))
|
||||||
|
} else {
|
||||||
|
p!(write("{:?}", int))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Char
|
// Char
|
||||||
ty::Char if char::try_from(int).is_ok() => {
|
ty::Char if char::try_from(int).is_ok() => {
|
||||||
|
@ -1408,85 +1416,64 @@ pub trait PrettyPrinter<'tcx>:
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pretty_print_const_value(
|
fn pretty_print_const_valtree(
|
||||||
mut self,
|
mut self,
|
||||||
ct: ConstValue<'tcx>,
|
valtree: ty::ValTree<'tcx>,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
print_ty: bool,
|
print_ty: bool,
|
||||||
) -> Result<Self::Const, Self::Error> {
|
) -> Result<Self::Const, Self::Error> {
|
||||||
define_scoped_cx!(self);
|
define_scoped_cx!(self);
|
||||||
|
|
||||||
if self.tcx().sess.verbose() {
|
if self.tcx().sess.verbose() {
|
||||||
p!(write("ConstValue({:?}: ", ct), print(ty), ")");
|
p!(write("ValTree({:?}: ", valtree), print(ty), ")");
|
||||||
return Ok(self);
|
return Ok(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
let u8_type = self.tcx().types.u8;
|
let u8_type = self.tcx().types.u8;
|
||||||
|
match (valtree, ty.kind()) {
|
||||||
match (ct, ty.kind()) {
|
(ty::ValTree::Branch(_), ty::Ref(_, inner_ty, _)) => match inner_ty.kind() {
|
||||||
// Byte/string slices, printed as (byte) string literals.
|
ty::Slice(t) if *t == u8_type => {
|
||||||
(ConstValue::Slice { data, start, end }, ty::Ref(_, inner, _)) => {
|
let bytes = valtree.try_to_raw_bytes(self.tcx(), ty).unwrap_or_else(|| {
|
||||||
match inner.kind() {
|
bug!(
|
||||||
ty::Slice(t) => {
|
"expected to convert valtree {:?} to raw bytes for type {:?}",
|
||||||
if *t == u8_type {
|
valtree,
|
||||||
// The `inspect` here is okay since we checked the bounds, and there are
|
t
|
||||||
// no relocations (we have an active slice reference here). We don't use
|
)
|
||||||
// this result to affect interpreter execution.
|
});
|
||||||
let byte_str = data
|
return self.pretty_print_byte_str(bytes);
|
||||||
.inner()
|
|
||||||
.inspect_with_uninit_and_ptr_outside_interpreter(start..end);
|
|
||||||
return self.pretty_print_byte_str(byte_str);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ty::Str => {
|
ty::Str => {
|
||||||
// The `inspect` here is okay since we checked the bounds, and there are no
|
let bytes = valtree.try_to_raw_bytes(self.tcx(), ty).unwrap_or_else(|| {
|
||||||
// relocations (we have an active `str` reference here). We don't use this
|
bug!("expected to convert valtree to raw bytes for type {:?}", ty)
|
||||||
// result to affect interpreter execution.
|
});
|
||||||
let slice = data
|
p!(write("{:?}", String::from_utf8_lossy(bytes)));
|
||||||
.inner()
|
|
||||||
.inspect_with_uninit_and_ptr_outside_interpreter(start..end);
|
|
||||||
p!(write("{:?}", String::from_utf8_lossy(slice)));
|
|
||||||
return Ok(self);
|
return Ok(self);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
},
|
||||||
}
|
(ty::ValTree::Branch(_), ty::Array(t, _)) if *t == u8_type => {
|
||||||
(ConstValue::ByRef { alloc, offset }, ty::Array(t, n)) if *t == u8_type => {
|
let bytes = valtree.try_to_raw_bytes(self.tcx(), *t).unwrap_or_else(|| {
|
||||||
let n = n.kind().try_to_bits(self.tcx().data_layout.pointer_size).unwrap();
|
bug!("expected to convert valtree to raw bytes for type {:?}", t)
|
||||||
// cast is ok because we already checked for pointer size (32 or 64 bit) above
|
});
|
||||||
let range = AllocRange { start: offset, size: Size::from_bytes(n) };
|
|
||||||
|
|
||||||
let byte_str = alloc.inner().get_bytes(&self.tcx(), range).unwrap();
|
|
||||||
p!("*");
|
p!("*");
|
||||||
p!(pretty_print_byte_str(byte_str));
|
p!(pretty_print_byte_str(bytes));
|
||||||
return Ok(self);
|
return Ok(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Aggregates, printed as array/tuple/struct/variant construction syntax.
|
// Aggregates, printed as array/tuple/struct/variant construction syntax.
|
||||||
//
|
(ty::ValTree::Branch(_), ty::Array(..) | ty::Tuple(..) | ty::Adt(..))
|
||||||
// NB: the `has_param_types_or_consts` check ensures that we can use
|
if !ty.has_param_types_or_consts() =>
|
||||||
// the `destructure_const` query with an empty `ty::ParamEnv` without
|
{
|
||||||
// introducing ICEs (e.g. via `layout_of`) from missing bounds.
|
|
||||||
// E.g. `transmute([0usize; 2]): (u8, *mut T)` needs to know `T: Sized`
|
|
||||||
// to be able to destructure the tuple into `(0u8, *mut T)
|
|
||||||
//
|
|
||||||
// FIXME(eddyb) for `--emit=mir`/`-Z dump-mir`, we should provide the
|
|
||||||
// correct `ty::ParamEnv` to allow printing *all* constant values.
|
|
||||||
(_, ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) if !ty.has_param_types_or_consts() => {
|
|
||||||
let Some(contents) = self.tcx().try_destructure_const(
|
let Some(contents) = self.tcx().try_destructure_const(
|
||||||
ty::ParamEnv::reveal_all()
|
ty::Const::from_value(self.tcx(), valtree, ty)
|
||||||
.and(self.tcx().mk_const(ty::ConstS { kind: ty::ConstKind::Value(ct), ty })),
|
|
||||||
) else {
|
) else {
|
||||||
// Fall back to debug pretty printing for invalid constants.
|
// Fall back to debug pretty printing for invalid constants.
|
||||||
p!(write("{:?}", ct));
|
p!(write("{:?}", valtree));
|
||||||
if print_ty {
|
if print_ty {
|
||||||
p!(": ", print(ty));
|
p!(": ", print(ty));
|
||||||
}
|
}
|
||||||
return Ok(self);
|
return Ok(self);
|
||||||
};
|
};
|
||||||
|
|
||||||
let fields = contents.fields.iter().copied();
|
let fields = contents.fields.iter().copied();
|
||||||
|
|
||||||
match *ty.kind() {
|
match *ty.kind() {
|
||||||
ty::Array(..) => {
|
ty::Array(..) => {
|
||||||
p!("[", comma_sep(fields), "]");
|
p!("[", comma_sep(fields), "]");
|
||||||
|
@ -1513,7 +1500,6 @@ pub trait PrettyPrinter<'tcx>:
|
||||||
contents.variant.expect("destructed const of adt without variant idx");
|
contents.variant.expect("destructed const of adt without variant idx");
|
||||||
let variant_def = &def.variant(variant_idx);
|
let variant_def = &def.variant(variant_idx);
|
||||||
p!(print_value_path(variant_def.def_id, substs));
|
p!(print_value_path(variant_def.def_id, substs));
|
||||||
|
|
||||||
match variant_def.ctor_kind {
|
match variant_def.ctor_kind {
|
||||||
CtorKind::Const => {}
|
CtorKind::Const => {}
|
||||||
CtorKind::Fn => {
|
CtorKind::Fn => {
|
||||||
|
@ -1535,21 +1521,20 @@ pub trait PrettyPrinter<'tcx>:
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(self);
|
return Ok(self);
|
||||||
}
|
}
|
||||||
|
(ty::ValTree::Leaf(leaf), _) => {
|
||||||
(ConstValue::Scalar(scalar), _) => {
|
return self.pretty_print_const_scalar_int(leaf, ty, print_ty);
|
||||||
return self.pretty_print_const_scalar(scalar, ty, print_ty);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME(oli-obk): also pretty print arrays and other aggregate constants by reading
|
// FIXME(oli-obk): also pretty print arrays and other aggregate constants by reading
|
||||||
// their fields instead of just dumping the memory.
|
// their fields instead of just dumping the memory.
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// fallback
|
// fallback
|
||||||
p!(write("{:?}", ct));
|
if valtree != ty::ValTree::zst() {
|
||||||
|
p!(write("{:?}", valtree));
|
||||||
|
}
|
||||||
if print_ty {
|
if print_ty {
|
||||||
p!(": ", print(ty));
|
p!(": ", print(ty));
|
||||||
}
|
}
|
||||||
|
@ -2296,7 +2281,6 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
|
||||||
Ok(inner)
|
Ok(inner)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(skip(self), level = "debug")]
|
|
||||||
fn prepare_late_bound_region_info<T>(&mut self, value: &ty::Binder<'tcx, T>)
|
fn prepare_late_bound_region_info<T>(&mut self, value: &ty::Binder<'tcx, T>)
|
||||||
where
|
where
|
||||||
T: TypeFoldable<'tcx>,
|
T: TypeFoldable<'tcx>,
|
||||||
|
@ -2309,7 +2293,6 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
|
||||||
impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector<'_, 'tcx> {
|
impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector<'_, 'tcx> {
|
||||||
type BreakTy = ();
|
type BreakTy = ();
|
||||||
|
|
||||||
#[instrument(skip(self), level = "trace")]
|
|
||||||
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
|
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||||
trace!("address: {:p}", r.0 .0);
|
trace!("address: {:p}", r.0 .0);
|
||||||
if let ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) = *r {
|
if let ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) = *r {
|
||||||
|
@ -2326,7 +2309,6 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
|
||||||
|
|
||||||
// We collect types in order to prevent really large types from compiling for
|
// We collect types in order to prevent really large types from compiling for
|
||||||
// a really long time. See issue #83150 for why this is necessary.
|
// a really long time. See issue #83150 for why this is necessary.
|
||||||
#[instrument(skip(self), level = "trace")]
|
|
||||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||||
let not_previously_inserted = self.type_collector.insert(ty);
|
let not_previously_inserted = self.type_collector.insert(ty);
|
||||||
if not_previously_inserted {
|
if not_previously_inserted {
|
||||||
|
@ -2353,6 +2335,7 @@ where
|
||||||
{
|
{
|
||||||
type Output = P;
|
type Output = P;
|
||||||
type Error = P::Error;
|
type Error = P::Error;
|
||||||
|
|
||||||
fn print(&self, cx: P) -> Result<Self::Output, Self::Error> {
|
fn print(&self, cx: P) -> Result<Self::Output, Self::Error> {
|
||||||
cx.in_binder(self)
|
cx.in_binder(self)
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
//! types or regions but can be other things. Examples of type relations are
|
//! types or regions but can be other things. Examples of type relations are
|
||||||
//! subtyping, type equality, etc.
|
//! subtyping, type equality, etc.
|
||||||
|
|
||||||
use crate::mir::interpret::{get_slice_bytes, ConstValue, GlobalAlloc, Scalar};
|
|
||||||
use crate::ty::error::{ExpectedFound, TypeError};
|
use crate::ty::error::{ExpectedFound, TypeError};
|
||||||
use crate::ty::subst::{GenericArg, GenericArgKind, Subst, SubstsRef};
|
use crate::ty::subst::{GenericArg, GenericArgKind, Subst, SubstsRef};
|
||||||
use crate::ty::{self, ImplSubject, Term, Ty, TyCtxt, TypeFoldable};
|
use crate::ty::{self, ImplSubject, Term, Ty, TyCtxt, TypeFoldable};
|
||||||
|
@ -613,9 +612,7 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
|
||||||
|
|
||||||
(ty::ConstKind::Param(a_p), ty::ConstKind::Param(b_p)) => a_p.index == b_p.index,
|
(ty::ConstKind::Param(a_p), ty::ConstKind::Param(b_p)) => a_p.index == b_p.index,
|
||||||
(ty::ConstKind::Placeholder(p1), ty::ConstKind::Placeholder(p2)) => p1 == p2,
|
(ty::ConstKind::Placeholder(p1), ty::ConstKind::Placeholder(p2)) => p1 == p2,
|
||||||
(ty::ConstKind::Value(a_val), ty::ConstKind::Value(b_val)) => {
|
(ty::ConstKind::Value(a_val), ty::ConstKind::Value(b_val)) => a_val == b_val,
|
||||||
check_const_value_eq(relation, a_val, b_val, a, b)?
|
|
||||||
}
|
|
||||||
|
|
||||||
(ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu))
|
(ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu))
|
||||||
if tcx.features().generic_const_exprs =>
|
if tcx.features().generic_const_exprs =>
|
||||||
|
@ -649,66 +646,6 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
|
||||||
if is_match { Ok(a) } else { Err(TypeError::ConstMismatch(expected_found(relation, a, b))) }
|
if is_match { Ok(a) } else { Err(TypeError::ConstMismatch(expected_found(relation, a, b))) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_const_value_eq<'tcx, R: TypeRelation<'tcx>>(
|
|
||||||
relation: &mut R,
|
|
||||||
a_val: ConstValue<'tcx>,
|
|
||||||
b_val: ConstValue<'tcx>,
|
|
||||||
// FIXME(oli-obk): these arguments should go away with valtrees
|
|
||||||
a: ty::Const<'tcx>,
|
|
||||||
b: ty::Const<'tcx>,
|
|
||||||
// FIXME(oli-obk): this should just be `bool` with valtrees
|
|
||||||
) -> RelateResult<'tcx, bool> {
|
|
||||||
let tcx = relation.tcx();
|
|
||||||
Ok(match (a_val, b_val) {
|
|
||||||
(ConstValue::Scalar(Scalar::Int(a_val)), ConstValue::Scalar(Scalar::Int(b_val))) => {
|
|
||||||
a_val == b_val
|
|
||||||
}
|
|
||||||
(
|
|
||||||
ConstValue::Scalar(Scalar::Ptr(a_val, _a_size)),
|
|
||||||
ConstValue::Scalar(Scalar::Ptr(b_val, _b_size)),
|
|
||||||
) => {
|
|
||||||
a_val == b_val
|
|
||||||
|| match (tcx.global_alloc(a_val.provenance), tcx.global_alloc(b_val.provenance)) {
|
|
||||||
(GlobalAlloc::Function(a_instance), GlobalAlloc::Function(b_instance)) => {
|
|
||||||
a_instance == b_instance
|
|
||||||
}
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
(ConstValue::Slice { .. }, ConstValue::Slice { .. }) => {
|
|
||||||
get_slice_bytes(&tcx, a_val) == get_slice_bytes(&tcx, b_val)
|
|
||||||
}
|
|
||||||
|
|
||||||
(ConstValue::ByRef { alloc: alloc_a, .. }, ConstValue::ByRef { alloc: alloc_b, .. })
|
|
||||||
if a.ty().is_ref() || b.ty().is_ref() =>
|
|
||||||
{
|
|
||||||
if a.ty().is_ref() && b.ty().is_ref() {
|
|
||||||
alloc_a == alloc_b
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(ConstValue::ByRef { .. }, ConstValue::ByRef { .. }) => {
|
|
||||||
let a_destructured = tcx.destructure_const(relation.param_env().and(a));
|
|
||||||
let b_destructured = tcx.destructure_const(relation.param_env().and(b));
|
|
||||||
|
|
||||||
// Both the variant and each field have to be equal.
|
|
||||||
if a_destructured.variant == b_destructured.variant {
|
|
||||||
for (a_field, b_field) in iter::zip(a_destructured.fields, b_destructured.fields) {
|
|
||||||
relation.consts(*a_field, *b_field)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => false,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>> {
|
impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>> {
|
||||||
fn relate<R: TypeRelation<'tcx>>(
|
fn relate<R: TypeRelation<'tcx>>(
|
||||||
relation: &mut R,
|
relation: &mut R,
|
||||||
|
|
|
@ -1,12 +1,16 @@
|
||||||
//! See docs in build/expr/mod.rs
|
//! See docs in build/expr/mod.rs
|
||||||
|
|
||||||
use crate::build::{lit_to_mir_constant, Builder};
|
use crate::build::{parse_float_into_constval, Builder};
|
||||||
|
use rustc_ast as ast;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_middle::mir::interpret::{ConstValue, LitToConstError, LitToConstInput, Scalar};
|
use rustc_middle::mir::interpret::{
|
||||||
|
Allocation, ConstValue, LitToConstError, LitToConstInput, Scalar,
|
||||||
|
};
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
use rustc_middle::thir::*;
|
use rustc_middle::thir::*;
|
||||||
use rustc_middle::ty::subst::SubstsRef;
|
use rustc_middle::ty::subst::SubstsRef;
|
||||||
use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt};
|
use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt};
|
||||||
|
use rustc_target::abi::Size;
|
||||||
|
|
||||||
impl<'a, 'tcx> Builder<'a, 'tcx> {
|
impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
/// Compile `expr`, yielding a compile-time constant. Assumes that
|
/// Compile `expr`, yielding a compile-time constant. Assumes that
|
||||||
|
@ -84,3 +88,54 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(skip(tcx, lit_input))]
|
||||||
|
pub(crate) fn lit_to_mir_constant<'tcx>(
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
lit_input: LitToConstInput<'tcx>,
|
||||||
|
) -> Result<ConstantKind<'tcx>, LitToConstError> {
|
||||||
|
let LitToConstInput { lit, ty, neg } = lit_input;
|
||||||
|
let trunc = |n| {
|
||||||
|
let param_ty = ty::ParamEnv::reveal_all().and(ty);
|
||||||
|
let width = tcx.layout_of(param_ty).map_err(|_| LitToConstError::Reported)?.size;
|
||||||
|
trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits());
|
||||||
|
let result = width.truncate(n);
|
||||||
|
trace!("trunc result: {}", result);
|
||||||
|
Ok(ConstValue::Scalar(Scalar::from_uint(result, width)))
|
||||||
|
};
|
||||||
|
|
||||||
|
let value = match (lit, &ty.kind()) {
|
||||||
|
(ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => {
|
||||||
|
let s = s.as_str();
|
||||||
|
let allocation = Allocation::from_bytes_byte_aligned_immutable(s.as_bytes());
|
||||||
|
let allocation = tcx.intern_const_alloc(allocation);
|
||||||
|
ConstValue::Slice { data: allocation, start: 0, end: s.len() }
|
||||||
|
}
|
||||||
|
(ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _))
|
||||||
|
if matches!(inner_ty.kind(), ty::Slice(_)) =>
|
||||||
|
{
|
||||||
|
let allocation = Allocation::from_bytes_byte_aligned_immutable(data as &[u8]);
|
||||||
|
let allocation = tcx.intern_const_alloc(allocation);
|
||||||
|
ConstValue::Slice { data: allocation, start: 0, end: data.len() }
|
||||||
|
}
|
||||||
|
(ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => {
|
||||||
|
let id = tcx.allocate_bytes(data);
|
||||||
|
ConstValue::Scalar(Scalar::from_pointer(id.into(), &tcx))
|
||||||
|
}
|
||||||
|
(ast::LitKind::Byte(n), ty::Uint(ty::UintTy::U8)) => {
|
||||||
|
ConstValue::Scalar(Scalar::from_uint(*n, Size::from_bytes(1)))
|
||||||
|
}
|
||||||
|
(ast::LitKind::Int(n, _), ty::Uint(_)) | (ast::LitKind::Int(n, _), ty::Int(_)) => {
|
||||||
|
trunc(if neg { (*n as i128).overflowing_neg().0 as u128 } else { *n })?
|
||||||
|
}
|
||||||
|
(ast::LitKind::Float(n, _), ty::Float(fty)) => {
|
||||||
|
parse_float_into_constval(*n, *fty, neg).ok_or(LitToConstError::Reported)?
|
||||||
|
}
|
||||||
|
(ast::LitKind::Bool(b), ty::Bool) => ConstValue::Scalar(Scalar::from_bool(*b)),
|
||||||
|
(ast::LitKind::Char(c), ty::Char) => ConstValue::Scalar(Scalar::from_char(*c)),
|
||||||
|
(ast::LitKind::Err(_), _) => return Err(LitToConstError::Reported),
|
||||||
|
_ => return Err(LitToConstError::TypeError),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(ConstantKind::Val(value, ty))
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::build;
|
use crate::build;
|
||||||
use crate::build::expr::as_place::PlaceBuilder;
|
use crate::build::expr::as_place::PlaceBuilder;
|
||||||
use crate::build::scope::DropKind;
|
use crate::build::scope::DropKind;
|
||||||
use crate::thir::constant::parse_float;
|
use crate::thir::constant::parse_float_into_scalar;
|
||||||
use crate::thir::pattern::pat_from_hir;
|
use crate::thir::pattern::pat_from_hir;
|
||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
|
@ -14,14 +14,16 @@ use rustc_index::vec::{Idx, IndexVec};
|
||||||
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
|
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
|
||||||
use rustc_middle::hir::place::PlaceBase as HirPlaceBase;
|
use rustc_middle::hir::place::PlaceBase as HirPlaceBase;
|
||||||
use rustc_middle::middle::region;
|
use rustc_middle::middle::region;
|
||||||
use rustc_middle::mir::interpret::Allocation;
|
use rustc_middle::mir::interpret::{
|
||||||
use rustc_middle::mir::interpret::{ConstValue, LitToConstError, LitToConstInput, Scalar};
|
Allocation, ConstValue, LitToConstError, LitToConstInput, Scalar,
|
||||||
|
};
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
use rustc_middle::thir::{BindingMode, Expr, ExprId, LintLevel, LocalVarId, PatKind, Thir};
|
use rustc_middle::thir::{BindingMode, Expr, ExprId, LintLevel, LocalVarId, PatKind, Thir};
|
||||||
use rustc_middle::ty::subst::Subst;
|
use rustc_middle::ty::subst::Subst;
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeckResults};
|
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeckResults};
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
use rustc_span::Symbol;
|
||||||
use rustc_target::abi::Size;
|
use rustc_target::abi::Size;
|
||||||
use rustc_target::spec::abi::Abi;
|
use rustc_target::spec::abi::Abi;
|
||||||
|
|
||||||
|
@ -266,57 +268,6 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(skip(tcx, lit_input))]
|
|
||||||
pub(crate) fn lit_to_mir_constant<'tcx>(
|
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
lit_input: LitToConstInput<'tcx>,
|
|
||||||
) -> Result<ConstantKind<'tcx>, LitToConstError> {
|
|
||||||
let LitToConstInput { lit, ty, neg } = lit_input;
|
|
||||||
let trunc = |n| {
|
|
||||||
let param_ty = ty::ParamEnv::reveal_all().and(ty);
|
|
||||||
let width = tcx.layout_of(param_ty).map_err(|_| LitToConstError::Reported)?.size;
|
|
||||||
trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits());
|
|
||||||
let result = width.truncate(n);
|
|
||||||
trace!("trunc result: {}", result);
|
|
||||||
Ok(ConstValue::Scalar(Scalar::from_uint(result, width)))
|
|
||||||
};
|
|
||||||
|
|
||||||
let value = match (lit, &ty.kind()) {
|
|
||||||
(ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => {
|
|
||||||
let s = s.as_str();
|
|
||||||
let allocation = Allocation::from_bytes_byte_aligned_immutable(s.as_bytes());
|
|
||||||
let allocation = tcx.intern_const_alloc(allocation);
|
|
||||||
ConstValue::Slice { data: allocation, start: 0, end: s.len() }
|
|
||||||
}
|
|
||||||
(ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _))
|
|
||||||
if matches!(inner_ty.kind(), ty::Slice(_)) =>
|
|
||||||
{
|
|
||||||
let allocation = Allocation::from_bytes_byte_aligned_immutable(data as &[u8]);
|
|
||||||
let allocation = tcx.intern_const_alloc(allocation);
|
|
||||||
ConstValue::Slice { data: allocation, start: 0, end: data.len() }
|
|
||||||
}
|
|
||||||
(ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => {
|
|
||||||
let id = tcx.allocate_bytes(data);
|
|
||||||
ConstValue::Scalar(Scalar::from_pointer(id.into(), &tcx))
|
|
||||||
}
|
|
||||||
(ast::LitKind::Byte(n), ty::Uint(ty::UintTy::U8)) => {
|
|
||||||
ConstValue::Scalar(Scalar::from_uint(*n, Size::from_bytes(1)))
|
|
||||||
}
|
|
||||||
(ast::LitKind::Int(n, _), ty::Uint(_)) | (ast::LitKind::Int(n, _), ty::Int(_)) => {
|
|
||||||
trunc(if neg { (*n as i128).overflowing_neg().0 as u128 } else { *n })?
|
|
||||||
}
|
|
||||||
(ast::LitKind::Float(n, _), ty::Float(fty)) => {
|
|
||||||
parse_float(*n, *fty, neg).ok_or(LitToConstError::Reported)?
|
|
||||||
}
|
|
||||||
(ast::LitKind::Bool(b), ty::Bool) => ConstValue::Scalar(Scalar::from_bool(*b)),
|
|
||||||
(ast::LitKind::Char(c), ty::Char) => ConstValue::Scalar(Scalar::from_char(*c)),
|
|
||||||
(ast::LitKind::Err(_), _) => return Err(LitToConstError::Reported),
|
|
||||||
_ => return Err(LitToConstError::TypeError),
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(ConstantKind::Val(value, ty))
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// BuildMir -- walks a crate, looking for fn items and methods to build MIR from
|
// BuildMir -- walks a crate, looking for fn items and methods to build MIR from
|
||||||
|
|
||||||
|
@ -1137,6 +1088,65 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_float_into_constval<'tcx>(
|
||||||
|
num: Symbol,
|
||||||
|
float_ty: ty::FloatTy,
|
||||||
|
neg: bool,
|
||||||
|
) -> Option<ConstValue<'tcx>> {
|
||||||
|
parse_float_into_scalar(num, float_ty, neg).map(ConstValue::Scalar)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[instrument(skip(tcx, lit_input))]
|
||||||
|
pub(crate) fn lit_to_mir_constant<'tcx>(
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
lit_input: LitToConstInput<'tcx>,
|
||||||
|
) -> Result<ConstantKind<'tcx>, LitToConstError> {
|
||||||
|
let LitToConstInput { lit, ty, neg } = lit_input;
|
||||||
|
let trunc = |n| {
|
||||||
|
let param_ty = ty::ParamEnv::reveal_all().and(ty);
|
||||||
|
let width = tcx.layout_of(param_ty).map_err(|_| LitToConstError::Reported)?.size;
|
||||||
|
trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits());
|
||||||
|
let result = width.truncate(n);
|
||||||
|
trace!("trunc result: {}", result);
|
||||||
|
Ok(ConstValue::Scalar(Scalar::from_uint(result, width)))
|
||||||
|
};
|
||||||
|
|
||||||
|
let value = match (lit, &ty.kind()) {
|
||||||
|
(ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => {
|
||||||
|
let s = s.as_str();
|
||||||
|
let allocation = Allocation::from_bytes_byte_aligned_immutable(s.as_bytes());
|
||||||
|
let allocation = tcx.intern_const_alloc(allocation);
|
||||||
|
ConstValue::Slice { data: allocation, start: 0, end: s.len() }
|
||||||
|
}
|
||||||
|
(ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _))
|
||||||
|
if matches!(inner_ty.kind(), ty::Slice(_)) =>
|
||||||
|
{
|
||||||
|
let allocation = Allocation::from_bytes_byte_aligned_immutable(data as &[u8]);
|
||||||
|
let allocation = tcx.intern_const_alloc(allocation);
|
||||||
|
ConstValue::Slice { data: allocation, start: 0, end: data.len() }
|
||||||
|
}
|
||||||
|
(ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => {
|
||||||
|
let id = tcx.allocate_bytes(data);
|
||||||
|
ConstValue::Scalar(Scalar::from_pointer(id.into(), &tcx))
|
||||||
|
}
|
||||||
|
(ast::LitKind::Byte(n), ty::Uint(ty::UintTy::U8)) => {
|
||||||
|
ConstValue::Scalar(Scalar::from_uint(*n, Size::from_bytes(1)))
|
||||||
|
}
|
||||||
|
(ast::LitKind::Int(n, _), ty::Uint(_)) | (ast::LitKind::Int(n, _), ty::Int(_)) => {
|
||||||
|
trunc(if neg { (*n as i128).overflowing_neg().0 as u128 } else { *n })?
|
||||||
|
}
|
||||||
|
(ast::LitKind::Float(n, _), ty::Float(fty)) => {
|
||||||
|
parse_float_into_constval(*n, *fty, neg).ok_or(LitToConstError::Reported)?
|
||||||
|
}
|
||||||
|
(ast::LitKind::Bool(b), ty::Bool) => ConstValue::Scalar(Scalar::from_bool(*b)),
|
||||||
|
(ast::LitKind::Char(c), ty::Char) => ConstValue::Scalar(Scalar::from_char(*c)),
|
||||||
|
(ast::LitKind::Err(_), _) => return Err(LitToConstError::Reported),
|
||||||
|
_ => return Err(LitToConstError::TypeError),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(ConstantKind::Val(value, ty))
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// Builder methods are broken up into modules, depending on what kind
|
// Builder methods are broken up into modules, depending on what kind
|
||||||
// of thing is being lowered. Note that they use the `unpack` macro
|
// of thing is being lowered. Note that they use the `unpack` macro
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
|
use rustc_apfloat::ieee::{Double, Single};
|
||||||
use rustc_apfloat::Float;
|
use rustc_apfloat::Float;
|
||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
use rustc_middle::mir::interpret::{
|
use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput, Scalar};
|
||||||
Allocation, ConstValue, LitToConstError, LitToConstInput, Scalar,
|
use rustc_middle::ty::{self, ParamEnv, ScalarInt, TyCtxt};
|
||||||
};
|
|
||||||
use rustc_middle::ty::{self, ParamEnv, TyCtxt};
|
|
||||||
use rustc_span::symbol::Symbol;
|
use rustc_span::symbol::Symbol;
|
||||||
use rustc_target::abi::Size;
|
|
||||||
|
|
||||||
// FIXME Once valtrees are available, get rid of this function and the query
|
|
||||||
pub(crate) fn lit_to_const<'tcx>(
|
pub(crate) fn lit_to_const<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
lit_input: LitToConstInput<'tcx>,
|
lit_input: LitToConstInput<'tcx>,
|
||||||
|
@ -20,58 +17,59 @@ pub(crate) fn lit_to_const<'tcx>(
|
||||||
trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits());
|
trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits());
|
||||||
let result = width.truncate(n);
|
let result = width.truncate(n);
|
||||||
trace!("trunc result: {}", result);
|
trace!("trunc result: {}", result);
|
||||||
Ok(ConstValue::Scalar(Scalar::from_uint(result, width)))
|
|
||||||
|
Ok(ScalarInt::try_from_uint(result, width)
|
||||||
|
.unwrap_or_else(|| bug!("expected to create ScalarInt from uint {:?}", result)))
|
||||||
};
|
};
|
||||||
|
|
||||||
let lit = match (lit, &ty.kind()) {
|
let valtree = match (lit, &ty.kind()) {
|
||||||
(ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => {
|
(ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => {
|
||||||
let s = s.as_str();
|
let str_bytes = s.as_str().as_bytes();
|
||||||
let allocation = Allocation::from_bytes_byte_aligned_immutable(s.as_bytes());
|
ty::ValTree::from_raw_bytes(tcx, str_bytes)
|
||||||
let allocation = tcx.intern_const_alloc(allocation);
|
|
||||||
ConstValue::Slice { data: allocation, start: 0, end: s.len() }
|
|
||||||
}
|
}
|
||||||
(ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _))
|
(ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _))
|
||||||
if matches!(inner_ty.kind(), ty::Slice(_)) =>
|
if matches!(inner_ty.kind(), ty::Slice(_)) =>
|
||||||
{
|
{
|
||||||
let allocation = Allocation::from_bytes_byte_aligned_immutable(data as &[u8]);
|
let bytes = data as &[u8];
|
||||||
let allocation = tcx.intern_const_alloc(allocation);
|
ty::ValTree::from_raw_bytes(tcx, bytes)
|
||||||
ConstValue::Slice { data: allocation, start: 0, end: data.len() }
|
|
||||||
}
|
}
|
||||||
(ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => {
|
(ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => {
|
||||||
let id = tcx.allocate_bytes(data);
|
let bytes = data as &[u8];
|
||||||
ConstValue::Scalar(Scalar::from_pointer(id.into(), &tcx))
|
ty::ValTree::from_raw_bytes(tcx, bytes)
|
||||||
}
|
}
|
||||||
(ast::LitKind::Byte(n), ty::Uint(ty::UintTy::U8)) => {
|
(ast::LitKind::Byte(n), ty::Uint(ty::UintTy::U8)) => {
|
||||||
ConstValue::Scalar(Scalar::from_uint(*n, Size::from_bytes(1)))
|
ty::ValTree::from_scalar_int((*n).into())
|
||||||
}
|
}
|
||||||
(ast::LitKind::Int(n, _), ty::Uint(_)) | (ast::LitKind::Int(n, _), ty::Int(_)) => {
|
(ast::LitKind::Int(n, _), ty::Uint(_)) | (ast::LitKind::Int(n, _), ty::Int(_)) => {
|
||||||
trunc(if neg { (*n as i128).overflowing_neg().0 as u128 } else { *n })?
|
let scalar_int =
|
||||||
|
trunc(if neg { (*n as i128).overflowing_neg().0 as u128 } else { *n })?;
|
||||||
|
ty::ValTree::from_scalar_int(scalar_int)
|
||||||
}
|
}
|
||||||
(ast::LitKind::Float(n, _), ty::Float(fty)) => {
|
(ast::LitKind::Float(n, _), ty::Float(fty)) => {
|
||||||
parse_float(*n, *fty, neg).ok_or(LitToConstError::Reported)?
|
parse_float_into_valtree(*n, *fty, neg).ok_or(LitToConstError::Reported)?
|
||||||
}
|
}
|
||||||
(ast::LitKind::Bool(b), ty::Bool) => ConstValue::Scalar(Scalar::from_bool(*b)),
|
(ast::LitKind::Bool(b), ty::Bool) => ty::ValTree::from_scalar_int((*b).into()),
|
||||||
(ast::LitKind::Char(c), ty::Char) => ConstValue::Scalar(Scalar::from_char(*c)),
|
(ast::LitKind::Char(c), ty::Char) => ty::ValTree::from_scalar_int((*c).into()),
|
||||||
(ast::LitKind::Err(_), _) => return Err(LitToConstError::Reported),
|
(ast::LitKind::Err(_), _) => return Err(LitToConstError::Reported),
|
||||||
_ => return Err(LitToConstError::TypeError),
|
_ => return Err(LitToConstError::TypeError),
|
||||||
};
|
};
|
||||||
Ok(ty::Const::from_value(tcx, lit, ty))
|
|
||||||
|
Ok(ty::Const::from_value(tcx, valtree, ty))
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME move this to rustc_mir_build::build
|
pub(crate) fn parse_float_into_scalar(
|
||||||
pub(crate) fn parse_float<'tcx>(
|
|
||||||
num: Symbol,
|
num: Symbol,
|
||||||
fty: ty::FloatTy,
|
float_ty: ty::FloatTy,
|
||||||
neg: bool,
|
neg: bool,
|
||||||
) -> Option<ConstValue<'tcx>> {
|
) -> Option<Scalar> {
|
||||||
let num = num.as_str();
|
let num = num.as_str();
|
||||||
use rustc_apfloat::ieee::{Double, Single};
|
match float_ty {
|
||||||
let scalar = match fty {
|
|
||||||
ty::FloatTy::F32 => {
|
ty::FloatTy::F32 => {
|
||||||
let Ok(rust_f) = num.parse::<f32>() else { return None };
|
let Ok(rust_f) = num.parse::<f32>() else { return None };
|
||||||
let mut f = num.parse::<Single>().unwrap_or_else(|e| {
|
let mut f = num.parse::<Single>().unwrap_or_else(|e| {
|
||||||
panic!("apfloat::ieee::Single failed to parse `{}`: {:?}", num, e)
|
panic!("apfloat::ieee::Single failed to parse `{}`: {:?}", num, e)
|
||||||
});
|
});
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
u128::from(rust_f.to_bits()) == f.to_bits(),
|
u128::from(rust_f.to_bits()) == f.to_bits(),
|
||||||
"apfloat::ieee::Single gave different result for `{}`: \
|
"apfloat::ieee::Single gave different result for `{}`: \
|
||||||
|
@ -82,16 +80,19 @@ pub(crate) fn parse_float<'tcx>(
|
||||||
Single::from_bits(rust_f.to_bits().into()),
|
Single::from_bits(rust_f.to_bits().into()),
|
||||||
rust_f.to_bits()
|
rust_f.to_bits()
|
||||||
);
|
);
|
||||||
|
|
||||||
if neg {
|
if neg {
|
||||||
f = -f;
|
f = -f;
|
||||||
}
|
}
|
||||||
Scalar::from_f32(f)
|
|
||||||
|
Some(Scalar::from_f32(f))
|
||||||
}
|
}
|
||||||
ty::FloatTy::F64 => {
|
ty::FloatTy::F64 => {
|
||||||
let Ok(rust_f) = num.parse::<f64>() else { return None };
|
let Ok(rust_f) = num.parse::<f64>() else { return None };
|
||||||
let mut f = num.parse::<Double>().unwrap_or_else(|e| {
|
let mut f = num.parse::<Double>().unwrap_or_else(|e| {
|
||||||
panic!("apfloat::ieee::Double failed to parse `{}`: {:?}", num, e)
|
panic!("apfloat::ieee::Double failed to parse `{}`: {:?}", num, e)
|
||||||
});
|
});
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
u128::from(rust_f.to_bits()) == f.to_bits(),
|
u128::from(rust_f.to_bits()) == f.to_bits(),
|
||||||
"apfloat::ieee::Double gave different result for `{}`: \
|
"apfloat::ieee::Double gave different result for `{}`: \
|
||||||
|
@ -102,12 +103,20 @@ pub(crate) fn parse_float<'tcx>(
|
||||||
Double::from_bits(rust_f.to_bits().into()),
|
Double::from_bits(rust_f.to_bits().into()),
|
||||||
rust_f.to_bits()
|
rust_f.to_bits()
|
||||||
);
|
);
|
||||||
|
|
||||||
if neg {
|
if neg {
|
||||||
f = -f;
|
f = -f;
|
||||||
}
|
}
|
||||||
Scalar::from_f64(f)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Some(ConstValue::Scalar(scalar))
|
Some(Scalar::from_f64(f))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_float_into_valtree<'tcx>(
|
||||||
|
num: Symbol,
|
||||||
|
float_ty: ty::FloatTy,
|
||||||
|
neg: bool,
|
||||||
|
) -> Option<ty::ValTree<'tcx>> {
|
||||||
|
parse_float_into_scalar(num, float_ty, neg).map(|s| ty::ValTree::Leaf(s.try_to_int().unwrap()))
|
||||||
}
|
}
|
||||||
|
|
|
@ -371,6 +371,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
ty::Adt(adt_def, substs) if adt_def.is_enum() => {
|
ty::Adt(adt_def, substs) if adt_def.is_enum() => {
|
||||||
let destructured = tcx.destructure_mir_constant(param_env, cv);
|
let destructured = tcx.destructure_mir_constant(param_env, cv);
|
||||||
|
|
||||||
PatKind::Variant {
|
PatKind::Variant {
|
||||||
adt_def: *adt_def,
|
adt_def: *adt_def,
|
||||||
substs,
|
substs,
|
||||||
|
@ -502,7 +503,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
|
||||||
// deref pattern.
|
// deref pattern.
|
||||||
_ => {
|
_ => {
|
||||||
if !pointee_ty.is_sized(tcx.at(span), param_env) {
|
if !pointee_ty.is_sized(tcx.at(span), param_env) {
|
||||||
// `tcx.deref_const()` below will ICE with an unsized type
|
// `tcx.deref_mirconstant()` below will ICE with an unsized type
|
||||||
// (except slices, which are handled in a separate arm above).
|
// (except slices, which are handled in a separate arm above).
|
||||||
let msg = format!("cannot use unsized non-slice type `{}` in constant patterns", pointee_ty);
|
let msg = format!("cannot use unsized non-slice type `{}` in constant patterns", pointee_ty);
|
||||||
if self.include_lint_checks {
|
if self.include_lint_checks {
|
||||||
|
|
|
@ -185,11 +185,11 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
(Some(PatKind::Constant { value: lo }), None) => {
|
(Some(PatKind::Constant { value: lo }), None) => {
|
||||||
let hi = ty.numeric_max_val(self.tcx)?;
|
let hi = ty.numeric_max_val(self.tcx)?;
|
||||||
Some((*lo, hi.into()))
|
Some((*lo, mir::ConstantKind::from_const(hi, self.tcx)))
|
||||||
}
|
}
|
||||||
(None, Some(PatKind::Constant { value: hi })) => {
|
(None, Some(PatKind::Constant { value: hi })) => {
|
||||||
let lo = ty.numeric_min_val(self.tcx)?;
|
let lo = ty.numeric_min_val(self.tcx)?;
|
||||||
Some((lo.into(), *hi))
|
Some((mir::ConstantKind::from_const(lo, self.tcx), *hi))
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
@ -798,11 +798,12 @@ pub(crate) fn compare_const_vals<'tcx>(
|
||||||
if let ty::Str = ty.kind() && let (
|
if let ty::Str = ty.kind() && let (
|
||||||
Some(a_val @ ConstValue::Slice { .. }),
|
Some(a_val @ ConstValue::Slice { .. }),
|
||||||
Some(b_val @ ConstValue::Slice { .. }),
|
Some(b_val @ ConstValue::Slice { .. }),
|
||||||
) = (a.try_val(), b.try_val())
|
) = (a.try_val(tcx), b.try_val(tcx))
|
||||||
{
|
{
|
||||||
let a_bytes = get_slice_bytes(&tcx, a_val);
|
let a_bytes = get_slice_bytes(&tcx, a_val);
|
||||||
let b_bytes = get_slice_bytes(&tcx, b_val);
|
let b_bytes = get_slice_bytes(&tcx, b_val);
|
||||||
return from_bool(a_bytes == b_bytes);
|
return from_bool(a_bytes == b_bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
fallback()
|
fallback()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1032,7 +1032,7 @@ where
|
||||||
Operand::Constant(Box::new(Constant {
|
Operand::Constant(Box::new(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()).into(),
|
literal: ConstantKind::from_usize(self.tcx(), val.into()),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ impl<'tcx> MirPass<'tcx> for ConstDebugInfo {
|
||||||
sess.opts.debugging_opts.unsound_mir_opts && sess.mir_opt_level() > 0
|
sess.opts.debugging_opts.unsound_mir_opts && sess.mir_opt_level() > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_pass(&self, _: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||||
trace!("running ConstDebugInfo on {:?}", body.source);
|
trace!("running ConstDebugInfo on {:?}", body.source);
|
||||||
|
|
||||||
for (local, constant) in find_optimization_oportunities(body) {
|
for (local, constant) in find_optimization_oportunities(body) {
|
||||||
|
|
|
@ -67,6 +67,7 @@ impl<'tcx> MirPass<'tcx> for ConstProp {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(skip(self, tcx), level = "debug")]
|
||||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||||
// will be evaluated by miri and produce its errors there
|
// will be evaluated by miri and produce its errors there
|
||||||
if body.source.promoted.is_some() {
|
if body.source.promoted.is_some() {
|
||||||
|
@ -687,7 +688,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).into(),
|
literal: ConstantKind::from_scalar(self.tcx, scalar, ty),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -765,20 +766,12 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||||
if let Some(Some(alloc)) = alloc {
|
if let Some(Some(alloc)) = alloc {
|
||||||
// Assign entire constant in a single statement.
|
// Assign entire constant in a single statement.
|
||||||
// We can't use aggregates, as we run after the aggregate-lowering `MirPhase`.
|
// We can't use aggregates, as we run after the aggregate-lowering `MirPhase`.
|
||||||
|
let const_val = ConstValue::ByRef { alloc, offset: Size::ZERO };
|
||||||
|
let literal = ConstantKind::Val(const_val, ty);
|
||||||
*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
|
literal,
|
||||||
.ecx
|
|
||||||
.tcx
|
|
||||||
.mk_const(ty::ConstS {
|
|
||||||
ty,
|
|
||||||
kind: ty::ConstKind::Value(ConstValue::ByRef {
|
|
||||||
alloc,
|
|
||||||
offset: Size::ZERO,
|
|
||||||
}),
|
|
||||||
})
|
|
||||||
.into(),
|
|
||||||
})));
|
})));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -470,7 +470,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).into(),
|
literal: ConstantKind::from_bool(self.tcx, val),
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -991,7 +991,7 @@ fn insert_panic_block<'tcx>(
|
||||||
cond: Operand::Constant(Box::new(Constant {
|
cond: Operand::Constant(Box::new(Constant {
|
||||||
span: body.span,
|
span: body.span,
|
||||||
user_ty: None,
|
user_ty: None,
|
||||||
literal: ty::Const::from_bool(tcx, false).into(),
|
literal: ConstantKind::from_bool(tcx, false),
|
||||||
})),
|
})),
|
||||||
expected: true,
|
expected: true,
|
||||||
msg: message,
|
msg: message,
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
use crate::MirPass;
|
use crate::MirPass;
|
||||||
use rustc_hir::Mutability;
|
use rustc_hir::Mutability;
|
||||||
use rustc_middle::mir::{
|
use rustc_middle::mir::{
|
||||||
BinOp, Body, Constant, LocalDecls, Operand, Place, ProjectionElem, Rvalue, SourceInfo,
|
BinOp, Body, Constant, ConstantKind, LocalDecls, Operand, Place, ProjectionElem, Rvalue,
|
||||||
Statement, StatementKind, Terminator, TerminatorKind, UnOp,
|
SourceInfo, Statement, StatementKind, Terminator, TerminatorKind, UnOp,
|
||||||
};
|
};
|
||||||
use rustc_middle::ty::{self, TyCtxt};
|
use rustc_middle::ty::{self, TyCtxt};
|
||||||
|
|
||||||
|
@ -129,8 +129,8 @@ impl<'tcx> InstCombineContext<'tcx, '_> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let constant =
|
let literal = ConstantKind::from_const(len, self.tcx);
|
||||||
Constant { span: source_info.span, literal: len.into(), user_ty: None };
|
let constant = Constant { span: source_info.span, literal, user_ty: None };
|
||||||
*rvalue = Rvalue::Use(Operand::Constant(Box::new(constant)));
|
*rvalue = Rvalue::Use(Operand::Constant(Box::new(constant)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -531,8 +531,10 @@ fn inner_optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> Body<'_> {
|
||||||
None => {}
|
None => {}
|
||||||
Some(other) => panic!("do not use `optimized_mir` for constants: {:?}", other),
|
Some(other) => panic!("do not use `optimized_mir` for constants: {:?}", other),
|
||||||
}
|
}
|
||||||
|
debug!("about to call mir_drops_elaborated...");
|
||||||
let mut body =
|
let mut body =
|
||||||
tcx.mir_drops_elaborated_and_const_checked(ty::WithOptConstParam::unknown(did)).steal();
|
tcx.mir_drops_elaborated_and_const_checked(ty::WithOptConstParam::unknown(did)).steal();
|
||||||
|
debug!("body: {:#?}", body);
|
||||||
run_optimization_passes(tcx, &mut body);
|
run_optimization_passes(tcx, &mut body);
|
||||||
|
|
||||||
debug_assert!(!body.has_free_regions(), "Free regions in optimized MIR");
|
debug_assert!(!body.has_free_regions(), "Free regions in optimized MIR");
|
||||||
|
|
|
@ -34,7 +34,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
|
||||||
Rvalue::Use(Operand::Constant(Box::new(Constant {
|
Rvalue::Use(Operand::Constant(Box::new(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).into(),
|
literal: ConstantKind::zero_sized(tcx.types.unit),
|
||||||
}))),
|
}))),
|
||||||
))),
|
))),
|
||||||
});
|
});
|
||||||
|
|
|
@ -15,7 +15,7 @@ impl<'tcx> MirPass<'tcx> for RemoveNoopLandingPads {
|
||||||
sess.panic_strategy() != PanicStrategy::Abort
|
sess.panic_strategy() != PanicStrategy::Abort
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_pass(&self, _: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||||
debug!("remove_noop_landing_pads({:?})", body);
|
debug!("remove_noop_landing_pads({:?})", body);
|
||||||
self.remove_nop_landing_pads(body)
|
self.remove_nop_landing_pads(body)
|
||||||
}
|
}
|
||||||
|
@ -81,6 +81,8 @@ impl RemoveNoopLandingPads {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_nop_landing_pads(&self, body: &mut Body<'_>) {
|
fn remove_nop_landing_pads(&self, body: &mut Body<'_>) {
|
||||||
|
debug!("body: {:#?}", body);
|
||||||
|
|
||||||
// make sure there's a single resume block
|
// make sure there's a single resume block
|
||||||
let resume_block = {
|
let resume_block = {
|
||||||
let patch = MirPatch::new(body);
|
let patch = MirPatch::new(body);
|
||||||
|
|
|
@ -430,7 +430,7 @@ impl<'tcx> CloneShimBuilder<'tcx> {
|
||||||
let func = Operand::Constant(Box::new(Constant {
|
let func = Operand::Constant(Box::new(Constant {
|
||||||
span: self.span,
|
span: self.span,
|
||||||
user_ty: None,
|
user_ty: None,
|
||||||
literal: ty::Const::zero_sized(tcx, func_ty).into(),
|
literal: ConstantKind::zero_sized(func_ty),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let ref_loc = self.make_place(
|
let ref_loc = self.make_place(
|
||||||
|
@ -630,7 +630,7 @@ fn build_call_shim<'tcx>(
|
||||||
Operand::Constant(Box::new(Constant {
|
Operand::Constant(Box::new(Constant {
|
||||||
span,
|
span,
|
||||||
user_ty: None,
|
user_ty: None,
|
||||||
literal: ty::Const::zero_sized(tcx, ty).into(),
|
literal: ConstantKind::zero_sized(ty),
|
||||||
})),
|
})),
|
||||||
rcvr.into_iter().collect::<Vec<_>>(),
|
rcvr.into_iter().collect::<Vec<_>>(),
|
||||||
)
|
)
|
||||||
|
|
|
@ -323,6 +323,7 @@ impl<'tcx> InliningMap<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(skip(tcx, mode), level = "debug")]
|
||||||
pub fn collect_crate_mono_items(
|
pub fn collect_crate_mono_items(
|
||||||
tcx: TyCtxt<'_>,
|
tcx: TyCtxt<'_>,
|
||||||
mode: MonoItemCollectionMode,
|
mode: MonoItemCollectionMode,
|
||||||
|
@ -362,6 +363,7 @@ pub fn collect_crate_mono_items(
|
||||||
|
|
||||||
// Find all non-generic items by walking the HIR. These items serve as roots to
|
// Find all non-generic items by walking the HIR. These items serve as roots to
|
||||||
// start monomorphizing from.
|
// start monomorphizing from.
|
||||||
|
#[instrument(skip(tcx, mode), level = "debug")]
|
||||||
fn collect_roots(tcx: TyCtxt<'_>, mode: MonoItemCollectionMode) -> Vec<MonoItem<'_>> {
|
fn collect_roots(tcx: TyCtxt<'_>, mode: MonoItemCollectionMode) -> Vec<MonoItem<'_>> {
|
||||||
debug!("collecting roots");
|
debug!("collecting roots");
|
||||||
let mut roots = MonoItems { compute_inlining: false, tcx, items: Vec::new() };
|
let mut roots = MonoItems { compute_inlining: false, tcx, items: Vec::new() };
|
||||||
|
@ -400,6 +402,7 @@ fn collect_roots(tcx: TyCtxt<'_>, mode: MonoItemCollectionMode) -> Vec<MonoItem<
|
||||||
|
|
||||||
/// Collect all monomorphized items reachable from `starting_point`, and emit a note diagnostic if a
|
/// Collect all monomorphized items reachable from `starting_point`, and emit a note diagnostic if a
|
||||||
/// post-monorphization error is encountered during a collection step.
|
/// post-monorphization error is encountered during a collection step.
|
||||||
|
#[instrument(skip(tcx, visited, recursion_depths, recursion_limit, inlining_map), level = "debug")]
|
||||||
fn collect_items_rec<'tcx>(
|
fn collect_items_rec<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
starting_point: Spanned<MonoItem<'tcx>>,
|
starting_point: Spanned<MonoItem<'tcx>>,
|
||||||
|
@ -752,13 +755,15 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
|
||||||
/// This does not walk the constant, as it has been handled entirely here and trying
|
/// This does not walk the constant, as it has been handled entirely here and trying
|
||||||
/// to walk it would attempt to evaluate the `ty::Const` inside, which doesn't necessarily
|
/// to walk it would attempt to evaluate the `ty::Const` inside, which doesn't necessarily
|
||||||
/// work, as some constants cannot be represented in the type system.
|
/// work, as some constants cannot be represented in the type system.
|
||||||
|
#[instrument(skip(self), level = "debug")]
|
||||||
fn visit_constant(&mut self, constant: &mir::Constant<'tcx>, location: Location) {
|
fn visit_constant(&mut self, constant: &mir::Constant<'tcx>, location: Location) {
|
||||||
let literal = self.monomorphize(constant.literal);
|
let literal = self.monomorphize(constant.literal);
|
||||||
let val = match literal {
|
let val = match literal {
|
||||||
mir::ConstantKind::Val(val, _) => val,
|
mir::ConstantKind::Val(val, _) => val,
|
||||||
mir::ConstantKind::Ty(ct) => match ct.kind() {
|
mir::ConstantKind::Ty(ct) => match ct.kind() {
|
||||||
ty::ConstKind::Value(val) => val,
|
ty::ConstKind::Value(val) => self.tcx.valtree_to_const_val((ct.ty(), val)),
|
||||||
ty::ConstKind::Unevaluated(ct) => {
|
ty::ConstKind::Unevaluated(ct) => {
|
||||||
|
debug!(?ct);
|
||||||
let param_env = ty::ParamEnv::reveal_all();
|
let param_env = ty::ParamEnv::reveal_all();
|
||||||
match self.tcx.const_eval_resolve(param_env, ct, None) {
|
match self.tcx.const_eval_resolve(param_env, ct, None) {
|
||||||
// The `monomorphize` call should have evaluated that constant already.
|
// The `monomorphize` call should have evaluated that constant already.
|
||||||
|
@ -778,6 +783,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
|
||||||
self.visit_ty(literal.ty(), TyContext::Location(location));
|
self.visit_ty(literal.ty(), TyContext::Location(location));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(skip(self), level = "debug")]
|
||||||
fn visit_const(&mut self, constant: ty::Const<'tcx>, location: Location) {
|
fn visit_const(&mut self, constant: ty::Const<'tcx>, location: Location) {
|
||||||
debug!("visiting const {:?} @ {:?}", constant, location);
|
debug!("visiting const {:?} @ {:?}", constant, location);
|
||||||
|
|
||||||
|
@ -785,7 +791,10 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
|
||||||
let param_env = ty::ParamEnv::reveal_all();
|
let param_env = ty::ParamEnv::reveal_all();
|
||||||
|
|
||||||
match substituted_constant.kind() {
|
match substituted_constant.kind() {
|
||||||
ty::ConstKind::Value(val) => collect_const_value(self.tcx, val, self.output),
|
ty::ConstKind::Value(val) => {
|
||||||
|
let const_val = self.tcx.valtree_to_const_val((constant.ty(), val));
|
||||||
|
collect_const_value(self.tcx, const_val, self.output)
|
||||||
|
}
|
||||||
ty::ConstKind::Unevaluated(unevaluated) => {
|
ty::ConstKind::Unevaluated(unevaluated) => {
|
||||||
match self.tcx.const_eval_resolve(param_env, unevaluated, None) {
|
match self.tcx.const_eval_resolve(param_env, unevaluated, None) {
|
||||||
// The `monomorphize` call should have evaluated that constant already.
|
// The `monomorphize` call should have evaluated that constant already.
|
||||||
|
@ -1120,6 +1129,7 @@ fn find_vtable_types_for_unsizing<'tcx>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(skip(tcx), level = "debug")]
|
||||||
fn create_fn_mono_item<'tcx>(
|
fn create_fn_mono_item<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
instance: Instance<'tcx>,
|
instance: Instance<'tcx>,
|
||||||
|
@ -1133,7 +1143,10 @@ fn create_fn_mono_item<'tcx>(
|
||||||
crate::util::dump_closure_profile(tcx, instance);
|
crate::util::dump_closure_profile(tcx, instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
respan(source, MonoItem::Fn(instance.polymorphize(tcx)))
|
let respanned = respan(source, MonoItem::Fn(instance.polymorphize(tcx)));
|
||||||
|
debug!(?respanned);
|
||||||
|
|
||||||
|
respanned
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a `MonoItem` for each method that is referenced by the vtable for
|
/// Creates a `MonoItem` for each method that is referenced by the vtable for
|
||||||
|
@ -1275,6 +1288,7 @@ impl<'v> RootCollector<'_, 'v> {
|
||||||
|
|
||||||
/// If `def_id` represents a root, pushes it onto the list of
|
/// If `def_id` represents a root, pushes it onto the list of
|
||||||
/// outputs. (Note that all roots must be monomorphic.)
|
/// outputs. (Note that all roots must be monomorphic.)
|
||||||
|
#[instrument(skip(self), level = "debug")]
|
||||||
fn push_if_root(&mut self, def_id: LocalDefId) {
|
fn push_if_root(&mut self, def_id: LocalDefId) {
|
||||||
if self.is_root(def_id) {
|
if self.is_root(def_id) {
|
||||||
debug!("RootCollector::push_if_root: found root def_id={:?}", def_id);
|
debug!("RootCollector::push_if_root: found root def_id={:?}", def_id);
|
||||||
|
@ -1415,17 +1429,17 @@ fn collect_miri<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut MonoIte
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Scans the MIR in order to find function calls, closures, and drop-glue.
|
/// Scans the MIR in order to find function calls, closures, and drop-glue.
|
||||||
|
#[instrument(skip(tcx, output), level = "debug")]
|
||||||
fn collect_neighbours<'tcx>(
|
fn collect_neighbours<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
instance: Instance<'tcx>,
|
instance: Instance<'tcx>,
|
||||||
output: &mut MonoItems<'tcx>,
|
output: &mut MonoItems<'tcx>,
|
||||||
) {
|
) {
|
||||||
debug!("collect_neighbours: {:?}", instance.def_id());
|
|
||||||
let body = tcx.instance_mir(instance.def);
|
let body = tcx.instance_mir(instance.def);
|
||||||
|
|
||||||
MirNeighborCollector { tcx, body: &body, output, instance }.visit_body(&body);
|
MirNeighborCollector { tcx, body: &body, output, instance }.visit_body(&body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(skip(tcx, output), level = "debug")]
|
||||||
fn collect_const_value<'tcx>(
|
fn collect_const_value<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
value: ConstValue<'tcx>,
|
value: ConstValue<'tcx>,
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||||
use rustc_hir::def_id::CrateNum;
|
use rustc_hir::def_id::CrateNum;
|
||||||
use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
|
use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
|
||||||
use rustc_middle::mir::interpret::{ConstValue, Scalar};
|
|
||||||
use rustc_middle::ty::print::{PrettyPrinter, Print, Printer};
|
use rustc_middle::ty::print::{PrettyPrinter, Print, Printer};
|
||||||
use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
|
use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
|
||||||
use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable};
|
use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable};
|
||||||
|
@ -30,6 +29,7 @@ pub(super) fn mangle<'tcx>(
|
||||||
match key.disambiguated_data.data {
|
match key.disambiguated_data.data {
|
||||||
DefPathData::TypeNs(_) | DefPathData::ValueNs(_) => {
|
DefPathData::TypeNs(_) | DefPathData::ValueNs(_) => {
|
||||||
instance_ty = tcx.type_of(ty_def_id);
|
instance_ty = tcx.type_of(ty_def_id);
|
||||||
|
debug!(?instance_ty);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -261,10 +261,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> {
|
||||||
fn print_const(self, ct: ty::Const<'tcx>) -> Result<Self::Const, Self::Error> {
|
fn print_const(self, ct: ty::Const<'tcx>) -> Result<Self::Const, Self::Error> {
|
||||||
// only print integers
|
// only print integers
|
||||||
match (ct.kind(), ct.ty().kind()) {
|
match (ct.kind(), ct.ty().kind()) {
|
||||||
(
|
(ty::ConstKind::Value(ty::ValTree::Leaf(scalar)), ty::Int(_) | ty::Uint(_)) => {
|
||||||
ty::ConstKind::Value(ConstValue::Scalar(Scalar::Int(scalar))),
|
|
||||||
ty::Int(_) | ty::Uint(_),
|
|
||||||
) => {
|
|
||||||
// The `pretty_print_const` formatting depends on -Zverbose
|
// The `pretty_print_const` formatting depends on -Zverbose
|
||||||
// flag, so we cannot reuse it here.
|
// flag, so we cannot reuse it here.
|
||||||
let signed = matches!(ct.ty().kind(), ty::Int(_));
|
let signed = matches!(ct.ty().kind(), ty::Int(_));
|
||||||
|
|
|
@ -5,7 +5,6 @@ use rustc_hir as hir;
|
||||||
use rustc_hir::def::CtorKind;
|
use rustc_hir::def::CtorKind;
|
||||||
use rustc_hir::def_id::{CrateNum, DefId};
|
use rustc_hir::def_id::{CrateNum, DefId};
|
||||||
use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
|
use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
|
||||||
use rustc_middle::mir::interpret::ConstValue;
|
|
||||||
use rustc_middle::ty::layout::IntegerExt;
|
use rustc_middle::ty::layout::IntegerExt;
|
||||||
use rustc_middle::ty::print::{Print, Printer};
|
use rustc_middle::ty::print::{Print, Printer};
|
||||||
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst};
|
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst};
|
||||||
|
@ -604,16 +603,18 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
|
||||||
if let Some(&i) = self.consts.get(&ct) {
|
if let Some(&i) = self.consts.get(&ct) {
|
||||||
return self.print_backref(i);
|
return self.print_backref(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
let start = self.out.len();
|
let start = self.out.len();
|
||||||
|
let ty = ct.ty();
|
||||||
|
|
||||||
match ct.ty().kind() {
|
match ty.kind() {
|
||||||
ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Char => {
|
ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Char => {
|
||||||
self = ct.ty().print(self)?;
|
self = ty.print(self)?;
|
||||||
|
|
||||||
let mut bits = ct.eval_bits(self.tcx, ty::ParamEnv::reveal_all(), ct.ty());
|
let mut bits = ct.eval_bits(self.tcx, ty::ParamEnv::reveal_all(), ty);
|
||||||
|
|
||||||
// Negative integer values are mangled using `n` as a "sign prefix".
|
// Negative integer values are mangled using `n` as a "sign prefix".
|
||||||
if let ty::Int(ity) = ct.ty().kind() {
|
if let ty::Int(ity) = ty.kind() {
|
||||||
let val =
|
let val =
|
||||||
Integer::from_int_ty(&self.tcx, *ity).size().sign_extend(bits) as i128;
|
Integer::from_int_ty(&self.tcx, *ity).size().sign_extend(bits) as i128;
|
||||||
if val < 0 {
|
if val < 0 {
|
||||||
|
@ -626,26 +627,34 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// HACK(eddyb) because `ty::Const` only supports sized values (for now),
|
// HACK(eddyb) because `ty::Const` only supports sized values (for now),
|
||||||
// we can't use `deref_const` + supporting `str`, we have to specially
|
// we can't use dereference the const + supporting `str`, we have to specially
|
||||||
// handle `&str` and include both `&` ("R") and `str` ("e") prefixes.
|
// handle `&str` and include both `&` ("R") and `str` ("e") prefixes.
|
||||||
ty::Ref(_, ty, hir::Mutability::Not) if *ty == self.tcx.types.str_ => {
|
ty::Ref(_, inner_ty, mutbl) => {
|
||||||
self.push("R");
|
self.push(match mutbl {
|
||||||
|
hir::Mutability::Not => "R",
|
||||||
|
hir::Mutability::Mut => "Q",
|
||||||
|
});
|
||||||
|
|
||||||
|
match inner_ty.kind() {
|
||||||
|
ty::Str if *mutbl == hir::Mutability::Not => {
|
||||||
match ct.kind() {
|
match ct.kind() {
|
||||||
ty::ConstKind::Value(ConstValue::Slice { data, start, end }) => {
|
ty::ConstKind::Value(valtree) => {
|
||||||
// NOTE(eddyb) the following comment was kept from `ty::print::pretty`:
|
let slice =
|
||||||
// The `inspect` here is okay since we checked the bounds, and there are no
|
valtree.try_to_raw_bytes(self.tcx(), ty).unwrap_or_else(|| {
|
||||||
// relocations (we have an active `str` reference here). We don't use this
|
bug!(
|
||||||
// result to affect interpreter execution.
|
"expected to get raw bytes from valtree {:?} for type {:}",
|
||||||
let slice = data
|
valtree, ty
|
||||||
.inner()
|
)
|
||||||
.inspect_with_uninit_and_ptr_outside_interpreter(start..end);
|
});
|
||||||
let s = std::str::from_utf8(slice).expect("non utf8 str from miri");
|
let s = std::str::from_utf8(slice).expect("non utf8 str from miri");
|
||||||
|
|
||||||
self.push("e");
|
self.push("e");
|
||||||
|
|
||||||
// FIXME(eddyb) use a specialized hex-encoding loop.
|
// FIXME(eddyb) use a specialized hex-encoding loop.
|
||||||
for byte in s.bytes() {
|
for byte in s.bytes() {
|
||||||
let _ = write!(self.out, "{:02x}", byte);
|
let _ = write!(self.out, "{:02x}", byte);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.push("_");
|
self.push("_");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -654,17 +663,21 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_ => {
|
||||||
ty::Ref(_, _, mutbl) => {
|
let pointee_ty = ct
|
||||||
self.push(match mutbl {
|
.ty()
|
||||||
hir::Mutability::Not => "R",
|
.builtin_deref(true)
|
||||||
hir::Mutability::Mut => "Q",
|
.expect("tried to dereference on non-ptr type")
|
||||||
});
|
.ty;
|
||||||
self = self.tcx.deref_const(ty::ParamEnv::reveal_all().and(ct)).print(self)?;
|
let dereferenced_const =
|
||||||
|
self.tcx.mk_const(ty::ConstS { val: ct.val(), ty: pointee_ty });
|
||||||
|
self = dereferenced_const.print(self)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::Array(..) | ty::Tuple(..) | ty::Adt(..) => {
|
ty::Array(..) | ty::Tuple(..) | ty::Adt(..) | ty::Slice(_) => {
|
||||||
let contents = self.tcx.destructure_const(ty::ParamEnv::reveal_all().and(ct));
|
let contents = self.tcx.destructure_const(ct);
|
||||||
let fields = contents.fields.iter().copied();
|
let fields = contents.fields.iter().copied();
|
||||||
|
|
||||||
let print_field_list = |mut this: Self| {
|
let print_field_list = |mut this: Self| {
|
||||||
|
@ -676,7 +689,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
|
||||||
};
|
};
|
||||||
|
|
||||||
match *ct.ty().kind() {
|
match *ct.ty().kind() {
|
||||||
ty::Array(..) => {
|
ty::Array(..) | ty::Slice(_) => {
|
||||||
self.push("A");
|
self.push("A");
|
||||||
self = print_field_list(self)?;
|
self = print_field_list(self)?;
|
||||||
}
|
}
|
||||||
|
@ -723,7 +736,6 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
bug!("symbol_names: unsupported constant of type `{}` ({:?})", ct.ty(), ct);
|
bug!("symbol_names: unsupported constant of type `{}` ({:?})", ct.ty(), ct);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ use super::*;
|
||||||
use crate::infer::region_constraints::{Constraint, RegionConstraintData};
|
use crate::infer::region_constraints::{Constraint, RegionConstraintData};
|
||||||
use crate::infer::InferCtxt;
|
use crate::infer::InferCtxt;
|
||||||
use crate::traits::project::ProjectAndUnifyResult;
|
use crate::traits::project::ProjectAndUnifyResult;
|
||||||
|
use rustc_middle::mir::interpret::ErrorHandled;
|
||||||
use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
|
use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
|
||||||
use rustc_middle::ty::{Region, RegionVid, Term};
|
use rustc_middle::ty::{Region, RegionVid, Term};
|
||||||
|
|
||||||
|
@ -834,7 +835,16 @@ impl<'tcx> AutoTraitFinder<'tcx> {
|
||||||
unevaluated,
|
unevaluated,
|
||||||
Some(obligation.cause.span),
|
Some(obligation.cause.span),
|
||||||
) {
|
) {
|
||||||
Ok(val) => Ok(ty::Const::from_value(select.tcx(), val, c.ty())),
|
Ok(Some(valtree)) => {
|
||||||
|
Ok(ty::Const::from_value(select.tcx(), valtree, c.ty()))
|
||||||
|
}
|
||||||
|
Ok(None) => {
|
||||||
|
let tcx = self.tcx;
|
||||||
|
let def_id = unevaluated.def.did;
|
||||||
|
let reported = tcx.sess.struct_span_err(tcx.def_span(def_id), &format!("unable to construct a constant value for the unevaluated constant {:?}", unevaluated)).emit();
|
||||||
|
|
||||||
|
Err(ErrorHandled::Reported(reported))
|
||||||
|
}
|
||||||
Err(err) => Err(err),
|
Err(err) => Err(err),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -13,9 +13,7 @@ use rustc_hir::def::DefKind;
|
||||||
use rustc_index::vec::IndexVec;
|
use rustc_index::vec::IndexVec;
|
||||||
use rustc_infer::infer::InferCtxt;
|
use rustc_infer::infer::InferCtxt;
|
||||||
use rustc_middle::mir;
|
use rustc_middle::mir;
|
||||||
use rustc_middle::mir::interpret::{
|
use rustc_middle::mir::interpret::{ErrorHandled, LitToConstError, LitToConstInput};
|
||||||
ConstValue, ErrorHandled, LitToConstError, LitToConstInput, Scalar,
|
|
||||||
};
|
|
||||||
use rustc_middle::thir;
|
use rustc_middle::thir;
|
||||||
use rustc_middle::thir::abstract_const::{self, Node, NodeId, NotConstEvaluatable};
|
use rustc_middle::thir::abstract_const::{self, Node, NodeId, NotConstEvaluatable};
|
||||||
use rustc_middle::ty::subst::{Subst, SubstsRef};
|
use rustc_middle::ty::subst::{Subst, SubstsRef};
|
||||||
|
@ -449,9 +447,8 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
|
||||||
self.nodes.push(Node::Leaf(constant))
|
self.nodes.push(Node::Leaf(constant))
|
||||||
}
|
}
|
||||||
&ExprKind::NonHirLiteral { lit , user_ty: _} => {
|
&ExprKind::NonHirLiteral { lit , user_ty: _} => {
|
||||||
// FIXME Construct a Valtree from this ScalarInt when introducing Valtrees
|
let val = ty::ValTree::from_scalar_int(lit);
|
||||||
let const_value = ConstValue::Scalar(Scalar::Int(lit));
|
self.nodes.push(Node::Leaf(ty::Const::from_value(self.tcx, val, node.ty)))
|
||||||
self.nodes.push(Node::Leaf(ty::Const::from_value(self.tcx, const_value, node.ty)))
|
|
||||||
}
|
}
|
||||||
&ExprKind::NamedConst { def_id, substs, user_ty: _ } => {
|
&ExprKind::NamedConst { def_id, substs, user_ty: _ } => {
|
||||||
let uneval = ty::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs);
|
let uneval = ty::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs);
|
||||||
|
|
|
@ -407,7 +407,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
|
||||||
let pred =
|
let pred =
|
||||||
ty::Binder::dummy(infcx.replace_bound_vars_with_placeholders(binder));
|
ty::Binder::dummy(infcx.replace_bound_vars_with_placeholders(binder));
|
||||||
ProcessResult::Changed(mk_pending(vec![
|
ProcessResult::Changed(mk_pending(vec![
|
||||||
obligation.with(pred.to_predicate(self.selcx.tcx())),
|
obligation.with(pred.to_predicate(self.selcx.tcx()))
|
||||||
]))
|
]))
|
||||||
}
|
}
|
||||||
ty::PredicateKind::TypeWellFormedFromEnv(..) => {
|
ty::PredicateKind::TypeWellFormedFromEnv(..) => {
|
||||||
|
@ -594,22 +594,24 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
|
||||||
|
|
||||||
let mut evaluate = |c: Const<'tcx>| {
|
let mut evaluate = |c: Const<'tcx>| {
|
||||||
if let ty::ConstKind::Unevaluated(unevaluated) = c.kind() {
|
if let ty::ConstKind::Unevaluated(unevaluated) = c.kind() {
|
||||||
match self.selcx.infcx().const_eval_resolve(
|
match self.selcx.infcx().try_const_eval_resolve(
|
||||||
obligation.param_env,
|
obligation.param_env,
|
||||||
unevaluated,
|
unevaluated,
|
||||||
|
c.ty(),
|
||||||
Some(obligation.cause.span),
|
Some(obligation.cause.span),
|
||||||
) {
|
) {
|
||||||
Ok(val) => Ok(Const::from_value(self.selcx.tcx(), val, c.ty())),
|
Ok(val) => Ok(val),
|
||||||
Err(ErrorHandled::TooGeneric) => {
|
Err(e) => match e {
|
||||||
|
ErrorHandled::TooGeneric => {
|
||||||
stalled_on.extend(
|
stalled_on.extend(
|
||||||
unevaluated
|
unevaluated.substs.iter().filter_map(
|
||||||
.substs
|
TyOrConstInferVar::maybe_from_generic_arg,
|
||||||
.iter()
|
),
|
||||||
.filter_map(TyOrConstInferVar::maybe_from_generic_arg),
|
|
||||||
);
|
);
|
||||||
Err(ErrorHandled::TooGeneric)
|
Err(ErrorHandled::TooGeneric)
|
||||||
}
|
}
|
||||||
Err(err) => Err(err),
|
_ => Err(e),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Ok(c)
|
Ok(c)
|
||||||
|
|
|
@ -618,11 +618,14 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(skip(self), level = "debug")]
|
||||||
fn fold_const(&mut self, constant: ty::Const<'tcx>) -> ty::Const<'tcx> {
|
fn fold_const(&mut self, constant: ty::Const<'tcx>) -> ty::Const<'tcx> {
|
||||||
if self.selcx.tcx().lazy_normalization() || !self.eager_inference_replacement {
|
if self.selcx.tcx().lazy_normalization() || !self.eager_inference_replacement {
|
||||||
constant
|
constant
|
||||||
} else {
|
} else {
|
||||||
let constant = constant.super_fold_with(self);
|
let constant = constant.super_fold_with(self);
|
||||||
|
debug!(?constant);
|
||||||
|
debug!("self.param_env: {:?}", self.param_env);
|
||||||
constant.eval(self.selcx.tcx(), self.param_env)
|
constant.eval(self.selcx.tcx(), self.param_env)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,7 +100,7 @@ impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Visitor to find the maximum escaping bound var
|
// Visitor to find the maximum escaping bound var
|
||||||
struct MaxEscapingBoundVarVisitor {
|
struct MaxEscapingBoundVarVisitor {
|
||||||
// The index which would count as escaping
|
// The index which would count as escaping
|
||||||
outer_index: ty::DebruijnIndex,
|
outer_index: ty::DebruijnIndex,
|
||||||
|
@ -336,12 +336,15 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
|
||||||
) -> Result<mir::ConstantKind<'tcx>, Self::Error> {
|
) -> Result<mir::ConstantKind<'tcx>, Self::Error> {
|
||||||
Ok(match constant {
|
Ok(match constant {
|
||||||
mir::ConstantKind::Ty(c) => {
|
mir::ConstantKind::Ty(c) => {
|
||||||
let const_folded = c.try_fold_with(self)?;
|
let const_folded = c.try_super_fold_with(self)?;
|
||||||
match const_folded.kind() {
|
match const_folded.kind() {
|
||||||
ty::ConstKind::Value(cv) => {
|
ty::ConstKind::Value(valtree) => {
|
||||||
// FIXME With Valtrees we need to convert `cv: ValTree`
|
let tcx = self.infcx.tcx;
|
||||||
// to a `ConstValue` here.
|
let ty = const_folded.ty();
|
||||||
mir::ConstantKind::Val(cv, const_folded.ty())
|
let const_val = tcx.valtree_to_const_val((ty, valtree));
|
||||||
|
debug!(?ty, ?valtree, ?const_val);
|
||||||
|
|
||||||
|
mir::ConstantKind::Val(const_val, ty)
|
||||||
}
|
}
|
||||||
_ => mir::ConstantKind::Ty(const_folded),
|
_ => mir::ConstantKind::Ty(const_folded),
|
||||||
}
|
}
|
||||||
|
|
|
@ -636,13 +636,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
|
|
||||||
let evaluate = |c: ty::Const<'tcx>| {
|
let evaluate = |c: ty::Const<'tcx>| {
|
||||||
if let ty::ConstKind::Unevaluated(unevaluated) = c.kind() {
|
if let ty::ConstKind::Unevaluated(unevaluated) = c.kind() {
|
||||||
self.infcx
|
match self.infcx.try_const_eval_resolve(
|
||||||
.const_eval_resolve(
|
|
||||||
obligation.param_env,
|
obligation.param_env,
|
||||||
unevaluated,
|
unevaluated,
|
||||||
|
c.ty(),
|
||||||
Some(obligation.cause.span),
|
Some(obligation.cause.span),
|
||||||
)
|
) {
|
||||||
.map(|val| ty::Const::from_value(self.tcx(), val, c.ty()))
|
Ok(val) => Ok(val),
|
||||||
|
Err(e) => Err(e),
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Ok(c)
|
Ok(c)
|
||||||
}
|
}
|
||||||
|
@ -2576,7 +2578,11 @@ impl<'o, 'tcx> TraitObligationStackList<'o, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn depth(&self) -> usize {
|
fn depth(&self) -> usize {
|
||||||
if let Some(head) = self.head { head.depth } else { 0 }
|
if let Some(head) = self.head {
|
||||||
|
head.depth
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,6 @@ pub(crate) fn provide(p: &mut Providers) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(tcx))]
|
|
||||||
fn try_normalize_after_erasing_regions<'tcx, T: TypeFoldable<'tcx> + PartialEq + Copy>(
|
fn try_normalize_after_erasing_regions<'tcx, T: TypeFoldable<'tcx> + PartialEq + Copy>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
goal: ParamEnvAnd<'tcx, T>,
|
goal: ParamEnvAnd<'tcx, T>,
|
||||||
|
|
|
@ -112,7 +112,6 @@ impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(tcx))]
|
|
||||||
fn resolve_instance<'tcx>(
|
fn resolve_instance<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
key: ty::ParamEnvAnd<'tcx, (DefId, SubstsRef<'tcx>)>,
|
key: ty::ParamEnvAnd<'tcx, (DefId, SubstsRef<'tcx>)>,
|
||||||
|
@ -141,7 +140,6 @@ fn resolve_instance_of_const_arg<'tcx>(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(tcx))]
|
|
||||||
fn inner_resolve_instance<'tcx>(
|
fn inner_resolve_instance<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
key: ty::ParamEnvAnd<'tcx, (ty::WithOptConstParam<DefId>, SubstsRef<'tcx>)>,
|
key: ty::ParamEnvAnd<'tcx, (ty::WithOptConstParam<DefId>, SubstsRef<'tcx>)>,
|
||||||
|
|
|
@ -15,7 +15,6 @@ use rustc_data_structures::thin_vec::ThinVec;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::{DefKind, Res};
|
use rustc_hir::def::{DefKind, Res};
|
||||||
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
|
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
|
||||||
use rustc_middle::mir::interpret::ConstValue;
|
|
||||||
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
|
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
|
||||||
use rustc_middle::ty::{self, DefIdTree, TyCtxt};
|
use rustc_middle::ty::{self, DefIdTree, TyCtxt};
|
||||||
use rustc_span::symbol::{kw, sym, Symbol};
|
use rustc_span::symbol::{kw, sym, Symbol};
|
||||||
|
@ -264,13 +263,13 @@ pub(crate) fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn print_evaluated_const(tcx: TyCtxt<'_>, def_id: DefId) -> Option<String> {
|
pub(crate) fn print_evaluated_const(tcx: TyCtxt<'_>, def_id: DefId) -> Option<String> {
|
||||||
tcx.const_eval_poly(def_id).ok().and_then(|val| {
|
tcx.const_eval_poly_for_typeck(def_id).ok().and_then(|val| {
|
||||||
let ty = tcx.type_of(def_id);
|
let ty = tcx.type_of(def_id);
|
||||||
match (val, ty.kind()) {
|
match (val, ty.kind()) {
|
||||||
(_, &ty::Ref(..)) => None,
|
(_, &ty::Ref(..)) => None,
|
||||||
(ConstValue::Scalar(_), &ty::Adt(_, _)) => None,
|
(Some(ty::ValTree::Branch(_)), &ty::Adt(_, _)) => None,
|
||||||
(ConstValue::Scalar(_), _) => {
|
(Some(ty::ValTree::Leaf(_)), _) => {
|
||||||
let const_ = ty::Const::from_value(tcx, val, ty);
|
let const_ = ty::Const::from_value(tcx, val.unwrap(), ty);
|
||||||
Some(print_const_with_custom_print_scalar(tcx, const_))
|
Some(print_const_with_custom_print_scalar(tcx, const_))
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
|
@ -308,10 +307,10 @@ fn print_const_with_custom_print_scalar(tcx: TyCtxt<'_>, ct: ty::Const<'_>) -> S
|
||||||
// Use a slightly different format for integer types which always shows the actual value.
|
// Use a slightly different format for integer types which always shows the actual value.
|
||||||
// For all other types, fallback to the original `pretty_print_const`.
|
// For all other types, fallback to the original `pretty_print_const`.
|
||||||
match (ct.kind(), ct.ty().kind()) {
|
match (ct.kind(), ct.ty().kind()) {
|
||||||
(ty::ConstKind::Value(ConstValue::Scalar(int)), ty::Uint(ui)) => {
|
(ty::ConstKind::Value(ty::ValTree::Leaf(int)), ty::Uint(ui)) => {
|
||||||
format!("{}{}", format_integer_with_underscore_sep(&int.to_string()), ui.name_str())
|
format!("{}{}", format_integer_with_underscore_sep(&int.to_string()), ui.name_str())
|
||||||
}
|
}
|
||||||
(ty::ConstKind::Value(ConstValue::Scalar(int)), ty::Int(i)) => {
|
(ty::ConstKind::Value(ty::ValTree::Leaf(int)), ty::Int(i)) => {
|
||||||
let ty = tcx.lift(ct.ty()).unwrap();
|
let ty = tcx.lift(ct.ty()).unwrap();
|
||||||
let size = tcx.layout_of(ty::ParamEnv::empty().and(ty)).unwrap().size;
|
let size = tcx.layout_of(ty::ParamEnv::empty().and(ty)).unwrap().size;
|
||||||
let data = int.assert_bits(size);
|
let data = int.assert_bits(size);
|
||||||
|
|
|
@ -14,7 +14,7 @@ impl Tr for str {
|
||||||
type Arr = [u8; 8];
|
type Arr = [u8; 8];
|
||||||
#[cfg(cfail)]
|
#[cfg(cfail)]
|
||||||
type Arr = [u8; Self::C];
|
type Arr = [u8; Self::C];
|
||||||
//[cfail]~^ ERROR cycle detected when simplifying constant
|
//[cfail]~^ ERROR cycle detected when evaluate type-level constant
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -19,10 +19,10 @@ fn main() -> () {
|
||||||
StorageLive(_1); // scope 0 at $DIR/box_expr.rs:7:9: 7:10
|
StorageLive(_1); // scope 0 at $DIR/box_expr.rs:7:9: 7:10
|
||||||
_2 = SizeOf(S); // scope 2 at $DIR/box_expr.rs:7:13: 7:25
|
_2 = SizeOf(S); // scope 2 at $DIR/box_expr.rs:7:13: 7:25
|
||||||
_3 = AlignOf(S); // scope 2 at $DIR/box_expr.rs:7:13: 7:25
|
_3 = AlignOf(S); // scope 2 at $DIR/box_expr.rs:7:13: 7:25
|
||||||
_4 = alloc::alloc::exchange_malloc(move _2, move _3) -> bb1; // scope 2 at $DIR/box_expr.rs:7:13: 7:25
|
_4 = : unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}(move _2, move _3) -> bb1; // scope 2 at $DIR/box_expr.rs:7:13: 7:25
|
||||||
// mir::Constant
|
// mir::Constant
|
||||||
// + span: $DIR/box_expr.rs:7:13: 7:25
|
// + span: $DIR/box_expr.rs:7:13: 7:25
|
||||||
// + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(Scalar(<ZST>)) }
|
// + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(ValTree::Branch(..)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
bb1: {
|
bb1: {
|
||||||
|
|
|
@ -21,44 +21,44 @@ fn main() -> () {
|
||||||
}
|
}
|
||||||
|
|
||||||
alloc1 (static: FOO, size: 16, align: 8) {
|
alloc1 (static: FOO, size: 16, align: 8) {
|
||||||
╾───────alloc28───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
|
╾───────alloc22───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
|
||||||
}
|
}
|
||||||
|
|
||||||
alloc28 (size: 72, align: 8) {
|
alloc22 (size: 72, align: 8) {
|
||||||
0x00 │ 00 00 00 00 __ __ __ __ ╾───────alloc13───────╼ │ ....░░░░╾──────╼
|
0x00 │ 00 00 00 00 __ __ __ __ ╾───────alloc9────────╼ │ ....░░░░╾──────╼
|
||||||
0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 __ __ __ __ │ ............░░░░
|
0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 __ __ __ __ │ ............░░░░
|
||||||
0x20 │ ╾───────alloc18───────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........
|
0x20 │ ╾───────alloc14───────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........
|
||||||
0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc26───────╼ │ ....*...╾──────╼
|
0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc20───────╼ │ ....*...╾──────╼
|
||||||
0x40 │ 03 00 00 00 00 00 00 00 │ ........
|
0x40 │ 03 00 00 00 00 00 00 00 │ ........
|
||||||
}
|
}
|
||||||
|
|
||||||
alloc13 (size: 0, align: 8) {}
|
alloc9 (size: 0, align: 8) {}
|
||||||
|
|
||||||
alloc18 (size: 16, align: 8) {
|
alloc14 (size: 16, align: 8) {
|
||||||
╾───────alloc16───────╼ ╾───────alloc17───────╼ │ ╾──────╼╾──────╼
|
╾───────alloc12───────╼ ╾───────alloc13───────╼ │ ╾──────╼╾──────╼
|
||||||
}
|
}
|
||||||
|
|
||||||
alloc16 (size: 1, align: 1) {
|
alloc12 (size: 1, align: 1) {
|
||||||
05 │ .
|
05 │ .
|
||||||
}
|
}
|
||||||
|
|
||||||
alloc17 (size: 1, align: 1) {
|
alloc13 (size: 1, align: 1) {
|
||||||
06 │ .
|
06 │ .
|
||||||
}
|
}
|
||||||
|
|
||||||
alloc26 (size: 24, align: 8) {
|
alloc20 (size: 24, align: 8) {
|
||||||
0x00 │ ╾─────alloc22+0x3─────╼ ╾───────alloc23───────╼ │ ╾──────╼╾──────╼
|
0x00 │ ╾─────alloc17+0x3─────╼ ╾───────alloc18───────╼ │ ╾──────╼╾──────╼
|
||||||
0x10 │ ╾─────alloc25+0x2─────╼ │ ╾──────╼
|
0x10 │ ╾─────alloc19+0x2─────╼ │ ╾──────╼
|
||||||
}
|
}
|
||||||
|
|
||||||
alloc22 (size: 4, align: 1) {
|
alloc17 (size: 4, align: 1) {
|
||||||
2a 45 15 6f │ *E.o
|
2a 45 15 6f │ *E.o
|
||||||
}
|
}
|
||||||
|
|
||||||
alloc23 (size: 1, align: 1) {
|
alloc18 (size: 1, align: 1) {
|
||||||
2a │ *
|
2a │ *
|
||||||
}
|
}
|
||||||
|
|
||||||
alloc25 (size: 4, align: 1) {
|
alloc19 (size: 4, align: 1) {
|
||||||
2a 45 15 6f │ *E.o
|
2a 45 15 6f │ *E.o
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,13 +22,13 @@
|
||||||
StorageLive(_3); // scope 0 at $DIR/boxes.rs:12:14: 12:22
|
StorageLive(_3); // scope 0 at $DIR/boxes.rs:12:14: 12:22
|
||||||
- _4 = SizeOf(i32); // scope 2 at $DIR/boxes.rs:12:14: 12:22
|
- _4 = SizeOf(i32); // scope 2 at $DIR/boxes.rs:12:14: 12:22
|
||||||
- _5 = AlignOf(i32); // scope 2 at $DIR/boxes.rs:12:14: 12:22
|
- _5 = AlignOf(i32); // scope 2 at $DIR/boxes.rs:12:14: 12:22
|
||||||
- _6 = alloc::alloc::exchange_malloc(move _4, move _5) -> bb1; // scope 2 at $DIR/boxes.rs:12:14: 12:22
|
- _6 = : unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}(move _4, move _5) -> bb1; // scope 2 at $DIR/boxes.rs:12:14: 12:22
|
||||||
+ _4 = const 4_usize; // scope 2 at $DIR/boxes.rs:12:14: 12:22
|
+ _4 = const 4_usize; // scope 2 at $DIR/boxes.rs:12:14: 12:22
|
||||||
+ _5 = const 4_usize; // scope 2 at $DIR/boxes.rs:12:14: 12:22
|
+ _5 = const 4_usize; // scope 2 at $DIR/boxes.rs:12:14: 12:22
|
||||||
+ _6 = alloc::alloc::exchange_malloc(const 4_usize, const 4_usize) -> bb1; // scope 2 at $DIR/boxes.rs:12:14: 12:22
|
+ _6 = : unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}(const 4_usize, const 4_usize) -> bb1; // scope 2 at $DIR/boxes.rs:12:14: 12:22
|
||||||
// mir::Constant
|
// mir::Constant
|
||||||
// + span: $DIR/boxes.rs:12:14: 12:22
|
// + span: $DIR/boxes.rs:12:14: 12:22
|
||||||
// + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(Scalar(<ZST>)) }
|
// + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(ValTree::Branch(..)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
bb1: {
|
bb1: {
|
||||||
|
|
|
@ -16,10 +16,10 @@
|
||||||
StorageLive(_1); // scope 0 at $DIR/derefer_inline_test.rs:10:5: 10:12
|
StorageLive(_1); // scope 0 at $DIR/derefer_inline_test.rs:10:5: 10:12
|
||||||
_2 = SizeOf(std::boxed::Box<u32>); // scope 1 at $DIR/derefer_inline_test.rs:10:5: 10:12
|
_2 = SizeOf(std::boxed::Box<u32>); // scope 1 at $DIR/derefer_inline_test.rs:10:5: 10:12
|
||||||
_3 = AlignOf(std::boxed::Box<u32>); // scope 1 at $DIR/derefer_inline_test.rs:10:5: 10:12
|
_3 = AlignOf(std::boxed::Box<u32>); // scope 1 at $DIR/derefer_inline_test.rs:10:5: 10:12
|
||||||
_4 = alloc::alloc::exchange_malloc(move _2, move _3) -> bb1; // scope 1 at $DIR/derefer_inline_test.rs:10:5: 10:12
|
_4 = : unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}(move _2, move _3) -> bb1; // scope 1 at $DIR/derefer_inline_test.rs:10:5: 10:12
|
||||||
// mir::Constant
|
// mir::Constant
|
||||||
// + span: $DIR/derefer_inline_test.rs:10:5: 10:12
|
// + span: $DIR/derefer_inline_test.rs:10:5: 10:12
|
||||||
// + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(Scalar(<ZST>)) }
|
// + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(ValTree::Branch(..)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
bb1: {
|
bb1: {
|
||||||
|
@ -56,10 +56,10 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
bb7 (cleanup): {
|
bb7 (cleanup): {
|
||||||
_6 = alloc::alloc::box_free::<Box<u32>, std::alloc::Global>(move (_5.0: std::ptr::Unique<std::boxed::Box<u32>>), move (_5.1: std::alloc::Global)) -> bb6; // scope 0 at $DIR/derefer_inline_test.rs:10:11: 10:12
|
_6 = : unsafe fn(Unique::<Box<u32>>, std::alloc::Global) {alloc::alloc::box_free::<Box<u32>, std::alloc::Global>}(move (_5.0: std::ptr::Unique<std::boxed::Box<u32>>), move (_5.1: std::alloc::Global)) -> bb6; // scope 0 at $DIR/derefer_inline_test.rs:10:11: 10:12
|
||||||
// mir::Constant
|
// mir::Constant
|
||||||
// + span: $DIR/derefer_inline_test.rs:10:11: 10:12
|
// + span: $DIR/derefer_inline_test.rs:10:11: 10:12
|
||||||
// + literal: Const { ty: unsafe fn(Unique<Box<u32>>, std::alloc::Global) {alloc::alloc::box_free::<Box<u32>, std::alloc::Global>}, val: Value(Scalar(<ZST>)) }
|
// + literal: Const { ty: unsafe fn(Unique<Box<u32>>, std::alloc::Global) {alloc::alloc::box_free::<Box<u32>, std::alloc::Global>}, val: Value(ValTree::Branch(..)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
bb8 (cleanup): {
|
bb8 (cleanup): {
|
||||||
|
|
|
@ -23,10 +23,10 @@
|
||||||
StorageLive(_1); // scope 0 at $DIR/inline-into-box-place.rs:8:9: 8:11
|
StorageLive(_1); // scope 0 at $DIR/inline-into-box-place.rs:8:9: 8:11
|
||||||
_2 = SizeOf(std::vec::Vec<u32>); // scope 2 at $DIR/inline-into-box-place.rs:8:29: 8:43
|
_2 = SizeOf(std::vec::Vec<u32>); // scope 2 at $DIR/inline-into-box-place.rs:8:29: 8:43
|
||||||
_3 = AlignOf(std::vec::Vec<u32>); // scope 2 at $DIR/inline-into-box-place.rs:8:29: 8:43
|
_3 = AlignOf(std::vec::Vec<u32>); // scope 2 at $DIR/inline-into-box-place.rs:8:29: 8:43
|
||||||
_4 = alloc::alloc::exchange_malloc(move _2, move _3) -> bb1; // scope 2 at $DIR/inline-into-box-place.rs:8:29: 8:43
|
_4 = : unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}(move _2, move _3) -> bb1; // scope 2 at $DIR/inline-into-box-place.rs:8:29: 8:43
|
||||||
// mir::Constant
|
// mir::Constant
|
||||||
// + span: $DIR/inline-into-box-place.rs:8:29: 8:43
|
// + span: $DIR/inline-into-box-place.rs:8:29: 8:43
|
||||||
// + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(Scalar(<ZST>)) }
|
// + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(ValTree::Branch(..)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
bb1: {
|
bb1: {
|
||||||
|
@ -36,7 +36,7 @@
|
||||||
+ StorageLive(_7); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
|
+ StorageLive(_7); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
|
||||||
+ _7 = &mut (*_5); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
|
+ _7 = &mut (*_5); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
|
||||||
+ StorageLive(_8); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
+ StorageLive(_8); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
||||||
+ _8 = const alloc::raw_vec::RawVec::<u32> { ptr: Unique::<u32> { pointer: NonNull::<u32> { pointer: {0x4 as *const u32} }, _marker: PhantomData::<u32> }, cap: 0_usize, alloc: std::alloc::Global }; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
+ _8 = const alloc::raw_vec::RawVec::<u32>::NEW; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
||||||
// mir::Constant
|
// mir::Constant
|
||||||
- // + span: $DIR/inline-into-box-place.rs:8:33: 8:41
|
- // + span: $DIR/inline-into-box-place.rs:8:33: 8:41
|
||||||
- // + user_ty: UserType(1)
|
- // + user_ty: UserType(1)
|
||||||
|
@ -46,7 +46,7 @@
|
||||||
- bb2: {
|
- bb2: {
|
||||||
+ // + span: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
+ // + span: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
||||||
+ // + user_ty: UserType(0)
|
+ // + user_ty: UserType(0)
|
||||||
+ // + literal: Const { ty: alloc::raw_vec::RawVec<u32>, val: Value(ByRef(..)) }
|
+ // + literal: Const { ty: alloc::raw_vec::RawVec<u32>, val: Unevaluated(alloc::raw_vec::RawVec::<T>::NEW, [u32], None) }
|
||||||
+ Deinit((*_7)); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
+ Deinit((*_7)); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
||||||
+ ((*_7).0: alloc::raw_vec::RawVec<u32>) = move _8; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
+ ((*_7).0: alloc::raw_vec::RawVec<u32>) = move _8; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
||||||
+ ((*_7).1: usize) = const 0_usize; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
+ ((*_7).1: usize) = const 0_usize; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
||||||
|
@ -71,10 +71,10 @@
|
||||||
- }
|
- }
|
||||||
-
|
-
|
||||||
- bb5 (cleanup): {
|
- bb5 (cleanup): {
|
||||||
- _6 = alloc::alloc::box_free::<Vec<u32>, std::alloc::Global>(move (_5.0: std::ptr::Unique<std::vec::Vec<u32>>), move (_5.1: std::alloc::Global)) -> bb4; // scope 0 at $DIR/inline-into-box-place.rs:8:42: 8:43
|
- _6 = : unsafe fn(Unique::<Vec<u32>>, std::alloc::Global) {alloc::alloc::box_free::<Vec<u32>, std::alloc::Global>}(move (_5.0: std::ptr::Unique<std::vec::Vec<u32>>), move (_5.1: std::alloc::Global)) -> bb4; // scope 0 at $DIR/inline-into-box-place.rs:8:42: 8:43
|
||||||
- // mir::Constant
|
- // mir::Constant
|
||||||
- // + span: $DIR/inline-into-box-place.rs:8:42: 8:43
|
- // + span: $DIR/inline-into-box-place.rs:8:42: 8:43
|
||||||
- // + literal: Const { ty: unsafe fn(Unique<Vec<u32>>, std::alloc::Global) {alloc::alloc::box_free::<Vec<u32>, std::alloc::Global>}, val: Value(Scalar(<ZST>)) }
|
- // + literal: Const { ty: unsafe fn(Unique<Vec<u32>>, std::alloc::Global) {alloc::alloc::box_free::<Vec<u32>, std::alloc::Global>}, val: Value(ValTree::Branch(..)) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,10 +31,10 @@ fn test() -> Option<Box<u32>> {
|
||||||
StorageLive(_1); // scope 0 at $DIR/issue-62289.rs:9:10: 9:21
|
StorageLive(_1); // scope 0 at $DIR/issue-62289.rs:9:10: 9:21
|
||||||
_2 = SizeOf(u32); // scope 1 at $DIR/issue-62289.rs:9:10: 9:21
|
_2 = SizeOf(u32); // scope 1 at $DIR/issue-62289.rs:9:10: 9:21
|
||||||
_3 = AlignOf(u32); // scope 1 at $DIR/issue-62289.rs:9:10: 9:21
|
_3 = AlignOf(u32); // scope 1 at $DIR/issue-62289.rs:9:10: 9:21
|
||||||
_4 = alloc::alloc::exchange_malloc(move _2, move _3) -> bb1; // scope 1 at $DIR/issue-62289.rs:9:10: 9:21
|
_4 = : unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}(move _2, move _3) -> bb1; // scope 1 at $DIR/issue-62289.rs:9:10: 9:21
|
||||||
// mir::Constant
|
// mir::Constant
|
||||||
// + span: $DIR/issue-62289.rs:9:10: 9:21
|
// + span: $DIR/issue-62289.rs:9:10: 9:21
|
||||||
// + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(Scalar(<ZST>)) }
|
// + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(ValTree::Branch(..)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
bb1: {
|
bb1: {
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
|
|
|
|
||||||
fn main() -> () {
|
fn main() -> () {
|
||||||
let mut _0: (); // return place in scope 0 at $DIR/region-subtyping-basic.rs:16:11: 16:11
|
let mut _0: (); // return place in scope 0 at $DIR/region-subtyping-basic.rs:16:11: 16:11
|
||||||
let mut _1: [usize; Const { ty: usize, kind: Value(Scalar(0x0000000000000003)) }]; // in scope 0 at $DIR/region-subtyping-basic.rs:17:9: 17:14
|
let mut _1: [usize; Const { ty: usize, kind: Value(Leaf(0x0000000000000003)) }]; // in scope 0 at $DIR/region-subtyping-basic.rs:17:9: 17:14
|
||||||
let _3: usize; // in scope 0 at $DIR/region-subtyping-basic.rs:18:16: 18:17
|
let _3: usize; // in scope 0 at $DIR/region-subtyping-basic.rs:18:16: 18:17
|
||||||
let mut _4: usize; // in scope 0 at $DIR/region-subtyping-basic.rs:18:14: 18:18
|
let mut _4: usize; // in scope 0 at $DIR/region-subtyping-basic.rs:18:14: 18:18
|
||||||
let mut _5: bool; // in scope 0 at $DIR/region-subtyping-basic.rs:18:14: 18:18
|
let mut _5: bool; // in scope 0 at $DIR/region-subtyping-basic.rs:18:14: 18:18
|
||||||
|
@ -63,7 +63,7 @@ fn main() -> () {
|
||||||
FakeRead(ForLet(None), _6); // bb1[4]: scope 2 at $DIR/region-subtyping-basic.rs:19:9: 19:10
|
FakeRead(ForLet(None), _6); // bb1[4]: scope 2 at $DIR/region-subtyping-basic.rs:19:9: 19:10
|
||||||
StorageLive(_7); // bb1[5]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12
|
StorageLive(_7); // bb1[5]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12
|
||||||
_7 = const ConstValue(Scalar(0x01): bool); // bb1[6]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12
|
_7 = const ConstValue(Scalar(0x01): bool); // bb1[6]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12
|
||||||
switchInt(move _7) -> [Const(Value(Scalar(0x00)): bool): bb4, otherwise: bb2]; // bb1[7]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12
|
switchInt(move _7) -> [ConstValue(Scalar(0x00): bool): bb4, otherwise: bb2]; // bb1[7]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12
|
||||||
}
|
}
|
||||||
|
|
||||||
bb2: {
|
bb2: {
|
||||||
|
|
|
@ -8,10 +8,10 @@ fn std::ptr::drop_in_place(_1: *mut Test) -> () {
|
||||||
bb0: {
|
bb0: {
|
||||||
Retag([raw] _1); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
Retag([raw] _1); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
||||||
_2 = &mut (*_1); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
_2 = &mut (*_1); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
||||||
_3 = <Test as Drop>::drop(move _2) -> bb1; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
_3 = : for<'r> fn(&'r mut Test) {<Test as Drop>::drop}(move _2) -> bb1; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
||||||
// mir::Constant
|
// mir::Constant
|
||||||
// + span: $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
// + span: $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
||||||
// + literal: Const { ty: for<'r> fn(&'r mut Test) {<Test as Drop>::drop}, val: Value(Scalar(<ZST>)) }
|
// + literal: Const { ty: for<'r> fn(&'r mut Test) {<Test as Drop>::drop}, val: Value(ValTree::Branch(..)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
bb1: {
|
bb1: {
|
||||||
|
|
|
@ -30,10 +30,10 @@ fn move_out_by_subslice() -> () {
|
||||||
StorageLive(_2); // scope 0 at $DIR/uniform_array_move_out.rs:11:14: 11:19
|
StorageLive(_2); // scope 0 at $DIR/uniform_array_move_out.rs:11:14: 11:19
|
||||||
_3 = SizeOf(i32); // scope 2 at $DIR/uniform_array_move_out.rs:11:14: 11:19
|
_3 = SizeOf(i32); // scope 2 at $DIR/uniform_array_move_out.rs:11:14: 11:19
|
||||||
_4 = AlignOf(i32); // scope 2 at $DIR/uniform_array_move_out.rs:11:14: 11:19
|
_4 = AlignOf(i32); // scope 2 at $DIR/uniform_array_move_out.rs:11:14: 11:19
|
||||||
_5 = alloc::alloc::exchange_malloc(move _3, move _4) -> [return: bb1, unwind: bb12]; // scope 2 at $DIR/uniform_array_move_out.rs:11:14: 11:19
|
_5 = : unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}(move _3, move _4) -> [return: bb1, unwind: bb12]; // scope 2 at $DIR/uniform_array_move_out.rs:11:14: 11:19
|
||||||
// mir::Constant
|
// mir::Constant
|
||||||
// + span: $DIR/uniform_array_move_out.rs:11:14: 11:19
|
// + span: $DIR/uniform_array_move_out.rs:11:14: 11:19
|
||||||
// + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(Scalar(<ZST>)) }
|
// + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(ValTree::Branch(..)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
bb1: {
|
bb1: {
|
||||||
|
@ -49,10 +49,10 @@ fn move_out_by_subslice() -> () {
|
||||||
StorageLive(_7); // scope 0 at $DIR/uniform_array_move_out.rs:11:21: 11:26
|
StorageLive(_7); // scope 0 at $DIR/uniform_array_move_out.rs:11:21: 11:26
|
||||||
_8 = SizeOf(i32); // scope 3 at $DIR/uniform_array_move_out.rs:11:21: 11:26
|
_8 = SizeOf(i32); // scope 3 at $DIR/uniform_array_move_out.rs:11:21: 11:26
|
||||||
_9 = AlignOf(i32); // scope 3 at $DIR/uniform_array_move_out.rs:11:21: 11:26
|
_9 = AlignOf(i32); // scope 3 at $DIR/uniform_array_move_out.rs:11:21: 11:26
|
||||||
_10 = alloc::alloc::exchange_malloc(move _8, move _9) -> [return: bb3, unwind: bb11]; // scope 3 at $DIR/uniform_array_move_out.rs:11:21: 11:26
|
_10 = : unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}(move _8, move _9) -> [return: bb3, unwind: bb11]; // scope 3 at $DIR/uniform_array_move_out.rs:11:21: 11:26
|
||||||
// mir::Constant
|
// mir::Constant
|
||||||
// + span: $DIR/uniform_array_move_out.rs:11:21: 11:26
|
// + span: $DIR/uniform_array_move_out.rs:11:21: 11:26
|
||||||
// + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(Scalar(<ZST>)) }
|
// + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(ValTree::Branch(..)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
bb3: {
|
bb3: {
|
||||||
|
|
|
@ -30,10 +30,10 @@ fn move_out_from_end() -> () {
|
||||||
StorageLive(_2); // scope 0 at $DIR/uniform_array_move_out.rs:5:14: 5:19
|
StorageLive(_2); // scope 0 at $DIR/uniform_array_move_out.rs:5:14: 5:19
|
||||||
_3 = SizeOf(i32); // scope 2 at $DIR/uniform_array_move_out.rs:5:14: 5:19
|
_3 = SizeOf(i32); // scope 2 at $DIR/uniform_array_move_out.rs:5:14: 5:19
|
||||||
_4 = AlignOf(i32); // scope 2 at $DIR/uniform_array_move_out.rs:5:14: 5:19
|
_4 = AlignOf(i32); // scope 2 at $DIR/uniform_array_move_out.rs:5:14: 5:19
|
||||||
_5 = alloc::alloc::exchange_malloc(move _3, move _4) -> [return: bb1, unwind: bb12]; // scope 2 at $DIR/uniform_array_move_out.rs:5:14: 5:19
|
_5 = : unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}(move _3, move _4) -> [return: bb1, unwind: bb12]; // scope 2 at $DIR/uniform_array_move_out.rs:5:14: 5:19
|
||||||
// mir::Constant
|
// mir::Constant
|
||||||
// + span: $DIR/uniform_array_move_out.rs:5:14: 5:19
|
// + span: $DIR/uniform_array_move_out.rs:5:14: 5:19
|
||||||
// + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(Scalar(<ZST>)) }
|
// + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(ValTree::Branch(..)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
bb1: {
|
bb1: {
|
||||||
|
@ -49,10 +49,10 @@ fn move_out_from_end() -> () {
|
||||||
StorageLive(_7); // scope 0 at $DIR/uniform_array_move_out.rs:5:21: 5:26
|
StorageLive(_7); // scope 0 at $DIR/uniform_array_move_out.rs:5:21: 5:26
|
||||||
_8 = SizeOf(i32); // scope 3 at $DIR/uniform_array_move_out.rs:5:21: 5:26
|
_8 = SizeOf(i32); // scope 3 at $DIR/uniform_array_move_out.rs:5:21: 5:26
|
||||||
_9 = AlignOf(i32); // scope 3 at $DIR/uniform_array_move_out.rs:5:21: 5:26
|
_9 = AlignOf(i32); // scope 3 at $DIR/uniform_array_move_out.rs:5:21: 5:26
|
||||||
_10 = alloc::alloc::exchange_malloc(move _8, move _9) -> [return: bb3, unwind: bb11]; // scope 3 at $DIR/uniform_array_move_out.rs:5:21: 5:26
|
_10 = : unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}(move _8, move _9) -> [return: bb3, unwind: bb11]; // scope 3 at $DIR/uniform_array_move_out.rs:5:21: 5:26
|
||||||
// mir::Constant
|
// mir::Constant
|
||||||
// + span: $DIR/uniform_array_move_out.rs:5:21: 5:26
|
// + span: $DIR/uniform_array_move_out.rs:5:21: 5:26
|
||||||
// + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(Scalar(<ZST>)) }
|
// + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(ValTree::Branch(..)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
bb3: {
|
bb3: {
|
||||||
|
|
|
@ -31,9 +31,9 @@ fn std::ptr::drop_in_place(_1: *mut Vec<i32>) -> () {
|
||||||
|
|
||||||
bb6: {
|
bb6: {
|
||||||
_2 = &mut (*_1); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
_2 = &mut (*_1); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
||||||
_3 = <Vec<i32> as Drop>::drop(move _2) -> [return: bb5, unwind: bb4]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
_3 = : for<'r> fn(&'r mut Vec::<i32>) {<Vec<i32> as Drop>::drop}(move _2) -> [return: bb5, unwind: bb4]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
||||||
// mir::Constant
|
// mir::Constant
|
||||||
// + span: $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
// + span: $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
||||||
// + literal: Const { ty: for<'r> fn(&'r mut Vec<i32>) {<Vec<i32> as Drop>::drop}, val: Value(Scalar(<ZST>)) }
|
// + literal: Const { ty: for<'r> fn(&'r mut Vec<i32>) {<Vec<i32> as Drop>::drop}, val: Value(ValTree::Branch(..)) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
// build-fail
|
// build-fail
|
||||||
//~^ ERROR cycle detected when normalizing `<() as Tr>::A` [E0391]
|
|
||||||
|
|
||||||
// Cyclic assoc. const defaults don't error unless *used*
|
// Cyclic assoc. const defaults don't error unless *used*
|
||||||
trait Tr {
|
trait Tr {
|
||||||
const A: u8 = Self::B;
|
const A: u8 = Self::B;
|
||||||
|
//~^ cycle detected when const-evaluating + checking `Tr::A`
|
||||||
|
|
||||||
const B: u8 = Self::A;
|
const B: u8 = Self::A;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,37 +1,15 @@
|
||||||
error[E0391]: cycle detected when normalizing `<() as Tr>::A`
|
error[E0391]: cycle detected when const-evaluating + checking `Tr::A`
|
||||||
|
|
--> $DIR/defaults-cyclic-fail.rs:5:5
|
||||||
note: ...which requires simplifying constant for the type system `Tr::A`...
|
|
||||||
--> $DIR/defaults-cyclic-fail.rs:6:5
|
|
||||||
|
|
|
|
||||||
LL | const A: u8 = Self::B;
|
LL | const A: u8 = Self::B;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
note: ...which requires simplifying constant for the type system `Tr::A`...
|
|
||||||
--> $DIR/defaults-cyclic-fail.rs:6:5
|
|
||||||
|
|
|
|
||||||
LL | const A: u8 = Self::B;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires const-evaluating + checking `Tr::A`...
|
|
||||||
--> $DIR/defaults-cyclic-fail.rs:6:5
|
|
||||||
|
|
|
||||||
LL | const A: u8 = Self::B;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
= note: ...which requires normalizing `<() as Tr>::B`...
|
|
||||||
note: ...which requires simplifying constant for the type system `Tr::B`...
|
|
||||||
--> $DIR/defaults-cyclic-fail.rs:8:5
|
|
||||||
|
|
|
||||||
LL | const B: u8 = Self::A;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires simplifying constant for the type system `Tr::B`...
|
|
||||||
--> $DIR/defaults-cyclic-fail.rs:8:5
|
|
||||||
|
|
|
||||||
LL | const B: u8 = Self::A;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires const-evaluating + checking `Tr::B`...
|
note: ...which requires const-evaluating + checking `Tr::B`...
|
||||||
--> $DIR/defaults-cyclic-fail.rs:8:5
|
--> $DIR/defaults-cyclic-fail.rs:8:5
|
||||||
|
|
|
|
||||||
LL | const B: u8 = Self::A;
|
LL | const B: u8 = Self::A;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= note: ...which again requires normalizing `<() as Tr>::A`, completing the cycle
|
= note: ...which again requires const-evaluating + checking `Tr::A`, completing the cycle
|
||||||
note: cycle used when const-evaluating + checking `main::promoted[1]`
|
note: cycle used when const-evaluating + checking `main::promoted[1]`
|
||||||
--> $DIR/defaults-cyclic-fail.rs:14:1
|
--> $DIR/defaults-cyclic-fail.rs:14:1
|
||||||
|
|
|
|
||||||
|
|
|
@ -4,13 +4,7 @@ error[E0391]: cycle detected when elaborating drops for `<impl at $DIR/issue-249
|
||||||
LL | const BAR: u32 = IMPL_REF_BAR;
|
LL | const BAR: u32 = IMPL_REF_BAR;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: ...which requires normalizing `IMPL_REF_BAR`...
|
note: ...which requires const-evaluating + checking `IMPL_REF_BAR`...
|
||||||
note: ...which requires simplifying constant for the type system `IMPL_REF_BAR`...
|
|
||||||
--> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:7:1
|
|
||||||
|
|
|
||||||
LL | const IMPL_REF_BAR: u32 = GlobalImplRef::BAR;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires simplifying constant for the type system `IMPL_REF_BAR`...
|
|
||||||
--> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:7:1
|
--> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:7:1
|
||||||
|
|
|
|
||||||
LL | const IMPL_REF_BAR: u32 = GlobalImplRef::BAR;
|
LL | const IMPL_REF_BAR: u32 = GlobalImplRef::BAR;
|
||||||
|
@ -20,17 +14,6 @@ note: ...which requires const-evaluating + checking `IMPL_REF_BAR`...
|
||||||
|
|
|
|
||||||
LL | const IMPL_REF_BAR: u32 = GlobalImplRef::BAR;
|
LL | const IMPL_REF_BAR: u32 = GlobalImplRef::BAR;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= note: ...which requires normalizing `<impl at $DIR/issue-24949-assoc-const-static-recursion-impl.rs:11:1: 13:2>::BAR`...
|
|
||||||
note: ...which requires simplifying constant for the type system `<impl at $DIR/issue-24949-assoc-const-static-recursion-impl.rs:11:1: 13:2>::BAR`...
|
|
||||||
--> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:12:5
|
|
||||||
|
|
|
||||||
LL | const BAR: u32 = IMPL_REF_BAR;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires simplifying constant for the type system `<impl at $DIR/issue-24949-assoc-const-static-recursion-impl.rs:11:1: 13:2>::BAR`...
|
|
||||||
--> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:12:5
|
|
||||||
|
|
|
||||||
LL | const BAR: u32 = IMPL_REF_BAR;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires const-evaluating + checking `<impl at $DIR/issue-24949-assoc-const-static-recursion-impl.rs:11:1: 13:2>::BAR`...
|
note: ...which requires const-evaluating + checking `<impl at $DIR/issue-24949-assoc-const-static-recursion-impl.rs:11:1: 13:2>::BAR`...
|
||||||
--> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:12:5
|
--> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:12:5
|
||||||
|
|
|
|
||||||
|
|
|
@ -4,13 +4,7 @@ error[E0391]: cycle detected when elaborating drops for `FooDefault::BAR`
|
||||||
LL | const BAR: u32 = DEFAULT_REF_BAR;
|
LL | const BAR: u32 = DEFAULT_REF_BAR;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: ...which requires normalizing `DEFAULT_REF_BAR`...
|
note: ...which requires const-evaluating + checking `DEFAULT_REF_BAR`...
|
||||||
note: ...which requires simplifying constant for the type system `DEFAULT_REF_BAR`...
|
|
||||||
--> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:11:1
|
|
||||||
|
|
|
||||||
LL | const DEFAULT_REF_BAR: u32 = <GlobalDefaultRef>::BAR;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires simplifying constant for the type system `DEFAULT_REF_BAR`...
|
|
||||||
--> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:11:1
|
--> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:11:1
|
||||||
|
|
|
|
||||||
LL | const DEFAULT_REF_BAR: u32 = <GlobalDefaultRef>::BAR;
|
LL | const DEFAULT_REF_BAR: u32 = <GlobalDefaultRef>::BAR;
|
||||||
|
@ -20,17 +14,6 @@ note: ...which requires const-evaluating + checking `DEFAULT_REF_BAR`...
|
||||||
|
|
|
|
||||||
LL | const DEFAULT_REF_BAR: u32 = <GlobalDefaultRef>::BAR;
|
LL | const DEFAULT_REF_BAR: u32 = <GlobalDefaultRef>::BAR;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= note: ...which requires normalizing `<GlobalDefaultRef as FooDefault>::BAR`...
|
|
||||||
note: ...which requires simplifying constant for the type system `FooDefault::BAR`...
|
|
||||||
--> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:8:5
|
|
||||||
|
|
|
||||||
LL | const BAR: u32 = DEFAULT_REF_BAR;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires simplifying constant for the type system `FooDefault::BAR`...
|
|
||||||
--> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:8:5
|
|
||||||
|
|
|
||||||
LL | const BAR: u32 = DEFAULT_REF_BAR;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires const-evaluating + checking `FooDefault::BAR`...
|
note: ...which requires const-evaluating + checking `FooDefault::BAR`...
|
||||||
--> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:8:5
|
--> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:8:5
|
||||||
|
|
|
|
||||||
|
|
|
@ -4,13 +4,7 @@ error[E0391]: cycle detected when elaborating drops for `<impl at $DIR/issue-249
|
||||||
LL | const BAR: u32 = TRAIT_REF_BAR;
|
LL | const BAR: u32 = TRAIT_REF_BAR;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: ...which requires normalizing `TRAIT_REF_BAR`...
|
note: ...which requires const-evaluating + checking `TRAIT_REF_BAR`...
|
||||||
note: ...which requires simplifying constant for the type system `TRAIT_REF_BAR`...
|
|
||||||
--> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:7:1
|
|
||||||
|
|
|
||||||
LL | const TRAIT_REF_BAR: u32 = <GlobalTraitRef>::BAR;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires simplifying constant for the type system `TRAIT_REF_BAR`...
|
|
||||||
--> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:7:1
|
--> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:7:1
|
||||||
|
|
|
|
||||||
LL | const TRAIT_REF_BAR: u32 = <GlobalTraitRef>::BAR;
|
LL | const TRAIT_REF_BAR: u32 = <GlobalTraitRef>::BAR;
|
||||||
|
@ -20,17 +14,6 @@ note: ...which requires const-evaluating + checking `TRAIT_REF_BAR`...
|
||||||
|
|
|
|
||||||
LL | const TRAIT_REF_BAR: u32 = <GlobalTraitRef>::BAR;
|
LL | const TRAIT_REF_BAR: u32 = <GlobalTraitRef>::BAR;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= note: ...which requires normalizing `<GlobalTraitRef as Foo>::BAR`...
|
|
||||||
note: ...which requires simplifying constant for the type system `<impl at $DIR/issue-24949-assoc-const-static-recursion-trait.rs:11:1: 13:2>::BAR`...
|
|
||||||
--> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:12:5
|
|
||||||
|
|
|
||||||
LL | const BAR: u32 = TRAIT_REF_BAR;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires simplifying constant for the type system `<impl at $DIR/issue-24949-assoc-const-static-recursion-trait.rs:11:1: 13:2>::BAR`...
|
|
||||||
--> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:12:5
|
|
||||||
|
|
|
||||||
LL | const BAR: u32 = TRAIT_REF_BAR;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires const-evaluating + checking `<impl at $DIR/issue-24949-assoc-const-static-recursion-trait.rs:11:1: 13:2>::BAR`...
|
note: ...which requires const-evaluating + checking `<impl at $DIR/issue-24949-assoc-const-static-recursion-trait.rs:11:1: 13:2>::BAR`...
|
||||||
--> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:12:5
|
--> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:12:5
|
||||||
|
|
|
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
// The `panic!()` below is important to trigger the fixed ICE.
|
// The `panic!()` below is important to trigger the fixed ICE.
|
||||||
|
|
||||||
const _CONST: &[u8] = &f(&[], |_| {});
|
const _CONST: &[u8] = &f(&[], |_| {});
|
||||||
|
//~^ ERROR any use of this value
|
||||||
|
//~| WARNING this was previously
|
||||||
|
|
||||||
const fn f<F>(_: &[u8], _: F) -> &[u8]
|
const fn f<F>(_: &[u8], _: F) -> &[u8]
|
||||||
where
|
where
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0080]: evaluation of constant value failed
|
error[E0080]: evaluation of constant value failed
|
||||||
--> $DIR/issue-81899.rs:10:5
|
--> $DIR/issue-81899.rs:12:5
|
||||||
|
|
|
|
||||||
LL | const _CONST: &[u8] = &f(&[], |_| {});
|
LL | const _CONST: &[u8] = &f(&[], |_| {});
|
||||||
| -------------- inside `_CONST` at $DIR/issue-81899.rs:4:24
|
| -------------- inside `_CONST` at $DIR/issue-81899.rs:4:24
|
||||||
|
@ -7,11 +7,23 @@ LL | const _CONST: &[u8] = &f(&[], |_| {});
|
||||||
LL | panic!()
|
LL | panic!()
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
| |
|
| |
|
||||||
| the evaluated program panicked at 'explicit panic', $DIR/issue-81899.rs:10:5
|
| the evaluated program panicked at 'explicit panic', $DIR/issue-81899.rs:12:5
|
||||||
| inside `f::<[closure@$DIR/issue-81899.rs:4:31: 4:37]>` at $SRC_DIR/std/src/panic.rs:LL:COL
|
| inside `f::<[closure@$DIR/issue-81899.rs:4:31: 4:37]>` at $SRC_DIR/std/src/panic.rs:LL:COL
|
||||||
|
|
|
|
||||||
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: any use of this value will cause an error
|
||||||
|
--> $DIR/issue-81899.rs:4:23
|
||||||
|
|
|
||||||
|
LL | const _CONST: &[u8] = &f(&[], |_| {});
|
||||||
|
| ----------------------^^^^^^^^^^^^^^^-
|
||||||
|
| |
|
||||||
|
| referenced constant has errors
|
||||||
|
|
|
||||||
|
= note: `#[deny(const_err)]` on by default
|
||||||
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||||
|
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0080`.
|
For more information about this error, try `rustc --explain E0080`.
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
// Regression test related to issue 88434
|
// Regression test related to issue 88434
|
||||||
|
|
||||||
const _CONST: &() = &f(&|_| {});
|
const _CONST: &() = &f(&|_| {});
|
||||||
|
//~^ ERROR any use of this value
|
||||||
|
//~| WARNING this was previously
|
||||||
|
|
||||||
const fn f<F>(_: &F)
|
const fn f<F>(_: &F)
|
||||||
where
|
where
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0080]: evaluation of constant value failed
|
error[E0080]: evaluation of constant value failed
|
||||||
--> $DIR/issue-88434-minimal-example.rs:9:5
|
--> $DIR/issue-88434-minimal-example.rs:11:5
|
||||||
|
|
|
|
||||||
LL | const _CONST: &() = &f(&|_| {});
|
LL | const _CONST: &() = &f(&|_| {});
|
||||||
| ---------- inside `_CONST` at $DIR/issue-88434-minimal-example.rs:3:22
|
| ---------- inside `_CONST` at $DIR/issue-88434-minimal-example.rs:3:22
|
||||||
|
@ -7,11 +7,23 @@ LL | const _CONST: &() = &f(&|_| {});
|
||||||
LL | panic!()
|
LL | panic!()
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
| |
|
| |
|
||||||
| the evaluated program panicked at 'explicit panic', $DIR/issue-88434-minimal-example.rs:9:5
|
| the evaluated program panicked at 'explicit panic', $DIR/issue-88434-minimal-example.rs:11:5
|
||||||
| inside `f::<[closure@$DIR/issue-88434-minimal-example.rs:3:25: 3:31]>` at $SRC_DIR/std/src/panic.rs:LL:COL
|
| inside `f::<[closure@$DIR/issue-88434-minimal-example.rs:3:25: 3:31]>` at $SRC_DIR/std/src/panic.rs:LL:COL
|
||||||
|
|
|
|
||||||
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: any use of this value will cause an error
|
||||||
|
--> $DIR/issue-88434-minimal-example.rs:3:21
|
||||||
|
|
|
||||||
|
LL | const _CONST: &() = &f(&|_| {});
|
||||||
|
| --------------------^^^^^^^^^^^-
|
||||||
|
| |
|
||||||
|
| referenced constant has errors
|
||||||
|
|
|
||||||
|
= note: `#[deny(const_err)]` on by default
|
||||||
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||||
|
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0080`.
|
For more information about this error, try `rustc --explain E0080`.
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
// Regression test for issue 88434
|
// Regression test for issue 88434
|
||||||
|
|
||||||
const _CONST: &[u8] = &f(&[], |_| {});
|
const _CONST: &[u8] = &f(&[], |_| {});
|
||||||
|
//~^ ERROR any use of this value will cause an error
|
||||||
|
//~| WARNING this was previously
|
||||||
|
|
||||||
const fn f<F>(_: &[u8], _: F) -> &[u8]
|
const fn f<F>(_: &[u8], _: F) -> &[u8]
|
||||||
where
|
where
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0080]: evaluation of constant value failed
|
error[E0080]: evaluation of constant value failed
|
||||||
--> $DIR/issue-88434-removal-index-should-be-less.rs:9:5
|
--> $DIR/issue-88434-removal-index-should-be-less.rs:11:5
|
||||||
|
|
|
|
||||||
LL | const _CONST: &[u8] = &f(&[], |_| {});
|
LL | const _CONST: &[u8] = &f(&[], |_| {});
|
||||||
| -------------- inside `_CONST` at $DIR/issue-88434-removal-index-should-be-less.rs:3:24
|
| -------------- inside `_CONST` at $DIR/issue-88434-removal-index-should-be-less.rs:3:24
|
||||||
|
@ -7,11 +7,23 @@ LL | const _CONST: &[u8] = &f(&[], |_| {});
|
||||||
LL | panic!()
|
LL | panic!()
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
| |
|
| |
|
||||||
| the evaluated program panicked at 'explicit panic', $DIR/issue-88434-removal-index-should-be-less.rs:9:5
|
| the evaluated program panicked at 'explicit panic', $DIR/issue-88434-removal-index-should-be-less.rs:11:5
|
||||||
| inside `f::<[closure@$DIR/issue-88434-removal-index-should-be-less.rs:3:31: 3:37]>` at $SRC_DIR/std/src/panic.rs:LL:COL
|
| inside `f::<[closure@$DIR/issue-88434-removal-index-should-be-less.rs:3:31: 3:37]>` at $SRC_DIR/std/src/panic.rs:LL:COL
|
||||||
|
|
|
|
||||||
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: any use of this value will cause an error
|
||||||
|
--> $DIR/issue-88434-removal-index-should-be-less.rs:3:23
|
||||||
|
|
|
||||||
|
LL | const _CONST: &[u8] = &f(&[], |_| {});
|
||||||
|
| ----------------------^^^^^^^^^^^^^^^-
|
||||||
|
| |
|
||||||
|
| referenced constant has errors
|
||||||
|
|
|
||||||
|
= note: `#[deny(const_err)]` on by default
|
||||||
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||||
|
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0080`.
|
For more information about this error, try `rustc --explain E0080`.
|
||||||
|
|
|
@ -2,7 +2,7 @@ error[E0308]: mismatched types
|
||||||
--> $DIR/different_generic_args_array.rs:9:9
|
--> $DIR/different_generic_args_array.rs:9:9
|
||||||
|
|
|
|
||||||
LL | x = Const::<{ [4] }> {};
|
LL | x = Const::<{ [4] }> {};
|
||||||
| ^^^^^^^^^^^^^^^^^^^ expected `3_usize`, found `4_usize`
|
| ^^^^^^^^^^^^^^^^^^^ expected `[3_usize]`, found `[4_usize]`
|
||||||
|
|
|
|
||||||
= note: expected struct `Const<[3_usize]>`
|
= note: expected struct `Const<[3_usize]>`
|
||||||
found struct `Const<[4_usize]>`
|
found struct `Const<[4_usize]>`
|
||||||
|
|
|
@ -10,7 +10,11 @@ note: ...which requires checking if `TensorDimension` fulfills its obligations..
|
||||||
LL | trait TensorDimension {
|
LL | trait TensorDimension {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^
|
||||||
= note: ...which again requires resolving instance `<LazyUpdim<T, { T::DIM }, DIM> as TensorDimension>::DIM`, completing the cycle
|
= note: ...which again requires resolving instance `<LazyUpdim<T, { T::DIM }, DIM> as TensorDimension>::DIM`, completing the cycle
|
||||||
= note: cycle used when normalizing `<LazyUpdim<T, { T::DIM }, DIM> as TensorDimension>::DIM`
|
note: cycle used when checking if `TensorDimension` fulfills its obligations
|
||||||
|
--> $DIR/issue-83765.rs:4:1
|
||||||
|
|
|
||||||
|
LL | trait TensorDimension {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ error[E0080]: evaluation of constant value failed
|
||||||
LL | copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
|
LL | copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
| |
|
| |
|
||||||
| memory access failed: alloc7 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
|
| memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
|
||||||
| inside `std::ptr::read::<u32>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
| inside `std::ptr::read::<u32>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
||||||
|
|
|
|
||||||
::: $DIR/out_of_bounds_read.rs:12:33
|
::: $DIR/out_of_bounds_read.rs:12:33
|
||||||
|
@ -18,7 +18,7 @@ error[E0080]: evaluation of constant value failed
|
||||||
LL | copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
|
LL | copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
| |
|
| |
|
||||||
| memory access failed: alloc7 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
|
| memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
|
||||||
| inside `std::ptr::read::<u32>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
| inside `std::ptr::read::<u32>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
||||||
|
|
|
|
||||||
::: $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
::: $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
||||||
|
@ -37,7 +37,7 @@ error[E0080]: evaluation of constant value failed
|
||||||
LL | copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
|
LL | copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
| |
|
| |
|
||||||
| memory access failed: alloc7 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
|
| memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
|
||||||
| inside `std::ptr::read::<u32>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
| inside `std::ptr::read::<u32>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
||||||
|
|
|
|
||||||
::: $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
|
::: $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
// compile-flags: -Ztreat-err-as-bug=2
|
// compile-flags: -Ztreat-err-as-bug=2
|
||||||
//~^ ERROR 1:1: 1:1: ty::ConstKind::Error constructed but no error reported
|
|
||||||
// build-fail
|
// build-fail
|
||||||
// failure-status: 101
|
// failure-status: 101
|
||||||
// rustc-env:RUST_BACKTRACE=1
|
// rustc-env:RUST_BACKTRACE=1
|
||||||
|
@ -23,5 +22,7 @@ const X: i32 = 1 / 0; //~WARN any use of this value will cause an error
|
||||||
fn main() {
|
fn main() {
|
||||||
let x: &'static i32 = &X;
|
let x: &'static i32 = &X;
|
||||||
//~^ ERROR evaluation of constant value failed
|
//~^ ERROR evaluation of constant value failed
|
||||||
|
//~| ERROR erroneous constant used
|
||||||
|
//~| WARNING this was previously accepted by the compiler
|
||||||
println!("x={}", x);
|
println!("x={}", x);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
warning: any use of this value will cause an error
|
warning: any use of this value will cause an error
|
||||||
--> $DIR/const-eval-query-stack.rs:20:16
|
--> $DIR/const-eval-query-stack.rs:19:16
|
||||||
|
|
|
|
||||||
LL | const X: i32 = 1 / 0;
|
LL | const X: i32 = 1 / 0;
|
||||||
| ---------------^^^^^-
|
| ---------------^^^^^-
|
||||||
|
@ -7,7 +7,7 @@ LL | const X: i32 = 1 / 0;
|
||||||
| attempt to divide `1_i32` by zero
|
| attempt to divide `1_i32` by zero
|
||||||
|
|
|
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/const-eval-query-stack.rs:19:8
|
--> $DIR/const-eval-query-stack.rs:18:8
|
||||||
|
|
|
|
||||||
LL | #[warn(const_err)]
|
LL | #[warn(const_err)]
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
@ -15,13 +15,23 @@ LL | #[warn(const_err)]
|
||||||
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
|
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
|
||||||
|
|
||||||
error[E0080]: evaluation of constant value failed
|
error[E0080]: evaluation of constant value failed
|
||||||
--> $DIR/const-eval-query-stack.rs:24:28
|
--> $DIR/const-eval-query-stack.rs:23:28
|
||||||
|
|
|
|
||||||
LL | let x: &'static i32 = &X;
|
LL | let x: &'static i32 = &X;
|
||||||
| ^ referenced constant has errors
|
| ^ referenced constant has errors
|
||||||
|
|
||||||
|
error: erroneous constant used
|
||||||
|
--> $DIR/const-eval-query-stack.rs:23:27
|
||||||
|
|
|
||||||
|
LL | let x: &'static i32 = &X;
|
||||||
|
| ^^ referenced constant has errors
|
||||||
|
|
|
||||||
|
= note: `#[deny(const_err)]` on by default
|
||||||
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||||
|
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
|
||||||
|
|
||||||
query stack during panic:
|
query stack during panic:
|
||||||
#0 [try_normalize_mir_const_after_erasing_regions] normalizing `main::promoted[1]`
|
#0 [mir_drops_elaborated_and_const_checked] elaborating drops for `main`
|
||||||
#1 [mir_drops_elaborated_and_const_checked] elaborating drops for `main`
|
#1 [optimized_mir] optimizing MIR for `main`
|
||||||
#2 [optimized_mir] optimizing MIR for `main`
|
#2 [collect_and_partition_mono_items] collect_and_partition_mono_items
|
||||||
#3 [collect_and_partition_mono_items] collect_and_partition_mono_items
|
|
||||||
end of query stack
|
end of query stack
|
||||||
|
|
|
@ -28,14 +28,22 @@ fn f32() {
|
||||||
const MASKED_NAN2: u32 = f32::NAN.to_bits() ^ 0x0055_5555;
|
const MASKED_NAN2: u32 = f32::NAN.to_bits() ^ 0x0055_5555;
|
||||||
|
|
||||||
const_assert!(f32::from_bits(MASKED_NAN1).is_nan());
|
const_assert!(f32::from_bits(MASKED_NAN1).is_nan());
|
||||||
|
//~^ ERROR any use of this value will cause an error
|
||||||
|
//~| WARNING this was previously accepted
|
||||||
const_assert!(f32::from_bits(MASKED_NAN1).is_nan());
|
const_assert!(f32::from_bits(MASKED_NAN1).is_nan());
|
||||||
|
//~^ ERROR any use of this value will cause an error
|
||||||
|
//~| WARNING this was previously accepted
|
||||||
|
|
||||||
// LLVM does not guarantee that loads and stores of NaNs preserve their exact bit pattern.
|
// LLVM does not guarantee that loads and stores of NaNs preserve their exact bit pattern.
|
||||||
// In practice, this seems to only cause a problem on x86, since the most widely used calling
|
// In practice, this seems to only cause a problem on x86, since the most widely used calling
|
||||||
// convention mandates that floating point values are returned on the x87 FPU stack. See #73328.
|
// convention mandates that floating point values are returned on the x87 FPU stack. See #73328.
|
||||||
if !cfg!(target_arch = "x86") {
|
if !cfg!(target_arch = "x86") {
|
||||||
const_assert!(f32::from_bits(MASKED_NAN1).to_bits(), MASKED_NAN1);
|
const_assert!(f32::from_bits(MASKED_NAN1).to_bits(), MASKED_NAN1);
|
||||||
|
//~^ ERROR any use of this value will cause an error
|
||||||
|
//~| WARNING this was previously accepted
|
||||||
const_assert!(f32::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2);
|
const_assert!(f32::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2);
|
||||||
|
//~^ ERROR any use of this value will cause an error
|
||||||
|
//~| WARNING this was previously accepted
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,12 +55,20 @@ fn f64() {
|
||||||
const MASKED_NAN2: u64 = f64::NAN.to_bits() ^ 0x0005_5555_5555_5555;
|
const MASKED_NAN2: u64 = f64::NAN.to_bits() ^ 0x0005_5555_5555_5555;
|
||||||
|
|
||||||
const_assert!(f64::from_bits(MASKED_NAN1).is_nan());
|
const_assert!(f64::from_bits(MASKED_NAN1).is_nan());
|
||||||
|
//~^ ERROR any use of this value will cause an error
|
||||||
|
//~| WARNING this was previously accepted
|
||||||
const_assert!(f64::from_bits(MASKED_NAN1).is_nan());
|
const_assert!(f64::from_bits(MASKED_NAN1).is_nan());
|
||||||
|
//~^ ERROR any use of this value will cause an error
|
||||||
|
//~| WARNING this was previously accepted
|
||||||
|
|
||||||
// See comment above.
|
// See comment above.
|
||||||
if !cfg!(target_arch = "x86") {
|
if !cfg!(target_arch = "x86") {
|
||||||
const_assert!(f64::from_bits(MASKED_NAN1).to_bits(), MASKED_NAN1);
|
const_assert!(f64::from_bits(MASKED_NAN1).to_bits(), MASKED_NAN1);
|
||||||
|
//~^ ERROR any use of this value will cause an error
|
||||||
|
//~| WARNING this was previously accepted
|
||||||
const_assert!(f64::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2);
|
const_assert!(f64::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2);
|
||||||
|
//~^ ERROR any use of this value will cause an error
|
||||||
|
//~| WARNING this was previously accepted
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,6 +56,55 @@ LL | const MASKED_NAN2: u32 = f32::NAN.to_bits() ^ 0x0055_5555;
|
||||||
|
|
|
|
||||||
= note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
error: any use of this value will cause an error
|
||||||
|
--> $DIR/const-float-bits-reject-conv.rs:30:34
|
||||||
|
|
|
||||||
|
LL | const _: () = assert!($a);
|
||||||
|
| --------------------------
|
||||||
|
...
|
||||||
|
LL | const_assert!(f32::from_bits(MASKED_NAN1).is_nan());
|
||||||
|
| ^^^^^^^^^^^ referenced constant has errors
|
||||||
|
|
|
||||||
|
= note: `#[deny(const_err)]` on by default
|
||||||
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||||
|
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
|
||||||
|
|
||||||
|
error: any use of this value will cause an error
|
||||||
|
--> $DIR/const-float-bits-reject-conv.rs:33:34
|
||||||
|
|
|
||||||
|
LL | const _: () = assert!($a);
|
||||||
|
| --------------------------
|
||||||
|
...
|
||||||
|
LL | const_assert!(f32::from_bits(MASKED_NAN1).is_nan());
|
||||||
|
| ^^^^^^^^^^^ referenced constant has errors
|
||||||
|
|
|
||||||
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||||
|
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
|
||||||
|
|
||||||
|
error: any use of this value will cause an error
|
||||||
|
--> $DIR/const-float-bits-reject-conv.rs:41:38
|
||||||
|
|
|
||||||
|
LL | const _: () = assert!($a == $b);
|
||||||
|
| --------------------------------
|
||||||
|
...
|
||||||
|
LL | const_assert!(f32::from_bits(MASKED_NAN1).to_bits(), MASKED_NAN1);
|
||||||
|
| ^^^^^^^^^^^ referenced constant has errors
|
||||||
|
|
|
||||||
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||||
|
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
|
||||||
|
|
||||||
|
error: any use of this value will cause an error
|
||||||
|
--> $DIR/const-float-bits-reject-conv.rs:44:38
|
||||||
|
|
|
||||||
|
LL | const _: () = assert!($a == $b);
|
||||||
|
| --------------------------------
|
||||||
|
...
|
||||||
|
LL | const_assert!(f32::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2);
|
||||||
|
| ^^^^^^^^^^^ referenced constant has errors
|
||||||
|
|
|
||||||
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||||
|
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
|
||||||
|
|
||||||
error[E0080]: evaluation of constant value failed
|
error[E0080]: evaluation of constant value failed
|
||||||
--> $SRC_DIR/core/src/num/f64.rs:LL:COL
|
--> $SRC_DIR/core/src/num/f64.rs:LL:COL
|
||||||
|
|
|
|
||||||
|
@ -78,10 +127,10 @@ LL | extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
|
||||||
LL | called_in_const.call_once(arg)
|
LL | called_in_const.call_once(arg)
|
||||||
| ------------------------------ inside `const_eval_select::<(f64,), fn(f64) -> u64 {core::f64::<impl f64>::to_bits::ct_f64_to_u64}, [closure@core::f64::<impl f64>::to_bits::{closure#0}], u64>` at $SRC_DIR/core/src/intrinsics.rs:LL:COL
|
| ------------------------------ inside `const_eval_select::<(f64,), fn(f64) -> u64 {core::f64::<impl f64>::to_bits::ct_f64_to_u64}, [closure@core::f64::<impl f64>::to_bits::{closure#0}], u64>` at $SRC_DIR/core/src/intrinsics.rs:LL:COL
|
||||||
|
|
|
|
||||||
::: $DIR/const-float-bits-reject-conv.rs:46:30
|
::: $DIR/const-float-bits-reject-conv.rs:54:30
|
||||||
|
|
|
|
||||||
LL | const MASKED_NAN1: u64 = f64::NAN.to_bits() ^ 0x000A_AAAA_AAAA_AAAA;
|
LL | const MASKED_NAN1: u64 = f64::NAN.to_bits() ^ 0x000A_AAAA_AAAA_AAAA;
|
||||||
| ------------------ inside `f64::MASKED_NAN1` at $DIR/const-float-bits-reject-conv.rs:46:30
|
| ------------------ inside `f64::MASKED_NAN1` at $DIR/const-float-bits-reject-conv.rs:54:30
|
||||||
|
|
|
|
||||||
= note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
@ -107,13 +156,61 @@ LL | extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
|
||||||
LL | called_in_const.call_once(arg)
|
LL | called_in_const.call_once(arg)
|
||||||
| ------------------------------ inside `const_eval_select::<(f64,), fn(f64) -> u64 {core::f64::<impl f64>::to_bits::ct_f64_to_u64}, [closure@core::f64::<impl f64>::to_bits::{closure#0}], u64>` at $SRC_DIR/core/src/intrinsics.rs:LL:COL
|
| ------------------------------ inside `const_eval_select::<(f64,), fn(f64) -> u64 {core::f64::<impl f64>::to_bits::ct_f64_to_u64}, [closure@core::f64::<impl f64>::to_bits::{closure#0}], u64>` at $SRC_DIR/core/src/intrinsics.rs:LL:COL
|
||||||
|
|
|
|
||||||
::: $DIR/const-float-bits-reject-conv.rs:47:30
|
::: $DIR/const-float-bits-reject-conv.rs:55:30
|
||||||
|
|
|
|
||||||
LL | const MASKED_NAN2: u64 = f64::NAN.to_bits() ^ 0x0005_5555_5555_5555;
|
LL | const MASKED_NAN2: u64 = f64::NAN.to_bits() ^ 0x0005_5555_5555_5555;
|
||||||
| ------------------ inside `f64::MASKED_NAN2` at $DIR/const-float-bits-reject-conv.rs:47:30
|
| ------------------ inside `f64::MASKED_NAN2` at $DIR/const-float-bits-reject-conv.rs:55:30
|
||||||
|
|
|
|
||||||
= note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: aborting due to 4 previous errors
|
error: any use of this value will cause an error
|
||||||
|
--> $DIR/const-float-bits-reject-conv.rs:57:34
|
||||||
|
|
|
||||||
|
LL | const _: () = assert!($a);
|
||||||
|
| --------------------------
|
||||||
|
...
|
||||||
|
LL | const_assert!(f64::from_bits(MASKED_NAN1).is_nan());
|
||||||
|
| ^^^^^^^^^^^ referenced constant has errors
|
||||||
|
|
|
||||||
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||||
|
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
|
||||||
|
|
||||||
|
error: any use of this value will cause an error
|
||||||
|
--> $DIR/const-float-bits-reject-conv.rs:60:34
|
||||||
|
|
|
||||||
|
LL | const _: () = assert!($a);
|
||||||
|
| --------------------------
|
||||||
|
...
|
||||||
|
LL | const_assert!(f64::from_bits(MASKED_NAN1).is_nan());
|
||||||
|
| ^^^^^^^^^^^ referenced constant has errors
|
||||||
|
|
|
||||||
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||||
|
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
|
||||||
|
|
||||||
|
error: any use of this value will cause an error
|
||||||
|
--> $DIR/const-float-bits-reject-conv.rs:66:38
|
||||||
|
|
|
||||||
|
LL | const _: () = assert!($a == $b);
|
||||||
|
| --------------------------------
|
||||||
|
...
|
||||||
|
LL | const_assert!(f64::from_bits(MASKED_NAN1).to_bits(), MASKED_NAN1);
|
||||||
|
| ^^^^^^^^^^^ referenced constant has errors
|
||||||
|
|
|
||||||
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||||
|
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
|
||||||
|
|
||||||
|
error: any use of this value will cause an error
|
||||||
|
--> $DIR/const-float-bits-reject-conv.rs:69:38
|
||||||
|
|
|
||||||
|
LL | const _: () = assert!($a == $b);
|
||||||
|
| --------------------------------
|
||||||
|
...
|
||||||
|
LL | const_assert!(f64::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2);
|
||||||
|
| ^^^^^^^^^^^ referenced constant has errors
|
||||||
|
|
|
||||||
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||||
|
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
|
||||||
|
|
||||||
|
error: aborting due to 12 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0080`.
|
For more information about this error, try `rustc --explain E0080`.
|
||||||
|
|
|
@ -6,6 +6,7 @@ const X: usize = 42 && 39;
|
||||||
//~| ERROR mismatched types
|
//~| ERROR mismatched types
|
||||||
//~| expected `usize`, found `bool`
|
//~| expected `usize`, found `bool`
|
||||||
const ARR: [i32; X] = [99; 34];
|
const ARR: [i32; X] = [99; 34];
|
||||||
|
//~^ ERROR evaluation of constant value failed
|
||||||
|
|
||||||
const X1: usize = 42 || 39;
|
const X1: usize = 42 || 39;
|
||||||
//~^ ERROR mismatched types
|
//~^ ERROR mismatched types
|
||||||
|
@ -15,6 +16,7 @@ const X1: usize = 42 || 39;
|
||||||
//~| ERROR mismatched types
|
//~| ERROR mismatched types
|
||||||
//~| expected `usize`, found `bool`
|
//~| expected `usize`, found `bool`
|
||||||
const ARR1: [i32; X1] = [99; 47];
|
const ARR1: [i32; X1] = [99; 47];
|
||||||
|
//~^ ERROR evaluation of constant value failed
|
||||||
|
|
||||||
const X2: usize = -42 || -39;
|
const X2: usize = -42 || -39;
|
||||||
//~^ ERROR mismatched types
|
//~^ ERROR mismatched types
|
||||||
|
@ -24,6 +26,7 @@ const X2: usize = -42 || -39;
|
||||||
//~| ERROR mismatched types
|
//~| ERROR mismatched types
|
||||||
//~| expected `usize`, found `bool`
|
//~| expected `usize`, found `bool`
|
||||||
const ARR2: [i32; X2] = [99; 18446744073709551607];
|
const ARR2: [i32; X2] = [99; 18446744073709551607];
|
||||||
|
//~^ ERROR evaluation of constant value failed
|
||||||
|
|
||||||
const X3: usize = -42 && -39;
|
const X3: usize = -42 && -39;
|
||||||
//~^ ERROR mismatched types
|
//~^ ERROR mismatched types
|
||||||
|
@ -33,36 +36,43 @@ const X3: usize = -42 && -39;
|
||||||
//~| ERROR mismatched types
|
//~| ERROR mismatched types
|
||||||
//~| expected `usize`, found `bool`
|
//~| expected `usize`, found `bool`
|
||||||
const ARR3: [i32; X3] = [99; 6];
|
const ARR3: [i32; X3] = [99; 6];
|
||||||
|
//~^ ERROR evaluation of constant value failed
|
||||||
|
|
||||||
const Y: usize = 42.0 == 42.0;
|
const Y: usize = 42.0 == 42.0;
|
||||||
//~^ ERROR mismatched types
|
//~^ ERROR mismatched types
|
||||||
//~| expected `usize`, found `bool`
|
//~| expected `usize`, found `bool`
|
||||||
const ARRR: [i32; Y] = [99; 1];
|
const ARRR: [i32; Y] = [99; 1];
|
||||||
|
//~^ ERROR evaluation of constant value failed
|
||||||
|
|
||||||
const Y1: usize = 42.0 >= 42.0;
|
const Y1: usize = 42.0 >= 42.0;
|
||||||
//~^ ERROR mismatched types
|
//~^ ERROR mismatched types
|
||||||
//~| expected `usize`, found `bool`
|
//~| expected `usize`, found `bool`
|
||||||
const ARRR1: [i32; Y1] = [99; 1];
|
const ARRR1: [i32; Y1] = [99; 1];
|
||||||
|
//~^ ERROR evaluation of constant value failed
|
||||||
|
|
||||||
const Y2: usize = 42.0 <= 42.0;
|
const Y2: usize = 42.0 <= 42.0;
|
||||||
//~^ ERROR mismatched types
|
//~^ ERROR mismatched types
|
||||||
//~| expected `usize`, found `bool`
|
//~| expected `usize`, found `bool`
|
||||||
const ARRR2: [i32; Y2] = [99; 1];
|
const ARRR2: [i32; Y2] = [99; 1];
|
||||||
|
//~^ ERROR evaluation of constant value failed
|
||||||
|
|
||||||
const Y3: usize = 42.0 > 42.0;
|
const Y3: usize = 42.0 > 42.0;
|
||||||
//~^ ERROR mismatched types
|
//~^ ERROR mismatched types
|
||||||
//~| expected `usize`, found `bool`
|
//~| expected `usize`, found `bool`
|
||||||
const ARRR3: [i32; Y3] = [99; 0];
|
const ARRR3: [i32; Y3] = [99; 0];
|
||||||
|
//~^ ERROR evaluation of constant value failed
|
||||||
|
|
||||||
const Y4: usize = 42.0 < 42.0;
|
const Y4: usize = 42.0 < 42.0;
|
||||||
//~^ ERROR mismatched types
|
//~^ ERROR mismatched types
|
||||||
//~| expected `usize`, found `bool`
|
//~| expected `usize`, found `bool`
|
||||||
const ARRR4: [i32; Y4] = [99; 0];
|
const ARRR4: [i32; Y4] = [99; 0];
|
||||||
|
//~^ ERROR evaluation of constant value failed
|
||||||
|
|
||||||
const Y5: usize = 42.0 != 42.0;
|
const Y5: usize = 42.0 != 42.0;
|
||||||
//~^ ERROR mismatched types
|
//~^ ERROR mismatched types
|
||||||
//~| expected `usize`, found `bool`
|
//~| expected `usize`, found `bool`
|
||||||
const ARRR5: [i32; Y5] = [99; 0];
|
const ARRR5: [i32; Y5] = [99; 0];
|
||||||
|
//~^ ERROR evaluation of constant value failed
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let _ = ARR;
|
let _ = ARR;
|
||||||
|
|
|
@ -16,96 +16,157 @@ error[E0308]: mismatched types
|
||||||
LL | const X: usize = 42 && 39;
|
LL | const X: usize = 42 && 39;
|
||||||
| ^^^^^^^^ expected `usize`, found `bool`
|
| ^^^^^^^^ expected `usize`, found `bool`
|
||||||
|
|
||||||
|
error[E0080]: evaluation of constant value failed
|
||||||
|
--> $DIR/const-integer-bool-ops.rs:8:18
|
||||||
|
|
|
||||||
|
LL | const ARR: [i32; X] = [99; 34];
|
||||||
|
| ^ referenced constant has errors
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/const-integer-bool-ops.rs:10:19
|
--> $DIR/const-integer-bool-ops.rs:11:19
|
||||||
|
|
|
|
||||||
LL | const X1: usize = 42 || 39;
|
LL | const X1: usize = 42 || 39;
|
||||||
| ^^ expected `bool`, found integer
|
| ^^ expected `bool`, found integer
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/const-integer-bool-ops.rs:10:25
|
--> $DIR/const-integer-bool-ops.rs:11:25
|
||||||
|
|
|
|
||||||
LL | const X1: usize = 42 || 39;
|
LL | const X1: usize = 42 || 39;
|
||||||
| ^^ expected `bool`, found integer
|
| ^^ expected `bool`, found integer
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/const-integer-bool-ops.rs:10:19
|
--> $DIR/const-integer-bool-ops.rs:11:19
|
||||||
|
|
|
|
||||||
LL | const X1: usize = 42 || 39;
|
LL | const X1: usize = 42 || 39;
|
||||||
| ^^^^^^^^ expected `usize`, found `bool`
|
| ^^^^^^^^ expected `usize`, found `bool`
|
||||||
|
|
||||||
|
error[E0080]: evaluation of constant value failed
|
||||||
|
--> $DIR/const-integer-bool-ops.rs:18:19
|
||||||
|
|
|
||||||
|
LL | const ARR1: [i32; X1] = [99; 47];
|
||||||
|
| ^^ referenced constant has errors
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/const-integer-bool-ops.rs:19:19
|
--> $DIR/const-integer-bool-ops.rs:21:19
|
||||||
|
|
|
|
||||||
LL | const X2: usize = -42 || -39;
|
LL | const X2: usize = -42 || -39;
|
||||||
| ^^^ expected `bool`, found integer
|
| ^^^ expected `bool`, found integer
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/const-integer-bool-ops.rs:19:26
|
--> $DIR/const-integer-bool-ops.rs:21:26
|
||||||
|
|
|
|
||||||
LL | const X2: usize = -42 || -39;
|
LL | const X2: usize = -42 || -39;
|
||||||
| ^^^ expected `bool`, found integer
|
| ^^^ expected `bool`, found integer
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/const-integer-bool-ops.rs:19:19
|
--> $DIR/const-integer-bool-ops.rs:21:19
|
||||||
|
|
|
|
||||||
LL | const X2: usize = -42 || -39;
|
LL | const X2: usize = -42 || -39;
|
||||||
| ^^^^^^^^^^ expected `usize`, found `bool`
|
| ^^^^^^^^^^ expected `usize`, found `bool`
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0080]: evaluation of constant value failed
|
||||||
--> $DIR/const-integer-bool-ops.rs:28:19
|
--> $DIR/const-integer-bool-ops.rs:28:19
|
||||||
|
|
|
|
||||||
|
LL | const ARR2: [i32; X2] = [99; 18446744073709551607];
|
||||||
|
| ^^ referenced constant has errors
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/const-integer-bool-ops.rs:31:19
|
||||||
|
|
|
||||||
LL | const X3: usize = -42 && -39;
|
LL | const X3: usize = -42 && -39;
|
||||||
| ^^^ expected `bool`, found integer
|
| ^^^ expected `bool`, found integer
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/const-integer-bool-ops.rs:28:26
|
--> $DIR/const-integer-bool-ops.rs:31:26
|
||||||
|
|
|
|
||||||
LL | const X3: usize = -42 && -39;
|
LL | const X3: usize = -42 && -39;
|
||||||
| ^^^ expected `bool`, found integer
|
| ^^^ expected `bool`, found integer
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/const-integer-bool-ops.rs:28:19
|
--> $DIR/const-integer-bool-ops.rs:31:19
|
||||||
|
|
|
|
||||||
LL | const X3: usize = -42 && -39;
|
LL | const X3: usize = -42 && -39;
|
||||||
| ^^^^^^^^^^ expected `usize`, found `bool`
|
| ^^^^^^^^^^ expected `usize`, found `bool`
|
||||||
|
|
||||||
|
error[E0080]: evaluation of constant value failed
|
||||||
|
--> $DIR/const-integer-bool-ops.rs:38:19
|
||||||
|
|
|
||||||
|
LL | const ARR3: [i32; X3] = [99; 6];
|
||||||
|
| ^^ referenced constant has errors
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/const-integer-bool-ops.rs:37:18
|
--> $DIR/const-integer-bool-ops.rs:41:18
|
||||||
|
|
|
|
||||||
LL | const Y: usize = 42.0 == 42.0;
|
LL | const Y: usize = 42.0 == 42.0;
|
||||||
| ^^^^^^^^^^^^ expected `usize`, found `bool`
|
| ^^^^^^^^^^^^ expected `usize`, found `bool`
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0080]: evaluation of constant value failed
|
||||||
--> $DIR/const-integer-bool-ops.rs:42:19
|
--> $DIR/const-integer-bool-ops.rs:44:19
|
||||||
|
|
|
|
||||||
LL | const Y1: usize = 42.0 >= 42.0;
|
LL | const ARRR: [i32; Y] = [99; 1];
|
||||||
| ^^^^^^^^^^^^ expected `usize`, found `bool`
|
| ^ referenced constant has errors
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/const-integer-bool-ops.rs:47:19
|
--> $DIR/const-integer-bool-ops.rs:47:19
|
||||||
|
|
|
|
||||||
|
LL | const Y1: usize = 42.0 >= 42.0;
|
||||||
|
| ^^^^^^^^^^^^ expected `usize`, found `bool`
|
||||||
|
|
||||||
|
error[E0080]: evaluation of constant value failed
|
||||||
|
--> $DIR/const-integer-bool-ops.rs:50:20
|
||||||
|
|
|
||||||
|
LL | const ARRR1: [i32; Y1] = [99; 1];
|
||||||
|
| ^^ referenced constant has errors
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/const-integer-bool-ops.rs:53:19
|
||||||
|
|
|
||||||
LL | const Y2: usize = 42.0 <= 42.0;
|
LL | const Y2: usize = 42.0 <= 42.0;
|
||||||
| ^^^^^^^^^^^^ expected `usize`, found `bool`
|
| ^^^^^^^^^^^^ expected `usize`, found `bool`
|
||||||
|
|
||||||
|
error[E0080]: evaluation of constant value failed
|
||||||
|
--> $DIR/const-integer-bool-ops.rs:56:20
|
||||||
|
|
|
||||||
|
LL | const ARRR2: [i32; Y2] = [99; 1];
|
||||||
|
| ^^ referenced constant has errors
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/const-integer-bool-ops.rs:52:19
|
--> $DIR/const-integer-bool-ops.rs:59:19
|
||||||
|
|
|
|
||||||
LL | const Y3: usize = 42.0 > 42.0;
|
LL | const Y3: usize = 42.0 > 42.0;
|
||||||
| ^^^^^^^^^^^ expected `usize`, found `bool`
|
| ^^^^^^^^^^^ expected `usize`, found `bool`
|
||||||
|
|
||||||
|
error[E0080]: evaluation of constant value failed
|
||||||
|
--> $DIR/const-integer-bool-ops.rs:62:20
|
||||||
|
|
|
||||||
|
LL | const ARRR3: [i32; Y3] = [99; 0];
|
||||||
|
| ^^ referenced constant has errors
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/const-integer-bool-ops.rs:57:19
|
--> $DIR/const-integer-bool-ops.rs:65:19
|
||||||
|
|
|
|
||||||
LL | const Y4: usize = 42.0 < 42.0;
|
LL | const Y4: usize = 42.0 < 42.0;
|
||||||
| ^^^^^^^^^^^ expected `usize`, found `bool`
|
| ^^^^^^^^^^^ expected `usize`, found `bool`
|
||||||
|
|
||||||
|
error[E0080]: evaluation of constant value failed
|
||||||
|
--> $DIR/const-integer-bool-ops.rs:68:20
|
||||||
|
|
|
||||||
|
LL | const ARRR4: [i32; Y4] = [99; 0];
|
||||||
|
| ^^ referenced constant has errors
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/const-integer-bool-ops.rs:62:19
|
--> $DIR/const-integer-bool-ops.rs:71:19
|
||||||
|
|
|
|
||||||
LL | const Y5: usize = 42.0 != 42.0;
|
LL | const Y5: usize = 42.0 != 42.0;
|
||||||
| ^^^^^^^^^^^^ expected `usize`, found `bool`
|
| ^^^^^^^^^^^^ expected `usize`, found `bool`
|
||||||
|
|
||||||
error: aborting due to 18 previous errors
|
error[E0080]: evaluation of constant value failed
|
||||||
|
--> $DIR/const-integer-bool-ops.rs:74:20
|
||||||
|
|
|
||||||
|
LL | const ARRR5: [i32; Y5] = [99; 0];
|
||||||
|
| ^^ referenced constant has errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0308`.
|
error: aborting due to 28 previous errors
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0080, E0308.
|
||||||
|
For more information about an error, try `rustc --explain E0080`.
|
||||||
|
|
|
@ -19,7 +19,13 @@ error[E0596]: cannot borrow data in a `&` reference as mutable
|
||||||
LL | const S: &'static mut str = &mut " hello ";
|
LL | const S: &'static mut str = &mut " hello ";
|
||||||
| ^^^^^^^^^^^^^^ cannot borrow as mutable
|
| ^^^^^^^^^^^^^^ cannot borrow as mutable
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error[E0080]: evaluation of constant value failed
|
||||||
|
--> $DIR/issue-76510.rs:11:70
|
||||||
|
|
|
||||||
|
LL | let s = transmute::<(*const u8, usize), &ManuallyDrop<str>>((S.as_ptr(), 3));
|
||||||
|
| ^ referenced constant has errors
|
||||||
|
|
||||||
Some errors have detailed explanations: E0596, E0658, E0764.
|
error: aborting due to 4 previous errors
|
||||||
For more information about an error, try `rustc --explain E0596`.
|
|
||||||
|
Some errors have detailed explanations: E0080, E0596, E0658, E0764.
|
||||||
|
For more information about an error, try `rustc --explain E0080`.
|
||||||
|
|
|
@ -9,6 +9,7 @@ const S: &'static mut str = &mut " hello ";
|
||||||
|
|
||||||
const fn trigger() -> [(); unsafe {
|
const fn trigger() -> [(); unsafe {
|
||||||
let s = transmute::<(*const u8, usize), &ManuallyDrop<str>>((S.as_ptr(), 3));
|
let s = transmute::<(*const u8, usize), &ManuallyDrop<str>>((S.as_ptr(), 3));
|
||||||
|
//~^ ERROR evaluation of constant value failed
|
||||||
0
|
0
|
||||||
}] {
|
}] {
|
||||||
[(); 0]
|
[(); 0]
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
error[E0391]: cycle detected when simplifying constant for the type system `Foo::bytes::{constant#0}`
|
error[E0391]: cycle detected when evaluate type-level constant
|
||||||
--> $DIR/const-size_of-cycle.rs:4:17
|
--> $DIR/const-size_of-cycle.rs:4:17
|
||||||
|
|
|
|
||||||
LL | bytes: [u8; std::mem::size_of::<Foo>()]
|
LL | bytes: [u8; std::mem::size_of::<Foo>()]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: ...which requires simplifying constant for the type system `Foo::bytes::{constant#0}`...
|
note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`...
|
||||||
--> $DIR/const-size_of-cycle.rs:4:17
|
--> $DIR/const-size_of-cycle.rs:4:17
|
||||||
|
|
|
|
||||||
LL | bytes: [u8; std::mem::size_of::<Foo>()]
|
LL | bytes: [u8; std::mem::size_of::<Foo>()]
|
||||||
|
@ -17,7 +17,7 @@ LL | bytes: [u8; std::mem::size_of::<Foo>()]
|
||||||
= note: ...which requires computing layout of `Foo`...
|
= note: ...which requires computing layout of `Foo`...
|
||||||
= note: ...which requires computing layout of `[u8; _]`...
|
= note: ...which requires computing layout of `[u8; _]`...
|
||||||
= note: ...which requires normalizing `[u8; _]`...
|
= note: ...which requires normalizing `[u8; _]`...
|
||||||
= note: ...which again requires simplifying constant for the type system `Foo::bytes::{constant#0}`, completing the cycle
|
= note: ...which again requires evaluate type-level constant, completing the cycle
|
||||||
note: cycle used when checking that `Foo` is well-formed
|
note: cycle used when checking that `Foo` is well-formed
|
||||||
--> $DIR/const-size_of-cycle.rs:3:1
|
--> $DIR/const-size_of-cycle.rs:3:1
|
||||||
|
|
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ const TUP: (usize,) = 5usize << 64;
|
||||||
//~^ ERROR mismatched types
|
//~^ ERROR mismatched types
|
||||||
//~| expected tuple, found `usize`
|
//~| expected tuple, found `usize`
|
||||||
const ARR: [i32; TUP.0] = [];
|
const ARR: [i32; TUP.0] = [];
|
||||||
|
//~^ ERROR evaluation of constant value failed
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,13 @@ help: use a trailing comma to create a tuple with one element
|
||||||
LL | const TUP: (usize,) = (5usize << 64,);
|
LL | const TUP: (usize,) = (5usize << 64,);
|
||||||
| + ++
|
| + ++
|
||||||
|
|
||||||
error: aborting due to previous error
|
error[E0080]: evaluation of constant value failed
|
||||||
|
--> $DIR/const-tup-index-span.rs:6:18
|
||||||
|
|
|
||||||
|
LL | const ARR: [i32; TUP.0] = [];
|
||||||
|
| ^^^ referenced constant has errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0308`.
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0080, E0308.
|
||||||
|
For more information about an error, try `rustc --explain E0080`.
|
||||||
|
|
|
@ -6,7 +6,7 @@ LL | fn main() {
|
||||||
|
|
|
|
||||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||||
= note: the raw bytes of the constant (size: 8, align: 8) {
|
= note: the raw bytes of the constant (size: 8, align: 8) {
|
||||||
╾───────alloc8────────╼ │ ╾──────╼
|
╾───────alloc7────────╼ │ ╾──────╼
|
||||||
}
|
}
|
||||||
|
|
||||||
error: erroneous constant used
|
error: erroneous constant used
|
||||||
|
|
|
@ -1,48 +1,20 @@
|
||||||
error[E0391]: cycle detected when simplifying constant for the type system `Foo::B::{constant#0}`
|
error[E0391]: cycle detected when const-evaluating + checking `Foo::B::{constant#0}`
|
||||||
--> $DIR/issue-36163.rs:4:9
|
--> $DIR/issue-36163.rs:4:9
|
||||||
|
|
|
|
||||||
LL | B = A,
|
LL | B = A,
|
||||||
| ^
|
| ^
|
||||||
|
|
|
|
||||||
note: ...which requires simplifying constant for the type system `Foo::B::{constant#0}`...
|
|
||||||
--> $DIR/issue-36163.rs:4:9
|
|
||||||
|
|
|
||||||
LL | B = A,
|
|
||||||
| ^
|
|
||||||
note: ...which requires const-evaluating + checking `Foo::B::{constant#0}`...
|
|
||||||
--> $DIR/issue-36163.rs:4:9
|
|
||||||
|
|
|
||||||
LL | B = A,
|
|
||||||
| ^
|
|
||||||
= note: ...which requires normalizing `A`...
|
|
||||||
note: ...which requires simplifying constant for the type system `A`...
|
|
||||||
--> $DIR/issue-36163.rs:1:1
|
|
||||||
|
|
|
||||||
LL | const A: isize = Foo::B as isize;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires simplifying constant for the type system `A`...
|
|
||||||
--> $DIR/issue-36163.rs:1:1
|
|
||||||
|
|
|
||||||
LL | const A: isize = Foo::B as isize;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires const-evaluating + checking `A`...
|
note: ...which requires const-evaluating + checking `A`...
|
||||||
--> $DIR/issue-36163.rs:1:1
|
--> $DIR/issue-36163.rs:1:1
|
||||||
|
|
|
|
||||||
LL | const A: isize = Foo::B as isize;
|
LL | const A: isize = Foo::B as isize;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
= note: ...which requires normalizing `A`...
|
= note: ...which again requires const-evaluating + checking `Foo::B::{constant#0}`, completing the cycle
|
||||||
= note: ...which again requires simplifying constant for the type system `Foo::B::{constant#0}`, completing the cycle
|
note: cycle used when simplifying constant for the type system `Foo::B::{constant#0}`
|
||||||
note: cycle used when collecting item types in top-level module
|
--> $DIR/issue-36163.rs:4:9
|
||||||
--> $DIR/issue-36163.rs:1:1
|
|
||||||
|
|
|
|
||||||
LL | / const A: isize = Foo::B as isize;
|
LL | B = A,
|
||||||
LL | |
|
| ^
|
||||||
LL | | enum Foo {
|
|
||||||
LL | | B = A,
|
|
||||||
LL | | }
|
|
||||||
LL | |
|
|
||||||
LL | | fn main() {}
|
|
||||||
| |____________^
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ use std::intrinsics;
|
||||||
|
|
||||||
struct Foo {
|
struct Foo {
|
||||||
bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
|
bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
|
||||||
//~^ ERROR cycle detected when simplifying constant for the type system
|
//~^ ERROR cycle detected when evaluate type-level constant
|
||||||
x: usize,
|
x: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
error[E0391]: cycle detected when simplifying constant for the type system `Foo::bytes::{constant#0}`
|
error[E0391]: cycle detected when evaluate type-level constant
|
||||||
--> $DIR/issue-44415.rs:6:17
|
--> $DIR/issue-44415.rs:6:17
|
||||||
|
|
|
|
||||||
LL | bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
|
LL | bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
|
|
|
||||||
note: ...which requires simplifying constant for the type system `Foo::bytes::{constant#0}`...
|
note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`...
|
||||||
--> $DIR/issue-44415.rs:6:17
|
--> $DIR/issue-44415.rs:6:17
|
||||||
|
|
|
|
||||||
LL | bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
|
LL | bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
|
||||||
|
@ -17,7 +17,7 @@ LL | bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
|
||||||
= note: ...which requires computing layout of `Foo`...
|
= note: ...which requires computing layout of `Foo`...
|
||||||
= note: ...which requires computing layout of `[u8; _]`...
|
= note: ...which requires computing layout of `[u8; _]`...
|
||||||
= note: ...which requires normalizing `[u8; _]`...
|
= note: ...which requires normalizing `[u8; _]`...
|
||||||
= note: ...which again requires simplifying constant for the type system `Foo::bytes::{constant#0}`, completing the cycle
|
= note: ...which again requires evaluate type-level constant, completing the cycle
|
||||||
note: cycle used when checking that `Foo` is well-formed
|
note: cycle used when checking that `Foo` is well-formed
|
||||||
--> $DIR/issue-44415.rs:5:1
|
--> $DIR/issue-44415.rs:5:1
|
||||||
|
|
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// build-pass
|
// check-pass
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let _ = &[(); usize::MAX];
|
let _ = &[(); usize::MAX];
|
||||||
|
|
|
@ -1,21 +1,10 @@
|
||||||
error[E0391]: cycle detected when normalizing `FOO`
|
error[E0391]: cycle detected when const-evaluating + checking `FOO`
|
||||||
|
|
|
||||||
note: ...which requires simplifying constant for the type system `FOO`...
|
|
||||||
--> $DIR/issue-17252.rs:1:1
|
--> $DIR/issue-17252.rs:1:1
|
||||||
|
|
|
|
||||||
LL | const FOO: usize = FOO;
|
LL | const FOO: usize = FOO;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
note: ...which requires simplifying constant for the type system `FOO`...
|
|
||||||
--> $DIR/issue-17252.rs:1:1
|
|
||||||
|
|
|
|
||||||
LL | const FOO: usize = FOO;
|
= note: ...which immediately requires const-evaluating + checking `FOO` again
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires const-evaluating + checking `FOO`...
|
|
||||||
--> $DIR/issue-17252.rs:1:1
|
|
||||||
|
|
|
||||||
LL | const FOO: usize = FOO;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
= note: ...which again requires normalizing `FOO`, completing the cycle
|
|
||||||
note: cycle used when const-evaluating + checking `main::{constant#0}`
|
note: cycle used when const-evaluating + checking `main::{constant#0}`
|
||||||
--> $DIR/issue-17252.rs:4:18
|
--> $DIR/issue-17252.rs:4:18
|
||||||
|
|
|
|
||||||
|
|
|
@ -1,26 +1,15 @@
|
||||||
error[E0391]: cycle detected when simplifying constant for the type system `X::A::{constant#0}`
|
error[E0391]: cycle detected when const-evaluating + checking `X::A::{constant#0}`
|
||||||
--> $DIR/issue-23302-1.rs:4:9
|
--> $DIR/issue-23302-1.rs:4:9
|
||||||
|
|
|
|
||||||
LL | A = X::A as isize,
|
LL | A = X::A as isize,
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: ...which requires simplifying constant for the type system `X::A::{constant#0}`...
|
= note: ...which immediately requires const-evaluating + checking `X::A::{constant#0}` again
|
||||||
|
note: cycle used when simplifying constant for the type system `X::A::{constant#0}`
|
||||||
--> $DIR/issue-23302-1.rs:4:9
|
--> $DIR/issue-23302-1.rs:4:9
|
||||||
|
|
|
|
||||||
LL | A = X::A as isize,
|
LL | A = X::A as isize,
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^
|
||||||
note: ...which requires const-evaluating + checking `X::A::{constant#0}`...
|
|
||||||
--> $DIR/issue-23302-1.rs:4:9
|
|
||||||
|
|
|
||||||
LL | A = X::A as isize,
|
|
||||||
| ^^^^^^^^^^^^^
|
|
||||||
= note: ...which requires normalizing `X::A as isize`...
|
|
||||||
= note: ...which again requires simplifying constant for the type system `X::A::{constant#0}`, completing the cycle
|
|
||||||
note: cycle used when collecting item types in top-level module
|
|
||||||
--> $DIR/issue-23302-1.rs:3:1
|
|
||||||
|
|
|
||||||
LL | enum X {
|
|
||||||
| ^^^^^^
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -1,26 +1,15 @@
|
||||||
error[E0391]: cycle detected when simplifying constant for the type system `Y::A::{constant#0}`
|
error[E0391]: cycle detected when const-evaluating + checking `Y::A::{constant#0}`
|
||||||
--> $DIR/issue-23302-2.rs:4:9
|
--> $DIR/issue-23302-2.rs:4:9
|
||||||
|
|
|
|
||||||
LL | A = Y::B as isize,
|
LL | A = Y::B as isize,
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: ...which requires simplifying constant for the type system `Y::A::{constant#0}`...
|
= note: ...which immediately requires const-evaluating + checking `Y::A::{constant#0}` again
|
||||||
|
note: cycle used when simplifying constant for the type system `Y::A::{constant#0}`
|
||||||
--> $DIR/issue-23302-2.rs:4:9
|
--> $DIR/issue-23302-2.rs:4:9
|
||||||
|
|
|
|
||||||
LL | A = Y::B as isize,
|
LL | A = Y::B as isize,
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^
|
||||||
note: ...which requires const-evaluating + checking `Y::A::{constant#0}`...
|
|
||||||
--> $DIR/issue-23302-2.rs:4:9
|
|
||||||
|
|
|
||||||
LL | A = Y::B as isize,
|
|
||||||
| ^^^^^^^^^^^^^
|
|
||||||
= note: ...which requires normalizing `Y::B as isize`...
|
|
||||||
= note: ...which again requires simplifying constant for the type system `Y::A::{constant#0}`, completing the cycle
|
|
||||||
note: cycle used when collecting item types in top-level module
|
|
||||||
--> $DIR/issue-23302-2.rs:3:1
|
|
||||||
|
|
|
||||||
LL | enum Y {
|
|
||||||
| ^^^^^^
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -1,38 +1,20 @@
|
||||||
error[E0391]: cycle detected when simplifying constant for the type system `A`
|
error[E0391]: cycle detected when const-evaluating + checking `A`
|
||||||
--> $DIR/issue-23302-3.rs:1:1
|
--> $DIR/issue-23302-3.rs:1:1
|
||||||
|
|
|
|
||||||
LL | const A: i32 = B;
|
LL | const A: i32 = B;
|
||||||
| ^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: ...which requires simplifying constant for the type system `A`...
|
|
||||||
--> $DIR/issue-23302-3.rs:1:1
|
|
||||||
|
|
|
||||||
LL | const A: i32 = B;
|
|
||||||
| ^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires const-evaluating + checking `A`...
|
|
||||||
--> $DIR/issue-23302-3.rs:1:1
|
|
||||||
|
|
|
||||||
LL | const A: i32 = B;
|
|
||||||
| ^^^^^^^^^^^^^^^^^
|
|
||||||
= note: ...which requires normalizing `B`...
|
|
||||||
note: ...which requires simplifying constant for the type system `B`...
|
|
||||||
--> $DIR/issue-23302-3.rs:3:1
|
|
||||||
|
|
|
||||||
LL | const B: i32 = A;
|
|
||||||
| ^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires simplifying constant for the type system `B`...
|
|
||||||
--> $DIR/issue-23302-3.rs:3:1
|
|
||||||
|
|
|
||||||
LL | const B: i32 = A;
|
|
||||||
| ^^^^^^^^^^^^^^^^^
|
|
||||||
note: ...which requires const-evaluating + checking `B`...
|
note: ...which requires const-evaluating + checking `B`...
|
||||||
--> $DIR/issue-23302-3.rs:3:1
|
--> $DIR/issue-23302-3.rs:3:1
|
||||||
|
|
|
|
||||||
LL | const B: i32 = A;
|
LL | const B: i32 = A;
|
||||||
| ^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^
|
||||||
= note: ...which requires normalizing `A`...
|
= note: ...which again requires const-evaluating + checking `A`, completing the cycle
|
||||||
= note: ...which again requires simplifying constant for the type system `A`, completing the cycle
|
note: cycle used when simplifying constant for the type system `A`
|
||||||
= note: cycle used when running analysis passes on this crate
|
--> $DIR/issue-23302-3.rs:1:1
|
||||||
|
|
|
||||||
|
LL | const A: i32 = B;
|
||||||
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ enum Foo {
|
||||||
|
|
||||||
enum Bar {
|
enum Bar {
|
||||||
A = Foo::A as isize
|
A = Foo::A as isize
|
||||||
|
//~^ ERROR evaluation of constant value failed
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue