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:
Guillaume Gomez 2023-09-21 13:25:39 +02:00 committed by GitHub
commit 208f6ed95c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
76 changed files with 461 additions and 493 deletions

View File

@ -13,7 +13,7 @@ use rustc_index::IndexSlice;
use rustc_infer::infer::LateBoundRegionConversionTime; use rustc_infer::infer::LateBoundRegionConversionTime;
use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::tcx::PlaceTy;
use rustc_middle::mir::{ 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, Operand, Place, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator,
TerminatorKind, TerminatorKind,
}; };
@ -101,12 +101,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let terminator = self.body[location.block].terminator(); let terminator = self.body[location.block].terminator();
debug!("add_moved_or_invoked_closure_note: terminator={:?}", terminator); debug!("add_moved_or_invoked_closure_note: terminator={:?}", terminator);
if let TerminatorKind::Call { if let TerminatorKind::Call {
func: Operand::Constant(box Constant { literal, .. }), func: Operand::Constant(box ConstOperand { const_, .. }),
args, args,
.. ..
} = &terminator.kind } = &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); debug!("add_moved_or_invoked_closure_note: id={:?}", id);
if Some(self.infcx.tcx.parent(id)) == self.infcx.tcx.lang_items().fn_once_trait() { if Some(self.infcx.tcx.parent(id)) == self.infcx.tcx.lang_items().fn_once_trait() {
let closure = match args.first() { let closure = match args.first() {

View File

@ -4,8 +4,7 @@ use crate::BorrowckInferCtxt;
use rustc_index::IndexSlice; use rustc_index::IndexSlice;
use rustc_infer::infer::NllRegionVariableOrigin; use rustc_infer::infer::NllRegionVariableOrigin;
use rustc_middle::mir::visit::{MutVisitor, TyContext}; use rustc_middle::mir::visit::{MutVisitor, TyContext};
use rustc_middle::mir::Constant; use rustc_middle::mir::{Body, ConstOperand, Location, Promoted};
use rustc_middle::mir::{Body, Location, Promoted};
use rustc_middle::ty::GenericArgsRef; use rustc_middle::ty::GenericArgsRef;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
use rustc_span::{Span, Symbol}; use rustc_span::{Span, Symbol};
@ -117,9 +116,9 @@ impl<'a, 'tcx> MutVisitor<'tcx> for RegionRenumberer<'a, 'tcx> {
} }
#[instrument(skip(self), level = "debug")] #[instrument(skip(self), level = "debug")]
fn visit_constant(&mut self, constant: &mut Constant<'tcx>, location: Location) { fn visit_constant(&mut self, constant: &mut ConstOperand<'tcx>, location: Location) {
let literal = constant.literal; let const_ = constant.const_;
constant.literal = self.renumber_regions(literal, || RegionCtxt::Location(location)); constant.const_ = self.renumber_regions(const_, || RegionCtxt::Location(location));
debug!("constant: {:#?}", constant); debug!("constant: {:#?}", constant);
} }
} }

View File

