mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
Add Ty
to mir::Const::Ty
This commit is contained in:
parent
8d6705cdb8
commit
60a5bebbe5
@ -346,7 +346,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
|
|||||||
} else {
|
} else {
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
let maybe_uneval = match constant.const_ {
|
let maybe_uneval = match constant.const_ {
|
||||||
Const::Ty(ct) => match ct.kind() {
|
Const::Ty(_, ct) => match ct.kind() {
|
||||||
ty::ConstKind::Unevaluated(_) => {
|
ty::ConstKind::Unevaluated(_) => {
|
||||||
bug!("should not encounter unevaluated Const::Ty here, got {:?}", ct)
|
bug!("should not encounter unevaluated Const::Ty here, got {:?}", ct)
|
||||||
}
|
}
|
||||||
@ -1856,7 +1856,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||||||
|
|
||||||
if let Operand::Constant(constant) = op {
|
if let Operand::Constant(constant) = op {
|
||||||
let maybe_uneval = match constant.const_ {
|
let maybe_uneval = match constant.const_ {
|
||||||
Const::Val(..) | Const::Ty(_) => None,
|
Const::Val(..) | Const::Ty(_, _) => None,
|
||||||
Const::Unevaluated(uv, _) => Some(uv),
|
Const::Unevaluated(uv, _) => Some(uv),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
) -> Result<Option<ty::ValTree<'tcx>>, ErrorHandled> {
|
) -> Result<Option<ty::ValTree<'tcx>>, ErrorHandled> {
|
||||||
let uv = match self.monomorphize(constant.const_) {
|
let uv = match self.monomorphize(constant.const_) {
|
||||||
mir::Const::Unevaluated(uv, _) => uv.shrink(),
|
mir::Const::Unevaluated(uv, _) => uv.shrink(),
|
||||||
mir::Const::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)),
|
||||||
|
@ -357,7 +357,7 @@ where
|
|||||||
|
|
||||||
// Check the qualifs of the value of `const` items.
|
// Check the qualifs of the value of `const` items.
|
||||||
let uneval = match constant.const_ {
|
let uneval = match constant.const_ {
|
||||||
Const::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(_, _)
|
||||||
@ -365,7 +365,7 @@ where
|
|||||||
{
|
{
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
Const::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)
|
||||||
}
|
}
|
||||||
Const::Unevaluated(uv, _) => Some(uv),
|
Const::Unevaluated(uv, _) => Some(uv),
|
||||||
|
@ -204,7 +204,9 @@ pub enum Const<'tcx> {
|
|||||||
/// 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`;
|
||||||
/// this ensures that we consistently produce "clean" values without data in the padding or
|
/// this ensures that we consistently produce "clean" values without data in the padding or
|
||||||
/// anything like that.
|
/// anything like that.
|
||||||
Ty(ty::Const<'tcx>),
|
///
|
||||||
|
/// FIXME(BoxyUwU): We should remove this `Ty` and look up the type for params via `ParamEnv`
|
||||||
|
Ty(Ty<'tcx>, ty::Const<'tcx>),
|
||||||
|
|
||||||
/// An unevaluated mir constant which is not part of the type system.
|
/// An unevaluated mir constant which is not part of the type system.
|
||||||
///
|
///
|
||||||
@ -237,8 +239,15 @@ impl<'tcx> Const<'tcx> {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn ty(&self) -> Ty<'tcx> {
|
pub fn ty(&self) -> Ty<'tcx> {
|
||||||
match self {
|
match self {
|
||||||
// THISPR
|
Const::Ty(ty, ct) => {
|
||||||
Const::Ty(c) => todo!(),
|
match ct.kind() {
|
||||||
|
// Dont use the outter ty as on invalid code we can wind up with them not being the same.
|
||||||
|
// this then results in allowing const eval to add `1_i64 + 1_usize` in cases where the mir
|
||||||
|
// was originally `({N: usize} + 1_usize)` under `generic_const_exprs`.
|
||||||
|
ty::ConstKind::Value(ty, _) => ty,
|
||||||
|
_ => *ty,
|
||||||
|
}
|
||||||
|
}
|
||||||
Const::Val(_, ty) | Const::Unevaluated(_, ty) => *ty,
|
Const::Val(_, ty) | Const::Unevaluated(_, ty) => *ty,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -248,7 +257,7 @@ impl<'tcx> Const<'tcx> {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_required_const(&self) -> bool {
|
pub fn is_required_const(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Const::Ty(c) => match c.kind() {
|
Const::Ty(_, c) => match c.kind() {
|
||||||
ty::ConstKind::Value(_, _) => false, // already a value, cannot error
|
ty::ConstKind::Value(_, _) => false, // already a value, cannot error
|
||||||
_ => true,
|
_ => true,
|
||||||
},
|
},
|
||||||
@ -260,7 +269,7 @@ impl<'tcx> Const<'tcx> {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn try_to_scalar(self) -> Option<Scalar> {
|
pub fn try_to_scalar(self) -> Option<Scalar> {
|
||||||
match self {
|
match self {
|
||||||
Const::Ty(c) => match c.kind() {
|
Const::Ty(_, c) => match c.kind() {
|
||||||
ty::ConstKind::Value(ty, valtree) if ty.is_primitive() => {
|
ty::ConstKind::Value(ty, valtree) if ty.is_primitive() => {
|
||||||
// A valtree of a type where leaves directly represent the scalar const value.
|
// A valtree of a type where leaves directly represent the scalar const value.
|
||||||
// Just checking whether it is a leaf is insufficient as e.g. references are leafs
|
// Just checking whether it is a leaf is insufficient as e.g. references are leafs
|
||||||
@ -279,7 +288,7 @@ impl<'tcx> Const<'tcx> {
|
|||||||
// This is equivalent to `self.try_to_scalar()?.try_to_int().ok()`, but measurably faster.
|
// This is equivalent to `self.try_to_scalar()?.try_to_int().ok()`, but measurably faster.
|
||||||
match self {
|
match self {
|
||||||
Const::Val(ConstValue::Scalar(Scalar::Int(x)), _) => Some(x),
|
Const::Val(ConstValue::Scalar(Scalar::Int(x)), _) => Some(x),
|
||||||
Const::Ty(c) => match c.kind() {
|
Const::Ty(_, c) => match c.kind() {
|
||||||
ty::ConstKind::Value(ty, valtree) if ty.is_primitive() => {
|
ty::ConstKind::Value(ty, valtree) if ty.is_primitive() => {
|
||||||
Some(valtree.unwrap_leaf())
|
Some(valtree.unwrap_leaf())
|
||||||
}
|
}
|
||||||
@ -307,7 +316,7 @@ impl<'tcx> Const<'tcx> {
|
|||||||
span: Span,
|
span: Span,
|
||||||
) -> Result<ConstValue<'tcx>, ErrorHandled> {
|
) -> Result<ConstValue<'tcx>, ErrorHandled> {
|
||||||
match self {
|
match self {
|
||||||
Const::Ty(c) => {
|
Const::Ty(_, c) => {
|
||||||
// We want to consistently have a "clean" value for type system constants (i.e., no
|
// We want to consistently have a "clean" value for type system constants (i.e., no
|
||||||
// data hidden in the padding), so we always go through a valtree here.
|
// data hidden in the padding), so we always go through a valtree here.
|
||||||
let (ty, val) = c.eval(tcx, param_env, span)?;
|
let (ty, val) = c.eval(tcx, param_env, span)?;
|
||||||
@ -327,7 +336,7 @@ impl<'tcx> Const<'tcx> {
|
|||||||
match self.eval(tcx, param_env, DUMMY_SP) {
|
match self.eval(tcx, param_env, DUMMY_SP) {
|
||||||
Ok(val) => Self::Val(val, self.ty()),
|
Ok(val) => Self::Val(val, self.ty()),
|
||||||
Err(ErrorHandled::Reported(guar, _span)) => {
|
Err(ErrorHandled::Reported(guar, _span)) => {
|
||||||
Self::Ty(ty::Const::new_error(tcx, guar.into()))
|
Self::Ty(Ty::new_error(tcx, guar.into()), ty::Const::new_error(tcx, guar.into()))
|
||||||
}
|
}
|
||||||
Err(ErrorHandled::TooGeneric(_span)) => self,
|
Err(ErrorHandled::TooGeneric(_span)) => self,
|
||||||
}
|
}
|
||||||
@ -339,7 +348,7 @@ impl<'tcx> Const<'tcx> {
|
|||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
) -> Option<Scalar> {
|
) -> Option<Scalar> {
|
||||||
if let Const::Ty(c) = self
|
if let Const::Ty(_, c) = self
|
||||||
&& let ty::ConstKind::Value(ty, val) = c.kind()
|
&& let ty::ConstKind::Value(ty, val) = c.kind()
|
||||||
&& ty.is_primitive()
|
&& ty.is_primitive()
|
||||||
{
|
{
|
||||||
@ -441,14 +450,14 @@ impl<'tcx> Const<'tcx> {
|
|||||||
Self::Val(val, ty)
|
Self::Val(val, ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_ty_const(c: ty::Const<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
|
pub fn from_ty_const(c: ty::Const<'tcx>, ty: Ty<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
|
||||||
match c.kind() {
|
match c.kind() {
|
||||||
ty::ConstKind::Value(ty, valtree) => {
|
ty::ConstKind::Value(ty, valtree) => {
|
||||||
// Make sure that if `c` is normalized, then the return value is normalized.
|
// Make sure that if `c` is normalized, then the return value is normalized.
|
||||||
let const_val = tcx.valtree_to_const_val((ty, valtree));
|
let const_val = tcx.valtree_to_const_val((ty, valtree));
|
||||||
Self::Val(const_val, ty)
|
Self::Val(const_val, ty)
|
||||||
}
|
}
|
||||||
_ => Self::Ty(c),
|
_ => Self::Ty(ty, c),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -460,7 +469,7 @@ impl<'tcx> Const<'tcx> {
|
|||||||
// - valtrees purposefully generate new allocations
|
// - valtrees purposefully generate new allocations
|
||||||
// - ConstValue::Slice also generate new allocations
|
// - ConstValue::Slice also generate new allocations
|
||||||
match self {
|
match self {
|
||||||
Const::Ty(c) => match c.kind() {
|
Const::Ty(_, c) => match c.kind() {
|
||||||
ty::ConstKind::Param(..) => true,
|
ty::ConstKind::Param(..) => true,
|
||||||
// A valtree may be a reference. Valtree references correspond to a
|
// A valtree may be a reference. Valtree references correspond to a
|
||||||
// different allocation each time they are evaluated. Valtrees for primitive
|
// different allocation each time they are evaluated. Valtrees for primitive
|
||||||
@ -519,7 +528,7 @@ impl<'tcx> UnevaluatedConst<'tcx> {
|
|||||||
impl<'tcx> Display for Const<'tcx> {
|
impl<'tcx> Display for Const<'tcx> {
|
||||||
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
|
||||||
match *self {
|
match *self {
|
||||||
Const::Ty(c) => pretty_print_const(c, fmt, true),
|
Const::Ty(_, c) => pretty_print_const(c, fmt, true),
|
||||||
Const::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.
|
||||||
Const::Unevaluated(c, _ty) => {
|
Const::Unevaluated(c, _ty) => {
|
||||||
|
@ -1313,7 +1313,7 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let val = match const_ {
|
let val = match const_ {
|
||||||
Const::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,)
|
||||||
@ -1417,7 +1417,7 @@ pub fn write_allocations<'tcx>(
|
|||||||
impl<'tcx> Visitor<'tcx> for CollectAllocIds {
|
impl<'tcx> Visitor<'tcx> for CollectAllocIds {
|
||||||
fn visit_constant(&mut self, c: &ConstOperand<'tcx>, _: Location) {
|
fn visit_constant(&mut self, c: &ConstOperand<'tcx>, _: Location) {
|
||||||
match c.const_ {
|
match c.const_ {
|
||||||
Const::Ty(_) | Const::Unevaluated(..) => {}
|
Const::Ty(_, _) | Const::Unevaluated(..) => {}
|
||||||
Const::Val(val, _) => {
|
Const::Val(val, _) => {
|
||||||
self.0.extend(alloc_ids_from_const_val(val));
|
self.0.extend(alloc_ids_from_const_val(val));
|
||||||
}
|
}
|
||||||
|
@ -895,7 +895,7 @@ macro_rules! make_mir_visitor {
|
|||||||
|
|
||||||
self.visit_span($(& $mutability)? *span);
|
self.visit_span($(& $mutability)? *span);
|
||||||
match const_ {
|
match const_ {
|
||||||
Const::Ty(ct) => self.visit_ty_const($(&$mutability)? *ct, location),
|
Const::Ty(_, ct) => self.visit_ty_const($(&$mutability)? *ct, location),
|
||||||
Const::Val(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)),
|
Const::Val(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)),
|
||||||
Const::Unevaluated(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)),
|
Const::Unevaluated(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)),
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ use rustc_middle::mir::interpret::{Allocation, LitToConstError, LitToConstInput,
|
|||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
use rustc_middle::thir::*;
|
use rustc_middle::thir::*;
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self, CanonicalUserType, CanonicalUserTypeAnnotation, TyCtxt, UserTypeAnnotationIndex,
|
self, CanonicalUserType, CanonicalUserTypeAnnotation, Ty, TyCtxt, UserTypeAnnotationIndex,
|
||||||
};
|
};
|
||||||
use rustc_middle::{bug, span_bug};
|
use rustc_middle::{bug, span_bug};
|
||||||
use rustc_target::abi::Size;
|
use rustc_target::abi::Size;
|
||||||
@ -50,7 +50,9 @@ pub(crate) fn as_constant_inner<'tcx>(
|
|||||||
let const_ = match lit_to_mir_constant(tcx, LitToConstInput { lit: &lit.node, ty, neg })
|
let const_ = match lit_to_mir_constant(tcx, LitToConstInput { lit: &lit.node, ty, neg })
|
||||||
{
|
{
|
||||||
Ok(c) => c,
|
Ok(c) => c,
|
||||||
Err(LitToConstError::Reported(guar)) => Const::Ty(ty::Const::new_error(tcx, guar)),
|
Err(LitToConstError::Reported(guar)) => {
|
||||||
|
Const::Ty(Ty::new_error(tcx, guar), ty::Const::new_error(tcx, guar))
|
||||||
|
}
|
||||||
Err(LitToConstError::TypeError) => {
|
Err(LitToConstError::TypeError) => {
|
||||||
bug!("encountered type error in `lit_to_mir_constant`")
|
bug!("encountered type error in `lit_to_mir_constant`")
|
||||||
}
|
}
|
||||||
@ -82,7 +84,7 @@ pub(crate) fn as_constant_inner<'tcx>(
|
|||||||
}
|
}
|
||||||
ExprKind::ConstParam { param, def_id: _ } => {
|
ExprKind::ConstParam { param, def_id: _ } => {
|
||||||
let const_param = ty::Const::new_param(tcx, param);
|
let const_param = ty::Const::new_param(tcx, param);
|
||||||
let const_ = Const::Ty(const_param);
|
let const_ = Const::Ty(expr.ty, const_param);
|
||||||
|
|
||||||
ConstOperand { user_ty: None, span, const_ }
|
ConstOperand { user_ty: None, span, const_ }
|
||||||
}
|
}
|
||||||
|
@ -101,9 +101,9 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||||||
// level of indirection can be eliminated
|
// level of indirection can be eliminated
|
||||||
|
|
||||||
let have_valtree =
|
let have_valtree =
|
||||||
matches!(cv, mir::Const::Ty(c) if matches!(c.kind(), ty::ConstKind::Value(_, _)));
|
matches!(cv, mir::Const::Ty(_, c) if matches!(c.kind(), ty::ConstKind::Value(_, _)));
|
||||||
let inlined_const_as_pat = match cv {
|
let inlined_const_as_pat = match cv {
|
||||||
mir::Const::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(_, _)
|
||||||
@ -336,9 +336,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 => {
|
ty::Str => PatKind::Constant {
|
||||||
PatKind::Constant { value: mir::Const::Ty(ty::Const::new_value(tcx, cv, ty)) }
|
value: mir::Const::Ty(ty, ty::Const::new_value(tcx, cv, ty)),
|
||||||
}
|
},
|
||||||
// All other references are converted into deref patterns and then recursively
|
// All other references are converted into deref patterns and then recursively
|
||||||
// convert the dereferenced constant to a pattern that is the sub-pattern of the
|
// convert the dereferenced constant to a pattern that is the sub-pattern of the
|
||||||
// deref pattern.
|
// deref pattern.
|
||||||
@ -382,13 +382,15 @@ impl<'tcx> ConstToPat<'tcx> {
|
|||||||
self.saw_const_match_error.set(Some(e));
|
self.saw_const_match_error.set(Some(e));
|
||||||
return Err(FallbackToOpaqueConst);
|
return Err(FallbackToOpaqueConst);
|
||||||
} else {
|
} else {
|
||||||
PatKind::Constant { value: mir::Const::Ty(ty::Const::new_value(tcx, cv, ty)) }
|
PatKind::Constant {
|
||||||
|
value: mir::Const::Ty(ty, ty::Const::new_value(tcx, cv, ty)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ty::Pat(..) | ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::RawPtr(..) => {
|
ty::Pat(..) | ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::RawPtr(..) => {
|
||||||
// The raw pointers we see here have been "vetted" by valtree construction to be
|
// The raw pointers we see here have been "vetted" by valtree construction to be
|
||||||
// just integers, so we simply allow them.
|
// just integers, so we simply allow them.
|
||||||
PatKind::Constant { value: mir::Const::Ty(ty::Const::new_value(tcx, cv, ty)) }
|
PatKind::Constant { value: mir::Const::Ty(ty, ty::Const::new_value(tcx, cv, ty)) }
|
||||||
}
|
}
|
||||||
ty::FnPtr(..) => {
|
ty::FnPtr(..) => {
|
||||||
unreachable!(
|
unreachable!(
|
||||||
|
@ -580,7 +580,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
|||||||
.tcx
|
.tcx
|
||||||
.const_eval_global_id_for_typeck(param_env_reveal_all, cid, span)
|
.const_eval_global_id_for_typeck(param_env_reveal_all, cid, span)
|
||||||
.map(|val| match val {
|
.map(|val| match val {
|
||||||
Some(valtree) => mir::Const::Ty(ty::Const::new_value(self.tcx, valtree, ty)),
|
Some(valtree) => mir::Const::Ty(ty, ty::Const::new_value(self.tcx, valtree, ty)),
|
||||||
None => mir::Const::Val(
|
None => mir::Const::Val(
|
||||||
self.tcx
|
self.tcx
|
||||||
.const_eval_global_id(param_env_reveal_all, cid, span)
|
.const_eval_global_id(param_env_reveal_all, cid, span)
|
||||||
@ -659,7 +659,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(Const::Ty(c), id, span).kind,
|
Ok(c) => return self.const_to_pat(Const::Ty(ty, c), id, span).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.
|
||||||
@ -681,8 +681,11 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
|||||||
// but something more principled, like a trait query checking whether this can be turned into a valtree.
|
// but something more principled, like a trait query checking whether this can be turned into a valtree.
|
||||||
if let Ok(Some(valtree)) = self.tcx.const_eval_resolve_for_typeck(self.param_env, ct, span)
|
if let Ok(Some(valtree)) = self.tcx.const_eval_resolve_for_typeck(self.param_env, ct, span)
|
||||||
{
|
{
|
||||||
let subpattern =
|
let subpattern = self.const_to_pat(
|
||||||
self.const_to_pat(Const::Ty(ty::Const::new_value(self.tcx, valtree, ty)), id, span);
|
Const::Ty(ty, ty::Const::new_value(self.tcx, valtree, ty)),
|
||||||
|
id,
|
||||||
|
span,
|
||||||
|
);
|
||||||
PatKind::InlineConstant { subpattern, def: def_id }
|
PatKind::InlineConstant { subpattern, def: def_id }
|
||||||
} else {
|
} else {
|
||||||
// If that fails, convert it to an opaque constant pattern.
|
// If that fails, convert it to an opaque constant pattern.
|
||||||
@ -720,10 +723,12 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
|||||||
_ => span_bug!(expr.span, "not a literal: {:?}", expr),
|
_ => span_bug!(expr.span, "not a literal: {:?}", expr),
|
||||||
};
|
};
|
||||||
|
|
||||||
let lit_input =
|
let ct_ty = self.typeck_results.expr_ty(expr);
|
||||||
LitToConstInput { lit: &lit.node, ty: self.typeck_results.expr_ty(expr), neg };
|
let lit_input = LitToConstInput { lit: &lit.node, ty: ct_ty, 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) => self.const_to_pat(Const::Ty(constant), expr.hir_id, lit.span).kind,
|
Ok(constant) => {
|
||||||
|
self.const_to_pat(Const::Ty(ct_ty, constant), expr.hir_id, lit.span).kind
|
||||||
|
}
|
||||||
Err(LitToConstError::Reported(e)) => PatKind::Error(e),
|
Err(LitToConstError::Reported(e)) => PatKind::Error(e),
|
||||||
Err(LitToConstError::TypeError) => bug!("lower_lit: had type error"),
|
Err(LitToConstError::TypeError) => bug!("lower_lit: had type error"),
|
||||||
}
|
}
|
||||||
|
@ -203,7 +203,8 @@ 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.kind()
|
&& let ty::Array(_, len) = operand_ty.kind()
|
||||||
&& let Some(len) = Const::Ty(*len).try_eval_scalar_int(self.tcx, self.param_env)
|
&& let Some(len) = Const::Ty(self.tcx.types.usize, *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());
|
||||||
}
|
}
|
||||||
@ -221,7 +222,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() {
|
||||||
Const::Ty(*len)
|
Const::Ty(self.tcx.types.usize, *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[..] {
|
||||||
|
@ -1108,7 +1108,11 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
|||||||
// Trivial case: we are fetching a statically known length.
|
// Trivial case: we are fetching a statically known length.
|
||||||
let place_ty = place.ty(self.local_decls, self.tcx).ty;
|
let place_ty = place.ty(self.local_decls, self.tcx).ty;
|
||||||
if let ty::Array(_, len) = place_ty.kind() {
|
if let ty::Array(_, len) = place_ty.kind() {
|
||||||
return self.insert_constant(Const::from_ty_const(*len, self.tcx));
|
return self.insert_constant(Const::from_ty_const(
|
||||||
|
*len,
|
||||||
|
self.tcx.types.usize,
|
||||||
|
self.tcx,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut inner = self.simplify_place_value(place, location)?;
|
let mut inner = self.simplify_place_value(place, location)?;
|
||||||
@ -1130,7 +1134,11 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
|||||||
&& let Some(to) = to.builtin_deref(true)
|
&& let Some(to) = to.builtin_deref(true)
|
||||||
&& let ty::Slice(..) = to.kind()
|
&& let ty::Slice(..) = to.kind()
|
||||||
{
|
{
|
||||||
return self.insert_constant(Const::from_ty_const(*len, self.tcx));
|
return self.insert_constant(Const::from_ty_const(
|
||||||
|
*len,
|
||||||
|
self.tcx.types.usize,
|
||||||
|
self.tcx,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fallback: a symbolic `Len`.
|
// Fallback: a symbolic `Len`.
|
||||||
|
@ -150,7 +150,7 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let const_ = Const::from_ty_const(len, self.tcx);
|
let const_ = Const::from_ty_const(len, self.tcx.types.usize, self.tcx);
|
||||||
let constant = ConstOperand { span: source_info.span, const_, 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)));
|
||||||
}
|
}
|
||||||
|
@ -95,7 +95,7 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> {
|
|||||||
*rvalue = Rvalue::Use(Operand::Constant(Box::new(ConstOperand {
|
*rvalue = Rvalue::Use(Operand::Constant(Box::new(ConstOperand {
|
||||||
span: rustc_span::DUMMY_SP,
|
span: rustc_span::DUMMY_SP,
|
||||||
user_ty: None,
|
user_ty: None,
|
||||||
const_: Const::from_ty_const(len, self.tcx),
|
const_: Const::from_ty_const(len, self.tcx.types.usize, self.tcx),
|
||||||
})));
|
})));
|
||||||
}
|
}
|
||||||
self.super_rvalue(rvalue, loc);
|
self.super_rvalue(rvalue, loc);
|
||||||
|
@ -263,7 +263,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
|
|||||||
|
|
||||||
fn visit_constant(&mut self, ct: &mir::ConstOperand<'tcx>, location: Location) {
|
fn visit_constant(&mut self, ct: &mir::ConstOperand<'tcx>, location: Location) {
|
||||||
match ct.const_ {
|
match ct.const_ {
|
||||||
mir::Const::Ty(c) => {
|
mir::Const::Ty(_, c) => {
|
||||||
c.visit_with(self);
|
c.visit_with(self);
|
||||||
}
|
}
|
||||||
mir::Const::Unevaluated(mir::UnevaluatedConst { def, args: _, promoted }, ty) => {
|
mir::Const::Unevaluated(mir::UnevaluatedConst { def, args: _, promoted }, ty) => {
|
||||||
|
@ -737,7 +737,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
|
|||||||
// this). We show this to the user as `usize::MAX..` which is slightly incorrect but
|
// this). We show this to the user as `usize::MAX..` which is slightly incorrect but
|
||||||
// probably clear enough.
|
// probably clear enough.
|
||||||
let c = ty.numeric_max_val(cx.tcx).unwrap();
|
let c = ty.numeric_max_val(cx.tcx).unwrap();
|
||||||
let value = mir::Const::from_ty_const(c, cx.tcx);
|
let value = mir::Const::from_ty_const(c, ty.0, cx.tcx);
|
||||||
lo = PatRangeBoundary::Finite(value);
|
lo = PatRangeBoundary::Finite(value);
|
||||||
}
|
}
|
||||||
let hi = if let Some(hi) = range.hi.minus_one() {
|
let hi = if let Some(hi) = range.hi.minus_one() {
|
||||||
|
@ -251,7 +251,9 @@ impl RustcInternal for MirConst {
|
|||||||
fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||||
let constant = tables.mir_consts[self.id];
|
let constant = tables.mir_consts[self.id];
|
||||||
match constant {
|
match constant {
|
||||||
rustc_middle::mir::Const::Ty(ty) => rustc_middle::mir::Const::Ty(tcx.lift(ty).unwrap()),
|
rustc_middle::mir::Const::Ty(ty, ct) => {
|
||||||
|
rustc_middle::mir::Const::Ty(tcx.lift(ty).unwrap(), tcx.lift(ct).unwrap())
|
||||||
|
}
|
||||||
rustc_middle::mir::Const::Unevaluated(uneval, ty) => {
|
rustc_middle::mir::Const::Unevaluated(uneval, ty) => {
|
||||||
rustc_middle::mir::Const::Unevaluated(
|
rustc_middle::mir::Const::Unevaluated(
|
||||||
tcx.lift(uneval).unwrap(),
|
tcx.lift(uneval).unwrap(),
|
||||||
|
@ -398,7 +398,8 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
|
|||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(mir::Const::Ty(ty::Const::zero_sized(tables.tcx, ty_internal)).stable(&mut *tables))
|
Ok(mir::Const::Ty(ty_internal, ty::Const::zero_sized(tables.tcx, ty_internal))
|
||||||
|
.stable(&mut *tables))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_const_str(&self, value: &str) -> MirConst {
|
fn new_const_str(&self, value: &str) -> MirConst {
|
||||||
|
@ -729,9 +729,9 @@ impl<'tcx> Stable<'tcx> for rustc_middle::mir::Const<'tcx> {
|
|||||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||||
let id = tables.intern_mir_const(tables.tcx.lift(*self).unwrap());
|
let id = tables.intern_mir_const(tables.tcx.lift(*self).unwrap());
|
||||||
match *self {
|
match *self {
|
||||||
mir::Const::Ty(c) => MirConst::new(
|
mir::Const::Ty(ty, c) => MirConst::new(
|
||||||
stable_mir::ty::ConstantKind::Ty(c.stable(tables)),
|
stable_mir::ty::ConstantKind::Ty(c.stable(tables)),
|
||||||
c.ty().stable(tables),
|
ty.stable(tables),
|
||||||
id,
|
id,
|
||||||
),
|
),
|
||||||
mir::Const::Unevaluated(unev_const, ty) => {
|
mir::Const::Unevaluated(unev_const, ty) => {
|
||||||
|
@ -447,7 +447,7 @@ pub fn mir_const_from_ty_const<'tcx>(
|
|||||||
ty::ExprCt(_) => unimplemented!(),
|
ty::ExprCt(_) => unimplemented!(),
|
||||||
};
|
};
|
||||||
let stable_ty = tables.intern_ty(ty);
|
let stable_ty = tables.intern_ty(ty);
|
||||||
let id = tables.intern_mir_const(mir::Const::Ty(ty_const));
|
let id = tables.intern_mir_const(mir::Const::Ty(ty, ty_const));
|
||||||
stable_mir::ty::MirConst::new(kind, stable_ty, id)
|
stable_mir::ty::MirConst::new(kind, stable_ty, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user