mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
Rollup merge of #115972 - RalfJung:const-consistency, r=oli-obk
rename mir::Constant -> mir::ConstOperand, mir::ConstKind -> mir::Const Also, be more consistent with the `to/eval_bits` methods... we had some that take a type and some that take a size, and then sometimes the one that takes a type is called `bits_for_ty`. Turns out that `ty::Const`/`mir::ConstKind` carry their type with them, so we don't need to even pass the type to those `eval_bits` functions at all. However this is not properly consistent yet: in `ty` we have most of the methods on `ty::Const`, but in `mir` we have them on `mir::ConstKind`. And indeed those two types are the ones that correspond to each other. So `mir::ConstantKind` should actually be renamed to `mir::Const`. But what to do with `mir::Constant`? It carries around a span, that's really more like a constant operand that appears as a MIR operand... it's more suited for `syntax.rs` than `consts.rs`, but the bigger question is, which name should it get if we want to align the `mir` and `ty` types? `ConstOperand`? `ConstOp`? `Literal`? It's not a literal but it has a field called `literal` so it would at least be consistently wrong-ish... ``@oli-obk`` any ideas?
This commit is contained in:
commit
208f6ed95c
@ -13,7 +13,7 @@ use rustc_index::IndexSlice;
|
||||
use rustc_infer::infer::LateBoundRegionConversionTime;
|
||||
use rustc_middle::mir::tcx::PlaceTy;
|
||||
use rustc_middle::mir::{
|
||||
AggregateKind, CallSource, Constant, FakeReadCause, Local, LocalInfo, LocalKind, Location,
|
||||
AggregateKind, CallSource, ConstOperand, FakeReadCause, Local, LocalInfo, LocalKind, Location,
|
||||
Operand, Place, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator,
|
||||
TerminatorKind,
|
||||
};
|
||||
@ -101,12 +101,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
let terminator = self.body[location.block].terminator();
|
||||
debug!("add_moved_or_invoked_closure_note: terminator={:?}", terminator);
|
||||
if let TerminatorKind::Call {
|
||||
func: Operand::Constant(box Constant { literal, .. }),
|
||||
func: Operand::Constant(box ConstOperand { const_, .. }),
|
||||
args,
|
||||
..
|
||||
} = &terminator.kind
|
||||
{
|
||||
if let ty::FnDef(id, _) = *literal.ty().kind() {
|
||||
if let ty::FnDef(id, _) = *const_.ty().kind() {
|
||||
debug!("add_moved_or_invoked_closure_note: id={:?}", id);
|
||||
if Some(self.infcx.tcx.parent(id)) == self.infcx.tcx.lang_items().fn_once_trait() {
|
||||
let closure = match args.first() {
|
||||
|
@ -4,8 +4,7 @@ use crate::BorrowckInferCtxt;
|
||||
use rustc_index::IndexSlice;
|
||||
use rustc_infer::infer::NllRegionVariableOrigin;
|
||||
use rustc_middle::mir::visit::{MutVisitor, TyContext};
|
||||
use rustc_middle::mir::Constant;
|
||||
use rustc_middle::mir::{Body, Location, Promoted};
|
||||
use rustc_middle::mir::{Body, ConstOperand, Location, Promoted};
|
||||
use rustc_middle::ty::GenericArgsRef;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc_span::{Span, Symbol};
|
||||
@ -117,9 +116,9 @@ impl<'a, 'tcx> MutVisitor<'tcx> for RegionRenumberer<'a, 'tcx> {
|
||||
}
|
||||
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
fn visit_constant(&mut self, constant: &mut Constant<'tcx>, location: Location) {
|
||||
let literal = constant.literal;
|
||||
constant.literal = self.renumber_regions(literal, || RegionCtxt::Location(location));
|
||||
fn visit_constant(&mut self, constant: &mut ConstOperand<'tcx>, location: Location) {
|
||||
let const_ = constant.const_;
|
||||
constant.const_ = self.renumber_regions(const_, || RegionCtxt::Location(location));
|
||||
debug!("constant: {:#?}", constant);
|
||||
}
|
||||
}
|
||||
|
@ -302,11 +302,11 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
|
||||
self.sanitize_place(place, location, context);
|
||||
}
|
||||
|
||||
fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
|
||||
fn visit_constant(&mut self, constant: &ConstOperand<'tcx>, location: Location) {
|
||||
debug!(?constant, ?location, "visit_constant");
|
||||
|
||||
self.super_constant(constant, location);
|
||||
let ty = self.sanitize_type(constant, constant.literal.ty());
|
||||
let ty = self.sanitize_type(constant, constant.const_.ty());
|
||||
|
||||
self.cx.infcx.tcx.for_each_free_region(&ty, |live_region| {
|
||||
let live_region_vid =
|
||||
@ -328,7 +328,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
|
||||
|
||||
if let Some(annotation_index) = constant.user_ty {
|
||||
if let Err(terr) = self.cx.relate_type_and_user_type(
|
||||
constant.literal.ty(),
|
||||
constant.const_.ty(),
|
||||
ty::Variance::Invariant,
|
||||
&UserTypeProjection { base: annotation_index, projs: vec![] },
|
||||
locations,
|
||||
@ -340,20 +340,20 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
|
||||
constant,
|
||||
"bad constant user type {:?} vs {:?}: {:?}",
|
||||
annotation,
|
||||
constant.literal.ty(),
|
||||
constant.const_.ty(),
|
||||
terr,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
let tcx = self.tcx();
|
||||
let maybe_uneval = match constant.literal {
|
||||
ConstantKind::Ty(ct) => match ct.kind() {
|
||||
let maybe_uneval = match constant.const_ {
|
||||
Const::Ty(ct) => match ct.kind() {
|
||||
ty::ConstKind::Unevaluated(_) => {
|
||||
bug!("should not encounter unevaluated ConstantKind::Ty here, got {:?}", ct)
|
||||
bug!("should not encounter unevaluated Const::Ty here, got {:?}", ct)
|
||||
}
|
||||
_ => None,
|
||||
},
|
||||
ConstantKind::Unevaluated(uv, _) => Some(uv),
|
||||
Const::Unevaluated(uv, _) => Some(uv),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
@ -384,7 +384,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
|
||||
check_err(self, promoted_body, ty, promoted_ty);
|
||||
} else {
|
||||
self.cx.ascribe_user_type(
|
||||
constant.literal.ty(),
|
||||
constant.const_.ty(),
|
||||
UserType::TypeOf(uv.def, UserArgs { args: uv.args, user_self_ty: None }),
|
||||
locations.span(&self.cx.body),
|
||||
);
|
||||
@ -392,7 +392,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
|
||||
} else if let Some(static_def_id) = constant.check_static_ptr(tcx) {
|
||||
let unnormalized_ty = tcx.type_of(static_def_id).instantiate_identity();
|
||||
let normalized_ty = self.cx.normalize(unnormalized_ty, locations);
|
||||
let literal_ty = constant.literal.ty().builtin_deref(true).unwrap().ty;
|
||||
let literal_ty = constant.const_.ty().builtin_deref(true).unwrap().ty;
|
||||
|
||||
if let Err(terr) = self.cx.eq_types(
|
||||
literal_ty,
|
||||
@ -404,7 +404,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
if let ty::FnDef(def_id, args) = *constant.literal.ty().kind() {
|
||||
if let ty::FnDef(def_id, args) = *constant.const_.ty().kind() {
|
||||
let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, args);
|
||||
self.cx.normalize_and_prove_instantiated_predicates(
|
||||
def_id,
|
||||
@ -1801,9 +1801,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
debug!(?op, ?location, "check_operand");
|
||||
|
||||
if let Operand::Constant(constant) = op {
|
||||
let maybe_uneval = match constant.literal {
|
||||
ConstantKind::Val(..) | ConstantKind::Ty(_) => None,
|
||||
ConstantKind::Unevaluated(uv, _) => Some(uv),
|
||||
let maybe_uneval = match constant.const_ {
|
||||
Const::Val(..) | Const::Ty(_) => None,
|
||||
Const::Unevaluated(uv, _) => Some(uv),
|
||||
};
|
||||
|
||||
if let Some(uv) = maybe_uneval {
|
||||
|
@ -64,9 +64,9 @@ pub(crate) fn codegen_tls_ref<'tcx>(
|
||||
|
||||
pub(crate) fn eval_mir_constant<'tcx>(
|
||||
fx: &FunctionCx<'_, '_, 'tcx>,
|
||||
constant: &Constant<'tcx>,
|
||||
constant: &ConstOperand<'tcx>,
|
||||
) -> (ConstValue<'tcx>, Ty<'tcx>) {
|
||||
let cv = fx.monomorphize(constant.literal);
|
||||
let cv = fx.monomorphize(constant.const_);
|
||||
// This cannot fail because we checked all required_consts in advance.
|
||||
let val = cv
|
||||
.eval(fx.tcx, ty::ParamEnv::reveal_all(), Some(constant.span))
|
||||
@ -76,7 +76,7 @@ pub(crate) fn eval_mir_constant<'tcx>(
|
||||
|
||||
pub(crate) fn codegen_constant_operand<'tcx>(
|
||||
fx: &mut FunctionCx<'_, '_, 'tcx>,
|
||||
constant: &Constant<'tcx>,
|
||||
constant: &ConstOperand<'tcx>,
|
||||
) -> CValue<'tcx> {
|
||||
let (const_val, ty) = eval_mir_constant(fx, constant);
|
||||
codegen_const_value(fx, const_val, ty)
|
||||
|
@ -252,8 +252,8 @@ pub(crate) fn codegen_inline_asm<'tcx>(
|
||||
CInlineAsmOperand::Const { value }
|
||||
}
|
||||
InlineAsmOperand::SymFn { ref value } => {
|
||||
let literal = fx.monomorphize(value.literal);
|
||||
if let ty::FnDef(def_id, args) = *literal.ty().kind() {
|
||||
let const_ = fx.monomorphize(value.const_);
|
||||
if let ty::FnDef(def_id, args) = *const_.ty().kind() {
|
||||
let instance = ty::Instance::resolve_for_fn_ptr(
|
||||
fx.tcx,
|
||||
ty::ParamEnv::reveal_all(),
|
||||
|
@ -660,12 +660,12 @@ fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut S
|
||||
}
|
||||
_ => match ct.ty().kind() {
|
||||
ty::Int(ity) => {
|
||||
let bits = ct.eval_bits(tcx, ty::ParamEnv::reveal_all(), ct.ty());
|
||||
let bits = ct.eval_bits(tcx, ty::ParamEnv::reveal_all());
|
||||
let val = Integer::from_int_ty(&tcx, *ity).size().sign_extend(bits) as i128;
|
||||
write!(output, "{val}")
|
||||
}
|
||||
ty::Uint(_) => {
|
||||
let val = ct.eval_bits(tcx, ty::ParamEnv::reveal_all(), ct.ty());
|
||||
let val = ct.eval_bits(tcx, ty::ParamEnv::reveal_all());
|
||||
write!(output, "{val}")
|
||||
}
|
||||
ty::Bool => {
|
||||
|
@ -1098,8 +1098,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
InlineAsmOperandRef::Const { string }
|
||||
}
|
||||
mir::InlineAsmOperand::SymFn { ref value } => {
|
||||
let literal = self.monomorphize(value.literal);
|
||||
if let ty::FnDef(def_id, args) = *literal.ty().kind() {
|
||||
let const_ = self.monomorphize(value.const_);
|
||||
if let ty::FnDef(def_id, args) = *const_.ty().kind() {
|
||||
let instance = ty::Instance::resolve_for_fn_ptr(
|
||||
bx.tcx(),
|
||||
ty::ParamEnv::reveal_all(),
|
||||
|
@ -13,37 +13,37 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
pub fn eval_mir_constant_to_operand(
|
||||
&self,
|
||||
bx: &mut Bx,
|
||||
constant: &mir::Constant<'tcx>,
|
||||
constant: &mir::ConstOperand<'tcx>,
|
||||
) -> OperandRef<'tcx, Bx::Value> {
|
||||
let val = self.eval_mir_constant(constant);
|
||||
let ty = self.monomorphize(constant.ty());
|
||||
OperandRef::from_const(bx, val, ty)
|
||||
}
|
||||
|
||||
pub fn eval_mir_constant(&self, constant: &mir::Constant<'tcx>) -> mir::ConstValue<'tcx> {
|
||||
self.monomorphize(constant.literal)
|
||||
pub fn eval_mir_constant(&self, constant: &mir::ConstOperand<'tcx>) -> mir::ConstValue<'tcx> {
|
||||
self.monomorphize(constant.const_)
|
||||
.eval(self.cx.tcx(), ty::ParamEnv::reveal_all(), Some(constant.span))
|
||||
.expect("erroneous constant not captured by required_consts")
|
||||
}
|
||||
|
||||
/// This is a convenience helper for `simd_shuffle_indices`. It has the precondition
|
||||
/// that the given `constant` is an `ConstantKind::Unevaluated` and must be convertible to
|
||||
/// that the given `constant` is an `Const::Unevaluated` and must be convertible to
|
||||
/// a `ValTree`. If you want a more general version of this, talk to `wg-const-eval` on zulip.
|
||||
///
|
||||
/// Note that this function is cursed, since usually MIR consts should not be evaluated to valtrees!
|
||||
pub fn eval_unevaluated_mir_constant_to_valtree(
|
||||
&self,
|
||||
constant: &mir::Constant<'tcx>,
|
||||
constant: &mir::ConstOperand<'tcx>,
|
||||
) -> Result<Option<ty::ValTree<'tcx>>, ErrorHandled> {
|
||||
let uv = match self.monomorphize(constant.literal) {
|
||||
mir::ConstantKind::Unevaluated(uv, _) => uv.shrink(),
|
||||
mir::ConstantKind::Ty(c) => match c.kind() {
|
||||
let uv = match self.monomorphize(constant.const_) {
|
||||
mir::Const::Unevaluated(uv, _) => uv.shrink(),
|
||||
mir::Const::Ty(c) => match c.kind() {
|
||||
// A constant that came from a const generic but was then used as an argument to old-style
|
||||
// simd_shuffle (passing as argument instead of as a generic param).
|
||||
rustc_type_ir::ConstKind::Value(valtree) => return Ok(Some(valtree)),
|
||||
other => span_bug!(constant.span, "{other:#?}"),
|
||||
},
|
||||
// We should never encounter `ConstantKind::Val` unless MIR opts (like const prop) evaluate
|
||||
// We should never encounter `Const::Val` unless MIR opts (like const prop) evaluate
|
||||
// a constant and write that value back into `Operand`s. This could happen, but is unlikely.
|
||||
// Also: all users of `simd_shuffle` are on unstable and already need to take a lot of care
|
||||
// around intrinsics. For an issue to happen here, it would require a macro expanding to a
|
||||
@ -65,7 +65,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
pub fn simd_shuffle_indices(
|
||||
&mut self,
|
||||
bx: &Bx,
|
||||
constant: &mir::Constant<'tcx>,
|
||||
constant: &mir::ConstOperand<'tcx>,
|
||||
) -> (Bx::Value, Ty<'tcx>) {
|
||||
let ty = self.monomorphize(constant.ty());
|
||||
let val = self
|
||||
|
@ -1089,7 +1089,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
|
||||
pub fn eval_mir_constant(
|
||||
&self,
|
||||
val: &mir::ConstantKind<'tcx>,
|
||||
val: &mir::Const<'tcx>,
|
||||
span: Option<Span>,
|
||||
layout: Option<TyAndLayout<'tcx>>,
|
||||
) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
|
||||
|
@ -692,7 +692,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
|
||||
Constant(constant) => {
|
||||
let c =
|
||||
self.subst_from_current_frame_and_normalize_erasing_regions(constant.literal)?;
|
||||
self.subst_from_current_frame_and_normalize_erasing_regions(constant.const_)?;
|
||||
|
||||
// This can still fail:
|
||||
// * During ConstProp, with `TooGeneric` or since the `required_consts` were not all
|
||||
|
@ -346,8 +346,8 @@ where
|
||||
};
|
||||
|
||||
// Check the qualifs of the value of `const` items.
|
||||
let uneval = match constant.literal {
|
||||
ConstantKind::Ty(ct)
|
||||
let uneval = match constant.const_ {
|
||||
Const::Ty(ct)
|
||||
if matches!(
|
||||
ct.kind(),
|
||||
ty::ConstKind::Param(_) | ty::ConstKind::Error(_) | ty::ConstKind::Value(_)
|
||||
@ -355,11 +355,11 @@ where
|
||||
{
|
||||
None
|
||||
}
|
||||
ConstantKind::Ty(c) => {
|
||||
Const::Ty(c) => {
|
||||
bug!("expected ConstKind::Param or ConstKind::Value here, found {:?}", c)
|
||||
}
|
||||
ConstantKind::Unevaluated(uv, _) => Some(uv),
|
||||
ConstantKind::Val(..) => None,
|
||||
Const::Unevaluated(uv, _) => Some(uv),
|
||||
Const::Val(..) => None,
|
||||
};
|
||||
|
||||
if let Some(mir::UnevaluatedConst { def, args: _, promoted }) = uneval {
|
||||
@ -383,5 +383,5 @@ where
|
||||
}
|
||||
|
||||
// Otherwise use the qualifs of the type.
|
||||
Q::in_any_value_of_ty(cx, constant.literal.ty())
|
||||
Q::in_any_value_of_ty(cx, constant.const_.ty())
|
||||
}
|
||||
|
@ -372,7 +372,7 @@ impl<'tcx> Validator<'_, 'tcx> {
|
||||
StatementKind::Assign(box (
|
||||
_,
|
||||
Rvalue::Use(Operand::Constant(c)),
|
||||
)) => c.literal.try_eval_target_usize(self.tcx, self.param_env),
|
||||
)) => c.const_.try_eval_target_usize(self.tcx, self.param_env),
|
||||
_ => None,
|
||||
}
|
||||
} else {
|
||||
@ -554,7 +554,7 @@ impl<'tcx> Validator<'_, 'tcx> {
|
||||
// Integer division: the RHS must be a non-zero const.
|
||||
let const_val = match rhs {
|
||||
Operand::Constant(c) => {
|
||||
c.literal.try_eval_bits(self.tcx, self.param_env, lhs_ty)
|
||||
c.const_.try_eval_bits(self.tcx, self.param_env)
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
@ -766,10 +766,10 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
|
||||
if self.keep_original {
|
||||
rhs.clone()
|
||||
} else {
|
||||
let unit = Rvalue::Use(Operand::Constant(Box::new(Constant {
|
||||
let unit = Rvalue::Use(Operand::Constant(Box::new(ConstOperand {
|
||||
span: statement.source_info.span,
|
||||
user_ty: None,
|
||||
literal: ConstantKind::zero_sized(self.tcx.types.unit),
|
||||
const_: Const::zero_sized(self.tcx.types.unit),
|
||||
})));
|
||||
mem::replace(rhs, unit)
|
||||
},
|
||||
@ -844,10 +844,10 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
|
||||
let args = tcx.erase_regions(GenericArgs::identity_for_item(tcx, def));
|
||||
let uneval = mir::UnevaluatedConst { def, args, promoted: Some(promoted_id) };
|
||||
|
||||
Operand::Constant(Box::new(Constant {
|
||||
Operand::Constant(Box::new(ConstOperand {
|
||||
span,
|
||||
user_ty: None,
|
||||
literal: ConstantKind::Unevaluated(uneval, ty),
|
||||
const_: Const::Unevaluated(uneval, ty),
|
||||
}))
|
||||
};
|
||||
|
||||
@ -1041,8 +1041,8 @@ pub fn is_const_fn_in_array_repeat_expression<'tcx>(
|
||||
if let Some(Terminator { kind: TerminatorKind::Call { func, destination, .. }, .. }) =
|
||||
&block.terminator
|
||||
{
|
||||
if let Operand::Constant(box Constant { literal, .. }) = func {
|
||||
if let ty::FnDef(def_id, _) = *literal.ty().kind() {
|
||||
if let Operand::Constant(box ConstOperand { const_, .. }) = func {
|
||||
if let ty::FnDef(def_id, _) = *const_.ty().kind() {
|
||||
if destination == place {
|
||||
if ccx.tcx.is_const_fn(def_id) {
|
||||
return true;
|
||||
|
@ -6,13 +6,11 @@ use rustc_hir::{self as hir};
|
||||
use rustc_span::Span;
|
||||
use rustc_target::abi::{HasDataLayout, Size};
|
||||
|
||||
use crate::mir::interpret::{
|
||||
alloc_range, AllocId, ConstAllocation, ErrorHandled, GlobalAlloc, Scalar,
|
||||
};
|
||||
use crate::mir::interpret::{alloc_range, AllocId, ConstAllocation, ErrorHandled, Scalar};
|
||||
use crate::mir::{pretty_print_const_value, Promoted};
|
||||
use crate::ty::ScalarInt;
|
||||
use crate::ty::{self, print::pretty_print_const, List, Ty, TyCtxt};
|
||||
use crate::ty::{GenericArgs, GenericArgsRef};
|
||||
use crate::ty::{ScalarInt, UserTypeAnnotationIndex};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
/// Evaluated Constants
|
||||
@ -178,29 +176,10 @@ impl<'tcx> ConstValue<'tcx> {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
/// Constants
|
||||
///
|
||||
/// Two constants are equal if they are the same constant. Note that
|
||||
/// this does not necessarily mean that they are `==` in Rust. In
|
||||
/// particular, one must be wary of `NaN`!
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)]
|
||||
#[derive(TypeFoldable, TypeVisitable)]
|
||||
pub struct Constant<'tcx> {
|
||||
pub span: Span,
|
||||
|
||||
/// Optional user-given type: for something like
|
||||
/// `collect::<Vec<_>>`, this would be present and would
|
||||
/// indicate that `Vec<_>` was explicitly specified.
|
||||
///
|
||||
/// Needed for NLL to impose user-given type constraints.
|
||||
pub user_ty: Option<UserTypeAnnotationIndex>,
|
||||
|
||||
pub literal: ConstantKind<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable, Debug)]
|
||||
#[derive(TypeFoldable, TypeVisitable)]
|
||||
pub enum ConstantKind<'tcx> {
|
||||
pub enum Const<'tcx> {
|
||||
/// This constant came from the type system.
|
||||
///
|
||||
/// Any way of turning `ty::Const` into `ConstValue` should go through `valtree_to_const_val`;
|
||||
@ -221,46 +200,27 @@ pub enum ConstantKind<'tcx> {
|
||||
Val(ConstValue<'tcx>, Ty<'tcx>),
|
||||
}
|
||||
|
||||
impl<'tcx> Constant<'tcx> {
|
||||
pub fn check_static_ptr(&self, tcx: TyCtxt<'_>) -> Option<DefId> {
|
||||
match self.literal.try_to_scalar() {
|
||||
Some(Scalar::Ptr(ptr, _size)) => match tcx.global_alloc(ptr.provenance) {
|
||||
GlobalAlloc::Static(def_id) => {
|
||||
assert!(!tcx.is_thread_local_static(def_id));
|
||||
Some(def_id)
|
||||
}
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
pub fn ty(&self) -> Ty<'tcx> {
|
||||
self.literal.ty()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ConstantKind<'tcx> {
|
||||
impl<'tcx> Const<'tcx> {
|
||||
#[inline(always)]
|
||||
pub fn ty(&self) -> Ty<'tcx> {
|
||||
match self {
|
||||
ConstantKind::Ty(c) => c.ty(),
|
||||
ConstantKind::Val(_, ty) | ConstantKind::Unevaluated(_, ty) => *ty,
|
||||
Const::Ty(c) => c.ty(),
|
||||
Const::Val(_, ty) | Const::Unevaluated(_, ty) => *ty,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn try_to_scalar(self) -> Option<Scalar> {
|
||||
match self {
|
||||
ConstantKind::Ty(c) => match c.kind() {
|
||||
Const::Ty(c) => match c.kind() {
|
||||
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(),
|
||||
ConstantKind::Unevaluated(..) => None,
|
||||
Const::Val(val, _) => val.try_to_scalar(),
|
||||
Const::Unevaluated(..) => None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -287,17 +247,17 @@ impl<'tcx> ConstantKind<'tcx> {
|
||||
span: Option<Span>,
|
||||
) -> Result<ConstValue<'tcx>, ErrorHandled> {
|
||||
match self {
|
||||
ConstantKind::Ty(c) => {
|
||||
Const::Ty(c) => {
|
||||
// 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.
|
||||
let val = c.eval(tcx, param_env, span)?;
|
||||
Ok(tcx.valtree_to_const_val((self.ty(), val)))
|
||||
}
|
||||
ConstantKind::Unevaluated(uneval, _) => {
|
||||
Const::Unevaluated(uneval, _) => {
|
||||
// FIXME: We might want to have a `try_eval`-like function on `Unevaluated`
|
||||
tcx.const_eval_resolve(param_env, uneval, span)
|
||||
}
|
||||
ConstantKind::Val(val, _) => Ok(val),
|
||||
Const::Val(val, _) => Ok(val),
|
||||
}
|
||||
}
|
||||
|
||||
@ -332,23 +292,18 @@ impl<'tcx> ConstantKind<'tcx> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn try_eval_bits(
|
||||
&self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
) -> Option<u128> {
|
||||
pub fn try_eval_bits(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Option<u128> {
|
||||
let int = self.try_eval_scalar_int(tcx, param_env)?;
|
||||
assert_eq!(self.ty(), ty);
|
||||
let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size;
|
||||
let size =
|
||||
tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(self.ty())).ok()?.size;
|
||||
int.to_bits(size).ok()
|
||||
}
|
||||
|
||||
/// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type.
|
||||
#[inline]
|
||||
pub fn eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> u128 {
|
||||
self.try_eval_bits(tcx, param_env, ty)
|
||||
.unwrap_or_else(|| bug!("expected bits of {:#?}, got {:#?}", ty, self))
|
||||
pub fn eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> u128 {
|
||||
self.try_eval_bits(tcx, param_env)
|
||||
.unwrap_or_else(|| bug!("expected bits of {:#?}, got {:#?}", self.ty(), self))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -416,7 +371,7 @@ impl<'tcx> ConstantKind<'tcx> {
|
||||
Self::Val(val, ty)
|
||||
}
|
||||
|
||||
/// Literals are converted to `ConstantKindVal`, const generic parameters are eagerly
|
||||
/// Literals are converted to `Const::Val`, const generic parameters are eagerly
|
||||
/// converted to a constant, everything else becomes `Unevaluated`.
|
||||
#[instrument(skip(tcx), level = "debug", ret)]
|
||||
pub fn from_anon_const(
|
||||
@ -552,29 +507,13 @@ impl<'tcx> UnevaluatedConst<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Debug for Constant<'tcx> {
|
||||
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
|
||||
write!(fmt, "{self}")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Display for Constant<'tcx> {
|
||||
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
|
||||
match self.ty().kind() {
|
||||
ty::FnDef(..) => {}
|
||||
_ => write!(fmt, "const ")?,
|
||||
}
|
||||
Display::fmt(&self.literal, fmt)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Display for ConstantKind<'tcx> {
|
||||
impl<'tcx> Display for Const<'tcx> {
|
||||
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
|
||||
match *self {
|
||||
ConstantKind::Ty(c) => pretty_print_const(c, fmt, true),
|
||||
ConstantKind::Val(val, ty) => pretty_print_const_value(val, ty, fmt),
|
||||
Const::Ty(c) => pretty_print_const(c, fmt, true),
|
||||
Const::Val(val, ty) => pretty_print_const_value(val, ty, fmt),
|
||||
// FIXME(valtrees): Correctly print mir constants.
|
||||
ConstantKind::Unevaluated(..) => {
|
||||
Const::Unevaluated(..) => {
|
||||
fmt.write_str("_")?;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -318,7 +318,7 @@ pub struct Body<'tcx> {
|
||||
|
||||
/// Constants that are required to evaluate successfully for this MIR to be well-formed.
|
||||
/// We hold in this field all the constants we are not able to evaluate yet.
|
||||
pub required_consts: Vec<Constant<'tcx>>,
|
||||
pub required_consts: Vec<ConstOperand<'tcx>>,
|
||||
|
||||
/// Does this body use generic parameters. This is used for the `ConstEvaluatable` check.
|
||||
///
|
||||
@ -585,12 +585,12 @@ impl<'tcx> Body<'tcx> {
|
||||
&self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
normalize_const: impl Fn(ConstantKind<'tcx>) -> Result<ConstantKind<'tcx>, ErrorHandled>,
|
||||
normalize_const: impl Fn(Const<'tcx>) -> Result<Const<'tcx>, ErrorHandled>,
|
||||
) -> Result<(), ErrorHandled> {
|
||||
// For now, the only thing we have to check is is to ensure that all the constants used in
|
||||
// the body successfully evaluate.
|
||||
for &const_ in &self.required_consts {
|
||||
let c = normalize_const(const_.literal)?;
|
||||
let c = normalize_const(const_.const_)?;
|
||||
c.eval(tcx, param_env, Some(const_.span))?;
|
||||
}
|
||||
|
||||
@ -1096,7 +1096,7 @@ impl<'tcx> LocalDecl<'tcx> {
|
||||
pub enum VarDebugInfoContents<'tcx> {
|
||||
/// This `Place` only contains projection which satisfy `can_use_in_debuginfo`.
|
||||
Place(Place<'tcx>),
|
||||
Const(Constant<'tcx>),
|
||||
Const(ConstOperand<'tcx>),
|
||||
}
|
||||
|
||||
impl<'tcx> Debug for VarDebugInfoContents<'tcx> {
|
||||
|
@ -696,6 +696,17 @@ impl Debug for Statement<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for NonDivergingIntrinsic<'_> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::Assume(op) => write!(f, "assume({op:?})"),
|
||||
Self::CopyNonOverlapping(CopyNonOverlapping { src, dst, count }) => {
|
||||
write!(f, "copy_nonoverlapping(dst = {dst:?}, src = {src:?}, count = {count:?})")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Debug for TerminatorKind<'tcx> {
|
||||
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
|
||||
self.fmt_head(fmt)?;
|
||||
@ -1058,6 +1069,22 @@ impl<'tcx> Debug for Operand<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Debug for ConstOperand<'tcx> {
|
||||
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
|
||||
write!(fmt, "{self}")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Display for ConstOperand<'tcx> {
|
||||
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
|
||||
match self.ty().kind() {
|
||||
ty::FnDef(..) => {}
|
||||
_ => write!(fmt, "const ")?,
|
||||
}
|
||||
Display::fmt(&self.const_, fmt)
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Place<'_> {
|
||||
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
|
||||
self.as_ref().fmt(fmt)
|
||||
@ -1184,10 +1211,10 @@ fn use_verbose(ty: Ty<'_>, fn_def: bool) -> bool {
|
||||
}
|
||||
|
||||
impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
|
||||
fn visit_constant(&mut self, constant: &Constant<'tcx>, _location: Location) {
|
||||
let Constant { span, user_ty, literal } = constant;
|
||||
if use_verbose(literal.ty(), true) {
|
||||
self.push("mir::Constant");
|
||||
fn visit_constant(&mut self, constant: &ConstOperand<'tcx>, _location: Location) {
|
||||
let ConstOperand { span, user_ty, const_ } = constant;
|
||||
if use_verbose(const_.ty(), true) {
|
||||
self.push("mir::ConstOperand");
|
||||
self.push(&format!(
|
||||
"+ span: {}",
|
||||
self.tcx.sess.source_map().span_to_embeddable_string(*span)
|
||||
@ -1209,8 +1236,8 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
|
||||
ty::ValTree::Branch(_) => "Branch(..)".to_string(),
|
||||
};
|
||||
|
||||
let val = match literal {
|
||||
ConstantKind::Ty(ct) => match ct.kind() {
|
||||
let val = match const_ {
|
||||
Const::Ty(ct) => match ct.kind() {
|
||||
ty::ConstKind::Param(p) => format!("ty::Param({p})"),
|
||||
ty::ConstKind::Unevaluated(uv) => {
|
||||
format!("ty::Unevaluated({}, {:?})", self.tcx.def_path_str(uv.def), uv.args,)
|
||||
@ -1222,9 +1249,9 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
|
||||
ty::ConstKind::Placeholder(_)
|
||||
| ty::ConstKind::Infer(_)
|
||||
| ty::ConstKind::Expr(_)
|
||||
| ty::ConstKind::Bound(..) => bug!("unexpected MIR constant: {:?}", literal),
|
||||
| ty::ConstKind::Bound(..) => bug!("unexpected MIR constant: {:?}", const_),
|
||||
},
|
||||
ConstantKind::Unevaluated(uv, _) => {
|
||||
Const::Unevaluated(uv, _) => {
|
||||
format!(
|
||||
"Unevaluated({}, {:?}, {:?})",
|
||||
self.tcx.def_path_str(uv.def),
|
||||
@ -1232,13 +1259,13 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
|
||||
uv.promoted,
|
||||
)
|
||||
}
|
||||
ConstantKind::Val(val, ty) => format!("Value({})", fmt_val(*val, *ty)),
|
||||
Const::Val(val, ty) => format!("Value({})", fmt_val(*val, *ty)),
|
||||
};
|
||||
|
||||
// This reflects what `Const` looked liked before `val` was renamed
|
||||
// as `kind`. We print it like this to avoid having to update
|
||||
// expected output in a lot of tests.
|
||||
self.push(&format!("+ literal: Const {{ ty: {}, val: {} }}", literal.ty(), val));
|
||||
self.push(&format!("+ const_: Const {{ ty: {}, val: {} }}", const_.ty(), val));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1312,10 +1339,10 @@ pub fn write_allocations<'tcx>(
|
||||
struct CollectAllocIds(BTreeSet<AllocId>);
|
||||
|
||||
impl<'tcx> Visitor<'tcx> for CollectAllocIds {
|
||||
fn visit_constant(&mut self, c: &Constant<'tcx>, _: Location) {
|
||||
match c.literal {
|
||||
ConstantKind::Ty(_) | ConstantKind::Unevaluated(..) => {}
|
||||
ConstantKind::Val(val, _) => {
|
||||
fn visit_constant(&mut self, c: &ConstOperand<'tcx>, _: Location) {
|
||||
match c.const_ {
|
||||
Const::Ty(_) | Const::Unevaluated(..) => {}
|
||||
Const::Val(val, _) => {
|
||||
self.0.extend(alloc_ids_from_const_val(val));
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/// Functionality for statements, operands, places, and things that appear in them.
|
||||
use super::*;
|
||||
use super::{interpret::GlobalAlloc, *};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Statements
|
||||
@ -302,10 +302,10 @@ impl<'tcx> Operand<'tcx> {
|
||||
span: Span,
|
||||
) -> Self {
|
||||
let ty = Ty::new_fn_def(tcx, def_id, args);
|
||||
Operand::Constant(Box::new(Constant {
|
||||
Operand::Constant(Box::new(ConstOperand {
|
||||
span,
|
||||
user_ty: None,
|
||||
literal: ConstantKind::Val(ConstValue::ZeroSized, ty),
|
||||
const_: Const::Val(ConstValue::ZeroSized, ty),
|
||||
}))
|
||||
}
|
||||
|
||||
@ -333,10 +333,10 @@ impl<'tcx> Operand<'tcx> {
|
||||
};
|
||||
scalar_size == type_size
|
||||
});
|
||||
Operand::Constant(Box::new(Constant {
|
||||
Operand::Constant(Box::new(ConstOperand {
|
||||
span,
|
||||
user_ty: None,
|
||||
literal: ConstantKind::Val(ConstValue::Scalar(val), ty),
|
||||
const_: Const::Val(ConstValue::Scalar(val), ty),
|
||||
}))
|
||||
}
|
||||
|
||||
@ -356,9 +356,9 @@ impl<'tcx> Operand<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the `Constant` that is the target of this `Operand`, or `None` if this `Operand` is a
|
||||
/// Returns the `ConstOperand` that is the target of this `Operand`, or `None` if this `Operand` is a
|
||||
/// place.
|
||||
pub fn constant(&self) -> Option<&Constant<'tcx>> {
|
||||
pub fn constant(&self) -> Option<&ConstOperand<'tcx>> {
|
||||
match self {
|
||||
Operand::Constant(x) => Some(&**x),
|
||||
Operand::Copy(_) | Operand::Move(_) => None,
|
||||
@ -370,11 +370,31 @@ impl<'tcx> Operand<'tcx> {
|
||||
/// While this is unlikely in general, it's the normal case of what you'll
|
||||
/// find as the `func` in a [`TerminatorKind::Call`].
|
||||
pub fn const_fn_def(&self) -> Option<(DefId, GenericArgsRef<'tcx>)> {
|
||||
let const_ty = self.constant()?.literal.ty();
|
||||
let const_ty = self.constant()?.const_.ty();
|
||||
if let ty::FnDef(def_id, args) = *const_ty.kind() { Some((def_id, args)) } else { None }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ConstOperand<'tcx> {
|
||||
pub fn check_static_ptr(&self, tcx: TyCtxt<'_>) -> Option<DefId> {
|
||||
match self.const_.try_to_scalar() {
|
||||
Some(Scalar::Ptr(ptr, _size)) => match tcx.global_alloc(ptr.provenance) {
|
||||
GlobalAlloc::Static(def_id) => {
|
||||
assert!(!tcx.is_thread_local_static(def_id));
|
||||
Some(def_id)
|
||||
}
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn ty(&self) -> Ty<'tcx> {
|
||||
self.const_.ty()
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
/// Rvalues
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
//! This is in a dedicated file so that changes to this file can be reviewed more carefully.
|
||||
//! The intention is that this file only contains datatype declarations, no code.
|
||||
|
||||
use super::{BasicBlock, Constant, Local, UserTypeProjection};
|
||||
use super::{BasicBlock, Const, Local, UserTypeProjection};
|
||||
|
||||
use crate::mir::coverage::{CodeRegion, CoverageKind};
|
||||
use crate::traits::Reveal;
|
||||
@ -439,17 +439,6 @@ pub enum NonDivergingIntrinsic<'tcx> {
|
||||
CopyNonOverlapping(CopyNonOverlapping<'tcx>),
|
||||
}
|
||||
|
||||
impl std::fmt::Display for NonDivergingIntrinsic<'_> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::Assume(op) => write!(f, "assume({op:?})"),
|
||||
Self::CopyNonOverlapping(CopyNonOverlapping { src, dst, count }) => {
|
||||
write!(f, "copy_nonoverlapping(dst = {dst:?}, src = {src:?}, count = {count:?})")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Describes what kind of retag is to be performed.
|
||||
#[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, PartialEq, Eq, Hash, HashStable)]
|
||||
#[rustc_pass_by_value]
|
||||
@ -913,10 +902,10 @@ pub enum InlineAsmOperand<'tcx> {
|
||||
out_place: Option<Place<'tcx>>,
|
||||
},
|
||||
Const {
|
||||
value: Box<Constant<'tcx>>,
|
||||
value: Box<ConstOperand<'tcx>>,
|
||||
},
|
||||
SymFn {
|
||||
value: Box<Constant<'tcx>>,
|
||||
value: Box<ConstOperand<'tcx>>,
|
||||
},
|
||||
SymStatic {
|
||||
def_id: DefId,
|
||||
@ -1136,7 +1125,22 @@ pub enum Operand<'tcx> {
|
||||
Move(Place<'tcx>),
|
||||
|
||||
/// Constants are already semantically values, and remain unchanged.
|
||||
Constant(Box<Constant<'tcx>>),
|
||||
Constant(Box<ConstOperand<'tcx>>),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)]
|
||||
#[derive(TypeFoldable, TypeVisitable)]
|
||||
pub struct ConstOperand<'tcx> {
|
||||
pub span: Span,
|
||||
|
||||
/// Optional user-given type: for something like
|
||||
/// `collect::<Vec<_>>`, this would be present and would
|
||||
/// indicate that `Vec<_>` was explicitly specified.
|
||||
///
|
||||
/// Needed for NLL to impose user-given type constraints.
|
||||
pub user_ty: Option<UserTypeAnnotationIndex>,
|
||||
|
||||
pub const_: Const<'tcx>,
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
@ -227,7 +227,7 @@ impl<'tcx> Operand<'tcx> {
|
||||
{
|
||||
match self {
|
||||
&Operand::Copy(ref l) | &Operand::Move(ref l) => l.ty(local_decls, tcx).ty,
|
||||
Operand::Constant(c) => c.literal.ty(),
|
||||
Operand::Constant(c) => c.const_.ty(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -186,7 +186,7 @@ macro_rules! make_mir_visitor {
|
||||
|
||||
fn visit_constant(
|
||||
&mut self,
|
||||
constant: & $($mutability)? Constant<'tcx>,
|
||||
constant: & $($mutability)? ConstOperand<'tcx>,
|
||||
location: Location,
|
||||
) {
|
||||
self.super_constant(constant, location);
|
||||
@ -870,20 +870,20 @@ macro_rules! make_mir_visitor {
|
||||
|
||||
fn super_constant(
|
||||
&mut self,
|
||||
constant: & $($mutability)? Constant<'tcx>,
|
||||
constant: & $($mutability)? ConstOperand<'tcx>,
|
||||
location: Location
|
||||
) {
|
||||
let Constant {
|
||||
let ConstOperand {
|
||||
span,
|
||||
user_ty: _, // no visit method for this
|
||||
literal,
|
||||
const_,
|
||||
} = constant;
|
||||
|
||||
self.visit_span($(& $mutability)? *span);
|
||||
match literal {
|
||||
ConstantKind::Ty(ct) => self.visit_ty_const($(&$mutability)? *ct, location),
|
||||
ConstantKind::Val(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)),
|
||||
ConstantKind::Unevaluated(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)),
|
||||
match const_ {
|
||||
Const::Ty(ct) => self.visit_ty_const($(&$mutability)? *ct, location),
|
||||
Const::Val(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)),
|
||||
Const::Unevaluated(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -116,9 +116,8 @@ impl EraseType for Result<ty::Const<'_>, mir::interpret::LitToConstError> {
|
||||
type Result = [u8; size_of::<Result<ty::Const<'static>, mir::interpret::LitToConstError>>()];
|
||||
}
|
||||
|
||||
impl EraseType for Result<mir::ConstantKind<'_>, mir::interpret::LitToConstError> {
|
||||
type Result =
|
||||
[u8; size_of::<Result<mir::ConstantKind<'static>, mir::interpret::LitToConstError>>()];
|
||||
impl EraseType for Result<mir::Const<'_>, mir::interpret::LitToConstError> {
|
||||
type Result = [u8; size_of::<Result<mir::Const<'static>, mir::interpret::LitToConstError>>()];
|
||||
}
|
||||
|
||||
impl EraseType for Result<mir::ConstAlloc<'_>, mir::interpret::ErrorHandled> {
|
||||
@ -311,7 +310,7 @@ macro_rules! tcx_lifetime {
|
||||
tcx_lifetime! {
|
||||
rustc_middle::hir::Owner,
|
||||
rustc_middle::middle::exported_symbols::ExportedSymbol,
|
||||
rustc_middle::mir::ConstantKind,
|
||||
rustc_middle::mir::Const,
|
||||
rustc_middle::mir::DestructuredConstant,
|
||||
rustc_middle::mir::ConstAlloc,
|
||||
rustc_middle::mir::ConstValue,
|
||||
|
@ -416,7 +416,7 @@ impl<'tcx> Key for GenericArg<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Key for mir::ConstantKind<'tcx> {
|
||||
impl<'tcx> Key for mir::Const<'tcx> {
|
||||
type CacheSelector = DefaultCacheSelector<Self>;
|
||||
|
||||
fn default_span(&self, _: TyCtxt<'_>) -> Span {
|
||||
|
@ -1101,7 +1101,7 @@ rustc_queries! {
|
||||
desc { "destructuring type level constant"}
|
||||
}
|
||||
|
||||
/// Tries to destructure an `mir::ConstantKind` ADT or array into its variant index
|
||||
/// Tries to destructure an `mir::Const` ADT or array into its variant index
|
||||
/// and its field values. This should only be used for pretty printing.
|
||||
query try_destructure_mir_constant_for_diagnostics(
|
||||
key: (mir::ConstValue<'tcx>, Ty<'tcx>)
|
||||
|
@ -563,11 +563,11 @@ pub enum InlineAsmOperand<'tcx> {
|
||||
out_expr: Option<ExprId>,
|
||||
},
|
||||
Const {
|
||||
value: mir::ConstantKind<'tcx>,
|
||||
value: mir::Const<'tcx>,
|
||||
span: Span,
|
||||
},
|
||||
SymFn {
|
||||
value: mir::ConstantKind<'tcx>,
|
||||
value: mir::Const<'tcx>,
|
||||
span: Span,
|
||||
},
|
||||
SymStatic {
|
||||
@ -739,7 +739,7 @@ pub enum PatKind<'tcx> {
|
||||
/// * Opaque constants, that must not be matched structurally. So anything that does not derive
|
||||
/// `PartialEq` and `Eq`.
|
||||
Constant {
|
||||
value: mir::ConstantKind<'tcx>,
|
||||
value: mir::Const<'tcx>,
|
||||
},
|
||||
|
||||
Range(Box<PatRange<'tcx>>),
|
||||
@ -769,8 +769,8 @@ pub enum PatKind<'tcx> {
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, HashStable)]
|
||||
pub struct PatRange<'tcx> {
|
||||
pub lo: mir::ConstantKind<'tcx>,
|
||||
pub hi: mir::ConstantKind<'tcx>,
|
||||
pub lo: mir::Const<'tcx>,
|
||||
pub hi: mir::Const<'tcx>,
|
||||
pub end: RangeEnd,
|
||||
}
|
||||
|
||||
|
@ -26,13 +26,13 @@ pub trait Visitor<'a, 'tcx: 'a>: Sized {
|
||||
walk_pat(self, pat);
|
||||
}
|
||||
|
||||
// Note: We don't have visitors for `ty::Const` and `mir::ConstantKind`
|
||||
// Note: We don't have visitors for `ty::Const` and `mir::Const`
|
||||
// (even though these types occur in THIR) for consistency and to reduce confusion,
|
||||
// since the lazy creation of constants during thir construction causes most
|
||||
// 'constants' to not be of type `ty::Const` or `mir::ConstantKind` at that
|
||||
// 'constants' to not be of type `ty::Const` or `mir::Const` at that
|
||||
// stage (they are mostly still identified by `DefId` or `hir::Lit`, see
|
||||
// the variants `Literal`, `NonHirLiteral` and `NamedConst` in `thir::ExprKind`).
|
||||
// You have to manually visit `ty::Const` and `mir::ConstantKind` through the
|
||||
// You have to manually visit `ty::Const` and `mir::Const` through the
|
||||
// other `visit*` functions.
|
||||
}
|
||||
|
||||
|
@ -339,24 +339,19 @@ impl<'tcx> Const<'tcx> {
|
||||
/// 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>,
|
||||
ty: Ty<'tcx>,
|
||||
) -> Option<u128> {
|
||||
pub fn try_eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<u128> {
|
||||
let int = self.try_eval_scalar_int(tcx, param_env)?;
|
||||
assert_eq!(self.ty(), ty);
|
||||
let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size;
|
||||
let size =
|
||||
tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(self.ty())).ok()?.size;
|
||||
// if `ty` does not depend on generic parameters, use an empty param_env
|
||||
int.to_bits(size).ok()
|
||||
}
|
||||
|
||||
#[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>, ty: Ty<'tcx>) -> u128 {
|
||||
self.try_eval_bits(tcx, param_env, ty)
|
||||
.unwrap_or_else(|| bug!("expected bits of {:#?}, got {:#?}", ty, self))
|
||||
pub fn eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> u128 {
|
||||
self.try_eval_bits(tcx, param_env)
|
||||
.unwrap_or_else(|| bug!("expected bits of {:#?}, got {:#?}", self.ty(), self))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -17,8 +17,8 @@ pub fn find_self_call<'tcx>(
|
||||
&body[block].terminator
|
||||
{
|
||||
debug!("find_self_call: func={:?}", func);
|
||||
if let Operand::Constant(box Constant { literal, .. }) = func {
|
||||
if let ty::FnDef(def_id, fn_args) = *literal.ty().kind() {
|
||||
if let Operand::Constant(box ConstOperand { const_, .. }) = func {
|
||||
if let ty::FnDef(def_id, fn_args) = *const_.ty().kind() {
|
||||
if let Some(ty::AssocItem { fn_has_self_parameter: true, .. }) =
|
||||
tcx.opt_associated_item(def_id)
|
||||
{
|
||||
|
@ -49,7 +49,7 @@ impl<'tcx> CFG<'tcx> {
|
||||
block: BasicBlock,
|
||||
source_info: SourceInfo,
|
||||
temp: Place<'tcx>,
|
||||
constant: Constant<'tcx>,
|
||||
constant: ConstOperand<'tcx>,
|
||||
) {
|
||||
self.push_assign(
|
||||
block,
|
||||
@ -70,10 +70,10 @@ impl<'tcx> CFG<'tcx> {
|
||||
block,
|
||||
source_info,
|
||||
place,
|
||||
Rvalue::Use(Operand::Constant(Box::new(Constant {
|
||||
Rvalue::Use(Operand::Constant(Box::new(ConstOperand {
|
||||
span: source_info.span,
|
||||
user_ty: None,
|
||||
literal: ConstantKind::zero_sized(tcx.types.unit),
|
||||
const_: Const::zero_sized(tcx.types.unit),
|
||||
}))),
|
||||
);
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
|
||||
expected: "constant pattern".to_string(),
|
||||
});
|
||||
};
|
||||
values.push(value.eval_bits(self.tcx, self.param_env, arm.pattern.ty));
|
||||
values.push(value.eval_bits(self.tcx, self.param_env));
|
||||
targets.push(self.parse_block(arm.body)?);
|
||||
}
|
||||
|
||||
@ -283,12 +283,12 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
|
||||
ExprKind::StaticRef { alloc_id, ty, .. } => {
|
||||
let const_val =
|
||||
ConstValue::Scalar(Scalar::from_pointer((*alloc_id).into(), &self.tcx));
|
||||
let literal = ConstantKind::Val(const_val, *ty);
|
||||
let const_ = Const::Val(const_val, *ty);
|
||||
|
||||
Ok(Operand::Constant(Box::new(Constant {
|
||||
Ok(Operand::Constant(Box::new(ConstOperand {
|
||||
span: expr.span,
|
||||
user_ty: None,
|
||||
literal
|
||||
const_
|
||||
})))
|
||||
},
|
||||
)
|
||||
@ -301,7 +301,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
|
||||
| ExprKind::NonHirLiteral { .. }
|
||||
| ExprKind::ConstBlock { .. } => Ok({
|
||||
let value = as_constant_inner(expr, |_| None, self.tcx);
|
||||
value.literal.eval_bits(self.tcx, self.param_env, value.ty())
|
||||
value.const_.eval_bits(self.tcx, self.param_env)
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ use rustc_target::abi::Size;
|
||||
impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
/// Compile `expr`, yielding a compile-time constant. Assumes that
|
||||
/// `expr` is a valid compile-time constant!
|
||||
pub(crate) fn as_constant(&mut self, expr: &Expr<'tcx>) -> Constant<'tcx> {
|
||||
pub(crate) fn as_constant(&mut self, expr: &Expr<'tcx>) -> ConstOperand<'tcx> {
|
||||
let this = self;
|
||||
let tcx = this.tcx;
|
||||
let Expr { ty, temp_lifetime: _, span, ref kind } = *expr;
|
||||
@ -42,62 +42,62 @@ pub fn as_constant_inner<'tcx>(
|
||||
expr: &Expr<'tcx>,
|
||||
push_cuta: impl FnMut(&Box<CanonicalUserType<'tcx>>) -> Option<UserTypeAnnotationIndex>,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
) -> Constant<'tcx> {
|
||||
) -> ConstOperand<'tcx> {
|
||||
let Expr { ty, temp_lifetime: _, span, ref kind } = *expr;
|
||||
match *kind {
|
||||
ExprKind::Literal { lit, neg } => {
|
||||
let literal =
|
||||
match lit_to_mir_constant(tcx, LitToConstInput { lit: &lit.node, ty, neg }) {
|
||||
let const_ = match lit_to_mir_constant(tcx, LitToConstInput { lit: &lit.node, ty, neg })
|
||||
{
|
||||
Ok(c) => c,
|
||||
Err(LitToConstError::Reported(guar)) => {
|
||||
ConstantKind::Ty(ty::Const::new_error(tcx, guar, ty))
|
||||
Const::Ty(ty::Const::new_error(tcx, guar, ty))
|
||||
}
|
||||
Err(LitToConstError::TypeError) => {
|
||||
bug!("encountered type error in `lit_to_mir_constant`")
|
||||
}
|
||||
};
|
||||
|
||||
Constant { span, user_ty: None, literal }
|
||||
ConstOperand { span, user_ty: None, const_ }
|
||||
}
|
||||
ExprKind::NonHirLiteral { lit, ref user_ty } => {
|
||||
let user_ty = user_ty.as_ref().and_then(push_cuta);
|
||||
|
||||
let literal = ConstantKind::Val(ConstValue::Scalar(Scalar::Int(lit)), ty);
|
||||
let const_ = Const::Val(ConstValue::Scalar(Scalar::Int(lit)), ty);
|
||||
|
||||
Constant { span, user_ty, literal }
|
||||
ConstOperand { span, user_ty, const_ }
|
||||
}
|
||||
ExprKind::ZstLiteral { ref user_ty } => {
|
||||
let user_ty = user_ty.as_ref().and_then(push_cuta);
|
||||
|
||||
let literal = ConstantKind::Val(ConstValue::ZeroSized, ty);
|
||||
let const_ = Const::Val(ConstValue::ZeroSized, ty);
|
||||
|
||||
Constant { span, user_ty, literal }
|
||||
ConstOperand { span, user_ty, const_ }
|
||||
}
|
||||
ExprKind::NamedConst { def_id, args, ref user_ty } => {
|
||||
let user_ty = user_ty.as_ref().and_then(push_cuta);
|
||||
|
||||
let uneval = mir::UnevaluatedConst::new(def_id, args);
|
||||
let literal = ConstantKind::Unevaluated(uneval, ty);
|
||||
let const_ = Const::Unevaluated(uneval, ty);
|
||||
|
||||
Constant { user_ty, span, literal }
|
||||
ConstOperand { user_ty, span, const_ }
|
||||
}
|
||||
ExprKind::ConstParam { param, def_id: _ } => {
|
||||
let const_param = ty::Const::new_param(tcx, param, expr.ty);
|
||||
let literal = ConstantKind::Ty(const_param);
|
||||
let const_ = Const::Ty(const_param);
|
||||
|
||||
Constant { user_ty: None, span, literal }
|
||||
ConstOperand { user_ty: None, span, const_ }
|
||||
}
|
||||
ExprKind::ConstBlock { did: def_id, args } => {
|
||||
let uneval = mir::UnevaluatedConst::new(def_id, args);
|
||||
let literal = ConstantKind::Unevaluated(uneval, ty);
|
||||
let const_ = Const::Unevaluated(uneval, ty);
|
||||
|
||||
Constant { user_ty: None, span, literal }
|
||||
ConstOperand { user_ty: None, span, const_ }
|
||||
}
|
||||
ExprKind::StaticRef { alloc_id, ty, .. } => {
|
||||
let const_val = ConstValue::Scalar(Scalar::from_pointer(alloc_id.into(), &tcx));
|
||||
let literal = ConstantKind::Val(const_val, ty);
|
||||
let const_ = Const::Val(const_val, ty);
|
||||
|
||||
Constant { span, user_ty: None, literal }
|
||||
ConstOperand { span, user_ty: None, const_ }
|
||||
}
|
||||
_ => span_bug!(span, "expression is not a valid constant {:?}", kind),
|
||||
}
|
||||
@ -107,7 +107,7 @@ pub fn as_constant_inner<'tcx>(
|
||||
fn lit_to_mir_constant<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
lit_input: LitToConstInput<'tcx>,
|
||||
) -> Result<ConstantKind<'tcx>, LitToConstError> {
|
||||
) -> Result<Const<'tcx>, LitToConstError> {
|
||||
let LitToConstInput { lit, ty, neg } = lit_input;
|
||||
let trunc = |n| {
|
||||
let param_ty = ty::ParamEnv::reveal_all().and(ty);
|
||||
@ -173,5 +173,5 @@ fn lit_to_mir_constant<'tcx>(
|
||||
_ => return Err(LitToConstError::TypeError),
|
||||
};
|
||||
|
||||
Ok(ConstantKind::Val(value, ty))
|
||||
Ok(Const::Val(value, ty))
|
||||
}
|
||||
|
@ -249,7 +249,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
|
||||
let mut comparer = |range: u128, bin_op: BinOp| -> Place<'tcx> {
|
||||
let range_val =
|
||||
ConstantKind::from_bits(this.tcx, range, ty::ParamEnv::empty().and(unsigned_ty));
|
||||
Const::from_bits(this.tcx, range, ty::ParamEnv::empty().and(unsigned_ty));
|
||||
let lit_op = this.literal_operand(expr.span, range_val);
|
||||
let is_bin_op = this.temp(bool_ty, expr_span);
|
||||
this.cfg.push_assign(
|
||||
@ -485,10 +485,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
}
|
||||
ExprKind::Assign { .. } | ExprKind::AssignOp { .. } => {
|
||||
block = unpack!(this.stmt_expr(block, expr, None));
|
||||
block.and(Rvalue::Use(Operand::Constant(Box::new(Constant {
|
||||
block.and(Rvalue::Use(Operand::Constant(Box::new(ConstOperand {
|
||||
span: expr_span,
|
||||
user_ty: None,
|
||||
literal: ConstantKind::zero_sized(this.tcx.types.unit),
|
||||
const_: Const::zero_sized(this.tcx.types.unit),
|
||||
}))))
|
||||
}
|
||||
|
||||
@ -817,7 +817,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
fn neg_1_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> {
|
||||
let param_ty = ty::ParamEnv::empty().and(ty);
|
||||
let size = self.tcx.layout_of(param_ty).unwrap().size;
|
||||
let literal = ConstantKind::from_bits(self.tcx, size.unsigned_int_max(), param_ty);
|
||||
let literal = Const::from_bits(self.tcx, size.unsigned_int_max(), param_ty);
|
||||
|
||||
self.literal_operand(span, literal)
|
||||
}
|
||||
@ -828,7 +828,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
let param_ty = ty::ParamEnv::empty().and(ty);
|
||||
let bits = self.tcx.layout_of(param_ty).unwrap().size.bits();
|
||||
let n = 1 << (bits - 1);
|
||||
let literal = ConstantKind::from_bits(self.tcx, n, param_ty);
|
||||
let literal = Const::from_bits(self.tcx, n, param_ty);
|
||||
|
||||
self.literal_operand(span, literal)
|
||||
}
|
||||
|
@ -114,10 +114,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
true_block,
|
||||
source_info,
|
||||
destination,
|
||||
Constant {
|
||||
ConstOperand {
|
||||
span: expr_span,
|
||||
user_ty: None,
|
||||
literal: ConstantKind::from_bool(this.tcx, true),
|
||||
const_: Const::from_bool(this.tcx, true),
|
||||
},
|
||||
);
|
||||
|
||||
@ -125,10 +125,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
false_block,
|
||||
source_info,
|
||||
destination,
|
||||
Constant {
|
||||
ConstOperand {
|
||||
span: expr_span,
|
||||
user_ty: None,
|
||||
literal: ConstantKind::from_bool(this.tcx, false),
|
||||
const_: Const::from_bool(this.tcx, false),
|
||||
},
|
||||
);
|
||||
|
||||
@ -186,10 +186,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
short_circuit,
|
||||
source_info,
|
||||
destination,
|
||||
Constant {
|
||||
ConstOperand {
|
||||
span: expr.span,
|
||||
user_ty: None,
|
||||
literal: ConstantKind::from_bool(this.tcx, constant),
|
||||
const_: Const::from_bool(this.tcx, constant),
|
||||
},
|
||||
);
|
||||
let rhs = unpack!(this.expr_into_dest(destination, continuation, &this.thir[rhs]));
|
||||
@ -433,12 +433,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
}
|
||||
thir::InlineAsmOperand::Const { value, span } => {
|
||||
mir::InlineAsmOperand::Const {
|
||||
value: Box::new(Constant { span, user_ty: None, literal: value }),
|
||||
value: Box::new(ConstOperand {
|
||||
span,
|
||||
user_ty: None,
|
||||
const_: value,
|
||||
}),
|
||||
}
|
||||
}
|
||||
thir::InlineAsmOperand::SymFn { value, span } => {
|
||||
mir::InlineAsmOperand::SymFn {
|
||||
value: Box::new(Constant { span, user_ty: None, literal: value }),
|
||||
value: Box::new(ConstOperand {
|
||||
span,
|
||||
user_ty: None,
|
||||
const_: value,
|
||||
}),
|
||||
}
|
||||
}
|
||||
thir::InlineAsmOperand::SymStatic { def_id } => {
|
||||
|
@ -1005,13 +1005,13 @@ enum TestKind<'tcx> {
|
||||
///
|
||||
/// For `bool` we always generate two edges, one for `true` and one for
|
||||
/// `false`.
|
||||
options: FxIndexMap<ConstantKind<'tcx>, u128>,
|
||||
options: FxIndexMap<Const<'tcx>, u128>,
|
||||
},
|
||||
|
||||
/// Test for equality with value, possibly after an unsizing coercion to
|
||||
/// `ty`,
|
||||
Eq {
|
||||
value: ConstantKind<'tcx>,
|
||||
value: Const<'tcx>,
|
||||
// Integer types are handled by `SwitchInt`, and constants with ADT
|
||||
// types are converted back into patterns, so this can only be `&str`,
|
||||
// `&[T]`, `f32` or `f64`.
|
||||
@ -1622,9 +1622,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
// may want to add cases based on the candidates that are
|
||||
// available
|
||||
match test.kind {
|
||||
TestKind::SwitchInt { switch_ty, ref mut options } => {
|
||||
TestKind::SwitchInt { switch_ty: _, ref mut options } => {
|
||||
for candidate in candidates.iter() {
|
||||
if !self.add_cases_to_switch(&match_place, candidate, switch_ty, options) {
|
||||
if !self.add_cases_to_switch(&match_place, candidate, options) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -85,8 +85,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
&mut self,
|
||||
test_place: &PlaceBuilder<'tcx>,
|
||||
candidate: &Candidate<'pat, 'tcx>,
|
||||
switch_ty: Ty<'tcx>,
|
||||
options: &mut FxIndexMap<ConstantKind<'tcx>, u128>,
|
||||
options: &mut FxIndexMap<Const<'tcx>, u128>,
|
||||
) -> bool {
|
||||
let Some(match_pair) = candidate.match_pairs.iter().find(|mp| mp.place == *test_place)
|
||||
else {
|
||||
@ -95,9 +94,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
|
||||
match match_pair.pattern.kind {
|
||||
PatKind::Constant { value } => {
|
||||
options
|
||||
.entry(value)
|
||||
.or_insert_with(|| value.eval_bits(self.tcx, self.param_env, switch_ty));
|
||||
options.entry(value).or_insert_with(|| value.eval_bits(self.tcx, self.param_env));
|
||||
true
|
||||
}
|
||||
PatKind::Variant { .. } => {
|
||||
@ -255,10 +252,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
block,
|
||||
source_info,
|
||||
TerminatorKind::Call {
|
||||
func: Operand::Constant(Box::new(Constant {
|
||||
func: Operand::Constant(Box::new(ConstOperand {
|
||||
span: test.span,
|
||||
user_ty: None,
|
||||
literal: method,
|
||||
const_: method,
|
||||
})),
|
||||
args: vec![Operand::Move(ref_string)],
|
||||
destination: ref_str,
|
||||
@ -388,7 +385,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
block: BasicBlock,
|
||||
make_target_blocks: impl FnOnce(&mut Self) -> Vec<BasicBlock>,
|
||||
source_info: SourceInfo,
|
||||
value: ConstantKind<'tcx>,
|
||||
value: Const<'tcx>,
|
||||
mut val: Place<'tcx>,
|
||||
mut ty: Ty<'tcx>,
|
||||
) {
|
||||
@ -485,7 +482,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
block,
|
||||
source_info,
|
||||
TerminatorKind::Call {
|
||||
func: Operand::Constant(Box::new(Constant {
|
||||
func: Operand::Constant(Box::new(ConstOperand {
|
||||
span: source_info.span,
|
||||
|
||||
// FIXME(#54571): This constant comes from user input (a
|
||||
@ -494,7 +491,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
// Need to experiment.
|
||||
user_ty: None,
|
||||
|
||||
literal: method,
|
||||
const_: method,
|
||||
})),
|
||||
args: vec![Operand::Copy(val), expect],
|
||||
destination: eq_result,
|
||||
@ -800,11 +797,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
span_bug!(match_pair.pattern.span, "simplifiable pattern found: {:?}", match_pair.pattern)
|
||||
}
|
||||
|
||||
fn const_range_contains(
|
||||
&self,
|
||||
range: &PatRange<'tcx>,
|
||||
value: ConstantKind<'tcx>,
|
||||
) -> Option<bool> {
|
||||
fn const_range_contains(&self, range: &PatRange<'tcx>, value: Const<'tcx>) -> Option<bool> {
|
||||
use std::cmp::Ordering::*;
|
||||
|
||||
// For performance, it's important to only do the second
|
||||
@ -821,7 +814,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
fn values_not_contained_in_range(
|
||||
&self,
|
||||
range: &PatRange<'tcx>,
|
||||
options: &FxIndexMap<ConstantKind<'tcx>, u128>,
|
||||
options: &FxIndexMap<Const<'tcx>, u128>,
|
||||
) -> Option<bool> {
|
||||
for &val in options.keys() {
|
||||
if self.const_range_contains(range, val)? {
|
||||
@ -866,7 +859,7 @@ fn trait_method<'tcx>(
|
||||
trait_def_id: DefId,
|
||||
method_name: Symbol,
|
||||
args: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
|
||||
) -> ConstantKind<'tcx> {
|
||||
) -> Const<'tcx> {
|
||||
// The unhygienic comparison here is acceptable because this is only
|
||||
// used on known traits.
|
||||
let item = tcx
|
||||
@ -877,5 +870,5 @@ fn trait_method<'tcx>(
|
||||
|
||||
let method_ty = Ty::new_fn_def(tcx, item.def_id, args);
|
||||
|
||||
ConstantKind::zero_sized(method_ty)
|
||||
Const::zero_sized(method_ty)
|
||||
}
|
||||
|
@ -25,19 +25,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
|
||||
/// Convenience function for creating a literal operand, one
|
||||
/// without any user type annotation.
|
||||
pub(crate) fn literal_operand(
|
||||
&mut self,
|
||||
span: Span,
|
||||
literal: ConstantKind<'tcx>,
|
||||
) -> Operand<'tcx> {
|
||||
let constant = Box::new(Constant { span, user_ty: None, literal });
|
||||
pub(crate) fn literal_operand(&mut self, span: Span, const_: Const<'tcx>) -> Operand<'tcx> {
|
||||
let constant = Box::new(ConstOperand { span, user_ty: None, const_ });
|
||||
Operand::Constant(constant)
|
||||
}
|
||||
|
||||
/// Returns a zero literal operand for the appropriate type, works for
|
||||
/// bool, char and integers.
|
||||
pub(crate) fn zero_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> {
|
||||
let literal = ConstantKind::from_bits(self.tcx, 0, ty::ParamEnv::empty().and(ty));
|
||||
let literal = Const::from_bits(self.tcx, 0, ty::ParamEnv::empty().and(ty));
|
||||
|
||||
self.literal_operand(span, literal)
|
||||
}
|
||||
@ -54,10 +50,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
block,
|
||||
source_info,
|
||||
temp,
|
||||
Constant {
|
||||
ConstOperand {
|
||||
span: source_info.span,
|
||||
user_ty: None,
|
||||
literal: ConstantKind::from_usize(self.tcx, value),
|
||||
const_: Const::from_usize(self.tcx, value),
|
||||
},
|
||||
);
|
||||
temp
|
||||
|
@ -647,21 +647,15 @@ impl<'tcx> Cx<'tcx> {
|
||||
out_expr: out_expr.map(|expr| self.mirror_expr(expr)),
|
||||
},
|
||||
hir::InlineAsmOperand::Const { ref anon_const } => {
|
||||
let value = mir::ConstantKind::from_anon_const(
|
||||
tcx,
|
||||
anon_const.def_id,
|
||||
self.param_env,
|
||||
);
|
||||
let value =
|
||||
mir::Const::from_anon_const(tcx, anon_const.def_id, self.param_env);
|
||||
let span = tcx.def_span(anon_const.def_id);
|
||||
|
||||
InlineAsmOperand::Const { value, span }
|
||||
}
|
||||
hir::InlineAsmOperand::SymFn { ref anon_const } => {
|
||||
let value = mir::ConstantKind::from_anon_const(
|
||||
tcx,
|
||||
anon_const.def_id,
|
||||
self.param_env,
|
||||
);
|
||||
let value =
|
||||
mir::Const::from_anon_const(tcx, anon_const.def_id, self.param_env);
|
||||
let span = tcx.def_span(anon_const.def_id);
|
||||
|
||||
InlineAsmOperand::SymFn { value, span }
|
||||
|
@ -27,7 +27,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
||||
#[instrument(level = "debug", skip(self), ret)]
|
||||
pub(super) fn const_to_pat(
|
||||
&self,
|
||||
cv: mir::ConstantKind<'tcx>,
|
||||
cv: mir::Const<'tcx>,
|
||||
id: hir::HirId,
|
||||
span: Span,
|
||||
check_body_for_struct_match_violation: Option<DefId>,
|
||||
@ -104,7 +104,7 @@ impl<'tcx> ConstToPat<'tcx> {
|
||||
|
||||
fn to_pat(
|
||||
&mut self,
|
||||
cv: mir::ConstantKind<'tcx>,
|
||||
cv: mir::Const<'tcx>,
|
||||
check_body_for_struct_match_violation: Option<DefId>,
|
||||
) -> Box<Pat<'tcx>> {
|
||||
trace!(self.treat_byte_string_as_slice);
|
||||
@ -124,7 +124,7 @@ impl<'tcx> ConstToPat<'tcx> {
|
||||
debug!(?check_body_for_struct_match_violation, ?mir_structural_match_violation);
|
||||
|
||||
let inlined_const_as_pat = match cv {
|
||||
mir::ConstantKind::Ty(c) => match c.kind() {
|
||||
mir::Const::Ty(c) => match c.kind() {
|
||||
ty::ConstKind::Param(_)
|
||||
| ty::ConstKind::Infer(_)
|
||||
| ty::ConstKind::Bound(_, _)
|
||||
@ -144,10 +144,10 @@ impl<'tcx> ConstToPat<'tcx> {
|
||||
})
|
||||
}),
|
||||
},
|
||||
mir::ConstantKind::Unevaluated(_, _) => {
|
||||
mir::Const::Unevaluated(_, _) => {
|
||||
span_bug!(self.span, "unevaluated const in `to_pat`: {cv:?}")
|
||||
}
|
||||
mir::ConstantKind::Val(_, _) => Box::new(Pat {
|
||||
mir::Const::Val(_, _) => Box::new(Pat {
|
||||
span: self.span,
|
||||
ty: cv.ty(),
|
||||
kind: PatKind::Constant { value: cv },
|
||||
@ -385,9 +385,9 @@ impl<'tcx> ConstToPat<'tcx> {
|
||||
ty::Ref(_, pointee_ty, ..) => match *pointee_ty.kind() {
|
||||
// `&str` is represented as a valtree, let's keep using this
|
||||
// optimization for now.
|
||||
ty::Str => PatKind::Constant {
|
||||
value: mir::ConstantKind::Ty(ty::Const::new_value(tcx, cv, ty)),
|
||||
},
|
||||
ty::Str => {
|
||||
PatKind::Constant { value: mir::Const::Ty(ty::Const::new_value(tcx, cv, ty)) }
|
||||
}
|
||||
// Backwards compatibility hack: support references to non-structural types,
|
||||
// but hard error if we aren't behind a double reference. We could just use
|
||||
// the fallback code path below, but that would allow *more* of this fishy
|
||||
@ -445,9 +445,9 @@ impl<'tcx> ConstToPat<'tcx> {
|
||||
}
|
||||
}
|
||||
},
|
||||
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) => PatKind::Constant {
|
||||
value: mir::ConstantKind::Ty(ty::Const::new_value(tcx, cv, ty)),
|
||||
},
|
||||
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) => {
|
||||
PatKind::Constant { value: mir::Const::Ty(ty::Const::new_value(tcx, cv, ty)) }
|
||||
}
|
||||
ty::FnPtr(..) | ty::RawPtr(..) => unreachable!(),
|
||||
_ => {
|
||||
self.saw_const_match_error.set(true);
|
||||
|
@ -137,16 +137,16 @@ impl IntRange {
|
||||
fn from_constant<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
value: mir::ConstantKind<'tcx>,
|
||||
value: mir::Const<'tcx>,
|
||||
) -> Option<IntRange> {
|
||||
let ty = value.ty();
|
||||
let (target_size, bias) = Self::integral_size_and_signed_bias(tcx, ty)?;
|
||||
let val = match value {
|
||||
mir::ConstantKind::Ty(c) if let ty::ConstKind::Value(valtree) = c.kind() => {
|
||||
mir::Const::Ty(c) if let ty::ConstKind::Value(valtree) = c.kind() => {
|
||||
valtree.unwrap_leaf().to_bits(target_size).ok()
|
||||
},
|
||||
// This is a more general form of the previous case.
|
||||
_ => value.try_eval_bits(tcx, param_env, ty),
|
||||
_ => value.try_eval_bits(tcx, param_env),
|
||||
}?;
|
||||
|
||||
let val = val ^ bias;
|
||||
@ -225,8 +225,8 @@ impl IntRange {
|
||||
let (lo, hi) = (lo ^ bias, hi ^ bias);
|
||||
|
||||
let env = ty::ParamEnv::empty().and(ty);
|
||||
let lo_const = mir::ConstantKind::from_bits(tcx, lo, env);
|
||||
let hi_const = mir::ConstantKind::from_bits(tcx, hi, env);
|
||||
let lo_const = mir::Const::from_bits(tcx, lo, env);
|
||||
let hi_const = mir::Const::from_bits(tcx, hi, env);
|
||||
|
||||
let kind = if lo == hi {
|
||||
PatKind::Constant { value: lo_const }
|
||||
@ -619,9 +619,9 @@ pub(super) enum Constructor<'tcx> {
|
||||
/// Ranges of integer literal values (`2`, `2..=5` or `2..5`).
|
||||
IntRange(IntRange),
|
||||
/// Ranges of floating-point literal values (`2.0..=5.2`).
|
||||
FloatRange(mir::ConstantKind<'tcx>, mir::ConstantKind<'tcx>, RangeEnd),
|
||||
FloatRange(mir::Const<'tcx>, mir::Const<'tcx>, RangeEnd),
|
||||
/// String literals. Strings are not quite the same as `&[u8]` so we treat them separately.
|
||||
Str(mir::ConstantKind<'tcx>),
|
||||
Str(mir::Const<'tcx>),
|
||||
/// Array and slice patterns.
|
||||
Slice(Slice),
|
||||
/// Constants that must not be matched structurally. They are treated as black
|
||||
@ -1379,8 +1379,8 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
|
||||
let ty = lo.ty();
|
||||
ctor = if let Some(int_range) = IntRange::from_range(
|
||||
cx.tcx,
|
||||
lo.eval_bits(cx.tcx, cx.param_env, lo.ty()),
|
||||
hi.eval_bits(cx.tcx, cx.param_env, hi.ty()),
|
||||
lo.eval_bits(cx.tcx, cx.param_env),
|
||||
hi.eval_bits(cx.tcx, cx.param_env),
|
||||
ty,
|
||||
&end,
|
||||
) {
|
||||
|
@ -20,7 +20,7 @@ use rustc_index::Idx;
|
||||
use rustc_middle::mir::interpret::{
|
||||
ErrorHandled, GlobalId, LitToConstError, LitToConstInput, Scalar,
|
||||
};
|
||||
use rustc_middle::mir::{self, ConstantKind, UserTypeProjection};
|
||||
use rustc_middle::mir::{self, Const, UserTypeProjection};
|
||||
use rustc_middle::mir::{BorrowKind, Mutability};
|
||||
use rustc_middle::thir::{Ascription, BindingMode, FieldPat, LocalVarId, Pat, PatKind, PatRange};
|
||||
use rustc_middle::ty::CanonicalUserTypeAnnotation;
|
||||
@ -100,8 +100,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
||||
fn lower_pattern_range(
|
||||
&mut self,
|
||||
ty: Ty<'tcx>,
|
||||
lo: mir::ConstantKind<'tcx>,
|
||||
hi: mir::ConstantKind<'tcx>,
|
||||
lo: mir::Const<'tcx>,
|
||||
hi: mir::Const<'tcx>,
|
||||
end: RangeEnd,
|
||||
span: Span,
|
||||
lo_expr: Option<&hir::Expr<'tcx>>,
|
||||
@ -131,7 +131,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
||||
if let Some(hir::Expr { kind: hir::ExprKind::Lit(lit), .. }) = lo_expr
|
||||
&& let rustc_ast::ast::LitKind::Int(val, _) = lit.node
|
||||
{
|
||||
if lo.eval_bits(self.tcx, self.param_env, ty) != val {
|
||||
if lo.eval_bits(self.tcx, self.param_env) != val {
|
||||
lower_overflow = true;
|
||||
self.tcx.sess.emit_err(LiteralOutOfRange { span: lit.span, ty, max: max() });
|
||||
}
|
||||
@ -139,7 +139,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
||||
if let Some(hir::Expr { kind: hir::ExprKind::Lit(lit), .. }) = hi_expr
|
||||
&& let rustc_ast::ast::LitKind::Int(val, _) = lit.node
|
||||
{
|
||||
if hi.eval_bits(self.tcx, self.param_env, ty) != val {
|
||||
if hi.eval_bits(self.tcx, self.param_env) != val {
|
||||
higher_overflow = true;
|
||||
self.tcx.sess.emit_err(LiteralOutOfRange { span: lit.span, ty, max: max() });
|
||||
}
|
||||
@ -162,7 +162,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
||||
if let Some(hir::Expr { kind: hir::ExprKind::Lit(lit), .. }) = lo_expr
|
||||
&& let rustc_ast::ast::LitKind::Int(val, _) = lit.node
|
||||
{
|
||||
if lo.eval_bits(self.tcx, self.param_env, ty) != val {
|
||||
if lo.eval_bits(self.tcx, self.param_env) != val {
|
||||
lower_overflow = true;
|
||||
self.tcx.sess.emit_err(LiteralOutOfRange { span: lit.span, ty, max: max() });
|
||||
}
|
||||
@ -170,7 +170,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
||||
if let Some(hir::Expr { kind: hir::ExprKind::Lit(lit), .. }) = hi_expr
|
||||
&& let rustc_ast::ast::LitKind::Int(val, _) = lit.node
|
||||
{
|
||||
if hi.eval_bits(self.tcx, self.param_env, ty) != val {
|
||||
if hi.eval_bits(self.tcx, self.param_env) != val {
|
||||
higher_overflow = true;
|
||||
self.tcx.sess.emit_err(LiteralOutOfRange { span: lit.span, ty, max: max() });
|
||||
}
|
||||
@ -191,18 +191,18 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
||||
ty: Ty<'tcx>,
|
||||
lo: Option<&PatKind<'tcx>>,
|
||||
hi: Option<&PatKind<'tcx>>,
|
||||
) -> Option<(mir::ConstantKind<'tcx>, mir::ConstantKind<'tcx>)> {
|
||||
) -> Option<(mir::Const<'tcx>, mir::Const<'tcx>)> {
|
||||
match (lo, hi) {
|
||||
(Some(PatKind::Constant { value: lo }), Some(PatKind::Constant { value: hi })) => {
|
||||
Some((*lo, *hi))
|
||||
}
|
||||
(Some(PatKind::Constant { value: lo }), None) => {
|
||||
let hi = ty.numeric_max_val(self.tcx)?;
|
||||
Some((*lo, mir::ConstantKind::from_ty_const(hi, self.tcx)))
|
||||
Some((*lo, mir::Const::from_ty_const(hi, self.tcx)))
|
||||
}
|
||||
(None, Some(PatKind::Constant { value: hi })) => {
|
||||
let lo = ty.numeric_min_val(self.tcx)?;
|
||||
Some((mir::ConstantKind::from_ty_const(lo, self.tcx), *hi))
|
||||
Some((mir::Const::from_ty_const(lo, self.tcx), *hi))
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
@ -525,8 +525,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
||||
.tcx
|
||||
.const_eval_global_id_for_typeck(param_env_reveal_all, cid, Some(span))
|
||||
.map(|val| match val {
|
||||
Some(valtree) => mir::ConstantKind::Ty(ty::Const::new_value(self.tcx, valtree, ty)),
|
||||
None => mir::ConstantKind::Val(
|
||||
Some(valtree) => mir::Const::Ty(ty::Const::new_value(self.tcx, valtree, ty)),
|
||||
None => mir::Const::Val(
|
||||
self.tcx
|
||||
.const_eval_global_id(param_env_reveal_all, cid, Some(span))
|
||||
.expect("const_eval_global_id_for_typeck should have already failed"),
|
||||
@ -608,7 +608,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
||||
};
|
||||
if let Some(lit_input) = lit_input {
|
||||
match tcx.at(expr.span).lit_to_const(lit_input) {
|
||||
Ok(c) => return self.const_to_pat(ConstantKind::Ty(c), id, span, None).kind,
|
||||
Ok(c) => return self.const_to_pat(Const::Ty(c), id, span, None).kind,
|
||||
// If an error occurred, ignore that it's a literal
|
||||
// and leave reporting the error up to const eval of
|
||||
// the unevaluated constant below.
|
||||
@ -632,7 +632,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
||||
self.tcx.const_eval_resolve_for_typeck(self.param_env, ct, Some(span))
|
||||
{
|
||||
self.const_to_pat(
|
||||
ConstantKind::Ty(ty::Const::new_value(self.tcx, valtree, ty)),
|
||||
Const::Ty(ty::Const::new_value(self.tcx, valtree, ty)),
|
||||
id,
|
||||
span,
|
||||
None,
|
||||
@ -641,7 +641,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
||||
} else {
|
||||
// If that fails, convert it to an opaque constant pattern.
|
||||
match tcx.const_eval_resolve(self.param_env, uneval, Some(span)) {
|
||||
Ok(val) => self.const_to_pat(mir::ConstantKind::Val(val, ty), id, span, None).kind,
|
||||
Ok(val) => self.const_to_pat(mir::Const::Val(val, ty), id, span, None).kind,
|
||||
Err(ErrorHandled::TooGeneric(_)) => {
|
||||
// If we land here it means the const can't be evaluated because it's `TooGeneric`.
|
||||
self.tcx.sess.emit_err(ConstPatternDependsOnGenericParameter { span });
|
||||
@ -678,7 +678,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
||||
LitToConstInput { lit: &lit.node, ty: self.typeck_results.expr_ty(expr), neg };
|
||||
match self.tcx.at(expr.span).lit_to_const(lit_input) {
|
||||
Ok(constant) => {
|
||||
self.const_to_pat(ConstantKind::Ty(constant), expr.hir_id, lit.span, None).kind
|
||||
self.const_to_pat(Const::Ty(constant), expr.hir_id, lit.span, None).kind
|
||||
}
|
||||
Err(LitToConstError::Reported(_)) => PatKind::Wild,
|
||||
Err(LitToConstError::TypeError) => bug!("lower_lit: had type error"),
|
||||
@ -838,8 +838,8 @@ impl<'tcx> PatternFoldable<'tcx> for PatKind<'tcx> {
|
||||
#[instrument(skip(tcx), level = "debug")]
|
||||
pub(crate) fn compare_const_vals<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
a: mir::ConstantKind<'tcx>,
|
||||
b: mir::ConstantKind<'tcx>,
|
||||
a: mir::Const<'tcx>,
|
||||
b: mir::Const<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
) -> Option<Ordering> {
|
||||
assert_eq!(a.ty(), b.ty());
|
||||
@ -855,18 +855,18 @@ pub(crate) fn compare_const_vals<'tcx>(
|
||||
ty::Float(_) | ty::Int(_) => {} // require special handling, see below
|
||||
_ => match (a, b) {
|
||||
(
|
||||
mir::ConstantKind::Val(mir::ConstValue::Scalar(Scalar::Int(a)), _a_ty),
|
||||
mir::ConstantKind::Val(mir::ConstValue::Scalar(Scalar::Int(b)), _b_ty),
|
||||
mir::Const::Val(mir::ConstValue::Scalar(Scalar::Int(a)), _a_ty),
|
||||
mir::Const::Val(mir::ConstValue::Scalar(Scalar::Int(b)), _b_ty),
|
||||
) => return Some(a.cmp(&b)),
|
||||
(mir::ConstantKind::Ty(a), mir::ConstantKind::Ty(b)) => {
|
||||
(mir::Const::Ty(a), mir::Const::Ty(b)) => {
|
||||
return Some(a.kind().cmp(&b.kind()));
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
}
|
||||
|
||||
let a = a.eval_bits(tcx, param_env, ty);
|
||||
let b = b.eval_bits(tcx, param_env, ty);
|
||||
let a = a.eval_bits(tcx, param_env);
|
||||
let b = b.eval_bits(tcx, param_env);
|
||||
|
||||
use rustc_apfloat::Float;
|
||||
match *ty.kind() {
|
||||
|
@ -973,10 +973,10 @@ where
|
||||
}
|
||||
|
||||
fn constant_usize(&self, val: u16) -> Operand<'tcx> {
|
||||
Operand::Constant(Box::new(Constant {
|
||||
Operand::Constant(Box::new(ConstOperand {
|
||||
span: self.source_info.span,
|
||||
user_ty: None,
|
||||
literal: ConstantKind::from_usize(self.tcx(), val.into()),
|
||||
const_: Const::from_usize(self.tcx(), val.into()),
|
||||
}))
|
||||
}
|
||||
|
||||
|
@ -190,7 +190,7 @@ impl PeekCall {
|
||||
if let mir::TerminatorKind::Call { func: Operand::Constant(func), args, .. } =
|
||||
&terminator.kind
|
||||
{
|
||||
if let ty::FnDef(def_id, fn_args) = *func.literal.ty().kind() {
|
||||
if let ty::FnDef(def_id, fn_args) = *func.const_.ty().kind() {
|
||||
let name = tcx.item_name(def_id);
|
||||
if !tcx.is_intrinsic(def_id) || name != sym::rustc_peek {
|
||||
return None;
|
||||
|
@ -225,7 +225,7 @@ pub trait ValueAnalysis<'tcx> {
|
||||
|
||||
fn handle_constant(
|
||||
&self,
|
||||
constant: &Constant<'tcx>,
|
||||
constant: &ConstOperand<'tcx>,
|
||||
state: &mut State<Self::Value>,
|
||||
) -> Self::Value {
|
||||
self.super_constant(constant, state)
|
||||
@ -233,7 +233,7 @@ pub trait ValueAnalysis<'tcx> {
|
||||
|
||||
fn super_constant(
|
||||
&self,
|
||||
_constant: &Constant<'tcx>,
|
||||
_constant: &ConstOperand<'tcx>,
|
||||
_state: &mut State<Self::Value>,
|
||||
) -> Self::Value {
|
||||
Self::Value::TOP
|
||||
|
@ -181,13 +181,10 @@ fn insert_alignment_check<'tcx>(
|
||||
// Subtract 1 from the alignment to get the alignment mask
|
||||
let alignment_mask =
|
||||
local_decls.push(LocalDecl::with_source_info(tcx.types.usize, source_info)).into();
|
||||
let one = Operand::Constant(Box::new(Constant {
|
||||
let one = Operand::Constant(Box::new(ConstOperand {
|
||||
span: source_info.span,
|
||||
user_ty: None,
|
||||
literal: ConstantKind::Val(
|
||||
ConstValue::Scalar(Scalar::from_target_usize(1, &tcx)),
|
||||
tcx.types.usize,
|
||||
),
|
||||
const_: Const::Val(ConstValue::Scalar(Scalar::from_target_usize(1, &tcx)), tcx.types.usize),
|
||||
}));
|
||||
block_data.statements.push(Statement {
|
||||
source_info,
|
||||
@ -213,13 +210,10 @@ fn insert_alignment_check<'tcx>(
|
||||
|
||||
// Check if the alignment bits are all zero
|
||||
let is_ok = local_decls.push(LocalDecl::with_source_info(tcx.types.bool, source_info)).into();
|
||||
let zero = Operand::Constant(Box::new(Constant {
|
||||
let zero = Operand::Constant(Box::new(ConstOperand {
|
||||
span: source_info.span,
|
||||
user_ty: None,
|
||||
literal: ConstantKind::Val(
|
||||
ConstValue::Scalar(Scalar::from_target_usize(0, &tcx)),
|
||||
tcx.types.usize,
|
||||
),
|
||||
const_: Const::Val(ConstValue::Scalar(Scalar::from_target_usize(0, &tcx)), tcx.types.usize),
|
||||
}));
|
||||
block_data.statements.push(Statement {
|
||||
source_info,
|
||||
|
@ -142,9 +142,9 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> {
|
||||
|
||||
fn visit_operand(&mut self, op: &Operand<'tcx>, location: Location) {
|
||||
if let Operand::Constant(constant) = op {
|
||||
let maybe_uneval = match constant.literal {
|
||||
ConstantKind::Val(..) | ConstantKind::Ty(_) => None,
|
||||
ConstantKind::Unevaluated(uv, _) => Some(uv),
|
||||
let maybe_uneval = match constant.const_ {
|
||||
Const::Val(..) | Const::Ty(_) => None,
|
||||
Const::Unevaluated(uv, _) => Some(uv),
|
||||
};
|
||||
|
||||
if let Some(uv) = maybe_uneval {
|
||||
|
@ -4,7 +4,7 @@
|
||||
use rustc_middle::{
|
||||
mir::{
|
||||
visit::{PlaceContext, Visitor},
|
||||
Body, Constant, Local, Location, Operand, Rvalue, StatementKind, VarDebugInfoContents,
|
||||
Body, ConstOperand, Local, Location, Operand, Rvalue, StatementKind, VarDebugInfoContents,
|
||||
},
|
||||
ty::TyCtxt,
|
||||
};
|
||||
@ -45,7 +45,7 @@ struct LocalUseVisitor {
|
||||
local_assignment_locations: IndexVec<Local, Option<Location>>,
|
||||
}
|
||||
|
||||
fn find_optimization_opportunities<'tcx>(body: &Body<'tcx>) -> Vec<(Local, Constant<'tcx>)> {
|
||||
fn find_optimization_opportunities<'tcx>(body: &Body<'tcx>) -> Vec<(Local, ConstOperand<'tcx>)> {
|
||||
let mut visitor = LocalUseVisitor {
|
||||
local_mutating_uses: IndexVec::from_elem(0, &body.local_decls),
|
||||
local_assignment_locations: IndexVec::from_elem(None, &body.local_decls),
|
||||
|
@ -96,10 +96,10 @@ impl<'tcx> Visitor<'tcx> for ConstGotoOptimizationFinder<'_, 'tcx> {
|
||||
let (discr, targets) = target_bb_terminator.kind.as_switch()?;
|
||||
if discr.place() == Some(*place) {
|
||||
let switch_ty = place.ty(self.body.local_decls(), self.tcx).ty;
|
||||
debug_assert_eq!(switch_ty, _const.ty());
|
||||
// We now know that the Switch matches on the const place, and it is statementless
|
||||
// Now find which value in the Switch matches the const value.
|
||||
let const_value =
|
||||
_const.literal.try_eval_bits(self.tcx, self.param_env, switch_ty)?;
|
||||
let const_value = _const.const_.try_eval_bits(self.tcx, self.param_env)?;
|
||||
let target_to_use_in_goto = targets.target_for_value(const_value);
|
||||
self.optimizations.push(OptimizationToApply {
|
||||
bb_with_goto: location.block,
|
||||
|
@ -525,7 +525,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn replace_with_const(&mut self, place: Place<'tcx>) -> Option<ConstantKind<'tcx>> {
|
||||
fn replace_with_const(&mut self, place: Place<'tcx>) -> Option<Const<'tcx>> {
|
||||
// This will return None if the above `const_prop` invocation only "wrote" a
|
||||
// type whose creation requires no write. E.g. a generator whose initial state
|
||||
// consists solely of uninitialized memory (so it doesn't capture any locals).
|
||||
@ -541,7 +541,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||
let Right(imm) = imm else { return None };
|
||||
match *imm {
|
||||
Immediate::Scalar(scalar) if scalar.try_to_int().is_ok() => {
|
||||
Some(ConstantKind::from_scalar(self.tcx, scalar, value.layout.ty))
|
||||
Some(Const::from_scalar(self.tcx, scalar, value.layout.ty))
|
||||
}
|
||||
Immediate::ScalarPair(l, r) if l.try_to_int().is_ok() && r.try_to_int().is_ok() => {
|
||||
let alloc_id = self
|
||||
@ -551,7 +551,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||
})
|
||||
.ok()?;
|
||||
|
||||
Some(ConstantKind::Val(
|
||||
Some(Const::Val(
|
||||
ConstValue::Indirect { alloc_id, offset: Size::ZERO },
|
||||
value.layout.ty,
|
||||
))
|
||||
@ -731,7 +731,7 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> {
|
||||
if let Some(()) = self.eval_rvalue_with_identities(rvalue, *place) {
|
||||
// If this was already an evaluated constant, keep it.
|
||||
if let Rvalue::Use(Operand::Constant(c)) = rvalue
|
||||
&& let ConstantKind::Val(..) = c.literal
|
||||
&& let Const::Val(..) = c.const_
|
||||
{
|
||||
trace!("skipping replace of Rvalue::Use({:?} because it is already a const", c);
|
||||
} else if let Some(operand) = self.replace_with_const(*place) {
|
||||
|
@ -281,7 +281,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||
}
|
||||
|
||||
/// Returns the value, if any, of evaluating `c`.
|
||||
fn eval_constant(&mut self, c: &Constant<'tcx>, location: Location) -> Option<OpTy<'tcx>> {
|
||||
fn eval_constant(&mut self, c: &ConstOperand<'tcx>, location: Location) -> Option<OpTy<'tcx>> {
|
||||
// FIXME we need to revisit this for #67176
|
||||
if c.has_param() {
|
||||
return None;
|
||||
@ -293,7 +293,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||
// that the `RevealAll` pass has happened and that the body's consts
|
||||
// are normalized, so any call to resolve before that needs to be
|
||||
// manually normalized.
|
||||
let val = self.tcx.try_normalize_erasing_regions(self.param_env, c.literal).ok()?;
|
||||
let val = self.tcx.try_normalize_erasing_regions(self.param_env, c.const_).ok()?;
|
||||
|
||||
self.use_ecx(location, |this| this.ecx.eval_mir_constant(&val, Some(c.span), None))
|
||||
}
|
||||
@ -580,7 +580,7 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> {
|
||||
self.super_operand(operand, location);
|
||||
}
|
||||
|
||||
fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
|
||||
fn visit_constant(&mut self, constant: &ConstOperand<'tcx>, location: Location) {
|
||||
trace!("visit_constant: {:?}", constant);
|
||||
self.super_constant(constant, location);
|
||||
self.eval_constant(constant, location);
|
||||
|
@ -206,7 +206,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
|
||||
&& let operand_ty = operand.ty(self.local_decls, self.tcx)
|
||||
&& let Some(operand_ty) = operand_ty.builtin_deref(true)
|
||||
&& let ty::Array(_, len) = operand_ty.ty.kind()
|
||||
&& let Some(len) = ConstantKind::Ty(*len).try_eval_scalar_int(self.tcx, self.param_env)
|
||||
&& let Some(len) = Const::Ty(*len).try_eval_scalar_int(self.tcx, self.param_env)
|
||||
{
|
||||
state.insert_value_idx(target_len, FlatSet::Elem(len.into()), self.map());
|
||||
}
|
||||
@ -224,7 +224,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
|
||||
Rvalue::Len(place) => {
|
||||
let place_ty = place.ty(self.local_decls, self.tcx);
|
||||
if let ty::Array(_, len) = place_ty.ty.kind() {
|
||||
ConstantKind::Ty(*len)
|
||||
Const::Ty(*len)
|
||||
.try_eval_scalar(self.tcx, self.param_env)
|
||||
.map_or(FlatSet::Top, FlatSet::Elem)
|
||||
} else if let [ProjectionElem::Deref] = place.projection[..] {
|
||||
@ -295,11 +295,11 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
|
||||
|
||||
fn handle_constant(
|
||||
&self,
|
||||
constant: &Constant<'tcx>,
|
||||
constant: &ConstOperand<'tcx>,
|
||||
_state: &mut State<Self::Value>,
|
||||
) -> Self::Value {
|
||||
constant
|
||||
.literal
|
||||
.const_
|
||||
.try_eval_scalar(self.tcx, self.param_env)
|
||||
.map_or(FlatSet::Top, FlatSet::Elem)
|
||||
}
|
||||
@ -360,7 +360,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
Operand::Constant(box constant) => {
|
||||
if let Ok(constant) = self.ecx.eval_mir_constant(&constant.literal, None, None) {
|
||||
if let Ok(constant) = self.ecx.eval_mir_constant(&constant.const_, None, None) {
|
||||
self.assign_constant(state, place, constant, &[]);
|
||||
}
|
||||
}
|
||||
@ -518,10 +518,10 @@ pub(crate) struct Patch<'tcx> {
|
||||
/// For a given MIR location, this stores the values of the operands used by that location. In
|
||||
/// particular, this is before the effect, such that the operands of `_1 = _1 + _2` are
|
||||
/// properly captured. (This may become UB soon, but it is currently emitted even by safe code.)
|
||||
pub(crate) before_effect: FxHashMap<(Location, Place<'tcx>), ConstantKind<'tcx>>,
|
||||
pub(crate) before_effect: FxHashMap<(Location, Place<'tcx>), Const<'tcx>>,
|
||||
|
||||
/// Stores the assigned values for assignments where the Rvalue is constant.
|
||||
pub(crate) assignments: FxHashMap<Location, ConstantKind<'tcx>>,
|
||||
pub(crate) assignments: FxHashMap<Location, Const<'tcx>>,
|
||||
}
|
||||
|
||||
impl<'tcx> Patch<'tcx> {
|
||||
@ -529,8 +529,8 @@ impl<'tcx> Patch<'tcx> {
|
||||
Self { tcx, before_effect: FxHashMap::default(), assignments: FxHashMap::default() }
|
||||
}
|
||||
|
||||
fn make_operand(&self, literal: ConstantKind<'tcx>) -> Operand<'tcx> {
|
||||
Operand::Constant(Box::new(Constant { span: DUMMY_SP, user_ty: None, literal }))
|
||||
fn make_operand(&self, const_: Const<'tcx>) -> Operand<'tcx> {
|
||||
Operand::Constant(Box::new(ConstOperand { span: DUMMY_SP, user_ty: None, const_ }))
|
||||
}
|
||||
}
|
||||
|
||||
@ -549,12 +549,12 @@ impl<'tcx, 'locals> Collector<'tcx, 'locals> {
|
||||
place: Place<'tcx>,
|
||||
state: &State<FlatSet<Scalar>>,
|
||||
map: &Map,
|
||||
) -> Option<ConstantKind<'tcx>> {
|
||||
) -> Option<Const<'tcx>> {
|
||||
let FlatSet::Elem(Scalar::Int(value)) = state.get(place.as_ref(), &map) else {
|
||||
return None;
|
||||
};
|
||||
let ty = place.ty(self.local_decls, self.patch.tcx).ty;
|
||||
Some(ConstantKind::Val(ConstValue::Scalar(value.into()), ty))
|
||||
Some(Const::Val(ConstValue::Scalar(value.into()), ty))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -150,7 +150,7 @@ fn rvalue_hash<H: Hasher>(hasher: &mut H, rvalue: &Rvalue<'_>) {
|
||||
|
||||
fn operand_hash<H: Hasher>(hasher: &mut H, operand: &Operand<'_>) {
|
||||
match operand {
|
||||
Operand::Constant(box Constant { user_ty: _, literal, span: _ }) => literal.hash(hasher),
|
||||
Operand::Constant(box ConstOperand { user_ty: _, const_, span: _ }) => const_.hash(hasher),
|
||||
x => x.hash(hasher),
|
||||
};
|
||||
}
|
||||
@ -179,9 +179,9 @@ fn rvalue_eq<'tcx>(lhs: &Rvalue<'tcx>, rhs: &Rvalue<'tcx>) -> bool {
|
||||
fn operand_eq<'tcx>(lhs: &Operand<'tcx>, rhs: &Operand<'tcx>) -> bool {
|
||||
let res = match (lhs, rhs) {
|
||||
(
|
||||
Operand::Constant(box Constant { user_ty: _, literal, span: _ }),
|
||||
Operand::Constant(box Constant { user_ty: _, literal: literal2, span: _ }),
|
||||
) => literal == literal2,
|
||||
Operand::Constant(box ConstOperand { user_ty: _, const_, span: _ }),
|
||||
Operand::Constant(box ConstOperand { user_ty: _, const_: const2, span: _ }),
|
||||
) => const_ == const2,
|
||||
(x, y) => x == y,
|
||||
};
|
||||
debug!("operand_eq lhs: `{:?}` rhs: `{:?}` result: {:?}", lhs, rhs, res);
|
||||
|
@ -402,10 +402,10 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
|
||||
}
|
||||
|
||||
fn constant_bool(&self, span: Span, val: bool) -> Rvalue<'tcx> {
|
||||
Rvalue::Use(Operand::Constant(Box::new(Constant {
|
||||
Rvalue::Use(Operand::Constant(Box::new(ConstOperand {
|
||||
span,
|
||||
user_ty: None,
|
||||
literal: ConstantKind::from_bool(self.tcx, val),
|
||||
const_: Const::from_bool(self.tcx, val),
|
||||
})))
|
||||
}
|
||||
|
||||
|
@ -1189,10 +1189,10 @@ fn insert_panic_block<'tcx>(
|
||||
) -> BasicBlock {
|
||||
let assert_block = BasicBlock::new(body.basic_blocks.len());
|
||||
let term = TerminatorKind::Assert {
|
||||
cond: Operand::Constant(Box::new(Constant {
|
||||
cond: Operand::Constant(Box::new(ConstOperand {
|
||||
span: body.span,
|
||||
user_ty: None,
|
||||
literal: ConstantKind::from_bool(tcx, false),
|
||||
const_: Const::from_bool(tcx, false),
|
||||
})),
|
||||
expected: true,
|
||||
msg: Box::new(message),
|
||||
|
@ -652,11 +652,11 @@ impl<'tcx> Inliner<'tcx> {
|
||||
// `required_consts`, here we may not only have `ConstKind::Unevaluated`
|
||||
// because we are calling `subst_and_normalize_erasing_regions`.
|
||||
caller_body.required_consts.extend(
|
||||
callee_body.required_consts.iter().copied().filter(|&ct| match ct.literal {
|
||||
ConstantKind::Ty(_) => {
|
||||
callee_body.required_consts.iter().copied().filter(|&ct| match ct.const_ {
|
||||
Const::Ty(_) => {
|
||||
bug!("should never encounter ty::UnevaluatedConst in `required_consts`")
|
||||
}
|
||||
ConstantKind::Val(..) | ConstantKind::Unevaluated(..) => true,
|
||||
Const::Val(..) | Const::Unevaluated(..) => true,
|
||||
}),
|
||||
);
|
||||
}
|
||||
@ -824,7 +824,7 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
|
||||
}
|
||||
}
|
||||
TerminatorKind::Call { func: Operand::Constant(ref f), unwind, .. } => {
|
||||
let fn_ty = self.instance.subst_mir(tcx, ty::EarlyBinder::bind(&f.literal.ty()));
|
||||
let fn_ty = self.instance.subst_mir(tcx, ty::EarlyBinder::bind(&f.const_.ty()));
|
||||
self.cost += if let ty::FnDef(def_id, _) = *fn_ty.kind() && tcx.is_intrinsic(def_id) {
|
||||
// Don't give intrinsics the extra penalty for calls
|
||||
INSTR_COST
|
||||
|
@ -104,7 +104,7 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> {
|
||||
|
||||
fn try_eval_bool(&self, a: &Operand<'_>) -> Option<bool> {
|
||||
let a = a.constant()?;
|
||||
if a.literal.ty().is_bool() { a.literal.try_to_bool() } else { None }
|
||||
if a.const_.ty().is_bool() { a.const_.try_to_bool() } else { None }
|
||||
}
|
||||
|
||||
/// Transform "&(*a)" ==> "a".
|
||||
@ -136,8 +136,8 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> {
|
||||
return;
|
||||
}
|
||||
|
||||
let literal = ConstantKind::from_ty_const(len, self.tcx);
|
||||
let constant = Constant { span: source_info.span, literal, user_ty: None };
|
||||
let const_ = Const::from_ty_const(len, self.tcx);
|
||||
let constant = ConstOperand { span: source_info.span, const_, user_ty: None };
|
||||
*rvalue = Rvalue::Use(Operand::Constant(Box::new(constant)));
|
||||
}
|
||||
}
|
||||
|
@ -149,10 +149,10 @@ impl EnumSizeOpt {
|
||||
};
|
||||
|
||||
let place = Place::from(size_array_local);
|
||||
let constant_vals = Constant {
|
||||
let constant_vals = ConstOperand {
|
||||
span,
|
||||
user_ty: None,
|
||||
literal: ConstantKind::Val(
|
||||
const_: Const::Val(
|
||||
ConstValue::Indirect { alloc_id, offset: Size::ZERO },
|
||||
tmp_ty,
|
||||
),
|
||||
|
@ -31,9 +31,9 @@ use rustc_hir::intravisit::{self, Visitor};
|
||||
use rustc_index::IndexVec;
|
||||
use rustc_middle::mir::visit::Visitor as _;
|
||||
use rustc_middle::mir::{
|
||||
traversal, AnalysisPhase, Body, CallSource, ClearCrossCrate, ConstQualifs, Constant, LocalDecl,
|
||||
MirPass, MirPhase, Operand, Place, ProjectionElem, Promoted, RuntimePhase, Rvalue, SourceInfo,
|
||||
Statement, StatementKind, TerminatorKind, START_BLOCK,
|
||||
traversal, AnalysisPhase, Body, CallSource, ClearCrossCrate, ConstOperand, ConstQualifs,
|
||||
LocalDecl, MirPass, MirPhase, Operand, Place, ProjectionElem, Promoted, RuntimePhase, Rvalue,
|
||||
SourceInfo, Statement, StatementKind, TerminatorKind, START_BLOCK,
|
||||
};
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
|
||||
@ -149,14 +149,14 @@ fn remap_mir_for_const_eval_select<'tcx>(
|
||||
let terminator = bb.terminator.as_mut().expect("invalid terminator");
|
||||
match terminator.kind {
|
||||
TerminatorKind::Call {
|
||||
func: Operand::Constant(box Constant { ref literal, .. }),
|
||||
func: Operand::Constant(box ConstOperand { ref const_, .. }),
|
||||
ref mut args,
|
||||
destination,
|
||||
target,
|
||||
unwind,
|
||||
fn_span,
|
||||
..
|
||||
} if let ty::FnDef(def_id, _) = *literal.ty().kind()
|
||||
} if let ty::FnDef(def_id, _) = *const_.ty().kind()
|
||||
&& tcx.item_name(def_id) == sym::const_eval_select
|
||||
&& tcx.is_intrinsic(def_id) =>
|
||||
{
|
||||
|
@ -32,10 +32,10 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
|
||||
source_info: terminator.source_info,
|
||||
kind: StatementKind::Assign(Box::new((
|
||||
*destination,
|
||||
Rvalue::Use(Operand::Constant(Box::new(Constant {
|
||||
Rvalue::Use(Operand::Constant(Box::new(ConstOperand {
|
||||
span: terminator.source_info.span,
|
||||
user_ty: None,
|
||||
literal: ConstantKind::zero_sized(tcx.types.unit),
|
||||
const_: Const::zero_sized(tcx.types.unit),
|
||||
}))),
|
||||
))),
|
||||
});
|
||||
|
@ -98,10 +98,10 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification {
|
||||
StatementKind::Assign(box (lhs_f, Rvalue::Use(Operand::Constant(f_c)))),
|
||||
StatementKind::Assign(box (lhs_s, Rvalue::Use(Operand::Constant(s_c)))),
|
||||
) if lhs_f == lhs_s
|
||||
&& f_c.literal.ty().is_bool()
|
||||
&& s_c.literal.ty().is_bool()
|
||||
&& f_c.literal.try_eval_bool(tcx, param_env).is_some()
|
||||
&& s_c.literal.try_eval_bool(tcx, param_env).is_some() => {}
|
||||
&& f_c.const_.ty().is_bool()
|
||||
&& s_c.const_.ty().is_bool()
|
||||
&& f_c.const_.try_eval_bool(tcx, param_env).is_some()
|
||||
&& s_c.const_.try_eval_bool(tcx, param_env).is_some() => {}
|
||||
|
||||
// Otherwise we cannot optimize. Try another block.
|
||||
_ => continue 'outer,
|
||||
@ -128,8 +128,8 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification {
|
||||
StatementKind::Assign(box (_, Rvalue::Use(Operand::Constant(s_c)))),
|
||||
) => {
|
||||
// From earlier loop we know that we are dealing with bool constants only:
|
||||
let f_b = f_c.literal.try_eval_bool(tcx, param_env).unwrap();
|
||||
let s_b = s_c.literal.try_eval_bool(tcx, param_env).unwrap();
|
||||
let f_b = f_c.const_.try_eval_bool(tcx, param_env).unwrap();
|
||||
let s_b = s_c.const_.try_eval_bool(tcx, param_env).unwrap();
|
||||
if f_b == s_b {
|
||||
// Same value in both blocks. Use statement as is.
|
||||
(*f).clone()
|
||||
|
@ -90,10 +90,10 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> {
|
||||
&& let [PlaceElem::Deref] = &place.projection[..]
|
||||
&& let Some(len) = self.slice_lengths[place.local]
|
||||
{
|
||||
*rvalue = Rvalue::Use(Operand::Constant(Box::new(Constant {
|
||||
*rvalue = Rvalue::Use(Operand::Constant(Box::new(ConstOperand {
|
||||
span: rustc_span::DUMMY_SP,
|
||||
user_ty: None,
|
||||
literal: ConstantKind::from_ty_const(len, self.tcx),
|
||||
const_: Const::from_ty_const(len, self.tcx),
|
||||
})));
|
||||
}
|
||||
self.super_rvalue(rvalue, loc);
|
||||
|
@ -62,12 +62,12 @@ impl<'tcx> Replacer<'_, 'tcx> {
|
||||
layout.is_zst()
|
||||
}
|
||||
|
||||
fn make_zst(&self, ty: Ty<'tcx>) -> Constant<'tcx> {
|
||||
fn make_zst(&self, ty: Ty<'tcx>) -> ConstOperand<'tcx> {
|
||||
debug_assert!(self.known_to_be_zst(ty));
|
||||
Constant {
|
||||
ConstOperand {
|
||||
span: rustc_span::DUMMY_SP,
|
||||
user_ty: None,
|
||||
literal: ConstantKind::Val(ConstValue::ZeroSized, ty),
|
||||
const_: Const::Val(ConstValue::ZeroSized, ty),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,27 +1,27 @@
|
||||
use rustc_middle::mir::visit::Visitor;
|
||||
use rustc_middle::mir::{Constant, ConstantKind, Location};
|
||||
use rustc_middle::mir::{Const, ConstOperand, Location};
|
||||
use rustc_middle::ty::ConstKind;
|
||||
|
||||
pub struct RequiredConstsVisitor<'a, 'tcx> {
|
||||
required_consts: &'a mut Vec<Constant<'tcx>>,
|
||||
required_consts: &'a mut Vec<ConstOperand<'tcx>>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> RequiredConstsVisitor<'a, 'tcx> {
|
||||
pub fn new(required_consts: &'a mut Vec<Constant<'tcx>>) -> Self {
|
||||
pub fn new(required_consts: &'a mut Vec<ConstOperand<'tcx>>) -> Self {
|
||||
RequiredConstsVisitor { required_consts }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Visitor<'tcx> for RequiredConstsVisitor<'_, 'tcx> {
|
||||
fn visit_constant(&mut self, constant: &Constant<'tcx>, _: Location) {
|
||||
let literal = constant.literal;
|
||||
match literal {
|
||||
ConstantKind::Ty(c) => match c.kind() {
|
||||
fn visit_constant(&mut self, constant: &ConstOperand<'tcx>, _: Location) {
|
||||
let const_ = constant.const_;
|
||||
match const_ {
|
||||
Const::Ty(c) => match c.kind() {
|
||||
ConstKind::Param(_) | ConstKind::Error(_) | ConstKind::Value(_) => {}
|
||||
_ => bug!("only ConstKind::Param/Value should be encountered here, got {:#?}", c),
|
||||
},
|
||||
ConstantKind::Unevaluated(..) => self.required_consts.push(*constant),
|
||||
ConstantKind::Val(..) => {}
|
||||
Const::Unevaluated(..) => self.required_consts.push(*constant),
|
||||
Const::Val(..) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -35,12 +35,12 @@ impl<'tcx> MutVisitor<'tcx> for RevealAllVisitor<'tcx> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_constant(&mut self, constant: &mut Constant<'tcx>, _: Location) {
|
||||
fn visit_constant(&mut self, constant: &mut ConstOperand<'tcx>, _: Location) {
|
||||
// We have to use `try_normalize_erasing_regions` here, since it's
|
||||
// possible that we visit impossible-to-satisfy where clauses here,
|
||||
// see #91745
|
||||
if let Ok(c) = self.tcx.try_normalize_erasing_regions(self.param_env, constant.literal) {
|
||||
constant.literal = c;
|
||||
if let Ok(c) = self.tcx.try_normalize_erasing_regions(self.param_env, constant.const_) {
|
||||
constant.const_ = c;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -497,10 +497,10 @@ impl<'tcx> CloneShimBuilder<'tcx> {
|
||||
|
||||
// `func == Clone::clone(&ty) -> ty`
|
||||
let func_ty = Ty::new_fn_def(tcx, self.def_id, [ty]);
|
||||
let func = Operand::Constant(Box::new(Constant {
|
||||
let func = Operand::Constant(Box::new(ConstOperand {
|
||||
span: self.span,
|
||||
user_ty: None,
|
||||
literal: ConstantKind::zero_sized(func_ty),
|
||||
const_: Const::zero_sized(func_ty),
|
||||
}));
|
||||
|
||||
let ref_loc = self.make_place(
|
||||
@ -764,10 +764,10 @@ fn build_call_shim<'tcx>(
|
||||
CallKind::Direct(def_id) => {
|
||||
let ty = tcx.type_of(def_id).instantiate_identity();
|
||||
(
|
||||
Operand::Constant(Box::new(Constant {
|
||||
Operand::Constant(Box::new(ConstOperand {
|
||||
span,
|
||||
user_ty: None,
|
||||
literal: ConstantKind::zero_sized(ty),
|
||||
const_: Const::zero_sized(ty),
|
||||
})),
|
||||
rcvr.into_iter().collect::<Vec<_>>(),
|
||||
)
|
||||
|
@ -23,7 +23,7 @@ impl<'tcx> MirPass<'tcx> for SimplifyConstCondition {
|
||||
TerminatorKind::SwitchInt {
|
||||
discr: Operand::Constant(ref c), ref targets, ..
|
||||
} => {
|
||||
let constant = c.literal.try_eval_bits(tcx, param_env, c.ty());
|
||||
let constant = c.const_.try_eval_bits(tcx, param_env);
|
||||
if let Some(constant) = constant {
|
||||
let target = targets.target_for_value(constant);
|
||||
TerminatorKind::Goto { target }
|
||||
@ -33,7 +33,7 @@ impl<'tcx> MirPass<'tcx> for SimplifyConstCondition {
|
||||
}
|
||||
TerminatorKind::Assert {
|
||||
target, cond: Operand::Constant(ref c), expected, ..
|
||||
} => match c.literal.try_eval_bool(tcx, param_env) {
|
||||
} => match c.const_.try_eval_bool(tcx, param_env) {
|
||||
Some(v) if v == expected => TerminatorKind::Goto { target },
|
||||
_ => continue,
|
||||
},
|
||||
|
@ -206,12 +206,12 @@ fn find_branch_value_info<'tcx>(
|
||||
match (left, right) {
|
||||
(Constant(branch_value), Copy(to_switch_on) | Move(to_switch_on))
|
||||
| (Copy(to_switch_on) | Move(to_switch_on), Constant(branch_value)) => {
|
||||
let branch_value_ty = branch_value.literal.ty();
|
||||
let branch_value_ty = branch_value.const_.ty();
|
||||
// we only want to apply this optimization if we are matching on integrals (and chars), as it is not possible to switch on floats
|
||||
if !branch_value_ty.is_integral() && !branch_value_ty.is_char() {
|
||||
return None;
|
||||
};
|
||||
let branch_value_scalar = branch_value.literal.try_to_scalar()?;
|
||||
let branch_value_scalar = branch_value.const_.try_to_scalar()?;
|
||||
Some((branch_value_scalar, branch_value_ty, *to_switch_on))
|
||||
}
|
||||
_ => None,
|
||||
|
@ -746,20 +746,20 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
|
||||
/// 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.
|
||||
#[instrument(skip(self), level = "debug")]
|
||||
fn visit_constant(&mut self, constant: &mir::Constant<'tcx>, location: Location) {
|
||||
let literal = self.monomorphize(constant.literal);
|
||||
fn visit_constant(&mut self, constant: &mir::ConstOperand<'tcx>, location: Location) {
|
||||
let const_ = self.monomorphize(constant.const_);
|
||||
let param_env = ty::ParamEnv::reveal_all();
|
||||
let val = match literal.eval(self.tcx, param_env, None) {
|
||||
let val = match const_.eval(self.tcx, param_env, None) {
|
||||
Ok(v) => v,
|
||||
Err(ErrorHandled::Reported(..)) => return,
|
||||
Err(ErrorHandled::TooGeneric(..)) => span_bug!(
|
||||
self.body.source_info(location).span,
|
||||
"collection encountered polymorphic constant: {:?}",
|
||||
literal
|
||||
const_
|
||||
),
|
||||
};
|
||||
collect_const_value(self.tcx, val, self.output);
|
||||
MirVisitor::visit_ty(self, literal.ty(), TyContext::Location(location));
|
||||
MirVisitor::visit_ty(self, const_.ty(), TyContext::Location(location));
|
||||
}
|
||||
|
||||
fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, location: Location) {
|
||||
@ -796,7 +796,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
|
||||
for op in operands {
|
||||
match *op {
|
||||
mir::InlineAsmOperand::SymFn { ref value } => {
|
||||
let fn_ty = self.monomorphize(value.literal.ty());
|
||||
let fn_ty = self.monomorphize(value.const_.ty());
|
||||
visit_fn_use(self.tcx, fn_ty, false, source, &mut self.output, &[]);
|
||||
}
|
||||
mir::InlineAsmOperand::SymStatic { def_id } => {
|
||||
|
@ -9,13 +9,13 @@ use rustc_hir::{def::DefKind, def_id::DefId, ConstContext};
|
||||
use rustc_middle::mir::{
|
||||
self,
|
||||
visit::{TyContext, Visitor},
|
||||
Constant, ConstantKind, Local, LocalDecl, Location,
|
||||
Local, LocalDecl, Location,
|
||||
};
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::{
|
||||
self,
|
||||
visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor},
|
||||
Const, GenericArgsRef, Ty, TyCtxt, UnusedGenericParams,
|
||||
GenericArgsRef, Ty, TyCtxt, UnusedGenericParams,
|
||||
};
|
||||
use rustc_span::symbol::sym;
|
||||
use std::ops::ControlFlow;
|
||||
@ -261,12 +261,12 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
|
||||
self.super_local_decl(local, local_decl);
|
||||
}
|
||||
|
||||
fn visit_constant(&mut self, ct: &Constant<'tcx>, location: Location) {
|
||||
match ct.literal {
|
||||
ConstantKind::Ty(c) => {
|
||||
fn visit_constant(&mut self, ct: &mir::ConstOperand<'tcx>, location: Location) {
|
||||
match ct.const_ {
|
||||
mir::Const::Ty(c) => {
|
||||
c.visit_with(self);
|
||||
}
|
||||
ConstantKind::Unevaluated(mir::UnevaluatedConst { def, args: _, promoted }, ty) => {
|
||||
mir::Const::Unevaluated(mir::UnevaluatedConst { def, args: _, promoted }, ty) => {
|
||||
// Avoid considering `T` unused when constants are of the form:
|
||||
// `<Self as Foo<T>>::foo::promoted[p]`
|
||||
if let Some(p) = promoted {
|
||||
@ -280,7 +280,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
|
||||
|
||||
Visitor::visit_ty(self, ty, TyContext::Location(location));
|
||||
}
|
||||
ConstantKind::Val(_, ty) => Visitor::visit_ty(self, ty, TyContext::Location(location)),
|
||||
mir::Const::Val(_, ty) => Visitor::visit_ty(self, ty, TyContext::Location(location)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -291,7 +291,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
|
||||
|
||||
impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for MarkUsedGenericParams<'a, 'tcx> {
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn visit_const(&mut self, c: Const<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
if !c.has_non_region_param() {
|
||||
return ControlFlow::Continue(());
|
||||
}
|
||||
|
@ -14,8 +14,8 @@ use crate::stable_mir::ty::{
|
||||
};
|
||||
use crate::stable_mir::{self, CompilerError, Context};
|
||||
use rustc_hir as hir;
|
||||
use rustc_middle::mir;
|
||||
use rustc_middle::mir::interpret::{alloc_range, AllocId};
|
||||
use rustc_middle::mir::{self, ConstantKind};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, Variance};
|
||||
use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE};
|
||||
use rustc_span::ErrorGuaranteed;
|
||||
@ -539,14 +539,14 @@ impl<'tcx> Stable<'tcx> for mir::Operand<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::Constant<'tcx> {
|
||||
impl<'tcx> Stable<'tcx> for mir::ConstOperand<'tcx> {
|
||||
type T = stable_mir::mir::Constant;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
stable_mir::mir::Constant {
|
||||
span: self.span.stable(tables),
|
||||
user_ty: self.user_ty.map(|u| u.as_usize()).or(None),
|
||||
literal: self.literal.stable(tables),
|
||||
literal: self.const_.stable(tables),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1247,13 +1247,13 @@ impl<'tcx> Stable<'tcx> for ty::TraitDef {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for rustc_middle::mir::ConstantKind<'tcx> {
|
||||
impl<'tcx> Stable<'tcx> for rustc_middle::mir::Const<'tcx> {
|
||||
type T = stable_mir::ty::Const;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
match *self {
|
||||
ConstantKind::Ty(c) => c.stable(tables),
|
||||
ConstantKind::Unevaluated(unev_const, ty) => stable_mir::ty::Const {
|
||||
mir::Const::Ty(c) => c.stable(tables),
|
||||
mir::Const::Unevaluated(unev_const, ty) => stable_mir::ty::Const {
|
||||
literal: stable_mir::ty::ConstantKind::Unevaluated(
|
||||
stable_mir::ty::UnevaluatedConst {
|
||||
def: tables.const_def(unev_const.def),
|
||||
@ -1263,7 +1263,7 @@ impl<'tcx> Stable<'tcx> for rustc_middle::mir::ConstantKind<'tcx> {
|
||||
),
|
||||
ty: tables.intern_ty(ty),
|
||||
},
|
||||
ConstantKind::Val(val, ty) => stable_mir::ty::Const {
|
||||
mir::Const::Val(val, ty) => stable_mir::ty::Const {
|
||||
literal: stable_mir::ty::ConstantKind::Allocated(alloc::new_allocation(
|
||||
ty, val, tables,
|
||||
)),
|
||||
|
@ -118,7 +118,7 @@ fn encode_const<'tcx>(
|
||||
// bool value false is encoded as 0 and true as 1.
|
||||
match c.ty().kind() {
|
||||
ty::Int(ity) => {
|
||||
let bits = c.eval_bits(tcx, ty::ParamEnv::reveal_all(), c.ty());
|
||||
let bits = c.eval_bits(tcx, ty::ParamEnv::reveal_all());
|
||||
let val = Integer::from_int_ty(&tcx, *ity).size().sign_extend(bits) as i128;
|
||||
if val < 0 {
|
||||
s.push('n');
|
||||
@ -126,7 +126,7 @@ fn encode_const<'tcx>(
|
||||
let _ = write!(s, "{val}");
|
||||
}
|
||||
ty::Uint(_) => {
|
||||
let val = c.eval_bits(tcx, ty::ParamEnv::reveal_all(), c.ty());
|
||||
let val = c.eval_bits(tcx, ty::ParamEnv::reveal_all());
|
||||
let _ = write!(s, "{val}");
|
||||
}
|
||||
ty::Bool => {
|
||||
|
@ -594,7 +594,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
|
||||
ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Char => {
|
||||
self = ty.print(self)?;
|
||||
|
||||
let mut bits = ct.eval_bits(self.tcx, ty::ParamEnv::reveal_all(), ty);
|
||||
let mut bits = ct.eval_bits(self.tcx, ty::ParamEnv::reveal_all());
|
||||
|
||||
// Negative integer values are mangled using `n` as a "sign prefix".
|
||||
if let ty::Int(ity) = ty.kind() {
|
||||
|
@ -283,7 +283,7 @@ pub(crate) fn print_evaluated_const(
|
||||
(_, &ty::Ref(..)) => None,
|
||||
(mir::ConstValue::Scalar(_), &ty::Adt(_, _)) => None,
|
||||
(mir::ConstValue::Scalar(_), _) => {
|
||||
let const_ = mir::ConstantKind::from_value(val, ty);
|
||||
let const_ = mir::Const::from_value(val, ty);
|
||||
Some(print_const_with_custom_print_scalar(tcx, const_, underscores_and_type))
|
||||
}
|
||||
_ => None,
|
||||
@ -319,20 +319,20 @@ fn format_integer_with_underscore_sep(num: &str) -> String {
|
||||
|
||||
fn print_const_with_custom_print_scalar<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
ct: mir::ConstantKind<'tcx>,
|
||||
ct: mir::Const<'tcx>,
|
||||
underscores_and_type: bool,
|
||||
) -> String {
|
||||
// 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`.
|
||||
match (ct, ct.ty().kind()) {
|
||||
(mir::ConstantKind::Val(mir::ConstValue::Scalar(int), _), ty::Uint(ui)) => {
|
||||
(mir::Const::Val(mir::ConstValue::Scalar(int), _), ty::Uint(ui)) => {
|
||||
if underscores_and_type {
|
||||
format!("{}{}", format_integer_with_underscore_sep(&int.to_string()), ui.name_str())
|
||||
} else {
|
||||
int.to_string()
|
||||
}
|
||||
}
|
||||
(mir::ConstantKind::Val(mir::ConstValue::Scalar(int), _), ty::Int(i)) => {
|
||||
(mir::Const::Val(mir::ConstValue::Scalar(int), _), ty::Int(i)) => {
|
||||
let ty = ct.ty();
|
||||
let size = tcx.layout_of(ty::ParamEnv::empty().and(ty)).unwrap().size;
|
||||
let data = int.assert_bits(size);
|
||||
|
@ -50,7 +50,7 @@ impl<'tcx> LateLintPass<'tcx> for UnportableVariant {
|
||||
.tcx
|
||||
.const_eval_poly(def_id.to_def_id())
|
||||
.ok()
|
||||
.map(|val| rustc_middle::mir::ConstantKind::from_value(val, ty));
|
||||
.map(|val| rustc_middle::mir::Const::from_value(val, ty));
|
||||
if let Some(Constant::Int(val)) = constant.and_then(|c| miri_to_const(cx, c)) {
|
||||
if let ty::Adt(adt, _) = ty.kind() {
|
||||
if adt.is_enum() {
|
||||
|
@ -37,14 +37,14 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>)
|
||||
Some(lhs) => constant(cx, cx.typeck_results(), lhs)?,
|
||||
None => {
|
||||
let min_val_const = ty.numeric_min_val(cx.tcx)?;
|
||||
miri_to_const(cx, mir::ConstantKind::from_ty_const(min_val_const, cx.tcx))?
|
||||
miri_to_const(cx, mir::Const::from_ty_const(min_val_const, cx.tcx))?
|
||||
},
|
||||
};
|
||||
let rhs_const = match rhs {
|
||||
Some(rhs) => constant(cx, cx.typeck_results(), rhs)?,
|
||||
None => {
|
||||
let max_val_const = ty.numeric_max_val(cx.tcx)?;
|
||||
miri_to_const(cx, mir::ConstantKind::from_ty_const(max_val_const, cx.tcx))?
|
||||
miri_to_const(cx, mir::Const::from_ty_const(max_val_const, cx.tcx))?
|
||||
},
|
||||
};
|
||||
let lhs_val = lhs_const.int_value(cx, ty)?;
|
||||
|
@ -21,7 +21,7 @@ use std::iter;
|
||||
/// A `LitKind`-like enum to fold constant `Expr`s into.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Constant<'tcx> {
|
||||
Adt(rustc_middle::mir::ConstantKind<'tcx>),
|
||||
Adt(rustc_middle::mir::Const<'tcx>),
|
||||
/// A `String` (e.g., "abc").
|
||||
Str(String),
|
||||
/// A binary string (e.g., `b"abc"`).
|
||||
@ -482,7 +482,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
|
||||
.tcx
|
||||
.const_eval_resolve(self.param_env, mir::UnevaluatedConst::new(def_id, args), None)
|
||||
.ok()
|
||||
.map(|val| rustc_middle::mir::ConstantKind::from_value(val, ty))?;
|
||||
.map(|val| rustc_middle::mir::Const::from_value(val, ty))?;
|
||||
let result = miri_to_const(self.lcx, result)?;
|
||||
self.source = ConstantSource::Constant;
|
||||
Some(result)
|
||||
@ -655,10 +655,10 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn miri_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::ConstantKind<'tcx>) -> Option<Constant<'tcx>> {
|
||||
pub fn miri_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::Const<'tcx>) -> Option<Constant<'tcx>> {
|
||||
use rustc_middle::mir::ConstValue;
|
||||
match result {
|
||||
mir::ConstantKind::Val(ConstValue::Scalar(Scalar::Int(int)), _) => match result.ty().kind() {
|
||||
mir::Const::Val(ConstValue::Scalar(Scalar::Int(int)), _) => match result.ty().kind() {
|
||||
ty::Adt(adt_def, _) if adt_def.is_struct() => Some(Constant::Adt(result)),
|
||||
ty::Bool => Some(Constant::Bool(int == ScalarInt::TRUE)),
|
||||
ty::Uint(_) | ty::Int(_) => Some(Constant::Int(int.assert_bits(int.size()))),
|
||||
@ -671,11 +671,11 @@ pub fn miri_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::ConstantKind<'t
|
||||
ty::RawPtr(_) => Some(Constant::RawPtr(int.assert_bits(int.size()))),
|
||||
_ => None,
|
||||
},
|
||||
mir::ConstantKind::Val(cv, _) if matches!(result.ty().kind(), ty::Ref(_, inner_ty, _) if matches!(inner_ty.kind(), ty::Str)) => {
|
||||
mir::Const::Val(cv, _) if matches!(result.ty().kind(), ty::Ref(_, inner_ty, _) if matches!(inner_ty.kind(), ty::Str)) => {
|
||||
let data = cv.try_get_slice_bytes_for_diagnostics(lcx.tcx)?;
|
||||
String::from_utf8(data.to_owned()).ok().map(Constant::Str)
|
||||
}
|
||||
mir::ConstantKind::Val(ConstValue::Indirect { alloc_id, offset: _ }, _) => {
|
||||
mir::Const::Val(ConstValue::Indirect { alloc_id, offset: _ }, _) => {
|
||||
let alloc = lcx.tcx.global_alloc(alloc_id).unwrap_memory();
|
||||
match result.ty().kind() {
|
||||
ty::Adt(adt_def, _) if adt_def.is_struct() => Some(Constant::Adt(result)),
|
||||
@ -714,17 +714,17 @@ pub fn miri_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::ConstantKind<'t
|
||||
fn field_of_struct<'tcx>(
|
||||
adt_def: ty::AdtDef<'tcx>,
|
||||
lcx: &LateContext<'tcx>,
|
||||
result: mir::ConstantKind<'tcx>,
|
||||
result: mir::Const<'tcx>,
|
||||
field: &Ident,
|
||||
) -> Option<mir::ConstantKind<'tcx>> {
|
||||
if let mir::ConstantKind::Val(result, ty) = result
|
||||
) -> Option<mir::Const<'tcx>> {
|
||||
if let mir::Const::Val(result, ty) = result
|
||||
&& let Some(dc) = lcx.tcx.try_destructure_mir_constant_for_diagnostics((result, ty))
|
||||
&& let Some(dc_variant) = dc.variant
|
||||
&& let Some(variant) = adt_def.variants().get(dc_variant)
|
||||
&& let Some(field_idx) = variant.fields.iter().position(|el| el.name == field.name)
|
||||
&& let Some(&(val, ty)) = dc.fields.get(field_idx)
|
||||
{
|
||||
Some(mir::ConstantKind::Val(val, ty))
|
||||
Some(mir::Const::Val(val, ty))
|
||||
}
|
||||
else {
|
||||
None
|
||||
|
@ -97,7 +97,7 @@ use rustc_hir::{
|
||||
use rustc_lexer::{tokenize, TokenKind};
|
||||
use rustc_lint::{LateContext, Level, Lint, LintContext};
|
||||
use rustc_middle::hir::place::PlaceBase;
|
||||
use rustc_middle::mir::ConstantKind;
|
||||
use rustc_middle::mir::Const;
|
||||
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
|
||||
use rustc_middle::ty::binding::BindingMode;
|
||||
use rustc_middle::ty::fast_reject::SimplifiedType;
|
||||
@ -1510,7 +1510,7 @@ pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Opti
|
||||
&& let bnd_ty = subst.type_at(0)
|
||||
&& let Some(min_val) = bnd_ty.numeric_min_val(cx.tcx)
|
||||
&& let const_val = cx.tcx.valtree_to_const_val((bnd_ty, min_val.to_valtree()))
|
||||
&& let min_const_kind = ConstantKind::from_value(const_val, bnd_ty)
|
||||
&& let min_const_kind = Const::from_value(const_val, bnd_ty)
|
||||
&& let Some(min_const) = miri_to_const(cx, min_const_kind)
|
||||
&& let Some(start_const) = constant(cx, cx.typeck_results(), start)
|
||||
{
|
||||
@ -1526,7 +1526,7 @@ pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Opti
|
||||
&& let bnd_ty = subst.type_at(0)
|
||||
&& let Some(max_val) = bnd_ty.numeric_max_val(cx.tcx)
|
||||
&& let const_val = cx.tcx.valtree_to_const_val((bnd_ty, max_val.to_valtree()))
|
||||
&& let max_const_kind = ConstantKind::from_value(const_val, bnd_ty)
|
||||
&& let max_const_kind = Const::from_value(const_val, bnd_ty)
|
||||
&& let Some(max_const) = miri_to_const(cx, max_const_kind)
|
||||
&& let Some(end_const) = constant(cx, cx.typeck_results(), end)
|
||||
{
|
||||
|
@ -9,9 +9,9 @@ fn outer(_1: u8) -> u8 {
|
||||
StorageLive(_2); // scope 0 at $DIR/spans.rs:10:11: 10:13
|
||||
_2 = &_1; // scope 0 at $DIR/spans.rs:10:11: 10:13
|
||||
_0 = inner(move _2) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/spans.rs:10:5: 10:14
|
||||
// mir::Constant
|
||||
// mir::ConstOperand
|
||||
// + span: $DIR/spans.rs:10:5: 10:10
|
||||
// + literal: Const { ty: for<'a> fn(&'a u8) -> u8 {inner}, val: Value(inner) }
|
||||
// + const_: Const { ty: for<'a> fn(&'a u8) -> u8 {inner}, val: Value(inner) }
|
||||
}
|
||||
|
||||
bb1: {
|
||||
|
@ -9,9 +9,9 @@ fn outer(_1: u8) -> u8 {
|
||||
StorageLive(_2); // scope 0 at $DIR/spans.rs:10:11: 10:13
|
||||
_2 = &_1; // scope 0 at $DIR/spans.rs:10:11: 10:13
|
||||
_0 = inner(move _2) -> [return: bb1, unwind continue]; // scope 0 at $DIR/spans.rs:10:5: 10:14
|
||||
// mir::Constant
|
||||
// mir::ConstOperand
|
||||
// + span: $DIR/spans.rs:10:5: 10:10
|
||||
// + literal: Const { ty: for<'a> fn(&'a u8) -> u8 {inner}, val: Value(inner) }
|
||||
// + const_: Const { ty: for<'a> fn(&'a u8) -> u8 {inner}, val: Value(inner) }
|
||||
}
|
||||
|
||||
bb1: {
|
||||
|
Loading…
Reference in New Issue
Block a user