mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
Get rid of const eval_* and try_eval_* helpers
This commit is contained in:
parent
a2a1206811
commit
e83e4e8112
@ -187,10 +187,10 @@ fn do_mir_borrowck<'tcx>(
|
|||||||
|
|
||||||
let location_table = LocationTable::new(body);
|
let location_table = LocationTable::new(body);
|
||||||
|
|
||||||
let move_data = MoveData::gather_moves(body, tcx, param_env, |_| true);
|
let move_data = MoveData::gather_moves(body, tcx, |_| true);
|
||||||
let promoted_move_data = promoted
|
let promoted_move_data = promoted
|
||||||
.iter_enumerated()
|
.iter_enumerated()
|
||||||
.map(|(idx, body)| (idx, MoveData::gather_moves(body, tcx, param_env, |_| true)));
|
.map(|(idx, body)| (idx, MoveData::gather_moves(body, tcx, |_| true)));
|
||||||
|
|
||||||
let mut flow_inits = MaybeInitializedPlaces::new(tcx, body, &move_data)
|
let mut flow_inits = MaybeInitializedPlaces::new(tcx, body, &move_data)
|
||||||
.into_engine(tcx, body)
|
.into_engine(tcx, body)
|
||||||
|
@ -1128,7 +1128,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
let projected_ty = curr_projected_ty.projection_ty_core(
|
let projected_ty = curr_projected_ty.projection_ty_core(
|
||||||
tcx,
|
tcx,
|
||||||
self.param_env,
|
|
||||||
proj,
|
proj,
|
||||||
|this, field, ()| {
|
|this, field, ()| {
|
||||||
let ty = this.field_ty(tcx, field);
|
let ty = this.field_ty(tcx, field);
|
||||||
@ -1919,7 +1918,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||||||
// than 1.
|
// than 1.
|
||||||
// If the length is larger than 1, the repeat expression will need to copy the
|
// If the length is larger than 1, the repeat expression will need to copy the
|
||||||
// element, so we require the `Copy` trait.
|
// element, so we require the `Copy` trait.
|
||||||
if len.try_eval_target_usize(tcx, self.param_env).map_or(true, |len| len > 1) {
|
if len.try_to_target_usize(tcx).is_none_or(|len| len > 1) {
|
||||||
match operand {
|
match operand {
|
||||||
Operand::Copy(..) | Operand::Constant(..) => {
|
Operand::Copy(..) | Operand::Constant(..) => {
|
||||||
// These are always okay: direct use of a const, or a value that can evidently be copied.
|
// These are always okay: direct use of a const, or a value that can evidently be copied.
|
||||||
|
@ -1177,8 +1177,10 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||||||
ty::Uint(i) if i.bit_width() == Some(expected_int_bits) => args[0].immediate(),
|
ty::Uint(i) if i.bit_width() == Some(expected_int_bits) => args[0].immediate(),
|
||||||
ty::Array(elem, len)
|
ty::Array(elem, len)
|
||||||
if matches!(elem.kind(), ty::Uint(ty::UintTy::U8))
|
if matches!(elem.kind(), ty::Uint(ty::UintTy::U8))
|
||||||
&& len.try_eval_target_usize(bx.tcx, ty::ParamEnv::reveal_all())
|
&& len
|
||||||
== Some(expected_bytes) =>
|
.try_to_target_usize(bx.tcx)
|
||||||
|
.expect("expected monomorphic const in codegen")
|
||||||
|
== expected_bytes =>
|
||||||
{
|
{
|
||||||
let place = PlaceRef::alloca(bx, args[0].layout);
|
let place = PlaceRef::alloca(bx, args[0].layout);
|
||||||
args[0].val.store(bx, place);
|
args[0].val.store(bx, place);
|
||||||
@ -1243,12 +1245,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if name == sym::simd_shuffle_generic {
|
if name == sym::simd_shuffle_generic {
|
||||||
let idx = fn_args[2]
|
let idx = fn_args[2].expect_const().try_to_valtree().unwrap().0.unwrap_branch();
|
||||||
.expect_const()
|
|
||||||
.eval(tcx, ty::ParamEnv::reveal_all(), span)
|
|
||||||
.unwrap()
|
|
||||||
.1
|
|
||||||
.unwrap_branch();
|
|
||||||
let n = idx.len() as u64;
|
let n = idx.len() as u64;
|
||||||
|
|
||||||
let (out_len, out_ty) = require_simd!(ret_ty, SimdReturn);
|
let (out_len, out_ty) = require_simd!(ret_ty, SimdReturn);
|
||||||
@ -1467,8 +1464,10 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||||||
}
|
}
|
||||||
ty::Array(elem, len)
|
ty::Array(elem, len)
|
||||||
if matches!(elem.kind(), ty::Uint(ty::UintTy::U8))
|
if matches!(elem.kind(), ty::Uint(ty::UintTy::U8))
|
||||||
&& len.try_eval_target_usize(bx.tcx, ty::ParamEnv::reveal_all())
|
&& len
|
||||||
== Some(expected_bytes) =>
|
.try_to_target_usize(bx.tcx)
|
||||||
|
.expect("expected monomorphic const in codegen")
|
||||||
|
== expected_bytes =>
|
||||||
{
|
{
|
||||||
// Zero-extend iN to the array length:
|
// Zero-extend iN to the array length:
|
||||||
let ze = bx.zext(i_, bx.type_ix(expected_bytes * 8));
|
let ze = bx.zext(i_, bx.type_ix(expected_bytes * 8));
|
||||||
|
@ -23,7 +23,6 @@ use rustc_middle::ty::layout::{IntegerExt, TyAndLayout};
|
|||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self, ExistentialProjection, GenericArgKind, GenericArgsRef, ParamEnv, Ty, TyCtxt,
|
self, ExistentialProjection, GenericArgKind, GenericArgsRef, ParamEnv, Ty, TyCtxt,
|
||||||
};
|
};
|
||||||
use rustc_span::DUMMY_SP;
|
|
||||||
use rustc_target::abi::Integer;
|
use rustc_target::abi::Integer;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
@ -685,21 +684,25 @@ fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut S
|
|||||||
ty::ConstKind::Param(param) => {
|
ty::ConstKind::Param(param) => {
|
||||||
write!(output, "{}", param.name)
|
write!(output, "{}", param.name)
|
||||||
}
|
}
|
||||||
ty::ConstKind::Value(ty, _) => {
|
ty::ConstKind::Value(ty, valtree) => {
|
||||||
match ty.kind() {
|
match ty.kind() {
|
||||||
ty::Int(ity) => {
|
ty::Int(ity) => {
|
||||||
// FIXME: directly extract the bits from a valtree instead of evaluating an
|
// FIXME: directly extract the bits from a valtree instead of evaluating an
|
||||||
// already evaluated `Const` in order to get the bits.
|
// already evaluated `Const` in order to get the bits.
|
||||||
let bits = ct.eval_bits(tcx, ty::ParamEnv::reveal_all());
|
let bits = ct
|
||||||
|
.try_to_bits(tcx, ty::ParamEnv::reveal_all())
|
||||||
|
.expect("expected monomorphic const in codegen");
|
||||||
let val = Integer::from_int_ty(&tcx, *ity).size().sign_extend(bits) as i128;
|
let val = Integer::from_int_ty(&tcx, *ity).size().sign_extend(bits) as i128;
|
||||||
write!(output, "{val}")
|
write!(output, "{val}")
|
||||||
}
|
}
|
||||||
ty::Uint(_) => {
|
ty::Uint(_) => {
|
||||||
let val = ct.eval_bits(tcx, ty::ParamEnv::reveal_all());
|
let val = ct
|
||||||
|
.try_to_bits(tcx, ty::ParamEnv::reveal_all())
|
||||||
|
.expect("expected monomorphic const in codegen");
|
||||||
write!(output, "{val}")
|
write!(output, "{val}")
|
||||||
}
|
}
|
||||||
ty::Bool => {
|
ty::Bool => {
|
||||||
let val = ct.try_eval_bool(tcx, ty::ParamEnv::reveal_all()).unwrap();
|
let val = ct.try_to_bool().expect("expected monomorphic const in codegen");
|
||||||
write!(output, "{val}")
|
write!(output, "{val}")
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@ -711,8 +714,9 @@ fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut S
|
|||||||
// avoiding collisions and will make the emitted type names shorter.
|
// avoiding collisions and will make the emitted type names shorter.
|
||||||
let hash_short = tcx.with_stable_hashing_context(|mut hcx| {
|
let hash_short = tcx.with_stable_hashing_context(|mut hcx| {
|
||||||
let mut hasher = StableHasher::new();
|
let mut hasher = StableHasher::new();
|
||||||
let ct = ct.eval(tcx, ty::ParamEnv::reveal_all(), DUMMY_SP).unwrap();
|
hcx.while_hashing_spans(false, |hcx| {
|
||||||
hcx.while_hashing_spans(false, |hcx| ct.hash_stable(hcx, &mut hasher));
|
(ty, valtree).hash_stable(hcx, &mut hasher)
|
||||||
|
});
|
||||||
hasher.finish::<Hash64>()
|
hasher.finish::<Hash64>()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ pub(crate) fn try_destructure_mir_constant_for_user_output<'tcx>(
|
|||||||
|
|
||||||
// We go to `usize` as we cannot allocate anything bigger anyway.
|
// We go to `usize` as we cannot allocate anything bigger anyway.
|
||||||
let (field_count, variant, down) = match ty.kind() {
|
let (field_count, variant, down) = match ty.kind() {
|
||||||
ty::Array(_, len) => (len.eval_target_usize(tcx.tcx, param_env) as usize, None, op),
|
ty::Array(_, len) => (len.try_to_target_usize(tcx.tcx)? as usize, None, op),
|
||||||
ty::Adt(def, _) if def.variants().is_empty() => {
|
ty::Adt(def, _) if def.variants().is_empty() => {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
@ -391,7 +391,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||||||
let ptr = self.read_pointer(src)?;
|
let ptr = self.read_pointer(src)?;
|
||||||
let val = Immediate::new_slice(
|
let val = Immediate::new_slice(
|
||||||
ptr,
|
ptr,
|
||||||
length.eval_target_usize(*self.tcx, self.param_env),
|
length
|
||||||
|
.try_to_target_usize(*self.tcx)
|
||||||
|
.expect("expected monomorphic const in const eval"),
|
||||||
self,
|
self,
|
||||||
);
|
);
|
||||||
self.write_immediate(val, dest)
|
self.write_immediate(val, dest)
|
||||||
|
@ -1037,7 +1037,11 @@ fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(len) = len_const.try_eval_target_usize(tcx, tcx.param_env(def.did())) {
|
// FIXME(repr_simd): This check is nice, but perhaps unnecessary due to the fact
|
||||||
|
// we do not expect users to implement their own `repr(simd)` types. If they could,
|
||||||
|
// this check is easily side-steppable by hiding the const behind normalization.
|
||||||
|
// The consequence is that the error is, in general, only observable post-mono.
|
||||||
|
if let Some(len) = len_const.try_to_target_usize(tcx) {
|
||||||
if len == 0 {
|
if len == 0 {
|
||||||
struct_span_code_err!(tcx.dcx(), sp, E0075, "SIMD vector cannot be empty").emit();
|
struct_span_code_err!(tcx.dcx(), sp, E0075, "SIMD vector cannot be empty").emit();
|
||||||
return;
|
return;
|
||||||
|
@ -76,9 +76,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
|
|||||||
|
|
||||||
let (size, ty) = match elem_ty.kind() {
|
let (size, ty) = match elem_ty.kind() {
|
||||||
ty::Array(ty, len) => {
|
ty::Array(ty, len) => {
|
||||||
if let Some(len) =
|
if let Some(len) = len.try_to_target_usize(self.tcx) {
|
||||||
len.try_eval_target_usize(self.tcx, self.tcx.param_env(adt.did()))
|
|
||||||
{
|
|
||||||
(len, *ty)
|
(len, *ty)
|
||||||
} else {
|
} else {
|
||||||
return None;
|
return None;
|
||||||
|
@ -2601,7 +2601,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
|
|||||||
ty.tuple_fields().iter().find_map(|field| ty_find_init_error(cx, field, init))
|
ty.tuple_fields().iter().find_map(|field| ty_find_init_error(cx, field, init))
|
||||||
}
|
}
|
||||||
Array(ty, len) => {
|
Array(ty, len) => {
|
||||||
if matches!(len.try_eval_target_usize(cx.tcx, cx.param_env), Some(v) if v > 0) {
|
if matches!(len.try_to_target_usize(cx.tcx), Some(v) if v > 0) {
|
||||||
// Array length known at array non-empty -- recurse.
|
// Array length known at array non-empty -- recurse.
|
||||||
ty_find_init_error(cx, *ty, init)
|
ty_find_init_error(cx, *ty, init)
|
||||||
} else {
|
} else {
|
||||||
|
@ -346,7 +346,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ty::Array(ty, len) => match len.try_eval_target_usize(cx.tcx, cx.param_env) {
|
ty::Array(ty, len) => match len.try_to_target_usize(cx.tcx) {
|
||||||
// If the array is empty we don't lint, to avoid false positives
|
// If the array is empty we don't lint, to avoid false positives
|
||||||
Some(0) | None => None,
|
Some(0) | None => None,
|
||||||
// If the array is definitely non-empty, we can do `#[must_use]` checking.
|
// If the array is definitely non-empty, we can do `#[must_use]` checking.
|
||||||
|
@ -6,6 +6,7 @@ use rustc_session::RemapFileNameExt;
|
|||||||
use rustc_session::config::RemapPathScopeComponents;
|
use rustc_session::config::RemapPathScopeComponents;
|
||||||
use rustc_span::{DUMMY_SP, Span};
|
use rustc_span::{DUMMY_SP, Span};
|
||||||
use rustc_target::abi::{HasDataLayout, Size};
|
use rustc_target::abi::{HasDataLayout, Size};
|
||||||
|
use either::Either;
|
||||||
|
|
||||||
use crate::mir::interpret::{AllocId, ConstAllocation, ErrorHandled, Scalar, alloc_range};
|
use crate::mir::interpret::{AllocId, ConstAllocation, ErrorHandled, Scalar, alloc_range};
|
||||||
use crate::mir::{Promoted, pretty_print_const_value};
|
use crate::mir::{Promoted, pretty_print_const_value};
|
||||||
@ -320,8 +321,14 @@ impl<'tcx> Const<'tcx> {
|
|||||||
Const::Ty(_, c) => {
|
Const::Ty(_, c) => {
|
||||||
// We want to consistently have a "clean" value for type system constants (i.e., no
|
// We want to consistently have a "clean" value for type system constants (i.e., no
|
||||||
// data hidden in the padding), so we always go through a valtree here.
|
// data hidden in the padding), so we always go through a valtree here.
|
||||||
let (ty, val) = c.eval(tcx, param_env, span)?;
|
match c.eval_valtree(tcx, param_env, span) {
|
||||||
Ok(tcx.valtree_to_const_val((ty, val)))
|
Ok((ty, val)) => Ok(tcx.valtree_to_const_val((ty, val))),
|
||||||
|
Err(Either::Left(_bad_ty)) => Err(tcx
|
||||||
|
.dcx()
|
||||||
|
.delayed_bug("`mir::Const::eval` called on a non-valtree-compatible type")
|
||||||
|
.into()),
|
||||||
|
Err(Either::Right(e)) => Err(e),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Const::Unevaluated(uneval, _) => {
|
Const::Unevaluated(uneval, _) => {
|
||||||
// FIXME: We might want to have a `try_eval`-like function on `Unevaluated`
|
// FIXME: We might want to have a `try_eval`-like function on `Unevaluated`
|
||||||
|
@ -55,7 +55,7 @@ impl<'tcx> PlaceTy<'tcx> {
|
|||||||
/// `PlaceElem`, where we can just use the `Ty` that is already
|
/// `PlaceElem`, where we can just use the `Ty` that is already
|
||||||
/// stored inline on field projection elems.
|
/// stored inline on field projection elems.
|
||||||
pub fn projection_ty(self, tcx: TyCtxt<'tcx>, elem: PlaceElem<'tcx>) -> PlaceTy<'tcx> {
|
pub fn projection_ty(self, tcx: TyCtxt<'tcx>, elem: PlaceElem<'tcx>) -> PlaceTy<'tcx> {
|
||||||
self.projection_ty_core(tcx, ty::ParamEnv::empty(), &elem, |_, _, ty| ty, |_, ty| ty)
|
self.projection_ty_core(tcx, &elem, |_, _, ty| ty, |_, ty| ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `place_ty.projection_ty_core(tcx, elem, |...| { ... })`
|
/// `place_ty.projection_ty_core(tcx, elem, |...| { ... })`
|
||||||
@ -66,7 +66,6 @@ impl<'tcx> PlaceTy<'tcx> {
|
|||||||
pub fn projection_ty_core<V, T>(
|
pub fn projection_ty_core<V, T>(
|
||||||
self,
|
self,
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
|
||||||
elem: &ProjectionElem<V, T>,
|
elem: &ProjectionElem<V, T>,
|
||||||
mut handle_field: impl FnMut(&Self, FieldIdx, T) -> Ty<'tcx>,
|
mut handle_field: impl FnMut(&Self, FieldIdx, T) -> Ty<'tcx>,
|
||||||
mut handle_opaque_cast_and_subtype: impl FnMut(&Self, T) -> Ty<'tcx>,
|
mut handle_opaque_cast_and_subtype: impl FnMut(&Self, T) -> Ty<'tcx>,
|
||||||
@ -93,7 +92,9 @@ impl<'tcx> PlaceTy<'tcx> {
|
|||||||
ty::Slice(..) => self.ty,
|
ty::Slice(..) => self.ty,
|
||||||
ty::Array(inner, _) if !from_end => Ty::new_array(tcx, *inner, to - from),
|
ty::Array(inner, _) if !from_end => Ty::new_array(tcx, *inner, to - from),
|
||||||
ty::Array(inner, size) if from_end => {
|
ty::Array(inner, size) if from_end => {
|
||||||
let size = size.eval_target_usize(tcx, param_env);
|
let size = size
|
||||||
|
.try_to_target_usize(tcx)
|
||||||
|
.expect("expected subslice projection on fixed-size array");
|
||||||
let len = size - from - to;
|
let len = size - from - to;
|
||||||
Ty::new_array(tcx, *inner, len)
|
Ty::new_array(tcx, *inner, len)
|
||||||
}
|
}
|
||||||
|
@ -398,133 +398,65 @@ impl<'tcx> Const<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the evaluated constant
|
|
||||||
#[inline]
|
|
||||||
pub fn eval(
|
|
||||||
self,
|
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
param_env: ParamEnv<'tcx>,
|
|
||||||
span: Span,
|
|
||||||
) -> Result<(Ty<'tcx>, ValTree<'tcx>), ErrorHandled> {
|
|
||||||
self.eval_valtree(tcx, param_env, span).map_err(|err| {
|
|
||||||
match err {
|
|
||||||
Either::Right(err) => err,
|
|
||||||
Either::Left(_bad_ty) => {
|
|
||||||
// This can happen when we run on ill-typed code.
|
|
||||||
let e = tcx.dcx().span_delayed_bug(
|
|
||||||
span,
|
|
||||||
"`ty::Const::eval` called on a non-valtree-compatible type",
|
|
||||||
);
|
|
||||||
e.into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Normalizes the constant to a value or an error if possible.
|
/// Normalizes the constant to a value or an error if possible.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn normalize(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Self {
|
pub fn normalize(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Self {
|
||||||
match self.eval(tcx, param_env, DUMMY_SP) {
|
match self.eval_valtree(tcx, param_env, DUMMY_SP) {
|
||||||
Ok((ty, val)) => Self::new_value(tcx, val, ty),
|
Ok((ty, val)) => Self::new_value(tcx, val, ty),
|
||||||
Err(ErrorHandled::Reported(r, _span)) => Self::new_error(tcx, r.into()),
|
Err(Either::Left(_bad_ty)) => {
|
||||||
Err(ErrorHandled::TooGeneric(_span)) => self,
|
// This can happen when we run on ill-typed code.
|
||||||
|
Self::new_error(
|
||||||
|
tcx,
|
||||||
|
tcx.dcx()
|
||||||
|
.delayed_bug("`ty::Const::eval` called on a non-valtree-compatible type"),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
Err(Either::Right(ErrorHandled::Reported(r, _span))) => Self::new_error(tcx, r.into()),
|
||||||
|
Err(Either::Right(ErrorHandled::TooGeneric(_span))) => self,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn try_eval_scalar(
|
|
||||||
self,
|
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
|
||||||
) -> Option<(Ty<'tcx>, Scalar)> {
|
|
||||||
let (ty, val) = self.eval(tcx, param_env, DUMMY_SP).ok()?;
|
|
||||||
let val = val.try_to_scalar()?;
|
|
||||||
Some((ty, val))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
/// Attempts to evaluate the given constant to bits. Can fail to evaluate in the presence of
|
|
||||||
/// generics (or erroneous code) or if the value can't be represented as bits (e.g. because it
|
|
||||||
/// contains const generic parameters or pointers).
|
|
||||||
pub fn try_eval_scalar_int(
|
|
||||||
self,
|
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
param_env: ParamEnv<'tcx>,
|
|
||||||
) -> Option<(Ty<'tcx>, ScalarInt)> {
|
|
||||||
let (ty, scalar) = self.try_eval_scalar(tcx, param_env)?;
|
|
||||||
let val = scalar.try_to_scalar_int().ok()?;
|
|
||||||
Some((ty, val))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
/// Attempts to evaluate the given constant to bits. Can fail to evaluate in the presence of
|
|
||||||
/// generics (or erroneous code) or if the value can't be represented as bits (e.g. because it
|
|
||||||
/// contains const generic parameters or pointers).
|
|
||||||
pub fn try_eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<u128> {
|
|
||||||
let (ty, scalar) = self.try_eval_scalar_int(tcx, param_env)?;
|
|
||||||
let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size;
|
|
||||||
// if `ty` does not depend on generic parameters, use an empty param_env
|
|
||||||
Some(scalar.to_bits(size))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
/// 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>) -> u128 {
|
|
||||||
self.try_eval_bits(tcx, param_env)
|
|
||||||
.unwrap_or_else(|| bug!("failed to evalate {:#?} to bits", self))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn try_eval_target_usize(
|
|
||||||
self,
|
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
param_env: ParamEnv<'tcx>,
|
|
||||||
) -> Option<u64> {
|
|
||||||
let (_, scalar) = self.try_eval_scalar_int(tcx, param_env)?;
|
|
||||||
Some(scalar.to_target_usize(tcx))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn try_eval_bool(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<bool> {
|
|
||||||
let (_, scalar) = self.try_eval_scalar_int(tcx, param_env)?;
|
|
||||||
scalar.try_into().ok()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
/// Panics if the value cannot be evaluated or doesn't contain a valid `usize`.
|
|
||||||
pub fn eval_target_usize(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> u64 {
|
|
||||||
self.try_eval_target_usize(tcx, param_env)
|
|
||||||
.unwrap_or_else(|| bug!("expected usize, got {:#?}", self))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Panics if self.kind != ty::ConstKind::Value
|
/// Panics if self.kind != ty::ConstKind::Value
|
||||||
pub fn to_valtree(self) -> ty::ValTree<'tcx> {
|
pub fn to_valtree(self) -> (ty::ValTree<'tcx>, Ty<'tcx>) {
|
||||||
match self.kind() {
|
match self.kind() {
|
||||||
ty::ConstKind::Value(_, valtree) => valtree,
|
ty::ConstKind::Value(ty, valtree) => (valtree, ty),
|
||||||
_ => bug!("expected ConstKind::Value, got {:?}", self.kind()),
|
_ => bug!("expected ConstKind::Value, got {:?}", self.kind()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempts to convert to a `ValTree`
|
/// Attempts to convert to a `ValTree`
|
||||||
pub fn try_to_valtree(self) -> Option<ty::ValTree<'tcx>> {
|
pub fn try_to_valtree(self) -> Option<(ty::ValTree<'tcx>, Ty<'tcx>)> {
|
||||||
match self.kind() {
|
match self.kind() {
|
||||||
ty::ConstKind::Value(_, valtree) => Some(valtree),
|
ty::ConstKind::Value(ty, valtree) => Some((valtree, ty)),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn try_to_scalar(self) -> Option<Scalar> {
|
pub fn try_to_scalar(self) -> Option<(Scalar, Ty<'tcx>)> {
|
||||||
self.try_to_valtree()?.try_to_scalar()
|
let (valtree, ty) = self.try_to_valtree()?;
|
||||||
|
Some((valtree.try_to_scalar()?, ty))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn try_to_bool(self) -> Option<bool> {
|
pub fn try_to_bool(self) -> Option<bool> {
|
||||||
self.try_to_valtree()?.try_to_scalar_int()?.try_to_bool().ok()
|
self.try_to_valtree()?.0.try_to_scalar_int()?.try_to_bool().ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
|
pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
|
||||||
self.try_to_valtree()?.try_to_target_usize(tcx)
|
self.try_to_valtree()?.0.try_to_target_usize(tcx)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
/// Attempts to evaluate the given constant to bits. Can fail to evaluate in the presence of
|
||||||
|
/// generics (or erroneous code) or if the value can't be represented as bits (e.g. because it
|
||||||
|
/// contains const generic parameters or pointers).
|
||||||
|
pub fn try_to_bits(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<u128> {
|
||||||
|
let (scalar, ty) = self.try_to_scalar()?;
|
||||||
|
let scalar = scalar.try_to_scalar_int().ok()?;
|
||||||
|
let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size;
|
||||||
|
// if `ty` does not depend on generic parameters, use an empty param_env
|
||||||
|
Some(scalar.to_bits(size))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_ct_infer(self) -> bool {
|
pub fn is_ct_infer(self) -> bool {
|
||||||
|
@ -85,7 +85,7 @@ impl<'tcx> InhabitedPredicate<'tcx> {
|
|||||||
match self {
|
match self {
|
||||||
Self::False => Ok(false),
|
Self::False => Ok(false),
|
||||||
Self::True => Ok(true),
|
Self::True => Ok(true),
|
||||||
Self::ConstIsZero(const_) => match const_.try_eval_target_usize(tcx, param_env) {
|
Self::ConstIsZero(const_) => match const_.try_to_target_usize(tcx) {
|
||||||
None | Some(0) => Ok(true),
|
None | Some(0) => Ok(true),
|
||||||
Some(1..) => Ok(false),
|
Some(1..) => Ok(false),
|
||||||
},
|
},
|
||||||
|
@ -397,7 +397,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ty::Array(inner, len) if tcx.features().transmute_generic_consts => {
|
ty::Array(inner, len) if tcx.features().transmute_generic_consts => {
|
||||||
let len_eval = len.try_eval_target_usize(tcx, param_env);
|
let len_eval = len.try_to_target_usize(tcx);
|
||||||
if len_eval == Some(0) {
|
if len_eval == Some(0) {
|
||||||
return Ok(SizeSkeleton::Known(Size::from_bytes(0), None));
|
return Ok(SizeSkeleton::Known(Size::from_bytes(0), None));
|
||||||
}
|
}
|
||||||
|
@ -1117,7 +1117,12 @@ impl<'tcx> Ty<'tcx> {
|
|||||||
// The way we evaluate the `N` in `[T; N]` here only works since we use
|
// The way we evaluate the `N` in `[T; N]` here only works since we use
|
||||||
// `simd_size_and_type` post-monomorphization. It will probably start to ICE
|
// `simd_size_and_type` post-monomorphization. It will probably start to ICE
|
||||||
// if we use it in generic code. See the `simd-array-trait` ui test.
|
// if we use it in generic code. See the `simd-array-trait` ui test.
|
||||||
(f0_len.eval_target_usize(tcx, ParamEnv::empty()), *f0_elem_ty)
|
(
|
||||||
|
f0_len
|
||||||
|
.try_to_target_usize(tcx)
|
||||||
|
.expect("expected SIMD field to have definite array size"),
|
||||||
|
*f0_elem_ty,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -863,7 +863,7 @@ where
|
|||||||
ty::Adt(def, args) => self.open_drop_for_adt(*def, args),
|
ty::Adt(def, args) => self.open_drop_for_adt(*def, args),
|
||||||
ty::Dynamic(..) => self.complete_drop(self.succ, self.unwind),
|
ty::Dynamic(..) => self.complete_drop(self.succ, self.unwind),
|
||||||
ty::Array(ety, size) => {
|
ty::Array(ety, size) => {
|
||||||
let size = size.try_eval_target_usize(self.tcx(), self.elaborator.param_env());
|
let size = size.try_to_target_usize(self.tcx());
|
||||||
self.open_drop_for_array(*ety, size)
|
self.open_drop_for_array(*ety, size)
|
||||||
}
|
}
|
||||||
ty::Slice(ety) => self.drop_loop_pair(*ety),
|
ty::Slice(ety) => self.drop_loop_pair(*ety),
|
||||||
|
@ -18,18 +18,12 @@ struct MoveDataBuilder<'a, 'tcx, F> {
|
|||||||
body: &'a Body<'tcx>,
|
body: &'a Body<'tcx>,
|
||||||
loc: Location,
|
loc: Location,
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
|
||||||
data: MoveData<'tcx>,
|
data: MoveData<'tcx>,
|
||||||
filter: F,
|
filter: F,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> {
|
impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> {
|
||||||
fn new(
|
fn new(body: &'a Body<'tcx>, tcx: TyCtxt<'tcx>, filter: F) -> Self {
|
||||||
body: &'a Body<'tcx>,
|
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
|
||||||
filter: F,
|
|
||||||
) -> Self {
|
|
||||||
let mut move_paths = IndexVec::new();
|
let mut move_paths = IndexVec::new();
|
||||||
let mut path_map = IndexVec::new();
|
let mut path_map = IndexVec::new();
|
||||||
let mut init_path_map = IndexVec::new();
|
let mut init_path_map = IndexVec::new();
|
||||||
@ -59,7 +53,6 @@ impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> {
|
|||||||
body,
|
body,
|
||||||
loc: Location::START,
|
loc: Location::START,
|
||||||
tcx,
|
tcx,
|
||||||
param_env,
|
|
||||||
data: MoveData {
|
data: MoveData {
|
||||||
moves: IndexVec::new(),
|
moves: IndexVec::new(),
|
||||||
loc_map: LocationMap::new(body),
|
loc_map: LocationMap::new(body),
|
||||||
@ -308,10 +301,9 @@ impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> {
|
|||||||
pub(super) fn gather_moves<'tcx>(
|
pub(super) fn gather_moves<'tcx>(
|
||||||
body: &Body<'tcx>,
|
body: &Body<'tcx>,
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
|
||||||
filter: impl Fn(Ty<'tcx>) -> bool,
|
filter: impl Fn(Ty<'tcx>) -> bool,
|
||||||
) -> MoveData<'tcx> {
|
) -> MoveData<'tcx> {
|
||||||
let mut builder = MoveDataBuilder::new(body, tcx, param_env, filter);
|
let mut builder = MoveDataBuilder::new(body, tcx, filter);
|
||||||
|
|
||||||
builder.gather_args();
|
builder.gather_args();
|
||||||
|
|
||||||
@ -550,7 +542,9 @@ impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> {
|
|||||||
};
|
};
|
||||||
let base_ty = base_place.ty(self.body, self.tcx).ty;
|
let base_ty = base_place.ty(self.body, self.tcx).ty;
|
||||||
let len: u64 = match base_ty.kind() {
|
let len: u64 = match base_ty.kind() {
|
||||||
ty::Array(_, size) => size.eval_target_usize(self.tcx, self.param_env),
|
ty::Array(_, size) => size
|
||||||
|
.try_to_target_usize(self.tcx)
|
||||||
|
.expect("expected subslice projection on fixed-size array"),
|
||||||
_ => bug!("from_end: false slice pattern of non-array type"),
|
_ => bug!("from_end: false slice pattern of non-array type"),
|
||||||
};
|
};
|
||||||
for offset in from..to {
|
for offset in from..to {
|
||||||
|
@ -4,7 +4,7 @@ use std::ops::{Index, IndexMut};
|
|||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_index::{IndexSlice, IndexVec};
|
use rustc_index::{IndexSlice, IndexVec};
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
|
use rustc_middle::ty::{Ty, TyCtxt};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
@ -352,10 +352,9 @@ impl<'tcx> MoveData<'tcx> {
|
|||||||
pub fn gather_moves(
|
pub fn gather_moves(
|
||||||
body: &Body<'tcx>,
|
body: &Body<'tcx>,
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
param_env: ParamEnv<'tcx>,
|
|
||||||
filter: impl Fn(Ty<'tcx>) -> bool,
|
filter: impl Fn(Ty<'tcx>) -> bool,
|
||||||
) -> MoveData<'tcx> {
|
) -> MoveData<'tcx> {
|
||||||
builder::gather_moves(body, tcx, param_env, filter)
|
builder::gather_moves(body, tcx, filter)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// For the move path `mpi`, returns the root local variable that starts the path.
|
/// For the move path `mpi`, returns the root local variable that starts the path.
|
||||||
|
@ -40,8 +40,7 @@ pub fn sanity_check<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
|
|||||||
debug!("running rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id));
|
debug!("running rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
let param_env = tcx.param_env(def_id);
|
let move_data = MoveData::gather_moves(body, tcx, |_| true);
|
||||||
let move_data = MoveData::gather_moves(body, tcx, param_env, |_| true);
|
|
||||||
|
|
||||||
if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_maybe_init).is_some() {
|
if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_maybe_init).is_some() {
|
||||||
let flow_inits = MaybeInitializedPlaces::new(tcx, body, &move_data)
|
let flow_inits = MaybeInitializedPlaces::new(tcx, body, &move_data)
|
||||||
|
@ -1957,7 +1957,8 @@ fn check_must_not_suspend_ty<'tcx>(
|
|||||||
let descr_pre = &format!("{}array{} of ", data.descr_pre, plural_suffix);
|
let descr_pre = &format!("{}array{} of ", data.descr_pre, plural_suffix);
|
||||||
check_must_not_suspend_ty(tcx, ty, hir_id, param_env, SuspendCheckData {
|
check_must_not_suspend_ty(tcx, ty, hir_id, param_env, SuspendCheckData {
|
||||||
descr_pre,
|
descr_pre,
|
||||||
plural_len: len.try_eval_target_usize(tcx, param_env).unwrap_or(0) as usize + 1,
|
// FIXME(must_not_suspend): This is wrong. We should handle printing unevaluated consts.
|
||||||
|
plural_len: len.try_to_target_usize(tcx).unwrap_or(0) as usize + 1,
|
||||||
..data
|
..data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -58,8 +58,7 @@ impl<'tcx> crate::MirPass<'tcx> for ElaborateDrops {
|
|||||||
let param_env = tcx.param_env_reveal_all_normalized(def_id);
|
let param_env = tcx.param_env_reveal_all_normalized(def_id);
|
||||||
// For types that do not need dropping, the behaviour is trivial. So we only need to track
|
// For types that do not need dropping, the behaviour is trivial. So we only need to track
|
||||||
// init/uninit for types that do need dropping.
|
// init/uninit for types that do need dropping.
|
||||||
let move_data =
|
let move_data = MoveData::gather_moves(body, tcx, |ty| ty.needs_drop(tcx, param_env));
|
||||||
MoveData::gather_moves(body, tcx, param_env, |ty| ty.needs_drop(tcx, param_env));
|
|
||||||
let elaborate_patch = {
|
let elaborate_patch = {
|
||||||
let env = MoveDataParamEnv { move_data, param_env };
|
let env = MoveDataParamEnv { move_data, param_env };
|
||||||
|
|
||||||
|
@ -602,7 +602,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
|||||||
Len(place) => {
|
Len(place) => {
|
||||||
let len = if let ty::Array(_, n) = place.ty(self.local_decls(), self.tcx).ty.kind()
|
let len = if let ty::Array(_, n) = place.ty(self.local_decls(), self.tcx).ty.kind()
|
||||||
{
|
{
|
||||||
n.try_eval_target_usize(self.tcx, self.param_env)?
|
n.try_to_target_usize(self.tcx)?
|
||||||
} else {
|
} else {
|
||||||
match self.get_const(place)? {
|
match self.get_const(place)? {
|
||||||
Value::Immediate(src) => src.len(&self.ecx).discard_err()?,
|
Value::Immediate(src) => src.len(&self.ecx).discard_err()?,
|
||||||
|
@ -329,7 +329,7 @@ impl<'tcx> Validator<'_, 'tcx> {
|
|||||||
// Determine the type of the thing we are indexing.
|
// Determine the type of the thing we are indexing.
|
||||||
&& let ty::Array(_, len) = place_base.ty(self.body, self.tcx).ty.kind()
|
&& let ty::Array(_, len) = place_base.ty(self.body, self.tcx).ty.kind()
|
||||||
// It's an array; determine its length.
|
// It's an array; determine its length.
|
||||||
&& let Some(len) = len.try_eval_target_usize(self.tcx, self.param_env)
|
&& let Some(len) = len.try_to_target_usize(self.tcx)
|
||||||
// If the index is in-bounds, go ahead.
|
// If the index is in-bounds, go ahead.
|
||||||
&& idx < len
|
&& idx < len
|
||||||
{
|
{
|
||||||
@ -407,7 +407,7 @@ impl<'tcx> Validator<'_, 'tcx> {
|
|||||||
// mutably without consequences. However, only &mut []
|
// mutably without consequences. However, only &mut []
|
||||||
// is allowed right now.
|
// is allowed right now.
|
||||||
if let ty::Array(_, len) = ty.kind() {
|
if let ty::Array(_, len) = ty.kind() {
|
||||||
match len.try_eval_target_usize(self.tcx, self.param_env) {
|
match len.try_to_target_usize(self.tcx) {
|
||||||
Some(0) => {}
|
Some(0) => {}
|
||||||
_ => return Err(Unpromotable),
|
_ => return Err(Unpromotable),
|
||||||
}
|
}
|
||||||
|
@ -19,8 +19,7 @@ pub(super) struct RemoveUninitDrops;
|
|||||||
impl<'tcx> crate::MirPass<'tcx> for RemoveUninitDrops {
|
impl<'tcx> crate::MirPass<'tcx> for RemoveUninitDrops {
|
||||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||||
let param_env = tcx.param_env(body.source.def_id());
|
let param_env = tcx.param_env(body.source.def_id());
|
||||||
let move_data =
|
let move_data = MoveData::gather_moves(body, tcx, |ty| ty.needs_drop(tcx, param_env));
|
||||||
MoveData::gather_moves(body, tcx, param_env, |ty| ty.needs_drop(tcx, param_env));
|
|
||||||
|
|
||||||
let mut maybe_inits = MaybeInitializedPlaces::new(tcx, body, &move_data)
|
let mut maybe_inits = MaybeInitializedPlaces::new(tcx, body, &move_data)
|
||||||
.into_engine(tcx, body)
|
.into_engine(tcx, body)
|
||||||
|
@ -133,7 +133,9 @@ fn encode_const<'tcx>(
|
|||||||
// bool value false is encoded as 0 and true as 1.
|
// bool value false is encoded as 0 and true as 1.
|
||||||
match ct_ty.kind() {
|
match ct_ty.kind() {
|
||||||
ty::Int(ity) => {
|
ty::Int(ity) => {
|
||||||
let bits = c.eval_bits(tcx, ty::ParamEnv::reveal_all());
|
let bits = c
|
||||||
|
.try_to_bits(tcx, ty::ParamEnv::reveal_all())
|
||||||
|
.expect("expected monomorphic const in cfi");
|
||||||
let val = Integer::from_int_ty(&tcx, *ity).size().sign_extend(bits) as i128;
|
let val = Integer::from_int_ty(&tcx, *ity).size().sign_extend(bits) as i128;
|
||||||
if val < 0 {
|
if val < 0 {
|
||||||
s.push('n');
|
s.push('n');
|
||||||
@ -141,7 +143,9 @@ fn encode_const<'tcx>(
|
|||||||
let _ = write!(s, "{val}");
|
let _ = write!(s, "{val}");
|
||||||
}
|
}
|
||||||
ty::Uint(_) => {
|
ty::Uint(_) => {
|
||||||
let val = c.eval_bits(tcx, ty::ParamEnv::reveal_all());
|
let val = c
|
||||||
|
.try_to_bits(tcx, ty::ParamEnv::reveal_all())
|
||||||
|
.expect("expected monomorphic const in cfi");
|
||||||
let _ = write!(s, "{val}");
|
let _ = write!(s, "{val}");
|
||||||
}
|
}
|
||||||
ty::Bool => {
|
ty::Bool => {
|
||||||
|
@ -406,7 +406,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
|
|||||||
let tcx = tables.tcx;
|
let tcx = tables.tcx;
|
||||||
let mir_const = cnst.internal(&mut *tables, tcx);
|
let mir_const = cnst.internal(&mut *tables, tcx);
|
||||||
mir_const
|
mir_const
|
||||||
.try_eval_target_usize(tables.tcx, ParamEnv::empty())
|
.try_to_target_usize(tables.tcx)
|
||||||
.ok_or_else(|| Error::new(format!("Const `{cnst:?}` cannot be encoded as u64")))
|
.ok_or_else(|| Error::new(format!("Const `{cnst:?}` cannot be encoded as u64")))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -592,7 +592,9 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
|
|||||||
ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Char => {
|
ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Char => {
|
||||||
ct_ty.print(self)?;
|
ct_ty.print(self)?;
|
||||||
|
|
||||||
let mut bits = ct.eval_bits(self.tcx, ty::ParamEnv::reveal_all());
|
let mut bits = ct
|
||||||
|
.try_to_bits(self.tcx, ty::ParamEnv::reveal_all())
|
||||||
|
.expect("expected const to be monomorphic");
|
||||||
|
|
||||||
// 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) = ct_ty.kind() {
|
||||||
|
@ -231,7 +231,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
|||||||
// Arrays give us `[]`, `[{ty}; _]` and `[{ty}; N]`
|
// Arrays give us `[]`, `[{ty}; _]` and `[{ty}; N]`
|
||||||
if let ty::Array(aty, len) = self_ty.kind() {
|
if let ty::Array(aty, len) = self_ty.kind() {
|
||||||
flags.push((sym::_Self, Some("[]".to_string())));
|
flags.push((sym::_Self, Some("[]".to_string())));
|
||||||
let len = len.try_to_valtree().and_then(|v| v.try_to_target_usize(self.tcx));
|
let len = len.try_to_target_usize(self.tcx);
|
||||||
flags.push((sym::_Self, Some(format!("[{aty}; _]"))));
|
flags.push((sym::_Self, Some(format!("[{aty}; _]"))));
|
||||||
if let Some(n) = len {
|
if let Some(n) = len {
|
||||||
flags.push((sym::_Self, Some(format!("[{aty}; {n}]"))));
|
flags.push((sym::_Self, Some(format!("[{aty}; {n}]"))));
|
||||||
|
@ -85,7 +85,6 @@ mod rustc {
|
|||||||
use rustc_macros::TypeVisitable;
|
use rustc_macros::TypeVisitable;
|
||||||
use rustc_middle::traits::ObligationCause;
|
use rustc_middle::traits::ObligationCause;
|
||||||
use rustc_middle::ty::{Const, ParamEnv, Ty, TyCtxt, ValTree};
|
use rustc_middle::ty::{Const, ParamEnv, Ty, TyCtxt, ValTree};
|
||||||
use rustc_span::DUMMY_SP;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
@ -134,7 +133,7 @@ mod rustc {
|
|||||||
use rustc_middle::ty::ScalarInt;
|
use rustc_middle::ty::ScalarInt;
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
|
|
||||||
let Ok((ty, cv)) = c.eval(tcx, param_env, DUMMY_SP) else {
|
let Some((cv, ty)) = c.try_to_valtree() else {
|
||||||
return Some(Self {
|
return Some(Self {
|
||||||
alignment: true,
|
alignment: true,
|
||||||
lifetimes: true,
|
lifetimes: true,
|
||||||
|
@ -170,12 +170,12 @@ fn layout_of_uncached<'tcx>(
|
|||||||
if let Abi::Scalar(scalar) | Abi::ScalarPair(scalar, _) = &mut layout.abi {
|
if let Abi::Scalar(scalar) | Abi::ScalarPair(scalar, _) = &mut layout.abi {
|
||||||
if let Some(start) = start {
|
if let Some(start) = start {
|
||||||
scalar.valid_range_mut().start = start
|
scalar.valid_range_mut().start = start
|
||||||
.try_eval_bits(tcx, param_env)
|
.try_to_bits(tcx, param_env)
|
||||||
.ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
|
.ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
|
||||||
}
|
}
|
||||||
if let Some(end) = end {
|
if let Some(end) = end {
|
||||||
let mut end = end
|
let mut end = end
|
||||||
.try_eval_bits(tcx, param_env)
|
.try_to_bits(tcx, param_env)
|
||||||
.ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
|
.ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
|
||||||
if !include_end {
|
if !include_end {
|
||||||
end = end.wrapping_sub(1);
|
end = end.wrapping_sub(1);
|
||||||
@ -315,7 +315,7 @@ fn layout_of_uncached<'tcx>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let count = count
|
let count = count
|
||||||
.try_eval_target_usize(tcx, param_env)
|
.try_to_target_usize(tcx)
|
||||||
.ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
|
.ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
|
||||||
let element = cx.layout_of(element)?;
|
let element = cx.layout_of(element)?;
|
||||||
let size = element
|
let size = element
|
||||||
|
Loading…
Reference in New Issue
Block a user