@ -302,11 +302,11 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
self.sanitize_place(place, location, context); 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"); debug!(?constant, ?location, "visit_constant");
self.super_constant(constant, location); 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| { self.cx.infcx.tcx.for_each_free_region(&ty, |live_region| {
let live_region_vid = 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 Some(annotation_index) = constant.user_ty {
if let Err(terr) = self.cx.relate_type_and_user_type( if let Err(terr) = self.cx.relate_type_and_user_type(
constant.literal.ty(), constant.const_.ty(),
ty::Variance::Invariant, ty::Variance::Invariant,
&UserTypeProjection { base: annotation_index, projs: vec![] }, &UserTypeProjection { base: annotation_index, projs: vec![] },
locations, locations,
@ -340,20 +340,20 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
constant, constant,
"bad constant user type {:?} vs {:?}: {:?}", "bad constant user type {:?} vs {:?}: {:?}",
annotation, annotation,
constant.literal.ty(), constant.const_.ty(),
terr, terr,
); );
} }
} else { } else {
let tcx = self.tcx(); let tcx = self.tcx();
let maybe_uneval = match constant.literal { let maybe_uneval = match constant.const_ {
ConstantKind::Ty(ct) => match ct.kind() { Const::Ty(ct) => match ct.kind() {
ty::ConstKind::Unevaluated(_) => { ty::ConstKind::Unevaluated(_) => {
bug!("should not encounter unevaluated ConstantKind::Ty here, got {:?}", ct) bug!("should not encounter unevaluated Const::Ty here, got {:?}", ct)
} }
_ => None, _ => None,
}, },
ConstantKind::Unevaluated(uv, _) => Some(uv), Const::Unevaluated(uv, _) => Some(uv),
_ => None, _ => None,
}; };
@ -384,7 +384,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
check_err(self, promoted_body, ty, promoted_ty); check_err(self, promoted_body, ty, promoted_ty);
} else { } else {
self.cx.ascribe_user_type( self.cx.ascribe_user_type(
constant.literal.ty(), constant.const_.ty(),
UserType::TypeOf(uv.def, UserArgs { args: uv.args, user_self_ty: None }), UserType::TypeOf(uv.def, UserArgs { args: uv.args, user_self_ty: None }),
locations.span(&self.cx.body), 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) { } else if let Some(static_def_id) = constant.check_static_ptr(tcx) {
let unnormalized_ty = tcx.type_of(static_def_id).instantiate_identity(); let unnormalized_ty = tcx.type_of(static_def_id).instantiate_identity();
let normalized_ty = self.cx.normalize(unnormalized_ty, locations); 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( if let Err(terr) = self.cx.eq_types(
literal_ty, 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); let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, args);
self.cx.normalize_and_prove_instantiated_predicates( self.cx.normalize_and_prove_instantiated_predicates(
def_id, def_id,
@ -1801,9 +1801,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
debug!(?op, ?location, "check_operand"); debug!(?op, ?location, "check_operand");
if let Operand::Constant(constant) = op { if let Operand::Constant(constant) = op {
let maybe_uneval = match constant.literal { let maybe_uneval = match constant.const_ {
ConstantKind::Val(..) | ConstantKind::Ty(_) => None, Const::Val(..) | Const::Ty(_) => None,
ConstantKind::Unevaluated(uv, _) => Some(uv), Const::Unevaluated(uv, _) => Some(uv),
}; };
if let Some(uv) = maybe_uneval { if let Some(uv) = maybe_uneval {

View File

@ -64,9 +64,9 @@ pub(crate) fn codegen_tls_ref<'tcx>(
pub(crate) fn eval_mir_constant<'tcx>( pub(crate) fn eval_mir_constant<'tcx>(
fx: &FunctionCx<'_, '_, 'tcx>, fx: &FunctionCx<'_, '_, 'tcx>,
constant: &Constant<'tcx>, constant: &ConstOperand<'tcx>,
) -> (ConstValue<'tcx>, Ty<'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. // This cannot fail because we checked all required_consts in advance.
let val = cv let val = cv
.eval(fx.tcx, ty::ParamEnv::reveal_all(), Some(constant.span)) .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>( pub(crate) fn codegen_constant_operand<'tcx>(
fx: &mut FunctionCx<'_, '_, 'tcx>, fx: &mut FunctionCx<'_, '_, 'tcx>,
constant: &Constant<'tcx>, constant: &ConstOperand<'tcx>,
) -> CValue<'tcx> { ) -> CValue<'tcx> {
let (const_val, ty) = eval_mir_constant(fx, constant); let (const_val, ty) = eval_mir_constant(fx, constant);
codegen_const_value(fx, const_val, ty) codegen_const_value(fx, const_val, ty)

View File

@ -252,8 +252,8 @@ pub(crate) fn codegen_inline_asm<'tcx>(
CInlineAsmOperand::Const { value } CInlineAsmOperand::Const { value }
} }
InlineAsmOperand::SymFn { ref value } => { InlineAsmOperand::SymFn { ref value } => {
let literal = fx.monomorphize(value.literal); let const_ = fx.monomorphize(value.const_);
if let ty::FnDef(def_id, args) = *literal.ty().kind() { if let ty::FnDef(def_id, args) = *const_.ty().kind() {
let instance = ty::Instance::resolve_for_fn_ptr( let instance = ty::Instance::resolve_for_fn_ptr(
fx.tcx, fx.tcx,
ty::ParamEnv::reveal_all(), ty::ParamEnv::reveal_all(),

View File

@ -660,12 +660,12 @@ fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut S
} }
_ => match ct.ty().kind() { _ => match ct.ty().kind() {
ty::Int(ity) => { 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; let val = Integer::from_int_ty(&tcx, *ity).size().sign_extend(bits) as i128;
write!(output, "{val}") write!(output, "{val}")
} }
ty::Uint(_) => { ty::Uint(_) => {
let val = ct.eval_bits(tcx, ty::ParamEnv::reveal_all(), ct.ty()); let val = ct.eval_bits(tcx, ty::ParamEnv::reveal_all());
write!(output, "{val}") write!(output, "{val}")
} }
ty::Bool => { ty::Bool => {

View File

@ -1098,8 +1098,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
InlineAsmOperandRef::Const { string } InlineAsmOperandRef::Const { string }
} }
mir::InlineAsmOperand::SymFn { ref value } => { mir::InlineAsmOperand::SymFn { ref value } => {
let literal = self.monomorphize(value.literal); let const_ = self.monomorphize(value.const_);
if let ty::FnDef(def_id, args) = *literal.ty().kind() { if let ty::FnDef(def_id, args) = *const_.ty().kind() {
let instance = ty::Instance::resolve_for_fn_ptr( let instance = ty::Instance::resolve_for_fn_ptr(
bx.tcx(), bx.tcx(),
ty::ParamEnv::reveal_all(), ty::ParamEnv::reveal_all(),

View File

@ -13,37 +13,37 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
pub fn eval_mir_constant_to_operand( pub fn eval_mir_constant_to_operand(
&self, &self,
bx: &mut Bx, bx: &mut Bx,
constant: &mir::Constant<'tcx>, constant: &mir::ConstOperand<'tcx>,
) -> OperandRef<'tcx, Bx::Value> { ) -> OperandRef<'tcx, Bx::Value> {
let val = self.eval_mir_constant(constant); let val = self.eval_mir_constant(constant);
let ty = self.monomorphize(constant.ty()); let ty = self.monomorphize(constant.ty());
OperandRef::from_const(bx, val, ty) OperandRef::from_const(bx, val, ty)
} }
pub fn eval_mir_constant(&self, constant: &mir::Constant<'tcx>) -> mir::ConstValue<'tcx> { pub fn eval_mir_constant(&self, constant: &mir::ConstOperand<'tcx>) -> mir::ConstValue<'tcx> {
self.monomorphize(constant.literal) self.monomorphize(constant.const_)
.eval(self.cx.tcx(), ty::ParamEnv::reveal_all(), Some(constant.span)) .eval(self.cx.tcx(), ty::ParamEnv::reveal_all(), Some(constant.span))
.expect("erroneous constant not captured by required_consts") .expect("erroneous constant not captured by required_consts")
} }
/// This is a convenience helper for `simd_shuffle_indices`. It has the precondition /// 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. /// 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! /// Note that this function is cursed, since usually MIR consts should not be evaluated to valtrees!
pub fn eval_unevaluated_mir_constant_to_valtree( pub fn eval_unevaluated_mir_constant_to_valtree(
&self, &self,
constant: &mir::Constant<'tcx>, constant: &mir::ConstOperand<'tcx>,
) -> Result<Option<ty::ValTree<'tcx>>, ErrorHandled> { ) -> Result<Option<ty::ValTree<'tcx>>, ErrorHandled> {
let uv = match self.monomorphize(constant.literal) { let uv = match self.monomorphize(constant.const_) {
mir::ConstantKind::Unevaluated(uv, _) => uv.shrink(), mir::Const::Unevaluated(uv, _) => uv.shrink(),
mir::ConstantKind::Ty(c) => match c.kind() { 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 // 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). // simd_shuffle (passing as argument instead of as a generic param).
rustc_type_ir::ConstKind::Value(valtree) => return Ok(Some(valtree)), rustc_type_ir::ConstKind::Value(valtree) => return Ok(Some(valtree)),
other => span_bug!(constant.span, "{other:#?}"), 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. // 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 // 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 // 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( pub fn simd_shuffle_indices(
&mut self, &mut self,
bx: &Bx, bx: &Bx,
constant: &mir::Constant<'tcx>, constant: &mir::ConstOperand<'tcx>,
) -> (Bx::Value, Ty<'tcx>) { ) -> (Bx::Value, Ty<'tcx>) {
let ty = self.monomorphize(constant.ty()); let ty = self.monomorphize(constant.ty());
let val = self let val = self

View File

@ -1089,7 +1089,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
pub fn eval_mir_constant( pub fn eval_mir_constant(
&self, &self,
val: &mir::ConstantKind<'tcx>, val: &mir::Const<'tcx>,
span: Option<Span>, span: Option<Span>,
layout: Option<TyAndLayout<'tcx>>, layout: Option<TyAndLayout<'tcx>>,
) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {

View File

@ -692,7 +692,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
Constant(constant) => { Constant(constant) => {
let c = 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: // This can still fail:
// * During ConstProp, with `TooGeneric` or since the `required_consts` were not all // * During ConstProp, with `TooGeneric` or since the `required_consts` were not all

View File

@ -346,8 +346,8 @@ where
}; };
// Check the qualifs of the value of `const` items. // Check the qualifs of the value of `const` items.
let uneval = match constant.literal { let uneval = match constant.const_ {
ConstantKind::Ty(ct) Const::Ty(ct)
if matches!( if matches!(
ct.kind(), ct.kind(),
ty::ConstKind::Param(_) | ty::ConstKind::Error(_) | ty::ConstKind::Value(_) ty::ConstKind::Param(_) | ty::ConstKind::Error(_) | ty::ConstKind::Value(_)
@ -355,11 +355,11 @@ where
{ {
None None
} }
ConstantKind::Ty(c) => { Const::Ty(c) => {
bug!("expected ConstKind::Param or ConstKind::Value here, found {:?}", c) bug!("expected ConstKind::Param or ConstKind::Value here, found {:?}", c)
} }
ConstantKind::Unevaluated(uv, _) => Some(uv), Const::Unevaluated(uv, _) => Some(uv),
ConstantKind::Val(..) => None, Const::Val(..) => None,
}; };
if let Some(mir::UnevaluatedConst { def, args: _, promoted }) = uneval { if let Some(mir::UnevaluatedConst { def, args: _, promoted }) = uneval {
@ -383,5 +383,5 @@ where
} }
// Otherwise use the qualifs of the type. // 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())
} }

View File

@ -372,7 +372,7 @@ impl<'tcx> Validator<'_, 'tcx> {
StatementKind::Assign(box ( StatementKind::Assign(box (
_, _,
Rvalue::Use(Operand::Constant(c)), 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, _ => None,
} }
} else { } else {
@ -554,7 +554,7 @@ impl<'tcx> Validator<'_, 'tcx> {
// Integer division: the RHS must be a non-zero const. // Integer division: the RHS must be a non-zero const.
let const_val = match rhs { let const_val = match rhs {
Operand::Constant(c) => { 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, _ => None,
}; };
@ -766,10 +766,10 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
if self.keep_original { if self.keep_original {
rhs.clone() rhs.clone()
} else { } else {
let unit = Rvalue::Use(Operand::Constant(Box::new(Constant { let unit = Rvalue::Use(Operand::Constant(Box::new(ConstOperand {
span: statement.source_info.span, span: statement.source_info.span,
user_ty: None, user_ty: None,
literal: ConstantKind::zero_sized(self.tcx.types.unit), const_: Const::zero_sized(self.tcx.types.unit),
}))); })));
mem::replace(rhs, 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 args = tcx.erase_regions(GenericArgs::identity_for_item(tcx, def));
let uneval = mir::UnevaluatedConst { def, args, promoted: Some(promoted_id) }; let uneval = mir::UnevaluatedConst { def, args, promoted: Some(promoted_id) };
Operand::Constant(Box::new(Constant { Operand::Constant(Box::new(ConstOperand {
span, span,
user_ty: None, 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, .. }, .. }) = if let Some(Terminator { kind: TerminatorKind::Call { func, destination, .. }, .. }) =
&block.terminator &block.terminator
{ {
if let Operand::Constant(box Constant { literal, .. }) = func { if let Operand::Constant(box ConstOperand { const_, .. }) = func {
if let ty::FnDef(def_id, _) = *literal.ty().kind() { if let ty::FnDef(def_id, _) = *const_.ty().kind() {
if destination == place { if destination == place {
if ccx.tcx.is_const_fn(def_id) { if ccx.tcx.is_const_fn(def_id) {
return true; return true;

View File

@ -6,13 +6,11 @@ use rustc_hir::{self as hir};
use rustc_span::Span; use rustc_span::Span;
use rustc_target::abi::{HasDataLayout, Size}; use rustc_target::abi::{HasDataLayout, Size};
use crate::mir::interpret::{ use crate::mir::interpret::{alloc_range, AllocId, ConstAllocation, ErrorHandled, Scalar};
alloc_range, AllocId, ConstAllocation, ErrorHandled, GlobalAlloc, Scalar,
};
use crate::mir::{pretty_print_const_value, Promoted}; 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::{self, print::pretty_print_const, List, Ty, TyCtxt};
use crate::ty::{GenericArgs, GenericArgsRef}; use crate::ty::{GenericArgs, GenericArgsRef};
use crate::ty::{ScalarInt, UserTypeAnnotationIndex};
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
/// Evaluated Constants /// Evaluated Constants
@ -178,29 +176,10 @@ impl<'tcx> ConstValue<'tcx> {
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
/// Constants /// 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(Clone, Copy, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable, Debug)]
#[derive(TypeFoldable, TypeVisitable)] #[derive(TypeFoldable, TypeVisitable)]
pub enum ConstantKind<'tcx> { pub enum Const<'tcx> {
/// This constant came from the type system. /// This constant came from the type system.
/// ///
/// Any way of turning `ty::Const` into `ConstValue` should go through `valtree_to_const_val`; /// 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>), Val(ConstValue<'tcx>, Ty<'tcx>),
} }
impl<'tcx> Constant<'tcx> { impl<'tcx> Const<'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> {
#[inline(always)] #[inline(always)]
pub fn ty(&self) -> Ty<'tcx> { pub fn ty(&self) -> Ty<'tcx> {
match self { match self {
ConstantKind::Ty(c) => c.ty(), Const::Ty(c) => c.ty(),
ConstantKind::Val(_, ty) | ConstantKind::Unevaluated(_, ty) => *ty, Const::Val(_, ty) | Const::Unevaluated(_, ty) => *ty,
} }
} }
#[inline] #[inline]
pub fn try_to_scalar(self) -> Option<Scalar> { pub fn try_to_scalar(self) -> Option<Scalar> {
match self { match self {
ConstantKind::Ty(c) => match c.kind() { Const::Ty(c) => match c.kind() {
ty::ConstKind::Value(valtree) => match valtree { ty::ConstKind::Value(valtree) => match valtree {
ty::ValTree::Leaf(scalar_int) => Some(Scalar::Int(scalar_int)), ty::ValTree::Leaf(scalar_int) => Some(Scalar::Int(scalar_int)),
ty::ValTree::Branch(_) => None, ty::ValTree::Branch(_) => None,
}, },
_ => None, _ => None,
}, },
ConstantKind::Val(val, _) => val.try_to_scalar(), Const::Val(val, _) => val.try_to_scalar(),
ConstantKind::Unevaluated(..) => None, Const::Unevaluated(..) => None,
} }
} }
@ -287,17 +247,17 @@ impl<'tcx> ConstantKind<'tcx> {
span: Option<Span>, span: Option<Span>,
) -> Result<ConstValue<'tcx>, ErrorHandled> { ) -> Result<ConstValue<'tcx>, ErrorHandled> {
match self { match self {
ConstantKind::Ty(c) => { Const::Ty(c) => {
// We want to consistently have a "clean" value for type system constants (i.e., no // We want to consistently have a "clean" value for type system constants (i.e., no
// data hidden in the padding), so we always go through a valtree here. // data hidden in the padding), so we always go through a valtree here.
let val = c.eval(tcx, param_env, span)?; let val = c.eval(tcx, param_env, span)?;
Ok(tcx.valtree_to_const_val((self.ty(), val))) 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` // FIXME: We might want to have a `try_eval`-like function on `Unevaluated`
tcx.const_eval_resolve(param_env, uneval, span) 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] #[inline]
pub fn try_eval_bits( pub fn try_eval_bits(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Option<u128> {
&self,
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
ty: Ty<'tcx>,
) -> Option<u128> {
let int = self.try_eval_scalar_int(tcx, param_env)?; let int = self.try_eval_scalar_int(tcx, param_env)?;
assert_eq!(self.ty(), ty); let size =
let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size; tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(self.ty())).ok()?.size;
int.to_bits(size).ok() int.to_bits(size).ok()
} }
/// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type. /// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type.
#[inline] #[inline]
pub fn eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> u128 { pub fn eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> u128 {
self.try_eval_bits(tcx, param_env, ty) self.try_eval_bits(tcx, param_env)
.unwrap_or_else(|| bug!("expected bits of {:#?}, got {:#?}", ty, self)) .unwrap_or_else(|| bug!("expected bits of {:#?}, got {:#?}", self.ty(), self))
} }
#[inline] #[inline]
@ -416,7 +371,7 @@ impl<'tcx> ConstantKind<'tcx> {
Self::Val(val, ty) 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`. /// converted to a constant, everything else becomes `Unevaluated`.
#[instrument(skip(tcx), level = "debug", ret)] #[instrument(skip(tcx), level = "debug", ret)]
pub fn from_anon_const( pub fn from_anon_const(
@ -552,29 +507,13 @@ impl<'tcx> UnevaluatedConst<'tcx> {
} }
} }
impl<'tcx> Debug for Constant<'tcx> { impl<'tcx> Display for Const<'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> {
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
match *self { match *self {
ConstantKind::Ty(c) => pretty_print_const(c, fmt, true), Const::Ty(c) => pretty_print_const(c, fmt, true),
ConstantKind::Val(val, ty) => pretty_print_const_value(val, ty, fmt), Const::Val(val, ty) => pretty_print_const_value(val, ty, fmt),
// FIXME(valtrees): Correctly print mir constants. // FIXME(valtrees): Correctly print mir constants.
ConstantKind::Unevaluated(..) => { Const::Unevaluated(..) => {
fmt.write_str("_")?; fmt.write_str("_")?;
Ok(()) Ok(())
} }

View File

@ -318,7 +318,7 @@ pub struct Body<'tcx> {
/// Constants that are required to evaluate successfully for this MIR to be well-formed. /// 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. /// 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. /// Does this body use generic parameters. This is used for the `ConstEvaluatable` check.
/// ///
@ -585,12 +585,12 @@ impl<'tcx> Body<'tcx> {
&self, &self,
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'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> { ) -> Result<(), ErrorHandled> {
// For now, the only thing we have to check is is to ensure that all the constants used in // For now, the only thing we have to check is is to ensure that all the constants used in
// the body successfully evaluate. // the body successfully evaluate.
for &const_ in &self.required_consts { 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))?; c.eval(tcx, param_env, Some(const_.span))?;
} }
@ -1096,7 +1096,7 @@ impl<'tcx> LocalDecl<'tcx> {
pub enum VarDebugInfoContents<'tcx> { pub enum VarDebugInfoContents<'tcx> {
/// This `Place` only contains projection which satisfy `can_use_in_debuginfo`. /// This `Place` only contains projection which satisfy `can_use_in_debuginfo`.
Place(Place<'tcx>), Place(Place<'tcx>),
Const(Constant<'tcx>), Const(ConstOperand<'tcx>),
} }
impl<'tcx> Debug for VarDebugInfoContents<'tcx> { impl<'tcx> Debug for VarDebugInfoContents<'tcx> {

View File

@ -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> { impl<'tcx> Debug for TerminatorKind<'tcx> {
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
self.fmt_head(fmt)?; 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<'_> { impl Debug for Place<'_> {
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
self.as_ref().fmt(fmt) 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> { impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
fn visit_constant(&mut self, constant: &Constant<'tcx>, _location: Location) { fn visit_constant(&mut self, constant: &ConstOperand<'tcx>, _location: Location) {
let Constant { span, user_ty, literal } = constant; let ConstOperand { span, user_ty, const_ } = constant;
if use_verbose(literal.ty(), true) { if use_verbose(const_.ty(), true) {
self.push("mir::Constant"); self.push("mir::ConstOperand");
self.push(&format!( self.push(&format!(
"+ span: {}", "+ span: {}",
self.tcx.sess.source_map().span_to_embeddable_string(*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(), ty::ValTree::Branch(_) => "Branch(..)".to_string(),
}; };
let val = match literal { let val = match const_ {
ConstantKind::Ty(ct) => match ct.kind() { Const::Ty(ct) => match ct.kind() {
ty::ConstKind::Param(p) => format!("ty::Param({p})"), ty::ConstKind::Param(p) => format!("ty::Param({p})"),
ty::ConstKind::Unevaluated(uv) => { ty::ConstKind::Unevaluated(uv) => {
format!("ty::Unevaluated({}, {:?})", self.tcx.def_path_str(uv.def), uv.args,) 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::Placeholder(_)
| ty::ConstKind::Infer(_) | ty::ConstKind::Infer(_)
| ty::ConstKind::Expr(_) | 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!( format!(
"Unevaluated({}, {:?}, {:?})", "Unevaluated({}, {:?}, {:?})",
self.tcx.def_path_str(uv.def), self.tcx.def_path_str(uv.def),
@ -1232,13 +1259,13 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
uv.promoted, 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 // This reflects what `Const` looked liked before `val` was renamed
// as `kind`. We print it like this to avoid having to update // as `kind`. We print it like this to avoid having to update
// expected output in a lot of tests. // 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>); struct CollectAllocIds(BTreeSet<AllocId>);
impl<'tcx> Visitor<'tcx> for CollectAllocIds { impl<'tcx> Visitor<'tcx> for CollectAllocIds {
fn visit_constant(&mut self, c: &Constant<'tcx>, _: Location) { fn visit_constant(&mut self, c: &ConstOperand<'tcx>, _: Location) {
match c.literal { match c.const_ {
ConstantKind::Ty(_) | ConstantKind::Unevaluated(..) => {} Const::Ty(_) | Const::Unevaluated(..) => {}
ConstantKind::Val(val, _) => { Const::Val(val, _) => {
self.0.extend(alloc_ids_from_const_val(val)); self.0.extend(alloc_ids_from_const_val(val));
} }
} }

View File

@ -1,5 +1,5 @@
/// Functionality for statements, operands, places, and things that appear in them. /// Functionality for statements, operands, places, and things that appear in them.
use super::*; use super::{interpret::GlobalAlloc, *};
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// Statements // Statements
@ -302,10 +302,10 @@ impl<'tcx> Operand<'tcx> {
span: Span, span: Span,
) -> Self { ) -> Self {
let ty = Ty::new_fn_def(tcx, def_id, args); let ty = Ty::new_fn_def(tcx, def_id, args);
Operand::Constant(Box::new(Constant { Operand::Constant(Box::new(ConstOperand {
span, span,
user_ty: None, 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 scalar_size == type_size
}); });
Operand::Constant(Box::new(Constant { Operand::Constant(Box::new(ConstOperand {
span, span,
user_ty: None, 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. /// place.
pub fn constant(&self) -> Option<&Constant<'tcx>> { pub fn constant(&self) -> Option<&ConstOperand<'tcx>> {
match self { match self {
Operand::Constant(x) => Some(&**x), Operand::Constant(x) => Some(&**x),
Operand::Copy(_) | Operand::Move(_) => None, 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 /// While this is unlikely in general, it's the normal case of what you'll
/// find as the `func` in a [`TerminatorKind::Call`]. /// find as the `func` in a [`TerminatorKind::Call`].
pub fn const_fn_def(&self) -> Option<(DefId, GenericArgsRef<'tcx>)> { 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 } 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 /// Rvalues

View File

@ -3,7 +3,7 @@
//! This is in a dedicated file so that changes to this file can be reviewed more carefully. //! 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. //! 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::mir::coverage::{CodeRegion, CoverageKind};
use crate::traits::Reveal; use crate::traits::Reveal;
@ -439,17 +439,6 @@ pub enum NonDivergingIntrinsic<'tcx> {
CopyNonOverlapping(CopyNonOverlapping<'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. /// Describes what kind of retag is to be performed.
#[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, PartialEq, Eq, Hash, HashStable)] #[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, PartialEq, Eq, Hash, HashStable)]
#[rustc_pass_by_value] #[rustc_pass_by_value]
@ -913,10 +902,10 @@ pub enum InlineAsmOperand<'tcx> {
out_place: Option<Place<'tcx>>, out_place: Option<Place<'tcx>>,
}, },
Const { Const {
value: Box<Constant<'tcx>>, value: Box<ConstOperand<'tcx>>,
}, },
SymFn { SymFn {
value: Box<Constant<'tcx>>, value: Box<ConstOperand<'tcx>>,
}, },
SymStatic { SymStatic {
def_id: DefId, def_id: DefId,
@ -1136,7 +1125,22 @@ pub enum Operand<'tcx> {
Move(Place<'tcx>), Move(Place<'tcx>),
/// Constants are already semantically values, and remain unchanged. /// 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>,
} }
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////

View File

@ -227,7 +227,7 @@ impl<'tcx> Operand<'tcx> {
{ {
match self { match self {
&Operand::Copy(ref l) | &Operand::Move(ref l) => l.ty(local_decls, tcx).ty, &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(),
} }
} }
} }

View File

@ -186,7 +186,7 @@ macro_rules! make_mir_visitor {
fn visit_constant( fn visit_constant(
&mut self, &mut self,
constant: & $($mutability)? Constant<'tcx>, constant: & $($mutability)? ConstOperand<'tcx>,
location: Location, location: Location,
) { ) {
self.super_constant(constant, location); self.super_constant(constant, location);
@ -870,20 +870,20 @@ macro_rules! make_mir_visitor {
fn super_constant( fn super_constant(
&mut self, &mut self,
constant: & $($mutability)? Constant<'tcx>, constant: & $($mutability)? ConstOperand<'tcx>,
location: Location location: Location
) { ) {
let Constant { let ConstOperand {
span, span,
user_ty: _, // no visit method for this user_ty: _, // no visit method for this
literal, const_,
} = constant; } = constant;
self.visit_span($(& $mutability)? *span); self.visit_span($(& $mutability)? *span);
match literal { match const_ {
ConstantKind::Ty(ct) => self.visit_ty_const($(&$mutability)? *ct, location), Const::Ty(ct) => self.visit_ty_const($(&$mutability)? *ct, location),
ConstantKind::Val(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)), Const::Val(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)),
ConstantKind::Unevaluated(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)), Const::Unevaluated(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)),
} }
} }

View File

@ -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>>()]; type Result = [u8; size_of::<Result<ty::Const<'static>, mir::interpret::LitToConstError>>()];
} }
impl EraseType for Result<mir::ConstantKind<'_>, mir::interpret::LitToConstError> { impl EraseType for Result<mir::Const<'_>, mir::interpret::LitToConstError> {
type Result = type Result = [u8; size_of::<Result<mir::Const<'static>, mir::interpret::LitToConstError>>()];
[u8; size_of::<Result<mir::ConstantKind<'static>, mir::interpret::LitToConstError>>()];
} }
impl EraseType for Result<mir::ConstAlloc<'_>, mir::interpret::ErrorHandled> { impl EraseType for Result<mir::ConstAlloc<'_>, mir::interpret::ErrorHandled> {
@ -311,7 +310,7 @@ macro_rules! tcx_lifetime {
tcx_lifetime! { tcx_lifetime! {
rustc_middle::hir::Owner, rustc_middle::hir::Owner,
rustc_middle::middle::exported_symbols::ExportedSymbol, rustc_middle::middle::exported_symbols::ExportedSymbol,
rustc_middle::mir::ConstantKind, rustc_middle::mir::Const,
rustc_middle::mir::DestructuredConstant, rustc_middle::mir::DestructuredConstant,
rustc_middle::mir::ConstAlloc, rustc_middle::mir::ConstAlloc,
rustc_middle::mir::ConstValue, rustc_middle::mir::ConstValue,

View File

@ -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>; type CacheSelector = DefaultCacheSelector<Self>;
fn default_span(&self, _: TyCtxt<'_>) -> Span { fn default_span(&self, _: TyCtxt<'_>) -> Span {

View File

@ -1101,7 +1101,7 @@ rustc_queries! {
desc { "destructuring type level constant"} 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. /// and its field values. This should only be used for pretty printing.
query try_destructure_mir_constant_for_diagnostics( query try_destructure_mir_constant_for_diagnostics(
key: (mir::ConstValue<'tcx>, Ty<'tcx>) key: (mir::ConstValue<'tcx>, Ty<'tcx>)

View File

@ -563,11 +563,11 @@ pub enum InlineAsmOperand<'tcx> {
out_expr: Option<ExprId>, out_expr: Option<ExprId>,
}, },
Const { Const {
value: mir::ConstantKind<'tcx>, value: mir::Const<'tcx>,
span: Span, span: Span,
}, },
SymFn { SymFn {
value: mir::ConstantKind<'tcx>, value: mir::Const<'tcx>,
span: Span, span: Span,
}, },
SymStatic { SymStatic {
@ -739,7 +739,7 @@ pub enum PatKind<'tcx> {
/// * Opaque constants, that must not be matched structurally. So anything that does not derive /// * Opaque constants, that must not be matched structurally. So anything that does not derive
/// `PartialEq` and `Eq`. /// `PartialEq` and `Eq`.
Constant { Constant {
value: mir::ConstantKind<'tcx>, value: mir::Const<'tcx>,
}, },
Range(Box<PatRange<'tcx>>), Range(Box<PatRange<'tcx>>),
@ -769,8 +769,8 @@ pub enum PatKind<'tcx> {
#[derive(Clone, Debug, PartialEq, HashStable)] #[derive(Clone, Debug, PartialEq, HashStable)]
pub struct PatRange<'tcx> { pub struct PatRange<'tcx> {
pub lo: mir::ConstantKind<'tcx>, pub lo: mir::Const<'tcx>,
pub hi: mir::ConstantKind<'tcx>, pub hi: mir::Const<'tcx>,
pub end: RangeEnd, pub end: RangeEnd,
} }

View File

@ -26,13 +26,13 @@ pub trait Visitor<'a, 'tcx: 'a>: Sized {
walk_pat(self, pat); 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, // (even though these types occur in THIR) for consistency and to reduce confusion,
// since the lazy creation of constants during thir construction causes most // 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 // stage (they are mostly still identified by `DefId` or `hir::Lit`, see
// the variants `Literal`, `NonHirLiteral` and `NamedConst` in `thir::ExprKind`). // 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. // other `visit*` functions.
} }

View File

@ -339,24 +339,19 @@ impl<'tcx> Const<'tcx> {
/// Attempts to evaluate the given constant to bits. Can fail to evaluate in the presence of /// 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 /// generics (or erroneous code) or if the value can't be represented as bits (e.g. because it
/// contains const generic parameters or pointers). /// contains const generic parameters or pointers).
pub fn try_eval_bits( pub fn try_eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<u128> {
self,
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
ty: Ty<'tcx>,
) -> Option<u128> {
let int = self.try_eval_scalar_int(tcx, param_env)?; let int = self.try_eval_scalar_int(tcx, param_env)?;
assert_eq!(self.ty(), ty); let size =
let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.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 // if `ty` does not depend on generic parameters, use an empty param_env
int.to_bits(size).ok() int.to_bits(size).ok()
} }
#[inline] #[inline]
/// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type. /// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type.
pub fn eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>) -> u128 { pub fn eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> u128 {
self.try_eval_bits(tcx, param_env, ty) self.try_eval_bits(tcx, param_env)
.unwrap_or_else(|| bug!("expected bits of {:#?}, got {:#?}", ty, self)) .unwrap_or_else(|| bug!("expected bits of {:#?}, got {:#?}", self.ty(), self))
} }
#[inline] #[inline]

View File

@ -17,8 +17,8 @@ pub fn find_self_call<'tcx>(
&body[block].terminator &body[block].terminator
{ {
debug!("find_self_call: func={:?}", func); debug!("find_self_call: func={:?}", func);
if let Operand::Constant(box Constant { literal, .. }) = func { if let Operand::Constant(box ConstOperand { const_, .. }) = func {
if let ty::FnDef(def_id, fn_args) = *literal.ty().kind() { if let ty::FnDef(def_id, fn_args) = *const_.ty().kind() {
if let Some(ty::AssocItem { fn_has_self_parameter: true, .. }) = if let Some(ty::AssocItem { fn_has_self_parameter: true, .. }) =
tcx.opt_associated_item(def_id) tcx.opt_associated_item(def_id)
{ {

View File

@ -49,7 +49,7 @@ impl<'tcx> CFG<'tcx> {
block: BasicBlock, block: BasicBlock,
source_info: SourceInfo, source_info: SourceInfo,
temp: Place<'tcx>, temp: Place<'tcx>,
constant: Constant<'tcx>, constant: ConstOperand<'tcx>,
) { ) {
self.push_assign( self.push_assign(
block, block,
@ -70,10 +70,10 @@ impl<'tcx> CFG<'tcx> {
block, block,
source_info, source_info,
place, place,
Rvalue::Use(Operand::Constant(Box::new(Constant { Rvalue::Use(Operand::Constant(Box::new(ConstOperand {
span: source_info.span, span: source_info.span,
user_ty: None, user_ty: None,
literal: ConstantKind::zero_sized(tcx.types.unit), const_: Const::zero_sized(tcx.types.unit),
}))), }))),
); );
} }

View File

@ -100,7 +100,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
expected: "constant pattern".to_string(), 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)?); targets.push(self.parse_block(arm.body)?);
} }
@ -283,12 +283,12 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
ExprKind::StaticRef { alloc_id, ty, .. } => { ExprKind::StaticRef { alloc_id, ty, .. } => {
let const_val = let const_val =
ConstValue::Scalar(Scalar::from_pointer((*alloc_id).into(), &self.tcx)); 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, span: expr.span,
user_ty: None, user_ty: None,
literal const_
}))) })))
}, },
) )
@ -301,7 +301,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
| ExprKind::NonHirLiteral { .. } | ExprKind::NonHirLiteral { .. }
| ExprKind::ConstBlock { .. } => Ok({ | ExprKind::ConstBlock { .. } => Ok({
let value = as_constant_inner(expr, |_| None, self.tcx); 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)
}), }),
) )
} }

View File

@ -15,7 +15,7 @@ use rustc_target::abi::Size;
impl<'a, 'tcx> Builder<'a, 'tcx> { impl<'a, 'tcx> Builder<'a, 'tcx> {
/// Compile `expr`, yielding a compile-time constant. Assumes that /// Compile `expr`, yielding a compile-time constant. Assumes that
/// `expr` is a valid compile-time constant! /// `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 this = self;
let tcx = this.tcx; let tcx = this.tcx;
let Expr { ty, temp_lifetime: _, span, ref kind } = *expr; let Expr { ty, temp_lifetime: _, span, ref kind } = *expr;
@ -42,62 +42,62 @@ pub fn as_constant_inner<'tcx>(
expr: &Expr<'tcx>, expr: &Expr<'tcx>,
push_cuta: impl FnMut(&Box<CanonicalUserType<'tcx>>) -> Option<UserTypeAnnotationIndex>, push_cuta: impl FnMut(&Box<CanonicalUserType<'tcx>>) -> Option<UserTypeAnnotationIndex>,
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
) -> Constant<'tcx> { ) -> ConstOperand<'tcx> {
let Expr { ty, temp_lifetime: _, span, ref kind } = *expr; let Expr { ty, temp_lifetime: _, span, ref kind } = *expr;
match *kind { match *kind {
ExprKind::Literal { lit, neg } => { ExprKind::Literal { lit, neg } => {
let literal = let const_ = match lit_to_mir_constant(tcx, LitToConstInput { lit: &lit.node, ty, neg })
match lit_to_mir_constant(tcx, LitToConstInput { lit: &lit.node, ty, neg }) { {
Ok(c) => c, Ok(c) => c,
Err(LitToConstError::Reported(guar)) => { 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) => { Err(LitToConstError::TypeError) => {
bug!("encountered type error in `lit_to_mir_constant`") 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 } => { ExprKind::NonHirLiteral { lit, ref user_ty } => {
let user_ty = user_ty.as_ref().and_then(push_cuta); 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 } => { ExprKind::ZstLiteral { ref user_ty } => {
let user_ty = user_ty.as_ref().and_then(push_cuta); 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 } => { ExprKind::NamedConst { def_id, args, ref user_ty } => {
let user_ty = user_ty.as_ref().and_then(push_cuta); let user_ty = user_ty.as_ref().and_then(push_cuta);
let uneval = mir::UnevaluatedConst::new(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, span, literal } ConstOperand { user_ty, span, const_ }
} }
ExprKind::ConstParam { param, def_id: _ } => { ExprKind::ConstParam { param, def_id: _ } => {
let const_param = ty::Const::new_param(tcx, param, expr.ty); 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 } => { ExprKind::ConstBlock { did: def_id, args } => {
let uneval = mir::UnevaluatedConst::new(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, .. } => { ExprKind::StaticRef { alloc_id, ty, .. } => {
let const_val = ConstValue::Scalar(Scalar::from_pointer(alloc_id.into(), &tcx)); 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), _ => 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>( fn lit_to_mir_constant<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
lit_input: LitToConstInput<'tcx>, lit_input: LitToConstInput<'tcx>,
) -> Result<ConstantKind<'tcx>, LitToConstError> { ) -> Result<Const<'tcx>, LitToConstError> {
let LitToConstInput { lit, ty, neg } = lit_input; let LitToConstInput { lit, ty, neg } = lit_input;
let trunc = |n| { let trunc = |n| {
let param_ty = ty::ParamEnv::reveal_all().and(ty); let param_ty = ty::ParamEnv::reveal_all().and(ty);
@ -173,5 +173,5 @@ fn lit_to_mir_constant<'tcx>(
_ => return Err(LitToConstError::TypeError), _ => return Err(LitToConstError::TypeError),
}; };
Ok(ConstantKind::Val(value, ty)) Ok(Const::Val(value, ty))
} }

View File

@ -249,7 +249,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let mut comparer = |range: u128, bin_op: BinOp| -> Place<'tcx> { let mut comparer = |range: u128, bin_op: BinOp| -> Place<'tcx> {
let range_val = 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 lit_op = this.literal_operand(expr.span, range_val);
let is_bin_op = this.temp(bool_ty, expr_span); let is_bin_op = this.temp(bool_ty, expr_span);
this.cfg.push_assign( this.cfg.push_assign(
@ -485,10 +485,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
} }
ExprKind::Assign { .. } | ExprKind::AssignOp { .. } => { ExprKind::Assign { .. } | ExprKind::AssignOp { .. } => {
block = unpack!(this.stmt_expr(block, expr, None)); 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, span: expr_span,
user_ty: None, 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> { fn neg_1_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> {
let param_ty = ty::ParamEnv::empty().and(ty); let param_ty = ty::ParamEnv::empty().and(ty);
let size = self.tcx.layout_of(param_ty).unwrap().size; 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) self.literal_operand(span, literal)
} }
@ -828,7 +828,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let param_ty = ty::ParamEnv::empty().and(ty); let param_ty = ty::ParamEnv::empty().and(ty);
let bits = self.tcx.layout_of(param_ty).unwrap().size.bits(); let bits = self.tcx.layout_of(param_ty).unwrap().size.bits();
let n = 1 << (bits - 1); 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) self.literal_operand(span, literal)
} }

View File

@ -114,10 +114,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
true_block, true_block,
source_info, source_info,
destination, destination,
Constant { ConstOperand {
span: expr_span, span: expr_span,
user_ty: None, 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, false_block,
source_info, source_info,
destination, destination,
Constant { ConstOperand {
span: expr_span, span: expr_span,
user_ty: None, 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, short_circuit,
source_info, source_info,
destination, destination,
Constant { ConstOperand {
span: expr.span, span: expr.span,
user_ty: None, 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])); 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 } => { thir::InlineAsmOperand::Const { value, span } => {
mir::InlineAsmOperand::Const { 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 } => { thir::InlineAsmOperand::SymFn { value, span } => {
mir::InlineAsmOperand::SymFn { 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 } => { thir::InlineAsmOperand::SymStatic { def_id } => {

View File

@ -1005,13 +1005,13 @@ enum TestKind<'tcx> {
/// ///
/// For `bool` we always generate two edges, one for `true` and one for /// For `bool` we always generate two edges, one for `true` and one for
/// `false`. /// `false`.
options: FxIndexMap<ConstantKind<'tcx>, u128>, options: FxIndexMap<Const<'tcx>, u128>,
}, },
/// Test for equality with value, possibly after an unsizing coercion to /// Test for equality with value, possibly after an unsizing coercion to
/// `ty`, /// `ty`,
Eq { Eq {
value: ConstantKind<'tcx>, value: Const<'tcx>,
// Integer types are handled by `SwitchInt`, and constants with ADT // Integer types are handled by `SwitchInt`, and constants with ADT
// types are converted back into patterns, so this can only be `&str`, // types are converted back into patterns, so this can only be `&str`,
// `&[T]`, `f32` or `f64`. // `&[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 // may want to add cases based on the candidates that are
// available // available
match test.kind { match test.kind {
TestKind::SwitchInt { switch_ty, ref mut options } => { TestKind::SwitchInt { switch_ty: _, ref mut options } => {
for candidate in candidates.iter() { 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; break;
} }
} }

View File

@ -85,8 +85,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
&mut self, &mut self,
test_place: &PlaceBuilder<'tcx>, test_place: &PlaceBuilder<'tcx>,
candidate: &Candidate<'pat, 'tcx>, candidate: &Candidate<'pat, 'tcx>,
switch_ty: Ty<'tcx>, options: &mut FxIndexMap<Const<'tcx>, u128>,
options: &mut FxIndexMap<ConstantKind<'tcx>, u128>,
) -> bool { ) -> bool {
let Some(match_pair) = candidate.match_pairs.iter().find(|mp| mp.place == *test_place) let Some(match_pair) = candidate.match_pairs.iter().find(|mp| mp.place == *test_place)
else { else {
@ -95,9 +94,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
match match_pair.pattern.kind { match match_pair.pattern.kind {
PatKind::Constant { value } => { PatKind::Constant { value } => {
options options.entry(value).or_insert_with(|| value.eval_bits(self.tcx, self.param_env));
.entry(value)
.or_insert_with(|| value.eval_bits(self.tcx, self.param_env, switch_ty));
true true
} }
PatKind::Variant { .. } => { PatKind::Variant { .. } => {
@ -255,10 +252,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
block, block,
source_info, source_info,
TerminatorKind::Call { TerminatorKind::Call {
func: Operand::Constant(Box::new(Constant { func: Operand::Constant(Box::new(ConstOperand {
span: test.span, span: test.span,
user_ty: None, user_ty: None,
literal: method, const_: method,
})), })),
args: vec![Operand::Move(ref_string)], args: vec![Operand::Move(ref_string)],
destination: ref_str, destination: ref_str,
@ -388,7 +385,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
block: BasicBlock, block: BasicBlock,
make_target_blocks: impl FnOnce(&mut Self) -> Vec<BasicBlock>, make_target_blocks: impl FnOnce(&mut Self) -> Vec<BasicBlock>,
source_info: SourceInfo, source_info: SourceInfo,
value: ConstantKind<'tcx>, value: Const<'tcx>,
mut val: Place<'tcx>, mut val: Place<'tcx>,
mut ty: Ty<'tcx>, mut ty: Ty<'tcx>,
) { ) {
@ -485,7 +482,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
block, block,
source_info, source_info,
TerminatorKind::Call { TerminatorKind::Call {
func: Operand::Constant(Box::new(Constant { func: Operand::Constant(Box::new(ConstOperand {
span: source_info.span, span: source_info.span,
// FIXME(#54571): This constant comes from user input (a // FIXME(#54571): This constant comes from user input (a
@ -494,7 +491,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// Need to experiment. // Need to experiment.
user_ty: None, user_ty: None,
literal: method, const_: method,
})), })),
args: vec![Operand::Copy(val), expect], args: vec![Operand::Copy(val), expect],
destination: eq_result, 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) span_bug!(match_pair.pattern.span, "simplifiable pattern found: {:?}", match_pair.pattern)
} }
fn const_range_contains( fn const_range_contains(&self, range: &PatRange<'tcx>, value: Const<'tcx>) -> Option<bool> {
&self,
range: &PatRange<'tcx>,
value: ConstantKind<'tcx>,
) -> Option<bool> {
use std::cmp::Ordering::*; use std::cmp::Ordering::*;
// For performance, it's important to only do the second // 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( fn values_not_contained_in_range(
&self, &self,
range: &PatRange<'tcx>, range: &PatRange<'tcx>,
options: &FxIndexMap<ConstantKind<'tcx>, u128>, options: &FxIndexMap<Const<'tcx>, u128>,
) -> Option<bool> { ) -> Option<bool> {
for &val in options.keys() { for &val in options.keys() {
if self.const_range_contains(range, val)? { if self.const_range_contains(range, val)? {
@ -866,7 +859,7 @@ fn trait_method<'tcx>(
trait_def_id: DefId, trait_def_id: DefId,
method_name: Symbol, method_name: Symbol,
args: impl IntoIterator<Item: Into<GenericArg<'tcx>>>, args: impl IntoIterator<Item: Into<GenericArg<'tcx>>>,
) -> ConstantKind<'tcx> { ) -> Const<'tcx> {
// The unhygienic comparison here is acceptable because this is only // The unhygienic comparison here is acceptable because this is only
// used on known traits. // used on known traits.
let item = tcx let item = tcx
@ -877,5 +870,5 @@ fn trait_method<'tcx>(
let method_ty = Ty::new_fn_def(tcx, item.def_id, args); let method_ty = Ty::new_fn_def(tcx, item.def_id, args);
ConstantKind::zero_sized(method_ty) Const::zero_sized(method_ty)
} }

View File

@ -25,19 +25,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
/// Convenience function for creating a literal operand, one /// Convenience function for creating a literal operand, one
/// without any user type annotation. /// without any user type annotation.
pub(crate) fn literal_operand( pub(crate) fn literal_operand(&mut self, span: Span, const_: Const<'tcx>) -> Operand<'tcx> {
&mut self, let constant = Box::new(ConstOperand { span, user_ty: None, const_ });
span: Span,
literal: ConstantKind<'tcx>,
) -> Operand<'tcx> {
let constant = Box::new(Constant { span, user_ty: None, literal });
Operand::Constant(constant) Operand::Constant(constant)
} }
/// Returns a zero literal operand for the appropriate type, works for /// Returns a zero literal operand for the appropriate type, works for
/// bool, char and integers. /// bool, char and integers.
pub(crate) fn zero_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> { 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) self.literal_operand(span, literal)
} }
@ -54,10 +50,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
block, block,
source_info, source_info,
temp, temp,
Constant { ConstOperand {
span: source_info.span, span: source_info.span,
user_ty: None, user_ty: None,
literal: ConstantKind::from_usize(self.tcx, value), const_: Const::from_usize(self.tcx, value),
}, },
); );
temp temp

View File

@ -647,21 +647,15 @@ impl<'tcx> Cx<'tcx> {
out_expr: out_expr.map(|expr| self.mirror_expr(expr)), out_expr: out_expr.map(|expr| self.mirror_expr(expr)),
}, },
hir::InlineAsmOperand::Const { ref anon_const } => { hir::InlineAsmOperand::Const { ref anon_const } => {
let value = mir::ConstantKind::from_anon_const( let value =
tcx, mir::Const::from_anon_const(tcx, anon_const.def_id, self.param_env);
anon_const.def_id,
self.param_env,
);
let span = tcx.def_span(anon_const.def_id); let span = tcx.def_span(anon_const.def_id);
InlineAsmOperand::Const { value, span } InlineAsmOperand::Const { value, span }
} }
hir::InlineAsmOperand::SymFn { ref anon_const } => { hir::InlineAsmOperand::SymFn { ref anon_const } => {
let value = mir::ConstantKind::from_anon_const( let value =
tcx, mir::Const::from_anon_const(tcx, anon_const.def_id, self.param_env);
anon_const.def_id,
self.param_env,
);
let span = tcx.def_span(anon_const.def_id); let span = tcx.def_span(anon_const.def_id);
InlineAsmOperand::SymFn { value, span } InlineAsmOperand::SymFn { value, span }

View File

@ -27,7 +27,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
#[instrument(level = "debug", skip(self), ret)] #[instrument(level = "debug", skip(self), ret)]
pub(super) fn const_to_pat( pub(super) fn const_to_pat(
&self, &self,
cv: mir::ConstantKind<'tcx>, cv: mir::Const<'tcx>,
id: hir::HirId, id: hir::HirId,
span: Span, span: Span,
check_body_for_struct_match_violation: Option<DefId>, check_body_for_struct_match_violation: Option<DefId>,
@ -104,7 +104,7 @@ impl<'tcx> ConstToPat<'tcx> {
fn to_pat( fn to_pat(
&mut self, &mut self,
cv: mir::ConstantKind<'tcx>, cv: mir::Const<'tcx>,
check_body_for_struct_match_violation: Option<DefId>, check_body_for_struct_match_violation: Option<DefId>,
) -> Box<Pat<'tcx>> { ) -> Box<Pat<'tcx>> {
trace!(self.treat_byte_string_as_slice); 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); debug!(?check_body_for_struct_match_violation, ?mir_structural_match_violation);
let inlined_const_as_pat = match cv { 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::Param(_)
| ty::ConstKind::Infer(_) | ty::ConstKind::Infer(_)
| ty::ConstKind::Bound(_, _) | 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:?}") 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, span: self.span,
ty: cv.ty(), ty: cv.ty(),
kind: PatKind::Constant { value: cv }, kind: PatKind::Constant { value: cv },
@ -385,9 +385,9 @@ impl<'tcx> ConstToPat<'tcx> {
ty::Ref(_, pointee_ty, ..) => match *pointee_ty.kind() { ty::Ref(_, pointee_ty, ..) => match *pointee_ty.kind() {
// `&str` is represented as a valtree, let's keep using this // `&str` is represented as a valtree, let's keep using this
// optimization for now. // optimization for now.
ty::Str => PatKind::Constant { ty::Str => {
value: mir::ConstantKind::Ty(ty::Const::new_value(tcx, cv, ty)), PatKind::Constant { value: mir::Const::Ty(ty::Const::new_value(tcx, cv, ty)) }
}, }
// Backwards compatibility hack: support references to non-structural types, // Backwards compatibility hack: support references to non-structural types,
// but hard error if we aren't behind a double reference. We could just use // 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 // 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 { ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) => {
value: mir::ConstantKind::Ty(ty::Const::new_value(tcx, cv, ty)), PatKind::Constant { value: mir::Const::Ty(ty::Const::new_value(tcx, cv, ty)) }
}, }
ty::FnPtr(..) | ty::RawPtr(..) => unreachable!(), ty::FnPtr(..) | ty::RawPtr(..) => unreachable!(),
_ => { _ => {
self.saw_const_match_error.set(true); self.saw_const_match_error.set(true);

View File

@ -137,16 +137,16 @@ impl IntRange {
fn from_constant<'tcx>( fn from_constant<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
value: mir::ConstantKind<'tcx>, value: mir::Const<'tcx>,
) -> Option<IntRange> { ) -> Option<IntRange> {
let ty = value.ty(); let ty = value.ty();
let (target_size, bias) = Self::integral_size_and_signed_bias(tcx, ty)?; let (target_size, bias) = Self::integral_size_and_signed_bias(tcx, ty)?;
let val = match value { 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() valtree.unwrap_leaf().to_bits(target_size).ok()
}, },
// This is a more general form of the previous case. // 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; let val = val ^ bias;
@ -225,8 +225,8 @@ impl IntRange {
let (lo, hi) = (lo ^ bias, hi ^ bias); let (lo, hi) = (lo ^ bias, hi ^ bias);
let env = ty::ParamEnv::empty().and(ty); let env = ty::ParamEnv::empty().and(ty);
let lo_const = mir::ConstantKind::from_bits(tcx, lo, env); let lo_const = mir::Const::from_bits(tcx, lo, env);
let hi_const = mir::ConstantKind::from_bits(tcx, hi, env); let hi_const = mir::Const::from_bits(tcx, hi, env);
let kind = if lo == hi { let kind = if lo == hi {
PatKind::Constant { value: lo_const } 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`). /// Ranges of integer literal values (`2`, `2..=5` or `2..5`).
IntRange(IntRange), IntRange(IntRange),
/// Ranges of floating-point literal values (`2.0..=5.2`). /// 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. /// 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. /// Array and slice patterns.
Slice(Slice), Slice(Slice),
/// Constants that must not be matched structurally. They are treated as black /// 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(); let ty = lo.ty();
ctor = if let Some(int_range) = IntRange::from_range( ctor = if let Some(int_range) = IntRange::from_range(
cx.tcx, cx.tcx,
lo.eval_bits(cx.tcx, cx.param_env, lo.ty()), lo.eval_bits(cx.tcx, cx.param_env),
hi.eval_bits(cx.tcx, cx.param_env, hi.ty()), hi.eval_bits(cx.tcx, cx.param_env),
ty, ty,
&end, &end,
) { ) {

View File

@ -20,7 +20,7 @@ use rustc_index::Idx;
use rustc_middle::mir::interpret::{ use rustc_middle::mir::interpret::{
ErrorHandled, GlobalId, LitToConstError, LitToConstInput, Scalar, 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::mir::{BorrowKind, Mutability};
use rustc_middle::thir::{Ascription, BindingMode, FieldPat, LocalVarId, Pat, PatKind, PatRange}; use rustc_middle::thir::{Ascription, BindingMode, FieldPat, LocalVarId, Pat, PatKind, PatRange};
use rustc_middle::ty::CanonicalUserTypeAnnotation; use rustc_middle::ty::CanonicalUserTypeAnnotation;
@ -100,8 +100,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
fn lower_pattern_range( fn lower_pattern_range(
&mut self, &mut self,
ty: Ty<'tcx>, ty: Ty<'tcx>,
lo: mir::ConstantKind<'tcx>, lo: mir::Const<'tcx>,
hi: mir::ConstantKind<'tcx>, hi: mir::Const<'tcx>,
end: RangeEnd, end: RangeEnd,
span: Span, span: Span,
lo_expr: Option<&hir::Expr<'tcx>>, 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 if let Some(hir::Expr { kind: hir::ExprKind::Lit(lit), .. }) = lo_expr
&& let rustc_ast::ast::LitKind::Int(val, _) = lit.node && 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; lower_overflow = true;
self.tcx.sess.emit_err(LiteralOutOfRange { span: lit.span, ty, max: max() }); 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 if let Some(hir::Expr { kind: hir::ExprKind::Lit(lit), .. }) = hi_expr
&& let rustc_ast::ast::LitKind::Int(val, _) = lit.node && 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; higher_overflow = true;
self.tcx.sess.emit_err(LiteralOutOfRange { span: lit.span, ty, max: max() }); 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 if let Some(hir::Expr { kind: hir::ExprKind::Lit(lit), .. }) = lo_expr
&& let rustc_ast::ast::LitKind::Int(val, _) = lit.node && 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; lower_overflow = true;
self.tcx.sess.emit_err(LiteralOutOfRange { span: lit.span, ty, max: max() }); 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 if let Some(hir::Expr { kind: hir::ExprKind::Lit(lit), .. }) = hi_expr
&& let rustc_ast::ast::LitKind::Int(val, _) = lit.node && 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; higher_overflow = true;
self.tcx.sess.emit_err(LiteralOutOfRange { span: lit.span, ty, max: max() }); 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>, ty: Ty<'tcx>,
lo: Option<&PatKind<'tcx>>, lo: Option<&PatKind<'tcx>>,
hi: Option<&PatKind<'tcx>>, hi: Option<&PatKind<'tcx>>,
) -> Option<(mir::ConstantKind<'tcx>, mir::ConstantKind<'tcx>)> { ) -> Option<(mir::Const<'tcx>, mir::Const<'tcx>)> {
match (lo, hi) { match (lo, hi) {
(Some(PatKind::Constant { value: lo }), Some(PatKind::Constant { value: hi })) => { (Some(PatKind::Constant { value: lo }), Some(PatKind::Constant { value: hi })) => {
Some((*lo, *hi)) Some((*lo, *hi))
} }
(Some(PatKind::Constant { value: lo }), None) => { (Some(PatKind::Constant { value: lo }), None) => {
let hi = ty.numeric_max_val(self.tcx)?; let hi = ty.numeric_max_val(self.tcx)?;
Some((*lo, mir::ConstantKind::from_ty_const(hi, self.tcx))) Some((*lo, mir::Const::from_ty_const(hi, self.tcx)))
} }
(None, Some(PatKind::Constant { value: hi })) => { (None, Some(PatKind::Constant { value: hi })) => {
let lo = ty.numeric_min_val(self.tcx)?; let lo = ty.numeric_min_val(self.tcx)?;
Some((mir::ConstantKind::from_ty_const(lo, self.tcx), *hi)) Some((mir::Const::from_ty_const(lo, self.tcx), *hi))
} }
_ => None, _ => None,
} }
@ -525,8 +525,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
.tcx .tcx
.const_eval_global_id_for_typeck(param_env_reveal_all, cid, Some(span)) .const_eval_global_id_for_typeck(param_env_reveal_all, cid, Some(span))
.map(|val| match val { .map(|val| match val {
Some(valtree) => mir::ConstantKind::Ty(ty::Const::new_value(self.tcx, valtree, ty)), Some(valtree) => mir::Const::Ty(ty::Const::new_value(self.tcx, valtree, ty)),
None => mir::ConstantKind::Val( None => mir::Const::Val(
self.tcx self.tcx
.const_eval_global_id(param_env_reveal_all, cid, Some(span)) .const_eval_global_id(param_env_reveal_all, cid, Some(span))
.expect("const_eval_global_id_for_typeck should have already failed"), .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 { if let Some(lit_input) = lit_input {
match tcx.at(expr.span).lit_to_const(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 // If an error occurred, ignore that it's a literal
// and leave reporting the error up to const eval of // and leave reporting the error up to const eval of
// the unevaluated constant below. // 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.tcx.const_eval_resolve_for_typeck(self.param_env, ct, Some(span))
{ {
self.const_to_pat( 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, id,
span, span,
None, None,
@ -641,7 +641,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
} else { } else {
// If that fails, convert it to an opaque constant pattern. // If that fails, convert it to an opaque constant pattern.
match tcx.const_eval_resolve(self.param_env, uneval, Some(span)) { 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(_)) => { Err(ErrorHandled::TooGeneric(_)) => {
// If we land here it means the const can't be evaluated because it's `TooGeneric`. // If we land here it means the const can't be evaluated because it's `TooGeneric`.
self.tcx.sess.emit_err(ConstPatternDependsOnGenericParameter { span }); 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 }; LitToConstInput { lit: &lit.node, ty: self.typeck_results.expr_ty(expr), neg };
match self.tcx.at(expr.span).lit_to_const(lit_input) { match self.tcx.at(expr.span).lit_to_const(lit_input) {
Ok(constant) => { 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::Reported(_)) => PatKind::Wild,
Err(LitToConstError::TypeError) => bug!("lower_lit: had type error"), 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")] #[instrument(skip(tcx), level = "debug")]
pub(crate) fn compare_const_vals<'tcx>( pub(crate) fn compare_const_vals<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
a: mir::ConstantKind<'tcx>, a: mir::Const<'tcx>,
b: mir::ConstantKind<'tcx>, b: mir::Const<'tcx>,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
) -> Option<Ordering> { ) -> Option<Ordering> {
assert_eq!(a.ty(), b.ty()); 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 ty::Float(_) | ty::Int(_) => {} // require special handling, see below
_ => match (a, b) { _ => match (a, b) {
( (
mir::ConstantKind::Val(mir::ConstValue::Scalar(Scalar::Int(a)), _a_ty), mir::Const::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(b)), _b_ty),
) => return Some(a.cmp(&b)), ) => 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())); return Some(a.kind().cmp(&b.kind()));
} }
_ => {} _ => {}
}, },
} }
let a = a.eval_bits(tcx, param_env, ty); let a = a.eval_bits(tcx, param_env);
let b = b.eval_bits(tcx, param_env, ty); let b = b.eval_bits(tcx, param_env);
use rustc_apfloat::Float; use rustc_apfloat::Float;
match *ty.kind() { match *ty.kind() {

View File

@ -973,10 +973,10 @@ where
} }
fn constant_usize(&self, val: u16) -> Operand<'tcx> { fn constant_usize(&self, val: u16) -> Operand<'tcx> {
Operand::Constant(Box::new(Constant { Operand::Constant(Box::new(ConstOperand {
span: self.source_info.span, span: self.source_info.span,
user_ty: None, user_ty: None,
literal: ConstantKind::from_usize(self.tcx(), val.into()), const_: Const::from_usize(self.tcx(), val.into()),
})) }))
} }

View File

@ -190,7 +190,7 @@ impl PeekCall {
if let mir::TerminatorKind::Call { func: Operand::Constant(func), args, .. } = if let mir::TerminatorKind::Call { func: Operand::Constant(func), args, .. } =
&terminator.kind &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); let name = tcx.item_name(def_id);
if !tcx.is_intrinsic(def_id) || name != sym::rustc_peek { if !tcx.is_intrinsic(def_id) || name != sym::rustc_peek {
return None; return None;

View File

@ -225,7 +225,7 @@ pub trait ValueAnalysis<'tcx> {
fn handle_constant( fn handle_constant(
&self, &self,
constant: &Constant<'tcx>, constant: &ConstOperand<'tcx>,
state: &mut State<Self::Value>, state: &mut State<Self::Value>,
) -> Self::Value { ) -> Self::Value {
self.super_constant(constant, state) self.super_constant(constant, state)
@ -233,7 +233,7 @@ pub trait ValueAnalysis<'tcx> {
fn super_constant( fn super_constant(
&self, &self,
_constant: &Constant<'tcx>, _constant: &ConstOperand<'tcx>,
_state: &mut State<Self::Value>, _state: &mut State<Self::Value>,
) -> Self::Value { ) -> Self::Value {
Self::Value::TOP Self::Value::TOP

View File

@ -181,13 +181,10 @@ fn insert_alignment_check<'tcx>(
// Subtract 1 from the alignment to get the alignment mask // Subtract 1 from the alignment to get the alignment mask
let alignment_mask = let alignment_mask =
local_decls.push(LocalDecl::with_source_info(tcx.types.usize, source_info)).into(); 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, span: source_info.span,
user_ty: None, user_ty: None,
literal: ConstantKind::Val( const_: Const::Val(ConstValue::Scalar(Scalar::from_target_usize(1, &tcx)), tcx.types.usize),
ConstValue::Scalar(Scalar::from_target_usize(1, &tcx)),
tcx.types.usize,
),
})); }));
block_data.statements.push(Statement { block_data.statements.push(Statement {
source_info, source_info,
@ -213,13 +210,10 @@ fn insert_alignment_check<'tcx>(
// Check if the alignment bits are all zero // 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 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, span: source_info.span,
user_ty: None, user_ty: None,
literal: ConstantKind::Val( const_: Const::Val(ConstValue::Scalar(Scalar::from_target_usize(0, &tcx)), tcx.types.usize),
ConstValue::Scalar(Scalar::from_target_usize(0, &tcx)),
tcx.types.usize,
),
})); }));
block_data.statements.push(Statement { block_data.statements.push(Statement {
source_info, source_info,

View File

@ -142,9 +142,9 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> {
fn visit_operand(&mut self, op: &Operand<'tcx>, location: Location) { fn visit_operand(&mut self, op: &Operand<'tcx>, location: Location) {
if let Operand::Constant(constant) = op { if let Operand::Constant(constant) = op {
let maybe_uneval = match constant.literal { let maybe_uneval = match constant.const_ {
ConstantKind::Val(..) | ConstantKind::Ty(_) => None, Const::Val(..) | Const::Ty(_) => None,
ConstantKind::Unevaluated(uv, _) => Some(uv), Const::Unevaluated(uv, _) => Some(uv),
}; };
if let Some(uv) = maybe_uneval { if let Some(uv) = maybe_uneval {

View File

@ -4,7 +4,7 @@
use rustc_middle::{ use rustc_middle::{
mir::{ mir::{
visit::{PlaceContext, Visitor}, visit::{PlaceContext, Visitor},
Body, Constant, Local, Location, Operand, Rvalue, StatementKind, VarDebugInfoContents, Body, ConstOperand, Local, Location, Operand, Rvalue, StatementKind, VarDebugInfoContents,
}, },
ty::TyCtxt, ty::TyCtxt,
}; };
@ -45,7 +45,7 @@ struct LocalUseVisitor {
local_assignment_locations: IndexVec<Local, Option<Location>>, 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 { let mut visitor = LocalUseVisitor {
local_mutating_uses: IndexVec::from_elem(0, &body.local_decls), local_mutating_uses: IndexVec::from_elem(0, &body.local_decls),
local_assignment_locations: IndexVec::from_elem(None, &body.local_decls), local_assignment_locations: IndexVec::from_elem(None, &body.local_decls),

View File

@ -96,10 +96,10 @@ impl<'tcx> Visitor<'tcx> for ConstGotoOptimizationFinder<'_, 'tcx> {
let (discr, targets) = target_bb_terminator.kind.as_switch()?; let (discr, targets) = target_bb_terminator.kind.as_switch()?;
if discr.place() == Some(*place) { if discr.place() == Some(*place) {
let switch_ty = place.ty(self.body.local_decls(), self.tcx).ty; 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 // 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. // Now find which value in the Switch matches the const value.
let const_value = let const_value = _const.const_.try_eval_bits(self.tcx, self.param_env)?;
_const.literal.try_eval_bits(self.tcx, self.param_env, switch_ty)?;
let target_to_use_in_goto = targets.target_for_value(const_value); let target_to_use_in_goto = targets.target_for_value(const_value);
self.optimizations.push(OptimizationToApply { self.optimizations.push(OptimizationToApply {
bb_with_goto: location.block, bb_with_goto: location.block,

View File

@ -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 // 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 // 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). // 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 }; let Right(imm) = imm else { return None };
match *imm { match *imm {
Immediate::Scalar(scalar) if scalar.try_to_int().is_ok() => { 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() => { Immediate::ScalarPair(l, r) if l.try_to_int().is_ok() && r.try_to_int().is_ok() => {
let alloc_id = self let alloc_id = self
@ -551,7 +551,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
}) })
.ok()?; .ok()?;
Some(ConstantKind::Val( Some(Const::Val(
ConstValue::Indirect { alloc_id, offset: Size::ZERO }, ConstValue::Indirect { alloc_id, offset: Size::ZERO },
value.layout.ty, 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 let Some(()) = self.eval_rvalue_with_identities(rvalue, *place) {
// If this was already an evaluated constant, keep it. // If this was already an evaluated constant, keep it.
if let Rvalue::Use(Operand::Constant(c)) = rvalue 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); trace!("skipping replace of Rvalue::Use({:?} because it is already a const", c);
} else if let Some(operand) = self.replace_with_const(*place) { } else if let Some(operand) = self.replace_with_const(*place) {

View File

@ -281,7 +281,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
} }
/// Returns the value, if any, of evaluating `c`. /// 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 // FIXME we need to revisit this for #67176
if c.has_param() { if c.has_param() {
return None; return None;
@ -293,7 +293,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
// that the `RevealAll` pass has happened and that the body's consts // that the `RevealAll` pass has happened and that the body's consts
// are normalized, so any call to resolve before that needs to be // are normalized, so any call to resolve before that needs to be
// manually normalized. // 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)) 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); 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); trace!("visit_constant: {:?}", constant);
self.super_constant(constant, location); self.super_constant(constant, location);
self.eval_constant(constant, location); self.eval_constant(constant, location);

View File

@ -206,7 +206,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
&& let operand_ty = operand.ty(self.local_decls, self.tcx) && let operand_ty = operand.ty(self.local_decls, self.tcx)
&& let Some(operand_ty) = operand_ty.builtin_deref(true) && let Some(operand_ty) = operand_ty.builtin_deref(true)
&& let ty::Array(_, len) = operand_ty.ty.kind() && 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()); 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) => { Rvalue::Len(place) => {
let place_ty = place.ty(self.local_decls, self.tcx); let place_ty = place.ty(self.local_decls, self.tcx);
if let ty::Array(_, len) = place_ty.ty.kind() { if let ty::Array(_, len) = place_ty.ty.kind() {
ConstantKind::Ty(*len) Const::Ty(*len)
.try_eval_scalar(self.tcx, self.param_env) .try_eval_scalar(self.tcx, self.param_env)
.map_or(FlatSet::Top, FlatSet::Elem) .map_or(FlatSet::Top, FlatSet::Elem)
} else if let [ProjectionElem::Deref] = place.projection[..] { } else if let [ProjectionElem::Deref] = place.projection[..] {
@ -295,11 +295,11 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
fn handle_constant( fn handle_constant(
&self, &self,
constant: &Constant<'tcx>, constant: &ConstOperand<'tcx>,
_state: &mut State<Self::Value>, _state: &mut State<Self::Value>,
) -> Self::Value { ) -> Self::Value {
constant constant
.literal .const_
.try_eval_scalar(self.tcx, self.param_env) .try_eval_scalar(self.tcx, self.param_env)
.map_or(FlatSet::Top, FlatSet::Elem) .map_or(FlatSet::Top, FlatSet::Elem)
} }
@ -360,7 +360,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
} }
} }
Operand::Constant(box constant) => { 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, &[]); 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 /// 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 /// 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.) /// 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. /// 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> { impl<'tcx> Patch<'tcx> {
@ -529,8 +529,8 @@ impl<'tcx> Patch<'tcx> {
Self { tcx, before_effect: FxHashMap::default(), assignments: FxHashMap::default() } Self { tcx, before_effect: FxHashMap::default(), assignments: FxHashMap::default() }
} }
fn make_operand(&self, literal: ConstantKind<'tcx>) -> Operand<'tcx> { fn make_operand(&self, const_: Const<'tcx>) -> Operand<'tcx> {
Operand::Constant(Box::new(Constant { span: DUMMY_SP, user_ty: None, literal })) 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>, place: Place<'tcx>,
state: &State<FlatSet<Scalar>>, state: &State<FlatSet<Scalar>>,
map: &Map, map: &Map,
) -> Option<ConstantKind<'tcx>> { ) -> Option<Const<'tcx>> {
let FlatSet::Elem(Scalar::Int(value)) = state.get(place.as_ref(), &map) else { let FlatSet::Elem(Scalar::Int(value)) = state.get(place.as_ref(), &map) else {
return None; return None;
}; };
let ty = place.ty(self.local_decls, self.patch.tcx).ty; 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))
} }
} }

View File

@ -150,7 +150,7 @@ fn rvalue_hash<H: Hasher>(hasher: &mut H, rvalue: &Rvalue<'_>) {
fn operand_hash<H: Hasher>(hasher: &mut H, operand: &Operand<'_>) { fn operand_hash<H: Hasher>(hasher: &mut H, operand: &Operand<'_>) {
match 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), 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 { fn operand_eq<'tcx>(lhs: &Operand<'tcx>, rhs: &Operand<'tcx>) -> bool {
let res = match (lhs, rhs) { let res = match (lhs, rhs) {
( (
Operand::Constant(box Constant { user_ty: _, literal, span: _ }), Operand::Constant(box ConstOperand { user_ty: _, const_, span: _ }),
Operand::Constant(box Constant { user_ty: _, literal: literal2, span: _ }), Operand::Constant(box ConstOperand { user_ty: _, const_: const2, span: _ }),
) => literal == literal2, ) => const_ == const2,
(x, y) => x == y, (x, y) => x == y,
}; };
debug!("operand_eq lhs: `{:?}` rhs: `{:?}` result: {:?}", lhs, rhs, res); debug!("operand_eq lhs: `{:?}` rhs: `{:?}` result: {:?}", lhs, rhs, res);

View File

@ -402,10 +402,10 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
} }
fn constant_bool(&self, span: Span, val: bool) -> Rvalue<'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, span,
user_ty: None, user_ty: None,
literal: ConstantKind::from_bool(self.tcx, val), const_: Const::from_bool(self.tcx, val),
}))) })))
} }

View File

@ -1189,10 +1189,10 @@ fn insert_panic_block<'tcx>(
) -> BasicBlock { ) -> BasicBlock {
let assert_block = BasicBlock::new(body.basic_blocks.len()); let assert_block = BasicBlock::new(body.basic_blocks.len());
let term = TerminatorKind::Assert { let term = TerminatorKind::Assert {
cond: Operand::Constant(Box::new(Constant { cond: Operand::Constant(Box::new(ConstOperand {
span: body.span, span: body.span,
user_ty: None, user_ty: None,
literal: ConstantKind::from_bool(tcx, false), const_: Const::from_bool(tcx, false),
})), })),
expected: true, expected: true,
msg: Box::new(message), msg: Box::new(message),

View File

@ -652,11 +652,11 @@ impl<'tcx> Inliner<'tcx> {
// `required_consts`, here we may not only have `ConstKind::Unevaluated` // `required_consts`, here we may not only have `ConstKind::Unevaluated`
// because we are calling `subst_and_normalize_erasing_regions`. // because we are calling `subst_and_normalize_erasing_regions`.
caller_body.required_consts.extend( caller_body.required_consts.extend(
callee_body.required_consts.iter().copied().filter(|&ct| match ct.literal { callee_body.required_consts.iter().copied().filter(|&ct| match ct.const_ {
ConstantKind::Ty(_) => { Const::Ty(_) => {
bug!("should never encounter ty::UnevaluatedConst in `required_consts`") 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, .. } => { 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) { 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 // Don't give intrinsics the extra penalty for calls
INSTR_COST INSTR_COST

View File

@ -104,7 +104,7 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> {
fn try_eval_bool(&self, a: &Operand<'_>) -> Option<bool> { fn try_eval_bool(&self, a: &Operand<'_>) -> Option<bool> {
let a = a.constant()?; 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". /// Transform "&(*a)" ==> "a".
@ -136,8 +136,8 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> {
return; return;
} }
let literal = ConstantKind::from_ty_const(len, self.tcx); let const_ = Const::from_ty_const(len, self.tcx);
let constant = Constant { span: source_info.span, literal, user_ty: None }; let constant = ConstOperand { span: source_info.span, const_, user_ty: None };
*rvalue = Rvalue::Use(Operand::Constant(Box::new(constant))); *rvalue = Rvalue::Use(Operand::Constant(Box::new(constant)));
} }
} }

View File

@ -149,10 +149,10 @@ impl EnumSizeOpt {
}; };
let place = Place::from(size_array_local); let place = Place::from(size_array_local);
let constant_vals = Constant { let constant_vals = ConstOperand {
span, span,
user_ty: None, user_ty: None,
literal: ConstantKind::Val( const_: Const::Val(
ConstValue::Indirect { alloc_id, offset: Size::ZERO }, ConstValue::Indirect { alloc_id, offset: Size::ZERO },
tmp_ty, tmp_ty,
), ),

View File

@ -31,9 +31,9 @@ use rustc_hir::intravisit::{self, Visitor};
use rustc_index::IndexVec; use rustc_index::IndexVec;
use rustc_middle::mir::visit::Visitor as _; use rustc_middle::mir::visit::Visitor as _;
use rustc_middle::mir::{ use rustc_middle::mir::{
traversal, AnalysisPhase, Body, CallSource, ClearCrossCrate, ConstQualifs, Constant, LocalDecl, traversal, AnalysisPhase, Body, CallSource, ClearCrossCrate, ConstOperand, ConstQualifs,
MirPass, MirPhase, Operand, Place, ProjectionElem, Promoted, RuntimePhase, Rvalue, SourceInfo, LocalDecl, MirPass, MirPhase, Operand, Place, ProjectionElem, Promoted, RuntimePhase, Rvalue,
Statement, StatementKind, TerminatorKind, START_BLOCK, SourceInfo, Statement, StatementKind, TerminatorKind, START_BLOCK,
}; };
use rustc_middle::query::Providers; use rustc_middle::query::Providers;
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; 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"); let terminator = bb.terminator.as_mut().expect("invalid terminator");
match terminator.kind { match terminator.kind {
TerminatorKind::Call { TerminatorKind::Call {
func: Operand::Constant(box Constant { ref literal, .. }), func: Operand::Constant(box ConstOperand { ref const_, .. }),
ref mut args, ref mut args,
destination, destination,
target, target,
unwind, unwind,
fn_span, 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.item_name(def_id) == sym::const_eval_select
&& tcx.is_intrinsic(def_id) => && tcx.is_intrinsic(def_id) =>
{ {

View File

@ -32,10 +32,10 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
source_info: terminator.source_info, source_info: terminator.source_info,
kind: StatementKind::Assign(Box::new(( kind: StatementKind::Assign(Box::new((
*destination, *destination,
Rvalue::Use(Operand::Constant(Box::new(Constant { Rvalue::Use(Operand::Constant(Box::new(ConstOperand {
span: terminator.source_info.span, span: terminator.source_info.span,
user_ty: None, user_ty: None,
literal: ConstantKind::zero_sized(tcx.types.unit), const_: Const::zero_sized(tcx.types.unit),
}))), }))),
))), ))),
}); });

View File

@ -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_f, Rvalue::Use(Operand::Constant(f_c)))),
StatementKind::Assign(box (lhs_s, Rvalue::Use(Operand::Constant(s_c)))), StatementKind::Assign(box (lhs_s, Rvalue::Use(Operand::Constant(s_c)))),
) if lhs_f == lhs_s ) if lhs_f == lhs_s
&& f_c.literal.ty().is_bool() && f_c.const_.ty().is_bool()
&& s_c.literal.ty().is_bool() && s_c.const_.ty().is_bool()
&& f_c.literal.try_eval_bool(tcx, param_env).is_some() && f_c.const_.try_eval_bool(tcx, param_env).is_some()
&& s_c.literal.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. // Otherwise we cannot optimize. Try another block.
_ => continue 'outer, _ => continue 'outer,
@ -128,8 +128,8 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification {
StatementKind::Assign(box (_, Rvalue::Use(Operand::Constant(s_c)))), StatementKind::Assign(box (_, Rvalue::Use(Operand::Constant(s_c)))),
) => { ) => {
// From earlier loop we know that we are dealing with bool constants only: // 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 f_b = f_c.const_.try_eval_bool(tcx, param_env).unwrap();
let s_b = s_c.literal.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 { if f_b == s_b {
// Same value in both blocks. Use statement as is. // Same value in both blocks. Use statement as is.
(*f).clone() (*f).clone()

View File

@ -90,10 +90,10 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> {
&& let [PlaceElem::Deref] = &place.projection[..] && let [PlaceElem::Deref] = &place.projection[..]
&& let Some(len) = self.slice_lengths[place.local] && 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, span: rustc_span::DUMMY_SP,
user_ty: None, user_ty: None,
literal: ConstantKind::from_ty_const(len, self.tcx), const_: Const::from_ty_const(len, self.tcx),
}))); })));
} }
self.super_rvalue(rvalue, loc); self.super_rvalue(rvalue, loc);

View File

@ -62,12 +62,12 @@ impl<'tcx> Replacer<'_, 'tcx> {
layout.is_zst() 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)); debug_assert!(self.known_to_be_zst(ty));
Constant { ConstOperand {
span: rustc_span::DUMMY_SP, span: rustc_span::DUMMY_SP,
user_ty: None, user_ty: None,
literal: ConstantKind::Val(ConstValue::ZeroSized, ty), const_: Const::Val(ConstValue::ZeroSized, ty),
} }
} }
} }

View File

@ -1,27 +1,27 @@
use rustc_middle::mir::visit::Visitor; 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; use rustc_middle::ty::ConstKind;
pub struct RequiredConstsVisitor<'a, 'tcx> { 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> { 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 } RequiredConstsVisitor { required_consts }
} }
} }
impl<'tcx> Visitor<'tcx> for RequiredConstsVisitor<'_, 'tcx> { impl<'tcx> Visitor<'tcx> for RequiredConstsVisitor<'_, 'tcx> {
fn visit_constant(&mut self, constant: &Constant<'tcx>, _: Location) { fn visit_constant(&mut self, constant: &ConstOperand<'tcx>, _: Location) {
let literal = constant.literal; let const_ = constant.const_;
match literal { match const_ {
ConstantKind::Ty(c) => match c.kind() { Const::Ty(c) => match c.kind() {
ConstKind::Param(_) | ConstKind::Error(_) | ConstKind::Value(_) => {} ConstKind::Param(_) | ConstKind::Error(_) | ConstKind::Value(_) => {}
_ => bug!("only ConstKind::Param/Value should be encountered here, got {:#?}", c), _ => bug!("only ConstKind::Param/Value should be encountered here, got {:#?}", c),
}, },
ConstantKind::Unevaluated(..) => self.required_consts.push(*constant), Const::Unevaluated(..) => self.required_consts.push(*constant),
ConstantKind::Val(..) => {} Const::Val(..) => {}
} }
} }
} }

View File

@ -35,12 +35,12 @@ impl<'tcx> MutVisitor<'tcx> for RevealAllVisitor<'tcx> {
} }
#[inline] #[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 // We have to use `try_normalize_erasing_regions` here, since it's
// possible that we visit impossible-to-satisfy where clauses here, // possible that we visit impossible-to-satisfy where clauses here,
// see #91745 // see #91745
if let Ok(c) = self.tcx.try_normalize_erasing_regions(self.param_env, constant.literal) { if let Ok(c) = self.tcx.try_normalize_erasing_regions(self.param_env, constant.const_) {
constant.literal = c; constant.const_ = c;
} }
} }

View File

@ -497,10 +497,10 @@ impl<'tcx> CloneShimBuilder<'tcx> {
// `func == Clone::clone(&ty) -> ty` // `func == Clone::clone(&ty) -> ty`
let func_ty = Ty::new_fn_def(tcx, self.def_id, [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, span: self.span,
user_ty: None, user_ty: None,
literal: ConstantKind::zero_sized(func_ty), const_: Const::zero_sized(func_ty),
})); }));
let ref_loc = self.make_place( let ref_loc = self.make_place(
@ -764,10 +764,10 @@ fn build_call_shim<'tcx>(
CallKind::Direct(def_id) => { CallKind::Direct(def_id) => {
let ty = tcx.type_of(def_id).instantiate_identity(); let ty = tcx.type_of(def_id).instantiate_identity();
( (
Operand::Constant(Box::new(Constant { Operand::Constant(Box::new(ConstOperand {
span, span,
user_ty: None, user_ty: None,
literal: ConstantKind::zero_sized(ty), const_: Const::zero_sized(ty),
})), })),
rcvr.into_iter().collect::<Vec<_>>(), rcvr.into_iter().collect::<Vec<_>>(),
) )

View File

@ -23,7 +23,7 @@ impl<'tcx> MirPass<'tcx> for SimplifyConstCondition {
TerminatorKind::SwitchInt { TerminatorKind::SwitchInt {
discr: Operand::Constant(ref c), ref targets, .. 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 { if let Some(constant) = constant {
let target = targets.target_for_value(constant); let target = targets.target_for_value(constant);
TerminatorKind::Goto { target } TerminatorKind::Goto { target }
@ -33,7 +33,7 @@ impl<'tcx> MirPass<'tcx> for SimplifyConstCondition {
} }
TerminatorKind::Assert { TerminatorKind::Assert {
target, cond: Operand::Constant(ref c), expected, .. 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 }, Some(v) if v == expected => TerminatorKind::Goto { target },
_ => continue, _ => continue,
}, },

View File

@ -206,12 +206,12 @@ fn find_branch_value_info<'tcx>(
match (left, right) { match (left, right) {
(Constant(branch_value), Copy(to_switch_on) | Move(to_switch_on)) (Constant(branch_value), Copy(to_switch_on) | Move(to_switch_on))
| (Copy(to_switch_on) | Move(to_switch_on), Constant(branch_value)) => { | (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 // 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() { if !branch_value_ty.is_integral() && !branch_value_ty.is_char() {
return None; 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)) Some((branch_value_scalar, branch_value_ty, *to_switch_on))
} }
_ => None, _ => None,

View File

@ -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 /// to walk it would attempt to evaluate the `ty::Const` inside, which doesn't necessarily
/// work, as some constants cannot be represented in the type system. /// work, as some constants cannot be represented in the type system.
#[instrument(skip(self), level = "debug")] #[instrument(skip(self), level = "debug")]
fn visit_constant(&mut self, constant: &mir::Constant<'tcx>, location: Location) { fn visit_constant(&mut self, constant: &mir::ConstOperand<'tcx>, location: Location) {
let literal = self.monomorphize(constant.literal); let const_ = self.monomorphize(constant.const_);
let param_env = ty::ParamEnv::reveal_all(); 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, Ok(v) => v,
Err(ErrorHandled::Reported(..)) => return, Err(ErrorHandled::Reported(..)) => return,
Err(ErrorHandled::TooGeneric(..)) => span_bug!( Err(ErrorHandled::TooGeneric(..)) => span_bug!(
self.body.source_info(location).span, self.body.source_info(location).span,
"collection encountered polymorphic constant: {:?}", "collection encountered polymorphic constant: {:?}",
literal const_
), ),
}; };
collect_const_value(self.tcx, val, self.output); 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) { 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 { for op in operands {
match *op { match *op {
mir::InlineAsmOperand::SymFn { ref value } => { 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, &[]); visit_fn_use(self.tcx, fn_ty, false, source, &mut self.output, &[]);
} }
mir::InlineAsmOperand::SymStatic { def_id } => { mir::InlineAsmOperand::SymStatic { def_id } => {

View File

@ -9,13 +9,13 @@ use rustc_hir::{def::DefKind, def_id::DefId, ConstContext};
use rustc_middle::mir::{ use rustc_middle::mir::{
self, self,
visit::{TyContext, Visitor}, visit::{TyContext, Visitor},
Constant, ConstantKind, Local, LocalDecl, Location, Local, LocalDecl, Location,
}; };
use rustc_middle::query::Providers; use rustc_middle::query::Providers;
use rustc_middle::ty::{ use rustc_middle::ty::{
self, self,
visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}, visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor},
Const, GenericArgsRef, Ty, TyCtxt, UnusedGenericParams, GenericArgsRef, Ty, TyCtxt, UnusedGenericParams,
}; };
use rustc_span::symbol::sym; use rustc_span::symbol::sym;
use std::ops::ControlFlow; use std::ops::ControlFlow;
@ -261,12 +261,12 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
self.super_local_decl(local, local_decl); self.super_local_decl(local, local_decl);
} }
fn visit_constant(&mut self, ct: &Constant<'tcx>, location: Location) { fn visit_constant(&mut self, ct: &mir::ConstOperand<'tcx>, location: Location) {
match ct.literal { match ct.const_ {
ConstantKind::Ty(c) => { mir::Const::Ty(c) => {
c.visit_with(self); 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: // Avoid considering `T` unused when constants are of the form:
// `<Self as Foo<T>>::foo::promoted[p]` // `<Self as Foo<T>>::foo::promoted[p]`
if let Some(p) = promoted { 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)); 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> { impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for MarkUsedGenericParams<'a, 'tcx> {
#[instrument(level = "debug", skip(self))] #[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() { if !c.has_non_region_param() {
return ControlFlow::Continue(()); return ControlFlow::Continue(());
} }

View File

@ -14,8 +14,8 @@ use crate::stable_mir::ty::{
}; };
use crate::stable_mir::{self, CompilerError, Context}; use crate::stable_mir::{self, CompilerError, Context};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_middle::mir;
use rustc_middle::mir::interpret::{alloc_range, AllocId}; use rustc_middle::mir::interpret::{alloc_range, AllocId};
use rustc_middle::mir::{self, ConstantKind};
use rustc_middle::ty::{self, Ty, TyCtxt, Variance}; use rustc_middle::ty::{self, Ty, TyCtxt, Variance};
use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE};
use rustc_span::ErrorGuaranteed; 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; type T = stable_mir::mir::Constant;
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
stable_mir::mir::Constant { stable_mir::mir::Constant {
span: self.span.stable(tables), span: self.span.stable(tables),
user_ty: self.user_ty.map(|u| u.as_usize()).or(None), 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; type T = stable_mir::ty::Const;
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
match *self { match *self {
ConstantKind::Ty(c) => c.stable(tables), mir::Const::Ty(c) => c.stable(tables),
ConstantKind::Unevaluated(unev_const, ty) => stable_mir::ty::Const { mir::Const::Unevaluated(unev_const, ty) => stable_mir::ty::Const {
literal: stable_mir::ty::ConstantKind::Unevaluated( literal: stable_mir::ty::ConstantKind::Unevaluated(
stable_mir::ty::UnevaluatedConst { stable_mir::ty::UnevaluatedConst {
def: tables.const_def(unev_const.def), 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), 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( literal: stable_mir::ty::ConstantKind::Allocated(alloc::new_allocation(
ty, val, tables, ty, val, tables,
)), )),

View File

@ -118,7 +118,7 @@ fn encode_const<'tcx>(
// bool value false is encoded as 0 and true as 1. // bool value false is encoded as 0 and true as 1.
match c.ty().kind() { match c.ty().kind() {
ty::Int(ity) => { 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; let val = Integer::from_int_ty(&tcx, *ity).size().sign_extend(bits) as i128;
if val < 0 { if val < 0 {
s.push('n'); s.push('n');
@ -126,7 +126,7 @@ fn encode_const<'tcx>(
let _ = write!(s, "{val}"); let _ = write!(s, "{val}");
} }
ty::Uint(_) => { ty::Uint(_) => {
let val = c.eval_bits(tcx, ty::ParamEnv::reveal_all(), c.ty()); let val = c.eval_bits(tcx, ty::ParamEnv::reveal_all());
let _ = write!(s, "{val}"); let _ = write!(s, "{val}");
} }
ty::Bool => { ty::Bool => {

View File

@ -594,7 +594,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Char => { ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Char => {
self = ty.print(self)?; 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". // Negative integer values are mangled using `n` as a "sign prefix".
if let ty::Int(ity) = ty.kind() { if let ty::Int(ity) = ty.kind() {

View File

@ -283,7 +283,7 @@ pub(crate) fn print_evaluated_const(
(_, &ty::Ref(..)) => None, (_, &ty::Ref(..)) => None,
(mir::ConstValue::Scalar(_), &ty::Adt(_, _)) => None, (mir::ConstValue::Scalar(_), &ty::Adt(_, _)) => None,
(mir::ConstValue::Scalar(_), _) => { (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)) Some(print_const_with_custom_print_scalar(tcx, const_, underscores_and_type))
} }
_ => None, _ => None,
@ -319,20 +319,20 @@ fn format_integer_with_underscore_sep(num: &str) -> String {
fn print_const_with_custom_print_scalar<'tcx>( fn print_const_with_custom_print_scalar<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
ct: mir::ConstantKind<'tcx>, ct: mir::Const<'tcx>,
underscores_and_type: bool, underscores_and_type: bool,
) -> String { ) -> String {
// Use a slightly different format for integer types which always shows the actual value. // Use a slightly different format for integer types which always shows the actual value.
// For all other types, fallback to the original `pretty_print_const`. // For all other types, fallback to the original `pretty_print_const`.
match (ct, ct.ty().kind()) { 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 { if underscores_and_type {
format!("{}{}", format_integer_with_underscore_sep(&int.to_string()), ui.name_str()) format!("{}{}", format_integer_with_underscore_sep(&int.to_string()), ui.name_str())
} else { } else {
int.to_string() 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 ty = ct.ty();
let size = tcx.layout_of(ty::ParamEnv::empty().and(ty)).unwrap().size; let size = tcx.layout_of(ty::ParamEnv::empty().and(ty)).unwrap().size;
let data = int.assert_bits(size); let data = int.assert_bits(size);

View File

@ -50,7 +50,7 @@ impl<'tcx> LateLintPass<'tcx> for UnportableVariant {
.tcx .tcx
.const_eval_poly(def_id.to_def_id()) .const_eval_poly(def_id.to_def_id())
.ok() .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 Some(Constant::Int(val)) = constant.and_then(|c| miri_to_const(cx, c)) {
if let ty::Adt(adt, _) = ty.kind() { if let ty::Adt(adt, _) = ty.kind() {
if adt.is_enum() { if adt.is_enum() {

View File

@ -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)?, Some(lhs) => constant(cx, cx.typeck_results(), lhs)?,
None => { None => {
let min_val_const = ty.numeric_min_val(cx.tcx)?; 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 { let rhs_const = match rhs {
Some(rhs) => constant(cx, cx.typeck_results(), rhs)?, Some(rhs) => constant(cx, cx.typeck_results(), rhs)?,
None => { None => {
let max_val_const = ty.numeric_max_val(cx.tcx)?; 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)?; let lhs_val = lhs_const.int_value(cx, ty)?;

View File

@ -21,7 +21,7 @@ use std::iter;
/// A `LitKind`-like enum to fold constant `Expr`s into. /// A `LitKind`-like enum to fold constant `Expr`s into.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum Constant<'tcx> { pub enum Constant<'tcx> {
Adt(rustc_middle::mir::ConstantKind<'tcx>), Adt(rustc_middle::mir::Const<'tcx>),
/// A `String` (e.g., "abc"). /// A `String` (e.g., "abc").
Str(String), Str(String),
/// A binary string (e.g., `b"abc"`). /// A binary string (e.g., `b"abc"`).
@ -482,7 +482,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
.tcx .tcx
.const_eval_resolve(self.param_env, mir::UnevaluatedConst::new(def_id, args), None) .const_eval_resolve(self.param_env, mir::UnevaluatedConst::new(def_id, args), None)
.ok() .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)?; let result = miri_to_const(self.lcx, result)?;
self.source = ConstantSource::Constant; self.source = ConstantSource::Constant;
Some(result) 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; use rustc_middle::mir::ConstValue;
match result { 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::Adt(adt_def, _) if adt_def.is_struct() => Some(Constant::Adt(result)),
ty::Bool => Some(Constant::Bool(int == ScalarInt::TRUE)), ty::Bool => Some(Constant::Bool(int == ScalarInt::TRUE)),
ty::Uint(_) | ty::Int(_) => Some(Constant::Int(int.assert_bits(int.size()))), 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()))), ty::RawPtr(_) => Some(Constant::RawPtr(int.assert_bits(int.size()))),
_ => None, _ => 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)?; let data = cv.try_get_slice_bytes_for_diagnostics(lcx.tcx)?;
String::from_utf8(data.to_owned()).ok().map(Constant::Str) 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(); let alloc = lcx.tcx.global_alloc(alloc_id).unwrap_memory();
match result.ty().kind() { match result.ty().kind() {
ty::Adt(adt_def, _) if adt_def.is_struct() => Some(Constant::Adt(result)), 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>( fn field_of_struct<'tcx>(
adt_def: ty::AdtDef<'tcx>, adt_def: ty::AdtDef<'tcx>,
lcx: &LateContext<'tcx>, lcx: &LateContext<'tcx>,
result: mir::ConstantKind<'tcx>, result: mir::Const<'tcx>,
field: &Ident, field: &Ident,
) -> Option<mir::ConstantKind<'tcx>> { ) -> Option<mir::Const<'tcx>> {
if let mir::ConstantKind::Val(result, ty) = result if let mir::Const::Val(result, ty) = result
&& let Some(dc) = lcx.tcx.try_destructure_mir_constant_for_diagnostics((result, ty)) && let Some(dc) = lcx.tcx.try_destructure_mir_constant_for_diagnostics((result, ty))
&& let Some(dc_variant) = dc.variant && let Some(dc_variant) = dc.variant
&& let Some(variant) = adt_def.variants().get(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(field_idx) = variant.fields.iter().position(|el| el.name == field.name)
&& let Some(&(val, ty)) = dc.fields.get(field_idx) && let Some(&(val, ty)) = dc.fields.get(field_idx)
{ {
Some(mir::ConstantKind::Val(val, ty)) Some(mir::Const::Val(val, ty))
} }
else { else {
None None

View File

@ -97,7 +97,7 @@ use rustc_hir::{
use rustc_lexer::{tokenize, TokenKind}; use rustc_lexer::{tokenize, TokenKind};
use rustc_lint::{LateContext, Level, Lint, LintContext}; use rustc_lint::{LateContext, Level, Lint, LintContext};
use rustc_middle::hir::place::PlaceBase; 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::adjustment::{Adjust, Adjustment, AutoBorrow};
use rustc_middle::ty::binding::BindingMode; use rustc_middle::ty::binding::BindingMode;
use rustc_middle::ty::fast_reject::SimplifiedType; 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 bnd_ty = subst.type_at(0)
&& let Some(min_val) = bnd_ty.numeric_min_val(cx.tcx) && 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 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(min_const) = miri_to_const(cx, min_const_kind)
&& let Some(start_const) = constant(cx, cx.typeck_results(), start) && 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 bnd_ty = subst.type_at(0)
&& let Some(max_val) = bnd_ty.numeric_max_val(cx.tcx) && 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 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(max_const) = miri_to_const(cx, max_const_kind)
&& let Some(end_const) = constant(cx, cx.typeck_results(), end) && let Some(end_const) = constant(cx, cx.typeck_results(), end)
{ {

View File

@ -9,9 +9,9 @@ fn outer(_1: u8) -> u8 {
StorageLive(_2); // scope 0 at $DIR/spans.rs:10:11: 10:13 StorageLive(_2); // scope 0 at $DIR/spans.rs:10:11: 10:13
_2 = &_1; // 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 _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 // + 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: { bb1: {

View File

@ -9,9 +9,9 @@ fn outer(_1: u8) -> u8 {
StorageLive(_2); // scope 0 at $DIR/spans.rs:10:11: 10:13 StorageLive(_2); // scope 0 at $DIR/spans.rs:10:11: 10:13
_2 = &_1; // 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 _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 // + 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: { bb1: {