the Const::eval_bits methods don't need to be given the Ty
This commit is contained in:
parent
0692db1a90
commit
a2374e65aa
@ -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 => {
|
||||||
|
@ -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.literal.try_eval_bits(self.tcx, self.param_env)
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
|
@ -323,23 +323,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]
|
||||||
|
@ -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]
|
||||||
|
@ -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)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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.literal.eval_bits(self.tcx, self.param_env)
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -85,7 +85,6 @@ 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<ConstantKind<'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)
|
||||||
@ -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 { .. } => {
|
||||||
|
@ -146,7 +146,7 @@ impl IntRange {
|
|||||||
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;
|
||||||
@ -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,
|
||||||
) {
|
) {
|
||||||
|
@ -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() });
|
||||||
}
|
}
|
||||||
@ -865,8 +865,8 @@ pub(crate) fn compare_const_vals<'tcx>(
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
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() {
|
||||||
|
@ -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.literal.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,
|
||||||
|
@ -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.literal.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 }
|
||||||
|
@ -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 => {
|
||||||
|
@ -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() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user