rebase and use ty::Const in patterns again
This commit is contained in:
parent
ac60db231c
commit
0078e54185
13 changed files with 73 additions and 144 deletions
|
@ -184,13 +184,13 @@ pub(crate) fn destructure_mir_constant<'tcx>(
|
||||||
// We go to `usize` as we cannot allocate anything bigger anyway.
|
// We go to `usize` as we cannot allocate anything bigger anyway.
|
||||||
let (field_count, variant, down) = match val.ty().kind() {
|
let (field_count, variant, down) = match val.ty().kind() {
|
||||||
ty::Array(_, len) => (usize::try_from(len.eval_usize(tcx, param_env)).unwrap(), None, op),
|
ty::Array(_, len) => (usize::try_from(len.eval_usize(tcx, param_env)).unwrap(), None, op),
|
||||||
ty::Adt(def, _) if def.variants.is_empty() => {
|
ty::Adt(def, _) if def.variants().is_empty() => {
|
||||||
return mir::DestructuredMirConstant { variant: None, fields: &[] };
|
return mir::DestructuredMirConstant { variant: None, fields: &[] };
|
||||||
}
|
}
|
||||||
ty::Adt(def, _) => {
|
ty::Adt(def, _) => {
|
||||||
let variant = ecx.read_discriminant(&op).unwrap().1;
|
let variant = ecx.read_discriminant(&op).unwrap().1;
|
||||||
let down = ecx.operand_downcast(&op, variant).unwrap();
|
let down = ecx.operand_downcast(&op, variant).unwrap();
|
||||||
(def.variants[variant].fields.len(), Some(variant), down)
|
(def.variants()[variant].fields.len(), Some(variant), down)
|
||||||
}
|
}
|
||||||
ty::Tuple(substs) => (substs.len(), None, op),
|
ty::Tuple(substs) => (substs.len(), None, op),
|
||||||
_ => bug!("cannot destructure constant {:?}", val),
|
_ => bug!("cannot destructure constant {:?}", val),
|
||||||
|
@ -253,7 +253,7 @@ pub(crate) fn deref_mir_constant<'tcx>(
|
||||||
let mplace = ecx.deref_operand(&op).unwrap();
|
let mplace = ecx.deref_operand(&op).unwrap();
|
||||||
if let Some(alloc_id) = mplace.ptr.provenance {
|
if let Some(alloc_id) = mplace.ptr.provenance {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
tcx.get_global_alloc(alloc_id).unwrap().unwrap_memory().mutability,
|
tcx.get_global_alloc(alloc_id).unwrap().unwrap_memory().0.0.mutability,
|
||||||
Mutability::Not,
|
Mutability::Not,
|
||||||
"deref_const cannot be used with mutable allocations as \
|
"deref_const cannot be used with mutable allocations as \
|
||||||
that could allow pattern matching to observe mutable statics",
|
that could allow pattern matching to observe mutable statics",
|
||||||
|
|
|
@ -2711,7 +2711,7 @@ impl<'tcx> ConstantKind<'tcx> {
|
||||||
if let Some(val) = c.val().try_eval(tcx, param_env) {
|
if let Some(val) = c.val().try_eval(tcx, param_env) {
|
||||||
match val {
|
match val {
|
||||||
Ok(val) => Self::Val(val, c.ty()),
|
Ok(val) => Self::Val(val, c.ty()),
|
||||||
Err(ErrorReported) => Self::Ty(tcx.const_error(self.ty())),
|
Err(_) => Self::Ty(tcx.const_error(self.ty())),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self
|
self
|
||||||
|
|
|
@ -193,7 +193,7 @@ pub enum StmtKind<'tcx> {
|
||||||
|
|
||||||
// `Expr` is used a lot. Make sure it doesn't unintentionally get bigger.
|
// `Expr` is used a lot. Make sure it doesn't unintentionally get bigger.
|
||||||
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
|
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
|
||||||
rustc_data_structures::static_assert_size!(Expr<'_>, 144);
|
rustc_data_structures::static_assert_size!(Expr<'_>, 104);
|
||||||
|
|
||||||
/// A THIR expression.
|
/// A THIR expression.
|
||||||
#[derive(Debug, HashStable)]
|
#[derive(Debug, HashStable)]
|
||||||
|
@ -736,11 +736,7 @@ impl<'tcx> fmt::Display for Pat<'tcx> {
|
||||||
Some(adt_def.variant(variant_index))
|
Some(adt_def.variant(variant_index))
|
||||||
}
|
}
|
||||||
_ => self.ty.ty_adt_def().and_then(|adt| {
|
_ => self.ty.ty_adt_def().and_then(|adt| {
|
||||||
if !adt.is_enum() {
|
if !adt.is_enum() { Some(adt.non_enum_variant()) } else { None }
|
||||||
Some(adt.non_enum_variant())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@ use super::{
|
||||||
Arm, Block, Expr, ExprKind, Guard, InlineAsmOperand, Pat, PatKind, Stmt, StmtKind, Thir,
|
Arm, Block, Expr, ExprKind, Guard, InlineAsmOperand, Pat, PatKind, Stmt, StmtKind, Thir,
|
||||||
};
|
};
|
||||||
use crate::mir::ConstantKind;
|
use crate::mir::ConstantKind;
|
||||||
use crate::ty::Const;
|
|
||||||
|
|
||||||
pub trait Visitor<'a, 'tcx: 'a>: Sized {
|
pub trait Visitor<'a, 'tcx: 'a>: Sized {
|
||||||
fn thir(&self) -> &'a Thir<'tcx>;
|
fn thir(&self) -> &'a Thir<'tcx>;
|
||||||
|
|
|
@ -76,11 +76,7 @@ static_assert_size!(ConstKind<'_>, 40);
|
||||||
impl<'tcx> ConstKind<'tcx> {
|
impl<'tcx> ConstKind<'tcx> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn try_to_value(self) -> Option<ConstValue<'tcx>> {
|
pub fn try_to_value(self) -> Option<ConstValue<'tcx>> {
|
||||||
if let ConstKind::Value(val) = self {
|
if let ConstKind::Value(val) = self { Some(val) } else { None }
|
||||||
Some(val)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -1,17 +1,12 @@
|
||||||
//! See docs in build/expr/mod.rs
|
//! See docs in build/expr/mod.rs
|
||||||
|
|
||||||
use crate::build::Builder;
|
use crate::build::Builder;
|
||||||
use crate::thir::constant::parse_float;
|
|
||||||
use rustc_ast::ast;
|
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_middle::mir::interpret::{
|
use rustc_middle::mir::interpret::{ConstValue, LitToConstError, LitToConstInput, Scalar};
|
||||||
Allocation, ConstValue, LitToConstError, LitToConstInput, Scalar,
|
|
||||||
};
|
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
use rustc_middle::thir::*;
|
use rustc_middle::thir::*;
|
||||||
use rustc_middle::ty::subst::SubstsRef;
|
use rustc_middle::ty::subst::SubstsRef;
|
||||||
use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt};
|
use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt};
|
||||||
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
|
||||||
|
@ -32,11 +27,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
ExprKind::Literal { lit, neg } => {
|
ExprKind::Literal { lit, neg } => {
|
||||||
let literal =
|
let literal =
|
||||||
match lit_to_constant(tcx, LitToConstInput { lit: &lit.node, ty, neg }) {
|
match tcx.lit_to_mir_constant(LitToConstInput { lit: &lit.node, ty, neg }) {
|
||||||
Ok(c) => c,
|
Ok(c) => c,
|
||||||
Err(LitToConstError::Reported) => ConstantKind::Ty(tcx.const_error(ty)),
|
Err(LitToConstError::Reported) => ConstantKind::Ty(tcx.const_error(ty)),
|
||||||
Err(LitToConstError::TypeError) => {
|
Err(LitToConstError::TypeError) => {
|
||||||
bug!("encountered type error in `lit_to_constant")
|
bug!("encountered type error in `lit_to_mir_constant")
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -85,60 +80,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
|
|
||||||
Constant { span, user_ty: None, literal }
|
Constant { span, user_ty: None, literal }
|
||||||
}
|
}
|
||||||
ExprKind::ConstBlock { value } => {
|
|
||||||
Constant { span: span, user_ty: None, literal: value }
|
|
||||||
}
|
|
||||||
_ => span_bug!(span, "expression is not a valid constant {:?}", kind),
|
_ => span_bug!(span, "expression is not a valid constant {:?}", kind),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn lit_to_constant<'tcx>(
|
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
lit_input: LitToConstInput<'tcx>,
|
|
||||||
) -> Result<ConstantKind<'tcx>, LitToConstError> {
|
|
||||||
let LitToConstInput { lit, ty, neg } = lit_input;
|
|
||||||
let trunc = |n| {
|
|
||||||
let param_ty = ty::ParamEnv::reveal_all().and(ty);
|
|
||||||
let width = tcx.layout_of(param_ty).map_err(|_| LitToConstError::Reported)?.size;
|
|
||||||
trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits());
|
|
||||||
let result = width.truncate(n);
|
|
||||||
trace!("trunc result: {}", result);
|
|
||||||
Ok(ConstValue::Scalar(Scalar::from_uint(result, width)))
|
|
||||||
};
|
|
||||||
|
|
||||||
let value = match (lit, &ty.kind()) {
|
|
||||||
(ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => {
|
|
||||||
let s = s.as_str();
|
|
||||||
let allocation = Allocation::from_bytes_byte_aligned_immutable(s.as_bytes());
|
|
||||||
let allocation = tcx.intern_const_alloc(allocation);
|
|
||||||
ConstValue::Slice { data: allocation, start: 0, end: s.len() }
|
|
||||||
}
|
|
||||||
(ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _))
|
|
||||||
if matches!(inner_ty.kind(), ty::Slice(_)) =>
|
|
||||||
{
|
|
||||||
let allocation = Allocation::from_bytes_byte_aligned_immutable(data as &[u8]);
|
|
||||||
let allocation = tcx.intern_const_alloc(allocation);
|
|
||||||
ConstValue::Slice { data: allocation, start: 0, end: data.len() }
|
|
||||||
}
|
|
||||||
(ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => {
|
|
||||||
let id = tcx.allocate_bytes(data);
|
|
||||||
ConstValue::Scalar(Scalar::from_pointer(id.into(), &tcx))
|
|
||||||
}
|
|
||||||
(ast::LitKind::Byte(n), ty::Uint(ty::UintTy::U8)) => {
|
|
||||||
ConstValue::Scalar(Scalar::from_uint(*n, Size::from_bytes(1)))
|
|
||||||
}
|
|
||||||
(ast::LitKind::Int(n, _), ty::Uint(_)) | (ast::LitKind::Int(n, _), ty::Int(_)) => {
|
|
||||||
trunc(if neg { (*n as i128).overflowing_neg().0 as u128 } else { *n })?
|
|
||||||
}
|
|
||||||
(ast::LitKind::Float(n, _), ty::Float(fty)) => {
|
|
||||||
parse_float(*n, *fty, neg).ok_or(LitToConstError::Reported)?
|
|
||||||
}
|
|
||||||
(ast::LitKind::Bool(b), ty::Bool) => ConstValue::Scalar(Scalar::from_bool(*b)),
|
|
||||||
(ast::LitKind::Char(c), ty::Char) => ConstValue::Scalar(Scalar::from_char(*c)),
|
|
||||||
(ast::LitKind::Err(_), _) => return Err(LitToConstError::Reported),
|
|
||||||
_ => return Err(LitToConstError::TypeError),
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(ConstantKind::Val(value, ty))
|
|
||||||
}
|
|
||||||
|
|
|
@ -59,6 +59,56 @@ crate fn lit_to_const<'tcx>(
|
||||||
Ok(ty::Const::from_value(tcx, lit, ty))
|
Ok(ty::Const::from_value(tcx, lit, ty))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
crate fn lit_to_mir_constant<'tcx>(
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
lit_input: LitToConstInput<'tcx>,
|
||||||
|
) -> Result<ConstantKind<'tcx>, LitToConstError> {
|
||||||
|
let LitToConstInput { lit, ty, neg } = lit_input;
|
||||||
|
let trunc = |n| {
|
||||||
|
let param_ty = ty::ParamEnv::reveal_all().and(ty);
|
||||||
|
let width = tcx.layout_of(param_ty).map_err(|_| LitToConstError::Reported)?.size;
|
||||||
|
trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits());
|
||||||
|
let result = width.truncate(n);
|
||||||
|
trace!("trunc result: {}", result);
|
||||||
|
Ok(ConstValue::Scalar(Scalar::from_uint(result, width)))
|
||||||
|
};
|
||||||
|
|
||||||
|
let value = match (lit, &ty.kind()) {
|
||||||
|
(ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => {
|
||||||
|
let s = s.as_str();
|
||||||
|
let allocation = Allocation::from_bytes_byte_aligned_immutable(s.as_bytes());
|
||||||
|
let allocation = tcx.intern_const_alloc(allocation);
|
||||||
|
ConstValue::Slice { data: allocation, start: 0, end: s.len() }
|
||||||
|
}
|
||||||
|
(ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _))
|
||||||
|
if matches!(inner_ty.kind(), ty::Slice(_)) =>
|
||||||
|
{
|
||||||
|
let allocation = Allocation::from_bytes_byte_aligned_immutable(data as &[u8]);
|
||||||
|
let allocation = tcx.intern_const_alloc(allocation);
|
||||||
|
ConstValue::Slice { data: allocation, start: 0, end: data.len() }
|
||||||
|
}
|
||||||
|
(ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => {
|
||||||
|
let id = tcx.allocate_bytes(data);
|
||||||
|
ConstValue::Scalar(Scalar::from_pointer(id.into(), &tcx))
|
||||||
|
}
|
||||||
|
(ast::LitKind::Byte(n), ty::Uint(ty::UintTy::U8)) => {
|
||||||
|
ConstValue::Scalar(Scalar::from_uint(*n, Size::from_bytes(1)))
|
||||||
|
}
|
||||||
|
(ast::LitKind::Int(n, _), ty::Uint(_)) | (ast::LitKind::Int(n, _), ty::Int(_)) => {
|
||||||
|
trunc(if neg { (*n as i128).overflowing_neg().0 as u128 } else { *n })?
|
||||||
|
}
|
||||||
|
(ast::LitKind::Float(n, _), ty::Float(fty)) => {
|
||||||
|
parse_float(*n, *fty, neg).ok_or(LitToConstError::Reported)?
|
||||||
|
}
|
||||||
|
(ast::LitKind::Bool(b), ty::Bool) => ConstValue::Scalar(Scalar::from_bool(*b)),
|
||||||
|
(ast::LitKind::Char(c), ty::Char) => ConstValue::Scalar(Scalar::from_char(*c)),
|
||||||
|
(ast::LitKind::Err(_), _) => return Err(LitToConstError::Reported),
|
||||||
|
_ => return Err(LitToConstError::TypeError),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(ConstantKind::Val(value, ty))
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME move this to rustc_mir_build::build
|
// FIXME move this to rustc_mir_build::build
|
||||||
pub(crate) fn parse_float<'tcx>(
|
pub(crate) fn parse_float<'tcx>(
|
||||||
num: Symbol,
|
num: Symbol,
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
use crate::thir::pattern::pat_from_hir;
|
use crate::thir::pattern::pat_from_hir;
|
||||||
use crate::thir::util::UserAnnotatedTyHelpers;
|
use crate::thir::util::UserAnnotatedTyHelpers;
|
||||||
|
|
||||||
|
use rustc_ast::ast;
|
||||||
use rustc_data_structures::steal::Steal;
|
use rustc_data_structures::steal::Steal;
|
||||||
use rustc_errors::ErrorGuaranteed;
|
use rustc_errors::ErrorGuaranteed;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
|
@ -15,7 +16,7 @@ use rustc_middle::middle::region;
|
||||||
use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput};
|
use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput};
|
||||||
use rustc_middle::mir::ConstantKind;
|
use rustc_middle::mir::ConstantKind;
|
||||||
use rustc_middle::thir::*;
|
use rustc_middle::thir::*;
|
||||||
use rustc_middle::ty::{self, TyCtxt};
|
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
|
||||||
crate fn thir_body<'tcx>(
|
crate fn thir_body<'tcx>(
|
||||||
|
|
|
@ -377,10 +377,6 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_const(&mut self, ct: ty::Const<'tcx>) {
|
|
||||||
self.is_poly |= ct.has_param_types_or_consts();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_constant(&mut self, ct: mir::ConstantKind<'tcx>) {
|
fn visit_constant(&mut self, ct: mir::ConstantKind<'tcx>) {
|
||||||
self.is_poly |= ct.has_param_types_or_consts();
|
self.is_poly |= ct.has_param_types_or_consts();
|
||||||
}
|
}
|
||||||
|
@ -815,51 +811,3 @@ impl<'tcx> ConstUnifyCtxt<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Think I need these changes
|
|
||||||
=======
|
|
||||||
match (a_ct, b_ct) {
|
|
||||||
(mir::ConstantKind::Ty(a_ct), mir::ConstantKind::Ty(b_ct)) => {
|
|
||||||
match (a_ct.val(), b_ct.val()) {
|
|
||||||
// We can just unify errors with everything to reduce the amount of
|
|
||||||
// emitted errors here.
|
|
||||||
(ty::ConstKind::Error(_), _) | (_, ty::ConstKind::Error(_)) => true,
|
|
||||||
(ty::ConstKind::Param(a_param), ty::ConstKind::Param(b_param)) => {
|
|
||||||
a_param == b_param
|
|
||||||
}
|
|
||||||
(ty::ConstKind::Value(a_val), ty::ConstKind::Value(b_val)) => {
|
|
||||||
a_val == b_val
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we have `fn a<const N: usize>() -> [u8; N + 1]` and `fn b<const M: usize>() -> [u8; 1 + M]`
|
|
||||||
// we do not want to use `assert_eq!(a(), b())` to infer that `N` and `M` have to be `1`. This
|
|
||||||
// means that we only allow inference variables if they are equal.
|
|
||||||
(ty::ConstKind::Infer(a_val), ty::ConstKind::Infer(b_val)) => {
|
|
||||||
a_val == b_val
|
|
||||||
}
|
|
||||||
// We expand generic anonymous constants at the start of this function, so this
|
|
||||||
// branch should only be taking when dealing with associated constants, at
|
|
||||||
// which point directly comparing them seems like the desired behavior.
|
|
||||||
//
|
|
||||||
// FIXME(generic_const_exprs): This isn't actually the case.
|
|
||||||
// We also take this branch for concrete anonymous constants and
|
|
||||||
// expand generic anonymous constants with concrete substs.
|
|
||||||
(ty::ConstKind::Unevaluated(a_uv), ty::ConstKind::Unevaluated(b_uv)) => {
|
|
||||||
a_uv == b_uv
|
|
||||||
}
|
|
||||||
// FIXME(generic_const_exprs): We may want to either actually try
|
|
||||||
// to evaluate `a_ct` and `b_ct` if they are are fully concrete or something like
|
|
||||||
// this, for now we just return false here.
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(mir::ConstantKind::Val(a_val, a_ty), mir::ConstantKind::Val(b_val, b_ty)) => {
|
|
||||||
a_val == b_val && a_ty == b_ty
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
// FIXME Can it happen that we need to compare ConstantKind::Ty(ConstKind::Value)
|
|
||||||
// with a ConstantKind::Val and vice versa?
|
|
||||||
false
|
|
||||||
>>>>>>> 6064f16d846 (change thir to use mir::ConstantKind instead of ty::Const)
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
|
@ -407,7 +407,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
|
||||||
let pred =
|
let pred =
|
||||||
ty::Binder::dummy(infcx.replace_bound_vars_with_placeholders(binder));
|
ty::Binder::dummy(infcx.replace_bound_vars_with_placeholders(binder));
|
||||||
ProcessResult::Changed(mk_pending(vec![
|
ProcessResult::Changed(mk_pending(vec![
|
||||||
obligation.with(pred.to_predicate(self.selcx.tcx()))
|
obligation.with(pred.to_predicate(self.selcx.tcx())),
|
||||||
]))
|
]))
|
||||||
}
|
}
|
||||||
ty::PredicateKind::TypeWellFormedFromEnv(..) => {
|
ty::PredicateKind::TypeWellFormedFromEnv(..) => {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use clippy_utils::consts::{constant, constant_full_int, miri_to_const, FullInt};
|
use clippy_utils::consts::{constant, constant_full_int, FullInt};
|
||||||
use clippy_utils::diagnostics::span_lint_and_note;
|
use clippy_utils::diagnostics::span_lint_and_note;
|
||||||
use core::cmp::Ordering;
|
use core::cmp::Ordering;
|
||||||
use rustc_hir::{Arm, Expr, PatKind, RangeEnd};
|
use rustc_hir::{Arm, Expr, PatKind, RangeEnd};
|
||||||
|
@ -32,18 +32,15 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>)
|
||||||
.filter_map(|arm| {
|
.filter_map(|arm| {
|
||||||
if let Arm { pat, guard: None, .. } = *arm {
|
if let Arm { pat, guard: None, .. } = *arm {
|
||||||
if let PatKind::Range(ref lhs, ref rhs, range_end) = pat.kind {
|
if let PatKind::Range(ref lhs, ref rhs, range_end) = pat.kind {
|
||||||
let lhs_const = match lhs {
|
let lhs_val = match lhs {
|
||||||
Some(lhs) => constant(cx, cx.typeck_results(), lhs)?.0,
|
Some(lhs) => constant(cx, cx.typeck_results(), lhs)?.0.int_value(cx, ty)?,
|
||||||
None => miri_to_const(ty.numeric_min_val(cx.tcx)?)?,
|
None => FullInt::U(ty.numeric_min_val(cx.tcx)?),
|
||||||
};
|
};
|
||||||
let rhs_const = match rhs {
|
let rhs_val = match rhs {
|
||||||
Some(rhs) => constant(cx, cx.typeck_results(), rhs)?.0,
|
Some(rhs) => constant(cx, cx.typeck_results(), rhs)?.0.int_value(cx, ty)?,
|
||||||
None => miri_to_const(ty.numeric_max_val(cx.tcx)?)?,
|
None => FullInt::U(ty.numeric_max_val(cx.tcx)?),
|
||||||
};
|
};
|
||||||
|
|
||||||
let lhs_val = lhs_const.int_value(cx, ty)?;
|
|
||||||
let rhs_val = rhs_const.int_value(cx, ty)?;
|
|
||||||
|
|
||||||
let rhs_bound = match range_end {
|
let rhs_bound = match range_end {
|
||||||
RangeEnd::Included => EndBound::Included(rhs_val),
|
RangeEnd::Included => EndBound::Included(rhs_val),
|
||||||
RangeEnd::Excluded => EndBound::Excluded(rhs_val),
|
RangeEnd::Excluded => EndBound::Excluded(rhs_val),
|
||||||
|
|
|
@ -53,7 +53,7 @@ impl<'tcx> LateLintPass<'tcx> for NegMultiply {
|
||||||
fn check_mul(cx: &LateContext<'_>, span: Span, lit: &Expr<'_>, exp: &Expr<'_>) {
|
fn check_mul(cx: &LateContext<'_>, span: Span, lit: &Expr<'_>, exp: &Expr<'_>) {
|
||||||
if_chain! {
|
if_chain! {
|
||||||
if let ExprKind::Lit(ref l) = lit.kind;
|
if let ExprKind::Lit(ref l) = lit.kind;
|
||||||
if consts::lit_to_constant(&l.node, cx.typeck_results().expr_ty_opt(lit)) == Constant::Int(1);
|
if consts::lit_to_mir_constant(&l.node, cx.typeck_results().expr_ty_opt(lit)) == Constant::Int(1);
|
||||||
if cx.typeck_results().expr_ty(exp).is_integral();
|
if cx.typeck_results().expr_ty(exp).is_integral();
|
||||||
|
|
||||||
then {
|
then {
|
||||||
|
|
|
@ -179,7 +179,7 @@ impl Constant {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses a `LitKind` to a `Constant`.
|
/// Parses a `LitKind` to a `Constant`.
|
||||||
pub fn lit_to_constant(lit: &LitKind, ty: Option<Ty<'_>>) -> Constant {
|
pub fn lit_to_mir_constant(lit: &LitKind, ty: Option<Ty<'_>>) -> Constant {
|
||||||
match *lit {
|
match *lit {
|
||||||
LitKind::Str(ref is, _) => Constant::Str(is.to_string()),
|
LitKind::Str(ref is, _) => Constant::Str(is.to_string()),
|
||||||
LitKind::Byte(b) => Constant::Int(u128::from(b)),
|
LitKind::Byte(b) => Constant::Int(u128::from(b)),
|
||||||
|
@ -301,7 +301,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
|
||||||
if is_direct_expn_of(e.span, "cfg").is_some() {
|
if is_direct_expn_of(e.span, "cfg").is_some() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(lit_to_constant(&lit.node, self.typeck_results.expr_ty_opt(e)))
|
Some(lit_to_mir_constant(&lit.node, self.typeck_results.expr_ty_opt(e)))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ExprKind::Array(vec) => self.multi(vec).map(Constant::Vec),
|
ExprKind::Array(vec) => self.multi(vec).map(Constant::Vec),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue